Environment Module

Last modified by Thomas Mortagne on 2026/04/03 11:02

cogProvides a simple abstraction of the execution environment
TypeJAR
Category
Developed by

XWiki Development Team

Rating
0 Votes
LicenseGNU Lesser General Public License 2.1
Bundled With

XWiki Standard

Compatibility

XWiki 3.5M1+

Description

A lot XWiki modules can be used as Java libraries that can be used in one's own applications and thus run in various environments. However some of these libraries need to save temporary files or access configuration data that can be stored on the filesystem or even need to save data that should persist across restarts.

Thus XWiki offers this Environment abstraction that other modules can depend on whenever they need to interact with the Environment, making it possible to use them in various environment such a JavaSE, Servlet Container or other.

To use the Environment module just get the Environment component injected as in:

...
@Inject
private Environment environment
...

Note that you'll need to add a dependency on the Standard Environment JAR (for JavaSE) or the Servlet Environment JAR (for the Servlet environment).

Then you get access to the following Environment APIs:

public interface Environment
{
    /**
     * Gets the directory for storing temporary data. The content of this directory may be deleted across restarts and
     * thus is not a safe place to store permanent/important data.
     *
     * @return a {@link File} object pointing to a directory that the application can use for storing temporary files
     */
    @Nullable
    File getTemporaryDirectory();

    /**
     * Gets the root directory of a location for storing persisting data. Contrary to the Temporary Directory the
     * content of this directory is guaranteed to persist across time.
     *
     * @return a {@link File} object pointing to the root folder of the permanent directory
     */
    @Nullable
    File getPermanentDirectory();

    /**
     * @param resourcePath the full path of the resource to access (eg "/somefile.properties")
     * @return the resource location as a {@link URL} or null if not found
     */
    @Nullable
    URL getResource(String resourcePath);

    /**
     * @param prefixPath the resource folder from where to search for the resource
     * @param resourcePath the path of the resource to access, relative to the prefix
     * @return the resource location as a {@link URL}, or null if no resource with the provided path could be found (or
     *         if the resource path is trying to access a resource outside of the specified prefix)
     * @since 17.10.5
     * @since 18.2.0
     */
    @Unstable
    @Nullable
    URL getResource(String prefixPath, String resourcePath)

    /**
     * @param resourcePath the full path of the resource to access (eg "/somefile.properties")
     * @return the resource location as an {@link InputStream} or <code>null</code> if no resource exists at the
     *         specified name
     */
    @Nullable
    InputStream getResourceAsStream(String resourcePath);

    /**
     * @param prefixPath the resource folder from where to search for the resource
     * @param resourcePath the path of the resource to access, relative to the prefix
     * @return the resource content as an {@link InputStream}, or null if no resource with the provided path could be
     *         found (or if the resource path is trying to access a resource outside of the specified prefix)
     * @since 17.10.5
     * @since 18.2.0
     */
    @Unstable
    @Nullable
    InputStream getResourceAsStream(String prefixPath, String resourcePath)

    /**
     * @param resourcePath the full path of the resource to access (eg "/somefile.properties")
     * @return the date of last modification of the resource file, or null if the resource does not exist or the date
     *         cannot be found
     * @since 17.10.5
     * @since 18.2.0
     */
    @Nullable
    Date getResourceLastModified(String resourcePath)

    /**
     * @param prefixPath the resource folder from where to search for the resource
     * @param resourcePath the path of the resource to access, relative to the prefix
     * @return the date of last modification of the resource file, or null if the resource does not exist (or if the
     *         resource path is trying to access a resource outside of the specified prefix) or the date cannot be found
     * @since 17.10.5
     * @since 18.2.0
     */
    @Unstable
    @Nullable
    Date getResourceLastModified(String prefixPath, String resourcePath)
}

Default Values

In order to make it easy to use we're providing default values for the various Environment directories, as follows:

  • Temporary directory: We use the value of the java.io.tmpdir System property for the Standard Environment and the value of the javax.servlet.context.tempdir System property for the Servlet Environment.
  • Permanent directory: We use the Temporary Directory location if not set
  • Resources directory: We look for resources in the Class Loader that was used to load the Standard Environment component implementation class if not set. If set and the resource cannot be found we also fallback on that Class Loader.

To set different values, just look up the component implementations and use the setters available. For example:

StandardEnvironment environment = (StandardEnvironment) componentManager.lookup(Environment.class);
environment.setTemporaryDirectory(...);
environment.setPermanentDirectory(...);
environment.setResourceDirectory(...);
environment.setResourceClassLoader(...);

Initializing XWiki when using its libraries standalone

If you're using XWiki's libraries in your own application you'll need to initialize the XWiki Component Manager.

However you'll also need to initialize the Environment to tell what temporary, permanent and resource directories to use and to make it easy to initialize both the XWiki Component Manager and the Environment we're providing a System helper class.

The simplest way to use it is simply:

ComponentManager componentManager = System.initialize();

There are also other initialize(...) signatures:

public static ComponentManager initialize(ClassLoader classLoader)
public static ComponentManager initialize(File permanentDirectory)
public static ComponentManager initialize(File permanentDirectory, File resourceDirectory)
public static ComponentManager initialize(File permanentDirectory, File resourceDirectory, File temporaryDirectory)
public static ComponentManager initialize(File permanentDirectory, File resourceDirectory, File temporaryDirectory, ClassLoader classLoader)

XWiki 16.10.4+, 17.1.0+

Servlet Environment Resource Cache

Resource URLs of the servlet environment are cached in a cache named environment.servlet.resourceURLCache as they are frequently accessed and depending on the Servlet environment, this can significantly slow down (in tests, not having a cache doubled the time needed to request a page). This means that freshly added or removed files in the WAR like Velocity templates, JavaScript or CSS files might not have any effect. The cache can be bypassed by triggering a force-refresh in the browser. The size of the cache is 10k entries by default. The cache configuration can be changed as explained in the documentation of the cache module.

XWiki 18.2.0+, 17.10.5+

Path traversal protections in Servlet Environment

While some application servers prevent accessing resource outside the resource root folder, it's not always the case. This forced to add path traversal protections in various places.

Servlet Environment now includes path traversal protections so that you don't have to worry about them anymore: getResource[AsStream] always make sure that resources don't go outside the resource root. Also, APIs with a prefixPath are provided (and recommended) so that you can also prevent resources to go outside this specific resource folder.

XWiki 18.2.1+, 17.10.6+ But since this much stricter protection can break valid use cases (for example, the XWiki Debian package stores several of those resources in /etc/xwiki and the resource folder actually contains links to them), a property environment.servlet.allowedRealPaths has been introduced in the configuration file xwiki.properties to allow indicating these other locations where resources can be found. By default, /etc/xwiki is allowed, since it's a very common use case.

Get Connected