Jetty 12 temp directory cleanup (#9153)
+ `Server` now has setter/getter for a temp directory, which can be null + `Context` now has a getter for a temp directory, which is never null + Server root Context temp directory is either whatever is set, else a work directory, else java.io.tmpdir + WebInfConfiguration will still create a temp directory name, but defers to ContextHandler for creation/persistence of the temp directory + temp directory (and BASE) removed from the deployer, as it is now the server temp directory.
This commit is contained in:
parent
be3b8f0b9d
commit
94991c60c0
|
@ -33,7 +33,6 @@
|
|||
</Call>
|
||||
</Set>
|
||||
<Set name="scanInterval" property="jetty.deploy.scanInterval"/>
|
||||
<Set name="tempDir" property="jetty.deploy.tempDir" />
|
||||
</New>
|
||||
</Arg>
|
||||
</Call>
|
||||
|
|
|
@ -28,8 +28,5 @@ contextHandlerClass?=org.eclipse.jetty.server.handler.ResourceHandler$ResourceCo
|
|||
## Monitored directory scan period (seconds)
|
||||
# jetty.deploy.scanInterval=1
|
||||
|
||||
## Base temporary directory for deployed web applications.
|
||||
# jetty.deploy.tempDir=
|
||||
|
||||
## Default ContextHandler class for core deployments
|
||||
# contextHandlerClass=org.eclipse.jetty.server.handler.ResourceHandler$ResourceContext
|
||||
|
|
|
@ -272,46 +272,6 @@ public class ContextProvider extends ScanningAppProvider
|
|||
return cc == null ? new String[0] : cc.split(",");
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the temporary directory for deployment.
|
||||
* <p>
|
||||
* This is equivalent to setting the {@link Deployable#BASE_TEMP_DIR} property.
|
||||
* If not set, then the <code>java.io.tmpdir</code> System Property is used.
|
||||
*
|
||||
* @param directory the new work directory
|
||||
*/
|
||||
public void setTempDir(String directory)
|
||||
{
|
||||
_properties.put(Deployable.BASE_TEMP_DIR, directory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the temporary directory for deployment.
|
||||
* <p>
|
||||
* This is equivalent to setting the {@link Deployable#BASE_TEMP_DIR} property.
|
||||
* If not set, then the <code>java.io.tmpdir</code> System Property is used.
|
||||
*
|
||||
* @param directory the new work directory
|
||||
*/
|
||||
public void setTempDir(File directory)
|
||||
{
|
||||
_properties.put(Deployable.BASE_TEMP_DIR, directory.getAbsolutePath());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the temporary directory for deployment.
|
||||
* <p>
|
||||
* This is equivalent to getting the {@link Deployable#BASE_TEMP_DIR} property.
|
||||
*
|
||||
* @return the user supplied work directory (null if user has not set Temp Directory yet)
|
||||
*/
|
||||
@ManagedAttribute("temp directory for use, null if no user set temp directory")
|
||||
public File getTempDir()
|
||||
{
|
||||
String tmpDir = _properties.get(Deployable.BASE_TEMP_DIR);
|
||||
return tmpDir == null ? null : new File(tmpDir);
|
||||
}
|
||||
|
||||
protected ContextHandler initializeContextHandler(Object context, Path path, Map<String, String> properties)
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
</Call>
|
||||
</Set>
|
||||
<Set name="scanInterval" property="jetty.deploy.scanInterval"/>
|
||||
<Set name="tempDir" property="jetty.deploy.tempDir" />
|
||||
<Call name="loadPropertiesFromString">
|
||||
<Arg>
|
||||
<Property name="jetty.deploy.common.properties"/>
|
||||
|
|
|
@ -40,7 +40,7 @@ public interface Deployable
|
|||
};
|
||||
|
||||
String ATTRIBUTE_PREFIX = "jetty.deploy.attribute.";
|
||||
String BASE_TEMP_DIR = "jetty.deploy.tempDir";
|
||||
String TEMP_DIR = "jetty.deploy.tempDir";
|
||||
String CONFIGURATION_CLASSES = "jetty.deploy.configurationClasses";
|
||||
String CONTAINER_SCAN_JARS = "jetty.deploy.containerScanJarPattern";
|
||||
String CONTEXT_PATH = "jetty.deploy.contextPath";
|
||||
|
|
|
@ -13,11 +13,6 @@
|
|||
|
||||
package org.eclipse.jetty.osgi;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Dictionary;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
@ -26,15 +21,10 @@ import org.eclipse.jetty.deploy.App;
|
|||
import org.eclipse.jetty.deploy.AppProvider;
|
||||
import org.eclipse.jetty.deploy.DeploymentManager;
|
||||
import org.eclipse.jetty.ee.Deployable;
|
||||
import org.eclipse.jetty.osgi.util.BundleFileLocatorHelperFactory;
|
||||
import org.eclipse.jetty.osgi.util.OSGiClassLoader;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.server.handler.ContextHandler;
|
||||
import org.eclipse.jetty.util.StringUtil;
|
||||
import org.eclipse.jetty.util.component.AbstractLifeCycle;
|
||||
import org.eclipse.jetty.util.component.Environment;
|
||||
import org.eclipse.jetty.util.resource.Resource;
|
||||
import org.eclipse.jetty.xml.XmlConfiguration;
|
||||
import org.osgi.framework.Bundle;
|
||||
import org.osgi.framework.ServiceReference;
|
||||
import org.slf4j.Logger;
|
||||
|
@ -199,45 +189,6 @@ public abstract class AbstractContextProvider extends AbstractLifeCycle implemen
|
|||
return cc == null ? new String[0] : cc.split(",");
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the temporary directory for deployment.
|
||||
* <p>
|
||||
* This is equivalent to setting the {@link Deployable#BASE_TEMP_DIR} property.
|
||||
* If not set, then the <code>java.io.tmpdir</code> System Property is used.
|
||||
*
|
||||
* @param directory the new work directory
|
||||
*/
|
||||
public void setTempDir(String directory)
|
||||
{
|
||||
_properties.put(Deployable.BASE_TEMP_DIR, directory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the temporary directory for deployment.
|
||||
* <p>
|
||||
* This is equivalent to setting the {@link Deployable#BASE_TEMP_DIR} property.
|
||||
* If not set, then the <code>java.io.tmpdir</code> System Property is used.
|
||||
*
|
||||
* @param directory the new work directory
|
||||
*/
|
||||
public void setTempDir(File directory)
|
||||
{
|
||||
_properties.put(Deployable.BASE_TEMP_DIR, directory.getAbsolutePath());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the temporary directory for deployment.
|
||||
* <p>
|
||||
* This is equivalent to getting the {@link Deployable#BASE_TEMP_DIR} property.
|
||||
*
|
||||
* @return the user supplied work directory (null if user has not set Temp Directory yet)
|
||||
*/
|
||||
public File getTempDir()
|
||||
{
|
||||
String tmpDir = _properties.get(Deployable.BASE_TEMP_DIR);
|
||||
return tmpDir == null ? null : new File(tmpDir);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param tldBundles Comma separated list of bundles that contain tld jars
|
||||
* that should be setup on the context instances created here.
|
||||
|
|
|
@ -109,5 +109,6 @@
|
|||
<Set name="stopTimeout"><Property name="jetty.server.stopTimeout" default="5000"/></Set>
|
||||
<Set name="dumpAfterStart" property="jetty.server.dumpAfterStart"/>
|
||||
<Set name="dumpBeforeStop" property="jetty.server.dumpBeforeStop"/>
|
||||
<Set name="tempDirectory" property="jetty.server.tempDirectory"/>
|
||||
|
||||
</Configure>
|
||||
|
|
|
@ -93,6 +93,9 @@ etc/jetty.xml
|
|||
## Dump the state of the Jetty server, components, and webapps after startup
|
||||
# jetty.server.dumpAfterStart=false
|
||||
|
||||
## The temporary directory used by the Jetty server and as a root for its contexts
|
||||
# jetty.server.tempDirectory=
|
||||
|
||||
## Dump the state of the Jetty server, components, and webapps before shutdown
|
||||
# jetty.server.dumpBeforeStop=false
|
||||
# end::documentation-server-config[]
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
package org.eclipse.jetty.server;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
|
@ -70,4 +71,9 @@ public interface Context extends Attributes, Decorator, Executor
|
|||
* The empty string is returned if the full path is exactly the context path.
|
||||
*/
|
||||
String getPathInContext(String fullPath);
|
||||
|
||||
/**
|
||||
* @return A temporary directory, configured either for the context, the server or the JVM. Never null.
|
||||
*/
|
||||
File getTempDirectory();
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
package org.eclipse.jetty.server;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
|
@ -22,6 +23,7 @@ import java.util.ArrayList;
|
|||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
@ -39,6 +41,7 @@ import org.eclipse.jetty.server.handler.ErrorProcessor;
|
|||
import org.eclipse.jetty.util.Attributes;
|
||||
import org.eclipse.jetty.util.DecoratedObjectFactory;
|
||||
import org.eclipse.jetty.util.ExceptionUtil;
|
||||
import org.eclipse.jetty.util.IO;
|
||||
import org.eclipse.jetty.util.Jetty;
|
||||
import org.eclipse.jetty.util.NanoTime;
|
||||
import org.eclipse.jetty.util.Uptime;
|
||||
|
@ -61,7 +64,6 @@ import org.slf4j.LoggerFactory;
|
|||
|
||||
public class Server extends Handler.Wrapper implements Attributes
|
||||
{
|
||||
public static final String BASE_TEMP_DIR_ATTR = "org.eclipse.jetty.server.BaseTempDir";
|
||||
private static final Logger LOG = LoggerFactory.getLogger(Server.class);
|
||||
private static final String __serverInfo = "jetty/" + Server.getVersion();
|
||||
|
||||
|
@ -81,6 +83,7 @@ public class Server extends Handler.Wrapper implements Attributes
|
|||
private volatile DateField _dateField;
|
||||
private long _stopTimeout;
|
||||
private InvocationType _invocationType = InvocationType.NON_BLOCKING;
|
||||
private File _tempDirectory;
|
||||
|
||||
public Server()
|
||||
{
|
||||
|
@ -132,6 +135,48 @@ public class Server extends Handler.Wrapper implements Attributes
|
|||
return _serverInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Convenience method to call {@link #setTempDirectory(File)} from a String representation
|
||||
* of the temporary directory.</p>
|
||||
* @param temp A string representation of the temporary directory.
|
||||
* @see #setTempDirectory(File)
|
||||
*/
|
||||
public void setTempDirectory(String temp)
|
||||
{
|
||||
setTempDirectory(new File(temp));
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Set the temporary directory returned by {@link Context#getTempDirectory()} for the root
|
||||
* {@link Context} returned {@link #getContext()}. If not set explicitly here, then the root
|
||||
* {@link Context#getTempDirectory()} will return either the directory found at
|
||||
* {@code new File(IO.asFile(System.getProperty("jetty.base")), "work")} if it exists,
|
||||
* else the JVMs temporary directory as {@code IO.asFile(System.getProperty("java.io.tmpdir"))}.
|
||||
* @param temp A directory that must exist and be writable or null to get the default.
|
||||
*/
|
||||
public void setTempDirectory(File temp)
|
||||
{
|
||||
if (isStarted())
|
||||
throw new IllegalStateException(getState());
|
||||
if (temp != null && !temp.exists())
|
||||
throw new IllegalArgumentException("Does not exist: " + temp);
|
||||
if (temp != null && !temp.canWrite())
|
||||
throw new IllegalArgumentException("Cannot write: " + temp);
|
||||
_tempDirectory = temp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The server temporary directory if set, else null. To always obtain a non-null
|
||||
* temporary directory use {@link Context#getTempDirectory()} on {@link #getContext()}.
|
||||
* @see #getContext()
|
||||
* @see Context#getTempDirectory()
|
||||
*/
|
||||
@ManagedAttribute("temporary directory")
|
||||
public File getTempDirectory()
|
||||
{
|
||||
return _tempDirectory;
|
||||
}
|
||||
|
||||
public void setServerInfo(String serverInfo)
|
||||
{
|
||||
_serverInfo = serverInfo;
|
||||
|
@ -721,6 +766,10 @@ public class Server extends Handler.Wrapper implements Attributes
|
|||
|
||||
class ServerContext extends Attributes.Wrapper implements Context
|
||||
{
|
||||
private final File jettyBase = IO.asFile(System.getProperty("jetty.base"));
|
||||
private final File workDir = jettyBase != null && jettyBase.isDirectory() && jettyBase.canWrite() ? new File(jettyBase, "work") : null;
|
||||
private final File tempDir = workDir != null && workDir.isDirectory() && workDir.canWrite() ? workDir : IO.asFile(System.getProperty("java.io.tmpdir"));
|
||||
|
||||
private ServerContext()
|
||||
{
|
||||
super(Server.this);
|
||||
|
@ -804,6 +853,12 @@ public class Server extends Handler.Wrapper implements Attributes
|
|||
{
|
||||
return fullPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getTempDirectory()
|
||||
{
|
||||
return Objects.requireNonNullElse(Server.this.getTempDirectory(), tempDir);
|
||||
}
|
||||
}
|
||||
|
||||
private class ServerEnvironment extends Attributes.Wrapper implements Environment
|
||||
|
|
|
@ -46,6 +46,7 @@ import org.eclipse.jetty.server.SymlinkAllowedResourceAliasChecker;
|
|||
import org.eclipse.jetty.util.Attributes;
|
||||
import org.eclipse.jetty.util.Callback;
|
||||
import org.eclipse.jetty.util.DecoratedObjectFactory;
|
||||
import org.eclipse.jetty.util.IO;
|
||||
import org.eclipse.jetty.util.Index;
|
||||
import org.eclipse.jetty.util.StringUtil;
|
||||
import org.eclipse.jetty.util.TypeUtil;
|
||||
|
@ -122,6 +123,9 @@ public class ContextHandler extends Handler.Wrapper implements Attributes, Grace
|
|||
private boolean _allowNullPathInContext;
|
||||
private Index<ProtectedTargetType> _protectedTargets = Index.empty(false);
|
||||
private final List<AliasCheck> _aliasChecks = new CopyOnWriteArrayList<>();
|
||||
private File _tempDirectory;
|
||||
private boolean _tempDirectoryPersisted = false;
|
||||
private boolean _tempDirectoryCreated = false;
|
||||
|
||||
public enum Availability
|
||||
{
|
||||
|
@ -179,6 +183,64 @@ public class ContextHandler extends Handler.Wrapper implements Attributes, Grace
|
|||
return new ScopedContext();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The temporary directory configured for the context, or null if none configured.
|
||||
* @see Context#getTempDirectory()
|
||||
*/
|
||||
@ManagedAttribute(value = "temporary directory location", readonly = true)
|
||||
public File getTempDirectory()
|
||||
{
|
||||
return _tempDirectory;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Set the temporary directory returned by {@link ScopedContext#getTempDirectory()}. If not set here,
|
||||
* then the {@link Server#getTempDirectory()} is returned by {@link ScopedContext#getTempDirectory()}.</p>
|
||||
* <p>If {@link #isTempDirectoryPersistent()} is true, the directory set here is used directly but may
|
||||
* be created if it does not exist. If {@link #isTempDirectoryPersistent()} is false, then any {@code File} set
|
||||
* here will be deleted and recreated as a directory during {@link #start()} and will be deleted during
|
||||
* {@link #stop()}.</p>
|
||||
* @see #setTempDirectoryPersistent(boolean)
|
||||
* @param tempDirectory A directory. If it does not exist, it must be able to be created during start.
|
||||
*/
|
||||
public void setTempDirectory(File tempDirectory)
|
||||
{
|
||||
if (isStarted())
|
||||
throw new IllegalStateException("Started");
|
||||
|
||||
if (tempDirectory != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
tempDirectory = new File(tempDirectory.getCanonicalPath());
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
LOG.warn("Unable to find canonical path for {}", tempDirectory, e);
|
||||
}
|
||||
}
|
||||
_tempDirectory = tempDirectory;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Set if the temp directory for this context will be kept over a stop and start cycle.</p>
|
||||
*
|
||||
* @see #setTempDirectory(File)
|
||||
* @param persist true to persist the temp directory on shutdown / exit of the context
|
||||
*/
|
||||
public void setTempDirectoryPersistent(boolean persist)
|
||||
{
|
||||
_tempDirectoryPersisted = persist;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if tmp directory will persist between startups of the context
|
||||
*/
|
||||
public boolean isTempDirectoryPersistent()
|
||||
{
|
||||
return _tempDirectoryPersisted;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return A mutable MimeTypes that wraps the {@link Server#getMimeTypes()}
|
||||
* once {@link ContextHandler#setServer(Server)} has been called.
|
||||
|
@ -585,6 +647,7 @@ public class ContextHandler extends Handler.Wrapper implements Attributes, Grace
|
|||
_availability.set(Availability.STARTING);
|
||||
try
|
||||
{
|
||||
createTempDirectory();
|
||||
_context.call(super::doStart, null);
|
||||
_availability.compareAndSet(Availability.STARTING, Availability.AVAILABLE);
|
||||
LOG.info("Started {}", this);
|
||||
|
@ -595,10 +658,53 @@ public class ContextHandler extends Handler.Wrapper implements Attributes, Grace
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Create the temporary directory. If the directory exists, but is not persistent, then it is
|
||||
* first deleted and then recreated. Once created, this method is a noop if called again before
|
||||
* stopping the context.</p>
|
||||
*/
|
||||
protected void createTempDirectory()
|
||||
{
|
||||
File tempDirectory = getTempDirectory();
|
||||
if (tempDirectory != null && !_tempDirectoryCreated)
|
||||
{
|
||||
_tempDirectoryCreated = true;
|
||||
if (isTempDirectoryPersistent())
|
||||
{
|
||||
// Create the directory if it doesn't exist
|
||||
if (!tempDirectory.exists() && !tempDirectory.mkdirs())
|
||||
throw new IllegalArgumentException("Unable to create temp dir: " + tempDirectory);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Delete and recreate it to ensure it is empty
|
||||
if (tempDirectory.exists() && !IO.delete(tempDirectory))
|
||||
throw new IllegalArgumentException("Failed to delete temp dir: " + tempDirectory);
|
||||
if (!tempDirectory.mkdirs())
|
||||
throw new IllegalArgumentException("Unable to create temp dir: " + tempDirectory);
|
||||
|
||||
// ensure it is removed on exist
|
||||
tempDirectory.deleteOnExit();
|
||||
}
|
||||
|
||||
// is it usable
|
||||
if (!tempDirectory.canWrite() || !tempDirectory.isDirectory())
|
||||
throw new IllegalArgumentException("Temp dir " + tempDirectory + " not useable: writeable=" + tempDirectory.canWrite() + ", dir=" + tempDirectory.isDirectory());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doStop() throws Exception
|
||||
{
|
||||
_context.call(super::doStop, null);
|
||||
|
||||
File tempDirectory = getTempDirectory();
|
||||
|
||||
// if we're not persisting the temp dir contents delete it
|
||||
if (tempDirectory != null && tempDirectory.exists() && !isTempDirectoryPersistent())
|
||||
IO.delete(tempDirectory);
|
||||
|
||||
_tempDirectoryCreated = false;
|
||||
}
|
||||
|
||||
public boolean checkVirtualHost(Request request)
|
||||
|
@ -787,7 +893,7 @@ public class ContextHandler extends Handler.Wrapper implements Attributes, Grace
|
|||
if (path == null)
|
||||
{
|
||||
// allow user to unset variable
|
||||
setBaseResource((Resource)null);
|
||||
setBaseResource(null);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -806,7 +912,7 @@ public class ContextHandler extends Handler.Wrapper implements Attributes, Grace
|
|||
*/
|
||||
public void setBaseResourceAsString(String base)
|
||||
{
|
||||
setBaseResource((Resource)(base == null ? null : ResourceFactory.of(this).newResource(base)));
|
||||
setBaseResource((base == null ? null : ResourceFactory.of(this).newResource(base)));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1076,6 +1182,15 @@ public class ContextHandler extends Handler.Wrapper implements Attributes, Grace
|
|||
return _baseResource;
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getTempDirectory()
|
||||
{
|
||||
File tempDirectory = ContextHandler.this.getTempDirectory();
|
||||
if (tempDirectory == null)
|
||||
tempDirectory = getServer().getTempDirectory();
|
||||
return tempDirectory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getVirtualHosts()
|
||||
{
|
||||
|
|
|
@ -32,10 +32,8 @@ import org.eclipse.jetty.server.FormFields;
|
|||
import org.eclipse.jetty.server.Handler;
|
||||
import org.eclipse.jetty.server.Request;
|
||||
import org.eclipse.jetty.server.Response;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.util.Callback;
|
||||
import org.eclipse.jetty.util.Fields;
|
||||
import org.eclipse.jetty.util.IO;
|
||||
import org.eclipse.jetty.util.StringUtil;
|
||||
|
||||
public class DelayedHandler extends Handler.Wrapper
|
||||
|
@ -310,8 +308,7 @@ public class DelayedHandler extends Handler.Wrapper
|
|||
}
|
||||
else
|
||||
{
|
||||
Object baseTempDirectory = getRequest().getContext().getAttribute(Server.BASE_TEMP_DIR_ATTR);
|
||||
_formData.setFilesDirectory(IO.asFile(baseTempDirectory == null ? System.getProperty("java.io.tmpdir") : baseTempDirectory).toPath());
|
||||
_formData.setFilesDirectory(getRequest().getContext().getTempDirectory().toPath());
|
||||
readAndParse();
|
||||
// if we are done already, then we are still in the scope of the original process call and can
|
||||
// process directly, otherwise we must execute a call to process as we are within a serialized
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
package org.eclipse.jetty.server.handler;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.net.URL;
|
||||
|
@ -23,6 +24,7 @@ import java.util.concurrent.CountDownLatch;
|
|||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.eclipse.jetty.http.HttpFields;
|
||||
import org.eclipse.jetty.http.HttpHeader;
|
||||
|
@ -45,11 +47,20 @@ import org.eclipse.jetty.server.Request;
|
|||
import org.eclipse.jetty.server.Response;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.server.internal.HttpChannelState;
|
||||
import org.eclipse.jetty.toolchain.test.FS;
|
||||
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.eclipse.jetty.util.Callback;
|
||||
import org.eclipse.jetty.util.IO;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
|
@ -58,6 +69,7 @@ import static org.hamcrest.Matchers.is;
|
|||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
import static org.hamcrest.Matchers.sameInstance;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
@ -65,6 +77,8 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
|
|||
|
||||
public class ContextHandlerTest
|
||||
{
|
||||
public static final File TEST_BAD = MavenTestingUtils.getTargetTestingPath("testBad").toFile();
|
||||
public static final File TEST_OK = MavenTestingUtils.getTargetTestingPath("testOK").toFile();
|
||||
Server _server;
|
||||
ClassLoader _loader;
|
||||
ContextHandler _contextHandler;
|
||||
|
@ -93,6 +107,15 @@ public class ContextHandlerTest
|
|||
_server.stop();
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
public static void afterAll()
|
||||
{
|
||||
ensureWritable(TEST_OK);
|
||||
FS.ensureDeleted(TEST_OK.toPath());
|
||||
ensureWritable(TEST_BAD);
|
||||
FS.ensureDeleted(TEST_BAD.toPath());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMiss() throws Exception
|
||||
{
|
||||
|
@ -283,7 +306,7 @@ public class ContextHandlerTest
|
|||
Handler handler = new Handler.Abstract()
|
||||
{
|
||||
@Override
|
||||
public boolean process(Request request, Response response, Callback callback) throws Exception
|
||||
public boolean process(Request request, Response response, Callback callback)
|
||||
{
|
||||
assertInContext(request);
|
||||
scopeListener.assertInContext(request.getContext(), request);
|
||||
|
@ -649,6 +672,195 @@ public class ContextHandlerTest
|
|||
assertThrows(IllegalStateException.class, () -> handlerCollection.addHandler(contextHandlerA));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(booleans = {true, false})
|
||||
public void testSetTempDirectoryNotExists(boolean persistTempDir) throws Exception
|
||||
{
|
||||
Server server = new Server();
|
||||
ContextHandler context = new ContextHandler();
|
||||
server.setHandler(context);
|
||||
context.setTempDirectoryPersistent(persistTempDir);
|
||||
|
||||
// The temp directory is defined but has not been created.
|
||||
File tempDir = MavenTestingUtils.getTargetTestingPath("tempDir").toFile();
|
||||
IO.delete(tempDir);
|
||||
context.setTempDirectory(tempDir);
|
||||
assertThat(context.getTempDirectory(), is(tempDir));
|
||||
assertFalse(context.getTempDirectory().exists());
|
||||
|
||||
// Once server is started the WebApp temp directory exists and is valid directory.
|
||||
server.start();
|
||||
File tempDirectory = context.getTempDirectory();
|
||||
assertNotNull(tempDirectory);
|
||||
assertTrue(tempDirectory.exists());
|
||||
assertTrue(tempDirectory.isDirectory());
|
||||
|
||||
// Once server is stopped the WebApp temp should be deleted if persistTempDir is false.
|
||||
server.stop();
|
||||
tempDirectory = context.getTempDirectory();
|
||||
assertThat(tempDirectory != null && tempDirectory.exists(), is(persistTempDir));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(booleans = {true, false})
|
||||
public void testSetTempDirectoryExists(boolean persistTempDir) throws Exception
|
||||
{
|
||||
Server server = new Server();
|
||||
ContextHandler context = new ContextHandler();
|
||||
server.setHandler(context);
|
||||
context.setTempDirectoryPersistent(persistTempDir);
|
||||
|
||||
// The temp directory is defined and has already been created.
|
||||
File tempDir = MavenTestingUtils.getTargetTestingPath("tempDir").toFile();
|
||||
IO.delete(tempDir);
|
||||
assertFalse(tempDir.exists());
|
||||
assertTrue(tempDir.mkdir());
|
||||
context.setTempDirectory(tempDir);
|
||||
assertThat(context.getTempDirectory(), is(tempDir));
|
||||
assertTrue(tempDir.exists());
|
||||
|
||||
// create some content
|
||||
File someFile = new File(tempDir, "somefile.txt");
|
||||
assertTrue(someFile.createNewFile());
|
||||
assertTrue(someFile.exists());
|
||||
|
||||
// Once server is started the WebApp temp directory exists and is valid directory.
|
||||
server.start();
|
||||
File tempDirectory = context.getTempDirectory();
|
||||
assertNotNull(tempDirectory);
|
||||
assertTrue(tempDirectory.exists());
|
||||
assertTrue(tempDirectory.isDirectory());
|
||||
|
||||
// Contents exists if persistent else it was deleted
|
||||
if (persistTempDir)
|
||||
assertTrue(someFile.exists());
|
||||
else
|
||||
assertFalse(someFile.exists());
|
||||
|
||||
// Once server is stopped the WebApp temp should be deleted if persistTempDir is false.
|
||||
server.stop();
|
||||
tempDirectory = context.getTempDirectory();
|
||||
assertThat(tempDirectory != null && tempDirectory.exists(), is(persistTempDir));
|
||||
}
|
||||
|
||||
private static void ensureWritable(File file)
|
||||
{
|
||||
if (file.exists())
|
||||
{
|
||||
assertTrue(file.setWritable(true));
|
||||
if (file.isDirectory())
|
||||
{
|
||||
File[] files = file.listFiles();
|
||||
if (files != null)
|
||||
for (File child : files)
|
||||
ensureWritable(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static Stream<Arguments> okTempDirs() throws Exception
|
||||
{
|
||||
ensureWritable(TEST_OK);
|
||||
FS.ensureDeleted(TEST_OK.toPath());
|
||||
assertFalse(TEST_OK.exists());
|
||||
assertTrue(TEST_OK.mkdir());
|
||||
TEST_OK.deleteOnExit();
|
||||
|
||||
File notDirectory = new File(TEST_OK, "notDirectory.txt");
|
||||
assertTrue(notDirectory.createNewFile());
|
||||
|
||||
File notWritable = new File(TEST_OK, "notWritable");
|
||||
assertTrue(notWritable.mkdir());
|
||||
assertTrue(notWritable.setWritable(false));
|
||||
|
||||
File notWriteableParent = new File(TEST_OK, "notWritableParent");
|
||||
assertTrue(notWriteableParent.mkdir());
|
||||
File cantDelete = new File(notWriteableParent, "cantDelete");
|
||||
assertTrue(cantDelete.mkdirs());
|
||||
assertTrue(notWriteableParent.setWritable(false));
|
||||
|
||||
return Stream.of(
|
||||
Arguments.of(false, notDirectory),
|
||||
Arguments.of(false, notWritable),
|
||||
Arguments.of(true, cantDelete)
|
||||
);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("okTempDirs")
|
||||
public void testSetTempDirectoryOK(boolean persistent, File okTempDir) throws Exception
|
||||
{
|
||||
Server server = new Server();
|
||||
ContextHandler context = new ContextHandler();
|
||||
server.setHandler(context);
|
||||
context.setTempDirectory(okTempDir);
|
||||
context.setTempDirectoryPersistent(persistent);
|
||||
|
||||
server.start();
|
||||
|
||||
assertTrue(context.getTempDirectory().exists());
|
||||
assertTrue(context.getTempDirectory().isDirectory());
|
||||
assertThat(context.getTempDirectory().getAbsolutePath(), equalTo(okTempDir.getAbsolutePath()));
|
||||
|
||||
server.stop();
|
||||
|
||||
if (persistent)
|
||||
{
|
||||
assertTrue(context.getTempDirectory().exists());
|
||||
assertTrue(context.getTempDirectory().isDirectory());
|
||||
assertThat(context.getTempDirectory().getAbsolutePath(), equalTo(okTempDir.getAbsolutePath()));
|
||||
}
|
||||
else
|
||||
{
|
||||
assertFalse(context.getTempDirectory().exists());
|
||||
}
|
||||
}
|
||||
|
||||
public static Stream<Arguments> badTempDirs() throws Exception
|
||||
{
|
||||
ensureWritable(TEST_BAD);
|
||||
FS.ensureDeleted(TEST_BAD.toPath());
|
||||
assertFalse(TEST_BAD.exists());
|
||||
assertTrue(TEST_BAD.mkdir());
|
||||
TEST_BAD.deleteOnExit();
|
||||
|
||||
File notDirectory = new File(TEST_BAD, "notDirectory.txt");
|
||||
assertTrue(notDirectory.createNewFile());
|
||||
|
||||
File notWritable = new File(TEST_BAD, "notWritable");
|
||||
assertTrue(notWritable.mkdir());
|
||||
assertTrue(notWritable.setWritable(false));
|
||||
|
||||
File notWriteableParent = new File(TEST_BAD, "notWritableParent");
|
||||
assertTrue(notWriteableParent.mkdir());
|
||||
File cantCreate = new File(notWriteableParent, "temp");
|
||||
File cantDelete = new File(notWriteableParent, "cantDelete");
|
||||
assertTrue(cantDelete.mkdirs());
|
||||
assertTrue(notWriteableParent.setWritable(false));
|
||||
|
||||
return Stream.of(
|
||||
Arguments.of(true, notDirectory),
|
||||
Arguments.of(true, notWritable),
|
||||
Arguments.of(true, cantCreate),
|
||||
Arguments.of(false, cantCreate),
|
||||
Arguments.of(false, cantDelete)
|
||||
);
|
||||
}
|
||||
|
||||
@Disabled // TODO doesn't work on jenkins?
|
||||
@ParameterizedTest
|
||||
@MethodSource("badTempDirs")
|
||||
public void testSetTempDirectoryBad(boolean persistent, File badTempDir)
|
||||
{
|
||||
Server server = new Server();
|
||||
ContextHandler context = new ContextHandler();
|
||||
server.setHandler(context);
|
||||
context.setTempDirectory(badTempDir);
|
||||
context.setTempDirectoryPersistent(persistent);
|
||||
|
||||
assertThrows(IllegalArgumentException.class, server::start);
|
||||
}
|
||||
|
||||
private static class ScopeListener implements ContextHandler.ContextScopeListener
|
||||
{
|
||||
private static final Request NULL = new Request.Wrapper(null);
|
||||
|
|
|
@ -39,7 +39,7 @@ public class MavenQuickStartConfiguration extends QuickStartConfiguration
|
|||
public void deconfigure(WebAppContext context) throws Exception
|
||||
{
|
||||
//if we're not persisting the temp dir, get rid of any overlays
|
||||
if (!context.isPersistTempDirectory())
|
||||
if (!context.isTempDirectoryPersistent())
|
||||
{
|
||||
Resource originalBases = (Resource)context.getAttribute("org.eclipse.jetty.resources.originalBases");
|
||||
String originalBaseStr = originalBases.toString();
|
||||
|
|
|
@ -153,7 +153,7 @@ public class QuickStartGenerator
|
|||
ServerSupport.addWebApplication(server, webApp);
|
||||
|
||||
//leave everything unpacked for the forked process to use
|
||||
webApp.setPersistTempDirectory(true);
|
||||
webApp.setTempDirectoryPersistent(true);
|
||||
}
|
||||
|
||||
try
|
||||
|
|
|
@ -102,7 +102,7 @@ public class WebAppPropertyConverter
|
|||
//tmp dir
|
||||
props.put(TMP_DIR, webApp.getTempDirectory().getAbsolutePath());
|
||||
//props.put("tmp.dir.persist", Boolean.toString(originalPersistTemp));
|
||||
props.put(TMP_DIR_PERSIST, Boolean.toString(webApp.isPersistTempDirectory()));
|
||||
props.put(TMP_DIR_PERSIST, Boolean.toString(webApp.isTempDirectoryPersistent()));
|
||||
|
||||
//send over the calculated resource bases that includes unpacked overlays
|
||||
Resource baseResource = webApp.getBaseResource();
|
||||
|
@ -219,7 +219,7 @@ public class WebAppPropertyConverter
|
|||
|
||||
str = webAppProperties.getProperty(TMP_DIR_PERSIST);
|
||||
if (!StringUtil.isBlank(str))
|
||||
webApp.setPersistTempDirectory(Boolean.valueOf(str));
|
||||
webApp.setTempDirectoryPersistent(Boolean.valueOf(str));
|
||||
|
||||
//Get the calculated base dirs which includes the overlays
|
||||
str = webAppProperties.getProperty(BASE_DIRS);
|
||||
|
|
|
@ -96,7 +96,7 @@ public class TestWebAppPropertyConverter
|
|||
webApp.setContextPath("/foo");
|
||||
webApp.setBaseResourceAsPath(MavenTestingUtils.getTestResourcePathDir("root"));
|
||||
webApp.setTempDirectory(tmpDir);
|
||||
webApp.setPersistTempDirectory(false);
|
||||
webApp.setTempDirectoryPersistent(false);
|
||||
webApp.setClasses(classesDir);
|
||||
webApp.setTestClasses(testClassesDir);
|
||||
webApp.setWebInfLib(Arrays.asList(jar1, jar2));
|
||||
|
@ -149,7 +149,7 @@ public class TestWebAppPropertyConverter
|
|||
assertThat(webApp.getWebInfLib(), Matchers.contains(jar1, jar2));
|
||||
assertThat(webApp.getOverrideDescriptors(), Matchers.contains(override1.getAbsolutePath(), override2.getAbsolutePath()));
|
||||
assertEquals(tmpDir, webApp.getTempDirectory());
|
||||
assertEquals(true, webApp.isPersistTempDirectory());
|
||||
assertEquals(true, webApp.isTempDirectoryPersistent());
|
||||
assertEquals(war.getAbsolutePath(), webApp.getWar());
|
||||
assertEquals(webXml.getAbsolutePath(), webApp.getDescriptor());
|
||||
assertThat(webApp.getBaseResource(), instanceOf(CombinedResource.class));
|
||||
|
|
|
@ -818,7 +818,7 @@ public class QuickStartGeneratorConfiguration extends AbstractConfiguration
|
|||
{
|
||||
generateQuickStartWebXml(context, os);
|
||||
LOG.info("Generated {}", _quickStartWebXml);
|
||||
if (context.getAttribute(WebInfConfiguration.TEMPORARY_RESOURCE_BASE) != null && !context.isPersistTempDirectory())
|
||||
if (context.getAttribute(WebInfConfiguration.TEMPORARY_RESOURCE_BASE) != null && !context.isTempDirectoryPersistent())
|
||||
LOG.warn("Generated to non persistent location: {}", _quickStartWebXml);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
package org.eclipse.jetty.ee10.servlet;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.MalformedURLException;
|
||||
|
@ -103,6 +104,8 @@ import org.eclipse.jetty.util.resource.Resources;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static jakarta.servlet.ServletContext.TEMPDIR;
|
||||
|
||||
/**
|
||||
* Servlet Context.
|
||||
* <p>
|
||||
|
@ -284,7 +287,14 @@ public class ServletContextHandler extends ContextHandler implements Graceful
|
|||
// Link the handlers
|
||||
relinkHandlers();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setTempDirectory(File tempDirectory)
|
||||
{
|
||||
super.setTempDirectory(tempDirectory);
|
||||
setAttribute(TEMPDIR, getTempDirectory());
|
||||
}
|
||||
|
||||
public ServletContextApi newServletContextApi()
|
||||
{
|
||||
return new ServletContextApi();
|
||||
|
|
|
@ -45,7 +45,6 @@
|
|||
<Set name="extractWars" property="jetty.deploy.extractWars" />
|
||||
<Set name="parentLoaderPriority" property="jetty.deploy.parentLoaderPriority" />
|
||||
<Set name="configurationClasses" property="jetty.deploy.configurationClasses" />
|
||||
<Set name="tempDir" property="jetty.deploy.tempDir" />
|
||||
<Get name="properties">
|
||||
<Put name="jetty.deploy.containerScanJarPattern">
|
||||
<Property name="jetty.deploy.containerScanJarPattern">
|
||||
|
|
|
@ -38,9 +38,6 @@ etc/jetty-ee10-deploy.xml
|
|||
## Comma separated list of configuration classes to set.
|
||||
# jetty.deploy.configurationClasses=
|
||||
|
||||
## Base temporary directory for deployed web applications.
|
||||
# jetty.deploy.tempDir=
|
||||
|
||||
## Pattern to select jars from the container classloader to be scanned (or null to scan no jars)
|
||||
# jetty.deploy.containerScanJarPattern=.*/jakarta.servlet-api-[^/]*\.jar$|.*jakarta.servlet.jsp.jstl-.*\.jar$
|
||||
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
|
||||
package org.eclipse.jetty.ee10.webapp;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URI;
|
||||
|
@ -53,6 +52,7 @@ import org.eclipse.jetty.ee10.servlet.security.SecurityHandler;
|
|||
import org.eclipse.jetty.server.Connector;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.util.ExceptionUtil;
|
||||
import org.eclipse.jetty.util.IO;
|
||||
import org.eclipse.jetty.util.StringUtil;
|
||||
import org.eclipse.jetty.util.URIUtil;
|
||||
import org.eclipse.jetty.util.annotation.ManagedAttribute;
|
||||
|
@ -82,10 +82,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
{
|
||||
static final Logger LOG = LoggerFactory.getLogger(WebAppContext.class);
|
||||
|
||||
public static final String TEMPDIR = ServletContext.TEMPDIR;
|
||||
public static final String BASETEMPDIR = Server.BASE_TEMP_DIR_ATTR;
|
||||
public static final String WEB_DEFAULTS_XML = "org/eclipse/jetty/ee10/webapp/webdefault-ee10.xml";
|
||||
public static final String ERROR_PAGE = "org.eclipse.jetty.server.error_page";
|
||||
public static final String SERVER_SYS_CLASSES = "org.eclipse.jetty.webapp.systemClasses";
|
||||
public static final String SERVER_SRV_CLASSES = "org.eclipse.jetty.webapp.serverClasses";
|
||||
|
||||
|
@ -128,9 +125,6 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
|
||||
private String[] _contextWhiteList = null;
|
||||
|
||||
private File _tmpDir;
|
||||
private boolean _persistTmpDir = false;
|
||||
|
||||
private String _war;
|
||||
private List<Resource> _extraClasspath;
|
||||
private Throwable _unavailableException;
|
||||
|
@ -244,7 +238,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
switch (property)
|
||||
{
|
||||
case Deployable.WAR -> setWar(value);
|
||||
case Deployable.BASE_TEMP_DIR -> setAttribute(BASETEMPDIR, value);
|
||||
case Deployable.TEMP_DIR -> setTempDirectory(IO.asFile(value));
|
||||
case Deployable.CONFIGURATION_CLASSES -> setConfigurationClasses(value == null ? null : value.split(","));
|
||||
case Deployable.CONTAINER_SCAN_JARS -> setAttribute(MetaInfConfiguration.CONTAINER_JAR_PATTERN, value);
|
||||
case Deployable.EXTRACT_WARS -> setExtractWAR(Boolean.parseBoolean(value));
|
||||
|
@ -490,6 +484,12 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
_configurations.preConfigure(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createTempDirectory()
|
||||
{
|
||||
super.createTempDirectory();
|
||||
}
|
||||
|
||||
public boolean configure() throws Exception
|
||||
{
|
||||
return _configurations.configure(this);
|
||||
|
@ -583,13 +583,13 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
private void dumpUrl()
|
||||
{
|
||||
Connector[] connectors = getServer().getConnectors();
|
||||
for (int i = 0; i < connectors.length; i++)
|
||||
for (Connector connector : connectors)
|
||||
{
|
||||
String displayName = getDisplayName();
|
||||
if (displayName == null)
|
||||
displayName = "WebApp@" + Arrays.hashCode(connectors);
|
||||
|
||||
LOG.info("{} at http://{}{}", displayName, connectors[i].toString(), getContextPath());
|
||||
LOG.info("{} at http://{}{}", displayName, connector.toString(), getContextPath());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1152,59 +1152,6 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
_contextWhiteList = contextWhiteList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set temporary directory for context.
|
||||
* The jakarta.servlet.context.tempdir attribute is also set.
|
||||
*
|
||||
* @param dir Writable temporary directory.
|
||||
*/
|
||||
public void setTempDirectory(File dir)
|
||||
{
|
||||
if (isStarted())
|
||||
throw new IllegalStateException("Started");
|
||||
|
||||
if (dir != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
dir = new File(dir.getCanonicalPath());
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
LOG.warn("Unable to find canonical path for {}", dir, e);
|
||||
}
|
||||
}
|
||||
|
||||
_tmpDir = dir;
|
||||
setAttribute(TEMPDIR, _tmpDir);
|
||||
}
|
||||
|
||||
@ManagedAttribute(value = "temporary directory location", readonly = true)
|
||||
public File getTempDirectory()
|
||||
{
|
||||
return _tmpDir;
|
||||
}
|
||||
|
||||
/**
|
||||
* If true the temp directory for this
|
||||
* webapp will be kept when the webapp stops. Otherwise,
|
||||
* it will be deleted.
|
||||
*
|
||||
* @param persist true to persist the temp directory on shutdown / exit of the webapp
|
||||
*/
|
||||
public void setPersistTempDirectory(boolean persist)
|
||||
{
|
||||
_persistTmpDir = persist;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if tmp directory will persist between startups of the webapp
|
||||
*/
|
||||
public boolean isPersistTempDirectory()
|
||||
{
|
||||
return _persistTmpDir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the war of the webapp. From this value a {@link #setBaseResource(Resource)}
|
||||
* value is computed by {@link WebInfConfiguration}, which may be changed from
|
||||
|
|
|
@ -20,6 +20,7 @@ import java.nio.file.Files;
|
|||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
|
||||
import jakarta.servlet.ServletContext;
|
||||
import org.eclipse.jetty.server.Connector;
|
||||
import org.eclipse.jetty.server.NetworkConnector;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
|
@ -53,6 +54,9 @@ public class WebInfConfiguration extends AbstractConfiguration
|
|||
// Make a temp directory for the webapp if one is not already set
|
||||
resolveTempDirectory(context);
|
||||
|
||||
// Force early configuration (clearing) of the temporary directory so we can unpack into it.
|
||||
context.createTempDirectory();
|
||||
|
||||
// Extract webapp if necessary
|
||||
unpack(context);
|
||||
}
|
||||
|
@ -80,14 +84,6 @@ public class WebInfConfiguration extends AbstractConfiguration
|
|||
@Override
|
||||
public void deconfigure(WebAppContext context) throws Exception
|
||||
{
|
||||
File tempDirectory = context.getTempDirectory();
|
||||
|
||||
// if we're not persisting the temp dir contents delete it
|
||||
if (!context.isPersistTempDirectory())
|
||||
{
|
||||
IO.delete(tempDirectory);
|
||||
}
|
||||
|
||||
//if it wasn't explicitly configured by the user, then unset it
|
||||
Boolean tmpdirConfigured = (Boolean)context.getAttribute(TEMPDIR_CONFIGURED);
|
||||
if (tmpdirConfigured != null && !tmpdirConfigured)
|
||||
|
@ -128,10 +124,9 @@ public class WebInfConfiguration extends AbstractConfiguration
|
|||
* <p>
|
||||
* B. Create a directory based on global settings. The new directory
|
||||
* will be called <code>"Jetty-"+host+"-"+port+"__"+context+"-"+virtualhost+"-"+randomdigits+".dir"</code>
|
||||
* <p>
|
||||
* If the user has specified the context attribute {@link Server#BASE_TEMP_DIR_ATTR}, the
|
||||
* directory specified by this attribute will be the parent of the temp dir created. Otherwise,
|
||||
* the parent dir is <code>${java.io.tmpdir}</code>. Set delete on exit depends on value of persistTempDirectory.
|
||||
* If the temporary directory is persistent, then the random digits are not added to the name.
|
||||
* The {@link Server#getTempDirectory()} is used for the parent of a created temporary directory.
|
||||
* </p>
|
||||
*
|
||||
* @param context the context to resolve the temp directory from
|
||||
* @throws Exception if unable to resolve the temp directory
|
||||
|
@ -140,69 +135,25 @@ public class WebInfConfiguration extends AbstractConfiguration
|
|||
throws Exception
|
||||
{
|
||||
//If a tmp directory is already set we should use it
|
||||
File tmpDir = context.getTempDirectory();
|
||||
if (tmpDir != null)
|
||||
File tempDirectory = context.getTempDirectory();
|
||||
if (tempDirectory != null)
|
||||
{
|
||||
configureTempDirectory(tmpDir, context);
|
||||
context.setAttribute(TEMPDIR_CONFIGURED, Boolean.TRUE); //the tmp dir was set explicitly
|
||||
return;
|
||||
}
|
||||
|
||||
// No temp directory configured, try to establish one via the jakarta.servlet.context.tempdir.
|
||||
File servletTmpDir = asFile(context.getAttribute(WebAppContext.TEMPDIR));
|
||||
File servletTmpDir = IO.asFile(context.getAttribute(ServletContext.TEMPDIR));
|
||||
if (servletTmpDir != null)
|
||||
{
|
||||
// Use as tmpDir
|
||||
tmpDir = servletTmpDir;
|
||||
configureTempDirectory(tmpDir, context);
|
||||
// Ensure Attribute has File object
|
||||
context.setAttribute(WebAppContext.TEMPDIR, tmpDir);
|
||||
tempDirectory = servletTmpDir;
|
||||
// Set as TempDir in context.
|
||||
context.setTempDirectory(tmpDir);
|
||||
context.setTempDirectory(tempDirectory);
|
||||
return;
|
||||
}
|
||||
|
||||
//We need to make a temp dir. Check if the user has set a directory to use instead
|
||||
//of java.io.tmpdir as the parent of the dir
|
||||
File baseTemp = asFile(context.getAttribute(WebAppContext.BASETEMPDIR));
|
||||
if (baseTemp != null)
|
||||
{
|
||||
if (!baseTemp.isDirectory() || !baseTemp.canWrite())
|
||||
throw new IllegalStateException(WebAppContext.BASETEMPDIR + " is not a writable directory");
|
||||
|
||||
//Make a temp directory as a child of the given base dir
|
||||
makeTempDirectory(baseTemp, context);
|
||||
return;
|
||||
}
|
||||
|
||||
//Look for a directory named "work" in ${jetty.base} and
|
||||
//treat it as parent of a new temp dir (which we will persist)
|
||||
File jettyBase = asFile(System.getProperty("jetty.base"));
|
||||
if (jettyBase != null)
|
||||
{
|
||||
File work = new File(jettyBase, "work");
|
||||
if (work.exists() && work.isDirectory() && work.canWrite())
|
||||
{
|
||||
context.setPersistTempDirectory(true);
|
||||
makeTempDirectory(work, context);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//Make a temp directory in java.io.tmpdir
|
||||
makeTempDirectory(new File(System.getProperty("java.io.tmpdir")), context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an Object, return File reference for object.
|
||||
* Typically used to convert anonymous Object from getAttribute() calls to a File object.
|
||||
*
|
||||
* @param fileObject the file object to analyze and return from (supports type File, Path, and String).
|
||||
* @return the File object if it can be converted otherwise null.
|
||||
*/
|
||||
private File asFile(Object fileObject)
|
||||
{
|
||||
return IO.asFile(fileObject);
|
||||
makeTempDirectory(context.getServer().getContext().getTempDirectory(), context);
|
||||
}
|
||||
|
||||
public void makeTempDirectory(File parent, WebAppContext context)
|
||||
|
@ -211,60 +162,28 @@ public class WebInfConfiguration extends AbstractConfiguration
|
|||
if (parent == null || !parent.exists() || !parent.canWrite() || !parent.isDirectory())
|
||||
throw new IllegalStateException("Parent for temp dir not configured correctly: " + (parent == null ? "null" : "writeable=" + parent.canWrite()));
|
||||
|
||||
boolean persistent = context.isTempDirectoryPersistent() || "work".equals(parent.toPath().getFileName().toString());
|
||||
|
||||
//Create a name for the webapp
|
||||
String temp = getCanonicalNameForWebAppTmpDir(context);
|
||||
File tmpDir = null;
|
||||
if (context.isPersistTempDirectory())
|
||||
File tmpDir;
|
||||
if (persistent)
|
||||
{
|
||||
//if it is to be persisted, make sure it will be the same name
|
||||
//by not using File.createTempFile, which appends random digits
|
||||
tmpDir = new File(parent, temp);
|
||||
configureTempDirectory(tmpDir, context);
|
||||
}
|
||||
else
|
||||
{
|
||||
// ensure dir will always be unique by having classlib generate random path name
|
||||
tmpDir = Files.createTempDirectory(parent.toPath(), temp).toFile();
|
||||
tmpDir.deleteOnExit();
|
||||
ensureTempDirUsable(tmpDir);
|
||||
}
|
||||
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Set temp dir {}", tmpDir);
|
||||
context.setTempDirectory(tmpDir);
|
||||
}
|
||||
|
||||
public void configureTempDirectory(File dir, WebAppContext context)
|
||||
{
|
||||
if (dir == null)
|
||||
throw new IllegalArgumentException("Null temp dir");
|
||||
|
||||
// if dir exists and we don't want it persisted, delete it
|
||||
if (!context.isPersistTempDirectory() && dir.exists() && !IO.delete(dir))
|
||||
{
|
||||
throw new IllegalStateException("Failed to delete temp dir " + dir);
|
||||
}
|
||||
|
||||
// if it doesn't exist make it
|
||||
if (!dir.exists())
|
||||
{
|
||||
if (!dir.mkdirs())
|
||||
{
|
||||
throw new IllegalStateException("Unable to create temp dir " + dir);
|
||||
}
|
||||
}
|
||||
|
||||
if (!context.isPersistTempDirectory())
|
||||
dir.deleteOnExit();
|
||||
|
||||
ensureTempDirUsable(dir);
|
||||
}
|
||||
|
||||
private void ensureTempDirUsable(File dir)
|
||||
{
|
||||
// is it useable
|
||||
if (!dir.canWrite() || !dir.isDirectory())
|
||||
throw new IllegalStateException("Temp dir " + dir + " not useable: writeable=" + dir.canWrite() + ", dir=" + dir.isDirectory());
|
||||
context.setTempDirectoryPersistent(persistent);
|
||||
}
|
||||
|
||||
public void unpack(WebAppContext context) throws IOException
|
||||
|
@ -474,23 +393,22 @@ public class WebInfConfiguration extends AbstractConfiguration
|
|||
*/
|
||||
public static String getCanonicalNameForWebAppTmpDir(WebAppContext context)
|
||||
{
|
||||
StringBuffer canonicalName = new StringBuffer();
|
||||
StringBuilder canonicalName = new StringBuilder();
|
||||
canonicalName.append("jetty-");
|
||||
|
||||
//get the host and the port from the first connector
|
||||
Server server = context.getServer();
|
||||
if (server != null)
|
||||
{
|
||||
Connector[] connectors = context.getServer().getConnectors();
|
||||
Connector[] connectors = server.getConnectors();
|
||||
|
||||
if (connectors.length > 0)
|
||||
{
|
||||
//Get the host
|
||||
String host = null;
|
||||
int port = 0;
|
||||
if (connectors != null && (connectors[0] instanceof NetworkConnector))
|
||||
if (connectors[0] instanceof NetworkConnector connector)
|
||||
{
|
||||
NetworkConnector connector = (NetworkConnector)connectors[0];
|
||||
host = connector.getHost();
|
||||
port = connector.getLocalPort();
|
||||
if (port < 0)
|
||||
|
@ -499,12 +417,7 @@ public class WebInfConfiguration extends AbstractConfiguration
|
|||
if (host == null)
|
||||
host = "0.0.0.0";
|
||||
canonicalName.append(host);
|
||||
|
||||
//Get the port
|
||||
canonicalName.append("-");
|
||||
|
||||
//if not available (eg no connectors or connector not started),
|
||||
//try getting one that was configured.
|
||||
canonicalName.append(port);
|
||||
canonicalName.append("-");
|
||||
}
|
||||
|
|
|
@ -16,7 +16,6 @@ package org.eclipse.jetty.ee10.webapp;
|
|||
import java.io.File;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import jakarta.servlet.ServletContext;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
|
@ -25,14 +24,10 @@ import org.eclipse.jetty.toolchain.test.FS;
|
|||
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
|
||||
import org.eclipse.jetty.toolchain.test.jupiter.WorkDir;
|
||||
import org.eclipse.jetty.toolchain.test.jupiter.WorkDirExtension;
|
||||
import org.eclipse.jetty.util.IO;
|
||||
import org.eclipse.jetty.util.resource.FileSystemPool;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Tag;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.condition.DisabledOnOs;
|
||||
import org.junit.jupiter.api.condition.OS;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
|
@ -42,9 +37,6 @@ import static org.hamcrest.Matchers.empty;
|
|||
import static org.hamcrest.Matchers.is;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
@ExtendWith(WorkDirExtension.class)
|
||||
|
@ -92,35 +84,6 @@ public class TempDirTest
|
|||
assertThat(FileSystemPool.INSTANCE.mounts(), empty());
|
||||
}
|
||||
|
||||
/**
|
||||
* ServletContext.TEMPDIR has <code>null</code> value
|
||||
* so webappContent#tempDirectory is created under <code>java.io.tmpdir</code>
|
||||
*/
|
||||
@Test
|
||||
public void attributeWithNullValue() throws Exception
|
||||
{
|
||||
WebInfConfiguration webInfConfiguration = new WebInfConfiguration();
|
||||
WebAppContext webAppContext = new WebAppContext();
|
||||
webAppContext.setAttribute(ServletContext.TEMPDIR, null);
|
||||
webInfConfiguration.resolveTempDirectory(webAppContext);
|
||||
Path webappTempDir = webAppContext.getTempDirectory().toPath();
|
||||
Path javaIoTmpDir = Paths.get(System.getProperty("java.io.tmpdir"));
|
||||
assertEquals(javaIoTmpDir, webappTempDir.getParent());
|
||||
}
|
||||
|
||||
/**
|
||||
* ServletContext.TEMPDIR has <code>""</code> value
|
||||
* IllegalStateException
|
||||
*/
|
||||
@Test
|
||||
public void attributeWithEmptyStringValue()
|
||||
{
|
||||
WebInfConfiguration webInfConfiguration = new WebInfConfiguration();
|
||||
WebAppContext webAppContext = new WebAppContext();
|
||||
webAppContext.setAttribute(ServletContext.TEMPDIR, "");
|
||||
assertThrows(IllegalStateException.class, () -> webInfConfiguration.resolveTempDirectory(webAppContext));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test ServletContext.TEMPDIR as valid directory with types File, String and Path.
|
||||
*/
|
||||
|
@ -133,17 +96,10 @@ public class TempDirTest
|
|||
FS.ensureDirExists(tmpDir);
|
||||
switch (type)
|
||||
{
|
||||
case "File":
|
||||
webAppContext.setAttribute(ServletContext.TEMPDIR, tmpDir.toFile());
|
||||
break;
|
||||
case "String":
|
||||
webAppContext.setAttribute(ServletContext.TEMPDIR, tmpDir.toString());
|
||||
break;
|
||||
case "Path":
|
||||
webAppContext.setAttribute(ServletContext.TEMPDIR, tmpDir);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException();
|
||||
case "File" -> webAppContext.setAttribute(ServletContext.TEMPDIR, tmpDir.toFile());
|
||||
case "String" -> webAppContext.setAttribute(ServletContext.TEMPDIR, tmpDir.toString());
|
||||
case "Path" -> webAppContext.setAttribute(ServletContext.TEMPDIR, tmpDir);
|
||||
default -> throw new IllegalStateException();
|
||||
}
|
||||
|
||||
// Test we have correct value as the webapp temp directory.
|
||||
|
@ -160,23 +116,18 @@ public class TempDirTest
|
|||
@ValueSource(strings = {"File", "String", "Path"})
|
||||
public void attributeWithNonExistentDirectory(String type) throws Exception
|
||||
{
|
||||
Server server = new Server();
|
||||
WebAppContext webAppContext = new WebAppContext();
|
||||
Path tmpDir = workDir.getPath().resolve("foo_does_not_exist");
|
||||
server.setHandler(webAppContext);
|
||||
Path tmpDir = workDir.getPath().resolve("foo_did_not_exist");
|
||||
assertFalse(Files.exists(tmpDir));
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case "File":
|
||||
webAppContext.setAttribute(ServletContext.TEMPDIR, tmpDir.toFile());
|
||||
break;
|
||||
case "String":
|
||||
webAppContext.setAttribute(ServletContext.TEMPDIR, tmpDir.toString());
|
||||
break;
|
||||
case "Path":
|
||||
webAppContext.setAttribute(ServletContext.TEMPDIR, tmpDir);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException();
|
||||
case "File" -> webAppContext.setAttribute(ServletContext.TEMPDIR, tmpDir.toFile());
|
||||
case "String" -> webAppContext.setAttribute(ServletContext.TEMPDIR, tmpDir.toString());
|
||||
case "Path" -> webAppContext.setAttribute(ServletContext.TEMPDIR, tmpDir);
|
||||
default -> throw new IllegalStateException();
|
||||
}
|
||||
|
||||
// Test we have correct value as the webapp temp directory.
|
||||
|
@ -184,60 +135,20 @@ public class TempDirTest
|
|||
webInfConfiguration.resolveTempDirectory(webAppContext);
|
||||
Path webappTmpDir = webAppContext.getTempDirectory().toPath();
|
||||
assertThat(webappTmpDir, is(tmpDir));
|
||||
assertTrue(Files.exists(webappTmpDir));
|
||||
}
|
||||
|
||||
/**
|
||||
* WebAppContext.BASETEMPDIR has <code>null</code> value
|
||||
* so webappContent#tempDirectory is created under <code>java.io.tmpdir</code>
|
||||
* Test Server.setTempDirectory as valid directory
|
||||
*/
|
||||
@Test
|
||||
public void baseTempDirAttributeWithNullValue() throws Exception
|
||||
{
|
||||
WebInfConfiguration webInfConfiguration = new WebInfConfiguration();
|
||||
WebAppContext webAppContext = new WebAppContext();
|
||||
webAppContext.setAttribute(WebAppContext.BASETEMPDIR, null);
|
||||
webInfConfiguration.resolveTempDirectory(webAppContext);
|
||||
assertThat(webAppContext.getTempDirectory().getParent(), is(System.getProperty("java.io.tmpdir")));
|
||||
}
|
||||
|
||||
/**
|
||||
* WebAppContext.BASETEMPDIR has <code>""</code> value
|
||||
* IllegalStateException
|
||||
*/
|
||||
@Test
|
||||
public void baseTempDirAttributeWithEmptyStringValue()
|
||||
{
|
||||
WebInfConfiguration webInfConfiguration = new WebInfConfiguration();
|
||||
WebAppContext webAppContext = new WebAppContext();
|
||||
webAppContext.setAttribute(WebAppContext.BASETEMPDIR, "");
|
||||
assertThrows(IllegalStateException.class, () -> webInfConfiguration.resolveTempDirectory(webAppContext));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test WebAppContext.BASETEMPDIR as valid directory with types File, String and Path.
|
||||
*/
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings = {"File", "String", "Path"})
|
||||
public void baseTempDirAttributeWithValidDirectory(String type) throws Exception
|
||||
public void serverTempDirAttributeWithValidDirectory() throws Exception
|
||||
{
|
||||
WebAppContext webAppContext = new WebAppContext();
|
||||
Server server = new Server();
|
||||
webAppContext.setServer(server);
|
||||
Path tmpDir = workDir.getPath().resolve("temp_test");
|
||||
FS.ensureDirExists(tmpDir);
|
||||
switch (type)
|
||||
{
|
||||
case "File":
|
||||
webAppContext.setAttribute(WebAppContext.BASETEMPDIR, tmpDir.toFile());
|
||||
break;
|
||||
case "String":
|
||||
webAppContext.setAttribute(WebAppContext.BASETEMPDIR, tmpDir.toString());
|
||||
break;
|
||||
case "Path":
|
||||
webAppContext.setAttribute(WebAppContext.BASETEMPDIR, tmpDir);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
server.setTempDirectory(tmpDir.toFile());
|
||||
|
||||
// Test we have correct value as the webapp temp directory.
|
||||
WebInfConfiguration webInfConfiguration = new WebInfConfiguration();
|
||||
|
@ -247,53 +158,6 @@ public class TempDirTest
|
|||
assertThat(tempDirectory.getParentFile().toPath(), is(tmpDir));
|
||||
}
|
||||
|
||||
/**
|
||||
* WebAppContext.BASETEMPDIR as File to a non existent directory.
|
||||
*/
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings = {"File", "String", "Path"})
|
||||
public void baseTempDirAttributeWithNonExistentDirectory(String type) throws Exception
|
||||
{
|
||||
WebAppContext webAppContext = new WebAppContext();
|
||||
Path tmpDir = workDir.getPath().resolve("does_not_exists");
|
||||
Files.deleteIfExists(tmpDir);
|
||||
assertFalse(Files.exists(tmpDir));
|
||||
switch (type)
|
||||
{
|
||||
case "File":
|
||||
webAppContext.setAttribute(WebAppContext.BASETEMPDIR, tmpDir.toFile());
|
||||
break;
|
||||
case "String":
|
||||
webAppContext.setAttribute(WebAppContext.BASETEMPDIR, tmpDir.toString());
|
||||
break;
|
||||
case "Path":
|
||||
webAppContext.setAttribute(WebAppContext.BASETEMPDIR, tmpDir);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
// The base temp directory must exist for it to be used, if it does not exist or is not writable it will throw ISE.
|
||||
WebInfConfiguration webInfConfiguration = new WebInfConfiguration();
|
||||
assertThrows(IllegalStateException.class, () -> webInfConfiguration.resolveTempDirectory(webAppContext));
|
||||
assertFalse(Files.exists(tmpDir));
|
||||
}
|
||||
|
||||
/**
|
||||
* <code>${jetty.base}</code> exists but has no work subdirectory called work
|
||||
* so webappContent#tempDirectory is created under <code>java.io.tmpdir</code>
|
||||
*/
|
||||
@Test
|
||||
public void jettyBaseWorkDoesNotExist() throws Exception
|
||||
{
|
||||
Path workDir = jettyBase.resolve("work");
|
||||
FS.ensureDeleted(workDir);
|
||||
WebInfConfiguration webInfConfiguration = new WebInfConfiguration();
|
||||
WebAppContext webAppContext = new WebAppContext();
|
||||
webInfConfiguration.resolveTempDirectory(webAppContext);
|
||||
assertThat(webAppContext.getTempDirectory().getParent(), is(System.getProperty("java.io.tmpdir")));
|
||||
}
|
||||
|
||||
/**
|
||||
* <code>${jetty.base}</code> directory exists and has a subdirectory called work
|
||||
* so webappContent#tempDirectory is created under <code>java.io.tmpdir</code>
|
||||
|
@ -304,109 +168,10 @@ public class TempDirTest
|
|||
Path workDir = jettyBase.resolve("work");
|
||||
FS.ensureDirExists(workDir);
|
||||
WebInfConfiguration webInfConfiguration = new WebInfConfiguration();
|
||||
Server server = new Server();
|
||||
WebAppContext webAppContext = new WebAppContext();
|
||||
server.setHandler(webAppContext);
|
||||
webInfConfiguration.resolveTempDirectory(webAppContext);
|
||||
assertThat(webAppContext.getTempDirectory().getParent(), is(workDir.toString()));
|
||||
}
|
||||
|
||||
/**
|
||||
* ServletContext.TEMPDIR has invalid <code>String</code> directory value (wrong permission to write into it)
|
||||
*
|
||||
* Note that if run in the CI environment, the test will fail, because it runs as root,
|
||||
* so we _will_ have permission to write to this directory.
|
||||
*/
|
||||
@Tag("not-on-ci")
|
||||
@DisabledOnOs(value = OS.WINDOWS, disabledReason = "Test/Temp directory is always writable")
|
||||
@Test
|
||||
public void attributeWithInvalidPermissions()
|
||||
{
|
||||
WebInfConfiguration webInfConfiguration = new WebInfConfiguration();
|
||||
WebAppContext webAppContext = new WebAppContext();
|
||||
webAppContext.setAttribute(ServletContext.TEMPDIR, "/var/foo_jetty");
|
||||
assertThrows(IllegalStateException.class, () -> webInfConfiguration.resolveTempDirectory(webAppContext));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(booleans = {true, false})
|
||||
public void testDefaultTempDirectory(boolean persistTempDir) throws Exception
|
||||
{
|
||||
setupServer();
|
||||
webapp.setPersistTempDirectory(persistTempDir);
|
||||
|
||||
// Temp Directory Initially isn't set until started.
|
||||
File tempDirectory = webapp.getTempDirectory();
|
||||
assertNull(tempDirectory);
|
||||
|
||||
// Once server is started the WebApp temp directory exists and is valid directory.
|
||||
server.start();
|
||||
tempDirectory = webapp.getTempDirectory();
|
||||
assertNotNull(tempDirectory);
|
||||
assertTrue(tempDirectory.exists());
|
||||
assertTrue(tempDirectory.isDirectory());
|
||||
|
||||
// Once server is stopped the WebApp temp should be deleted if persistTempDir is false.
|
||||
server.stop();
|
||||
tempDirectory = webapp.getTempDirectory();
|
||||
assertNotNull(tempDirectory, "Temp Directory");
|
||||
if (persistTempDir)
|
||||
{
|
||||
assertTrue(tempDirectory.exists(), "Temp Directory should exist");
|
||||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(booleans = {true, false})
|
||||
public void testPreDefinedTempDirectory(boolean persistTempDir) throws Exception
|
||||
{
|
||||
setupServer();
|
||||
webapp.setPersistTempDirectory(persistTempDir);
|
||||
|
||||
// The temp directory is defined but has not been created.
|
||||
File webappTempDir = MavenTestingUtils.getTargetTestingPath("webappTempDir").toFile();
|
||||
IO.delete(webappTempDir);
|
||||
webapp.setTempDirectory(webappTempDir);
|
||||
assertThat(webapp.getTempDirectory(), is(webappTempDir));
|
||||
assertFalse(webappTempDir.exists());
|
||||
|
||||
// Once server is started the WebApp temp directory exists and is valid directory.
|
||||
server.start();
|
||||
File tempDirectory = webapp.getTempDirectory();
|
||||
assertNotNull(tempDirectory);
|
||||
assertTrue(tempDirectory.exists());
|
||||
assertTrue(tempDirectory.isDirectory());
|
||||
|
||||
// Once server is stopped the WebApp temp should be deleted if persistTempDir is false.
|
||||
server.stop();
|
||||
tempDirectory = webapp.getTempDirectory();
|
||||
assertThat(tempDirectory != null && tempDirectory.exists(), is(persistTempDir));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(booleans = {true, false})
|
||||
public void testPreExistingTempDirectory(boolean persistTempDir) throws Exception
|
||||
{
|
||||
setupServer();
|
||||
webapp.setPersistTempDirectory(persistTempDir);
|
||||
|
||||
// The temp directory is defined and has already been created.
|
||||
File webappTempDir = MavenTestingUtils.getTargetTestingPath("webappTempDir").toFile();
|
||||
IO.delete(webappTempDir);
|
||||
if (!webappTempDir.exists())
|
||||
assertTrue(webappTempDir.mkdir());
|
||||
webapp.setTempDirectory(webappTempDir);
|
||||
assertThat(webapp.getTempDirectory(), is(webappTempDir));
|
||||
assertTrue(webappTempDir.exists());
|
||||
|
||||
// Once server is started the WebApp temp directory exists and is valid directory.
|
||||
server.start();
|
||||
File tempDirectory = webapp.getTempDirectory();
|
||||
assertNotNull(tempDirectory);
|
||||
assertTrue(tempDirectory.exists());
|
||||
assertTrue(tempDirectory.isDirectory());
|
||||
|
||||
// Once server is stopped the WebApp temp should be deleted if persistTempDir is false.
|
||||
server.stop();
|
||||
tempDirectory = webapp.getTempDirectory();
|
||||
assertThat(tempDirectory != null && tempDirectory.exists(), is(persistTempDir));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,7 +37,6 @@
|
|||
<Set name="extractWars" property="jetty.deploy.extractWars" />
|
||||
<Set name="parentLoaderPriority" property="jetty.deploy.parentLoaderPriority" />
|
||||
<Set name="configurationClasses" property="jetty.deploy.configurationClasses" />
|
||||
<Set name="tempDir" property="jetty.deploy.tempDir" />
|
||||
<Get name="properties">
|
||||
<Put name="jetty.deploy.containerScanJarPattern">
|
||||
<Property name="jetty.deploy.containerScanJarPattern">
|
||||
|
|
|
@ -38,9 +38,6 @@ etc/jetty-ee8-deploy.xml
|
|||
## Comma separated list of configuration classes to set.
|
||||
# jetty.deploy.configurationClasses=
|
||||
|
||||
## Base temporary directory for deployed web applications.
|
||||
# jetty.deploy.tempDir=
|
||||
|
||||
## Pattern to select jars from the container classloader to be scanned (or null to scan no jars)
|
||||
# jetty.deploy.containerScanJarPattern=.*/jetty-servlet-api-[^/]*\.jar$|.*/javax.servlet.jsp.jstl-.*\.jar$
|
||||
|
||||
|
|
|
@ -252,7 +252,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
|
|||
return _coreContextHandler;
|
||||
}
|
||||
|
||||
public org.eclipse.jetty.server.handler.ContextHandler getCoreContextHandler()
|
||||
public CoreContextHandler getCoreContextHandler()
|
||||
{
|
||||
return _coreContextHandler;
|
||||
}
|
||||
|
@ -2390,6 +2390,15 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Expose configureTempDirectory so it can be triggered early by WebInfConfiguration#preConfigure
|
||||
*/
|
||||
@Override
|
||||
public void createTempDirectory()
|
||||
{
|
||||
super.createTempDirectory();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doStop() throws Exception
|
||||
{
|
||||
|
|
|
@ -37,7 +37,6 @@
|
|||
<Set name="extractWars" property="jetty.deploy.extractWars" />
|
||||
<Set name="parentLoaderPriority" property="jetty.deploy.parentLoaderPriority" />
|
||||
<Set name="configurationClasses" property="jetty.deploy.configurationClasses" />
|
||||
<Set name="tempDir" property="jetty.deploy.tempDir" />
|
||||
<Get name="properties">
|
||||
<Put name="jetty.deploy.containerScanJarPattern">
|
||||
<Property name="jetty.deploy.containerScanJarPattern">
|
||||
|
|
|
@ -38,9 +38,6 @@ etc/jetty-ee9-deploy.xml
|
|||
## Comma separated list of configuration classes to set.
|
||||
# jetty.deploy.configurationClasses=
|
||||
|
||||
## Base temporary directory for deployed web applications.
|
||||
# jetty.deploy.tempDir=
|
||||
|
||||
## Pattern to select jars from the container classloader to be scanned (or null to scan no jars)
|
||||
# jetty.deploy.containerScanJarPattern=.*/jetty-jakarta-servlet-api-[^/]*\.jar$|.*jakarta.servlet.jsp.jstl-.*\.jar$
|
||||
|
||||
|
|
|
@ -56,6 +56,7 @@ import org.eclipse.jetty.server.Handler;
|
|||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.util.Attributes;
|
||||
import org.eclipse.jetty.util.ExceptionUtil;
|
||||
import org.eclipse.jetty.util.IO;
|
||||
import org.eclipse.jetty.util.StringUtil;
|
||||
import org.eclipse.jetty.util.URIUtil;
|
||||
import org.eclipse.jetty.util.annotation.ManagedAttribute;
|
||||
|
@ -86,8 +87,6 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
{
|
||||
static final Logger LOG = LoggerFactory.getLogger(WebAppContext.class);
|
||||
|
||||
public static final String TEMPDIR = ServletContext.TEMPDIR;
|
||||
public static final String BASETEMPDIR = Server.BASE_TEMP_DIR_ATTR;
|
||||
public static final String WEB_DEFAULTS_XML = "org/eclipse/jetty/ee9/webapp/webdefault-ee9.xml";
|
||||
public static final String ERROR_PAGE = "org.eclipse.jetty.server.error_page";
|
||||
public static final String SERVER_SYS_CLASSES = "org.eclipse.jetty.ee9.webapp.systemClasses";
|
||||
|
@ -131,9 +130,6 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
|
||||
private String[] _contextWhiteList = null;
|
||||
|
||||
private File _tmpDir;
|
||||
private boolean _persistTmpDir = false;
|
||||
|
||||
private String _war;
|
||||
private List<Resource> _extraClasspath;
|
||||
private Throwable _unavailableException;
|
||||
|
@ -253,7 +249,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
switch (property)
|
||||
{
|
||||
case Deployable.WAR -> setWar(value);
|
||||
case Deployable.BASE_TEMP_DIR -> setAttribute(BASETEMPDIR, value);
|
||||
case Deployable.TEMP_DIR -> setTempDirectory(IO.asFile(value));
|
||||
case Deployable.CONFIGURATION_CLASSES -> setConfigurationClasses(value == null ? null : value.split(","));
|
||||
case Deployable.CONTAINER_SCAN_JARS -> setAttribute(MetaInfConfiguration.CONTAINER_JAR_PATTERN, value);
|
||||
case Deployable.EXTRACT_WARS -> setExtractWAR(Boolean.parseBoolean(value));
|
||||
|
@ -1158,29 +1154,14 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
*/
|
||||
public void setTempDirectory(File dir)
|
||||
{
|
||||
if (isStarted())
|
||||
throw new IllegalStateException("Started");
|
||||
|
||||
if (dir != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
dir = new File(dir.getCanonicalPath());
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
LOG.warn("Unable to find canonical path for {}", dir, e);
|
||||
}
|
||||
}
|
||||
|
||||
_tmpDir = dir;
|
||||
setAttribute(TEMPDIR, _tmpDir);
|
||||
getCoreContextHandler().setTempDirectory(dir);
|
||||
setAttribute(ServletContext.TEMPDIR, getCoreContextHandler().getTempDirectory());
|
||||
}
|
||||
|
||||
@ManagedAttribute(value = "temporary directory location", readonly = true)
|
||||
public File getTempDirectory()
|
||||
{
|
||||
return _tmpDir;
|
||||
return getCoreContextHandler().getTempDirectory();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1192,7 +1173,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
*/
|
||||
public void setPersistTempDirectory(boolean persist)
|
||||
{
|
||||
_persistTmpDir = persist;
|
||||
getCoreContextHandler().setTempDirectoryPersistent(persist);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1200,7 +1181,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
*/
|
||||
public boolean isPersistTempDirectory()
|
||||
{
|
||||
return _persistTmpDir;
|
||||
return getCoreContextHandler().isTempDirectoryPersistent();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -19,6 +19,7 @@ import java.net.URI;
|
|||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import jakarta.servlet.ServletContext;
|
||||
import org.eclipse.jetty.server.Connector;
|
||||
import org.eclipse.jetty.server.NetworkConnector;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
|
@ -38,7 +39,7 @@ public class WebInfConfiguration extends AbstractConfiguration
|
|||
private static final Logger LOG = LoggerFactory.getLogger(WebInfConfiguration.class);
|
||||
|
||||
public static final String TEMPDIR_CONFIGURED = "org.eclipse.jetty.tmpdirConfigured";
|
||||
public static final String TEMPORARY_RESOURCE_BASE = "org.eclipse.jetty.ee9.webapp.tmpResourceBase";
|
||||
public static final String TEMPORARY_RESOURCE_BASE = "org.eclipse.jetty.webapp.tmpResourceBase";
|
||||
|
||||
protected Resource _preUnpackBaseResource;
|
||||
|
||||
|
@ -52,6 +53,9 @@ public class WebInfConfiguration extends AbstractConfiguration
|
|||
// Make a temp directory for the webapp if one is not already set
|
||||
resolveTempDirectory(context);
|
||||
|
||||
// Force early configuration (clearing) of the temporary directory so we can unpack into it.
|
||||
context.getCoreContextHandler().createTempDirectory();
|
||||
|
||||
// Extract webapp if necessary
|
||||
unpack(context);
|
||||
}
|
||||
|
@ -79,14 +83,6 @@ public class WebInfConfiguration extends AbstractConfiguration
|
|||
@Override
|
||||
public void deconfigure(WebAppContext context) throws Exception
|
||||
{
|
||||
File tempDirectory = context.getTempDirectory();
|
||||
|
||||
// if we're not persisting the temp dir contents delete it
|
||||
if (!context.isPersistTempDirectory())
|
||||
{
|
||||
IO.delete(tempDirectory);
|
||||
}
|
||||
|
||||
//if it wasn't explicitly configured by the user, then unset it
|
||||
Boolean tmpdirConfigured = (Boolean)context.getAttribute(TEMPDIR_CONFIGURED);
|
||||
if (tmpdirConfigured != null && !tmpdirConfigured)
|
||||
|
@ -126,10 +122,9 @@ public class WebInfConfiguration extends AbstractConfiguration
|
|||
* <p>
|
||||
* B. Create a directory based on global settings. The new directory
|
||||
* will be called <code>"Jetty-"+host+"-"+port+"__"+context+"-"+virtualhost+"-"+randomdigits+".dir"</code>
|
||||
* <p>
|
||||
* If the user has specified the context attribute org.eclipse.jetty.ee9.webapp.basetempdir, the
|
||||
* directory specified by this attribute will be the parent of the temp dir created. Otherwise,
|
||||
* the parent dir is <code>${java.io.tmpdir}</code>. Set delete on exit depends on value of persistTempDirectory.
|
||||
* If the temporary directory is persistent, then the random digits are not added to the name.
|
||||
* The {@link Server#getTempDirectory()} is used for the parent of a created temporary directory.
|
||||
* </p>
|
||||
*
|
||||
* @param context the context to resolve the temp directory from
|
||||
* @throws Exception if unable to resolve the temp directory
|
||||
|
@ -138,78 +133,25 @@ public class WebInfConfiguration extends AbstractConfiguration
|
|||
throws Exception
|
||||
{
|
||||
//If a tmp directory is already set we should use it
|
||||
File tmpDir = context.getTempDirectory();
|
||||
if (tmpDir != null)
|
||||
File tempDirectory = context.getTempDirectory();
|
||||
if (tempDirectory != null)
|
||||
{
|
||||
configureTempDirectory(tmpDir, context);
|
||||
context.setAttribute(TEMPDIR_CONFIGURED, Boolean.TRUE); //the tmp dir was set explicitly
|
||||
return;
|
||||
}
|
||||
|
||||
// No temp directory configured, try to establish one via the jakarta.servlet.context.tempdir.
|
||||
File servletTmpDir = asFile(context.getAttribute(WebAppContext.TEMPDIR));
|
||||
File servletTmpDir = IO.asFile(context.getAttribute(ServletContext.TEMPDIR));
|
||||
if (servletTmpDir != null)
|
||||
{
|
||||
// Use as tmpDir
|
||||
tmpDir = servletTmpDir;
|
||||
configureTempDirectory(tmpDir, context);
|
||||
// Ensure Attribute has File object
|
||||
context.setAttribute(WebAppContext.TEMPDIR, tmpDir);
|
||||
tempDirectory = servletTmpDir;
|
||||
// Set as TempDir in context.
|
||||
context.setTempDirectory(tmpDir);
|
||||
context.setTempDirectory(tempDirectory);
|
||||
return;
|
||||
}
|
||||
|
||||
//We need to make a temp dir. Check if the user has set a directory to use instead
|
||||
//of java.io.tmpdir as the parent of the dir
|
||||
File baseTemp = asFile(context.getAttribute(WebAppContext.BASETEMPDIR));
|
||||
if (baseTemp != null)
|
||||
{
|
||||
if (!baseTemp.isDirectory() || !baseTemp.canWrite())
|
||||
throw new IllegalStateException(WebAppContext.BASETEMPDIR + " is not a writable directory");
|
||||
|
||||
//Make a temp directory as a child of the given base dir
|
||||
makeTempDirectory(baseTemp, context);
|
||||
return;
|
||||
}
|
||||
|
||||
//Look for a directory named "work" in ${jetty.base} and
|
||||
//treat it as parent of a new temp dir (which we will persist)
|
||||
File jettyBase = asFile(System.getProperty("jetty.base"));
|
||||
if (jettyBase != null)
|
||||
{
|
||||
File work = new File(jettyBase, "work");
|
||||
if (work.exists() && work.isDirectory() && work.canWrite())
|
||||
{
|
||||
context.setPersistTempDirectory(true);
|
||||
makeTempDirectory(work, context);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//Make a temp directory in java.io.tmpdir
|
||||
makeTempDirectory(new File(System.getProperty("java.io.tmpdir")), context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an Object, return File reference for object.
|
||||
* Typically used to convert anonymous Object from getAttribute() calls to a File object.
|
||||
*
|
||||
* @param fileattr the file attribute to analyze and return from (supports type File, Path, and String).
|
||||
* @return the File object if it can be converted otherwise null.
|
||||
*/
|
||||
private File asFile(Object fileattr)
|
||||
{
|
||||
if (fileattr == null)
|
||||
return null;
|
||||
if (fileattr instanceof File)
|
||||
return (File)fileattr;
|
||||
if (fileattr instanceof String)
|
||||
return new File((String)fileattr);
|
||||
if (fileattr instanceof Path)
|
||||
return ((Path)fileattr).toFile();
|
||||
|
||||
return null;
|
||||
makeTempDirectory(context.getServer().getContext().getTempDirectory(), context);
|
||||
}
|
||||
|
||||
public void makeTempDirectory(File parent, WebAppContext context)
|
||||
|
@ -218,60 +160,28 @@ public class WebInfConfiguration extends AbstractConfiguration
|
|||
if (parent == null || !parent.exists() || !parent.canWrite() || !parent.isDirectory())
|
||||
throw new IllegalStateException("Parent for temp dir not configured correctly: " + (parent == null ? "null" : "writeable=" + parent.canWrite()));
|
||||
|
||||
//Create a name for the webapp
|
||||
boolean persistent = context.isPersistTempDirectory() || "work".equals(parent.toPath().getFileName().toString());
|
||||
|
||||
//Create a name for the webapp
|
||||
String temp = getCanonicalNameForWebAppTmpDir(context);
|
||||
File tmpDir = null;
|
||||
if (context.isPersistTempDirectory())
|
||||
File tmpDir;
|
||||
if (persistent)
|
||||
{
|
||||
//if it is to be persisted, make sure it will be the same name
|
||||
//by not using File.createTempFile, which appends random digits
|
||||
tmpDir = new File(parent, temp);
|
||||
configureTempDirectory(tmpDir, context);
|
||||
}
|
||||
else
|
||||
{
|
||||
// ensure dir will always be unique by having classlib generate random path name
|
||||
tmpDir = Files.createTempDirectory(parent.toPath(), temp).toFile();
|
||||
tmpDir.deleteOnExit();
|
||||
ensureTempDirUsable(tmpDir);
|
||||
}
|
||||
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Set temp dir {}", tmpDir);
|
||||
context.setTempDirectory(tmpDir);
|
||||
}
|
||||
|
||||
public void configureTempDirectory(File dir, WebAppContext context)
|
||||
{
|
||||
if (dir == null)
|
||||
throw new IllegalArgumentException("Null temp dir");
|
||||
|
||||
// if dir exists and we don't want it persisted, delete it
|
||||
if (!context.isPersistTempDirectory() && dir.exists() && !IO.delete(dir))
|
||||
{
|
||||
throw new IllegalStateException("Failed to delete temp dir " + dir);
|
||||
}
|
||||
|
||||
// if it doesn't exist make it
|
||||
if (!dir.exists())
|
||||
{
|
||||
if (!dir.mkdirs())
|
||||
{
|
||||
throw new IllegalStateException("Unable to create temp dir " + dir);
|
||||
}
|
||||
}
|
||||
|
||||
if (!context.isPersistTempDirectory())
|
||||
dir.deleteOnExit();
|
||||
|
||||
ensureTempDirUsable(dir);
|
||||
}
|
||||
|
||||
private void ensureTempDirUsable(File dir)
|
||||
{
|
||||
// is it useable
|
||||
if (!dir.canWrite() || !dir.isDirectory())
|
||||
throw new IllegalStateException("Temp dir " + dir + " not useable: writeable=" + dir.canWrite() + ", dir=" + dir.isDirectory());
|
||||
context.setPersistTempDirectory(persistent);
|
||||
}
|
||||
|
||||
public void unpack(WebAppContext context) throws IOException
|
||||
|
@ -313,7 +223,6 @@ public class WebInfConfiguration extends AbstractConfiguration
|
|||
// Is the WAR usable directly?
|
||||
if (Resources.isReadableFile(webApp) && FileID.isJavaArchive(webApp.getURI()) && !webApp.getURI().getScheme().equalsIgnoreCase("jar"))
|
||||
{
|
||||
// No - then lets see if it can be turned into a jar URL.
|
||||
// Turned this into a jar URL.
|
||||
Resource jarWebApp = context.getResourceFactory().newJarFileResource(webApp.getURI());
|
||||
if (Resources.isReadableFile(jarWebApp)) // but only if it is readable
|
||||
|
@ -452,7 +361,6 @@ public class WebInfConfiguration extends AbstractConfiguration
|
|||
LOG.debug("Copying WEB-INF/classes from {} to {}", webInfClasses, webInfClassesDir.getAbsolutePath());
|
||||
webInfClasses.copyTo(webInfClassesDir.toPath());
|
||||
}
|
||||
|
||||
webInf = context.getResourceFactory().newResource(extractedWebInfDir.getCanonicalPath());
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,6 @@ package org.eclipse.jetty.ee9.webapp;
|
|||
import java.io.File;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import jakarta.servlet.ServletContext;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
|
@ -25,14 +24,10 @@ import org.eclipse.jetty.toolchain.test.FS;
|
|||
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
|
||||
import org.eclipse.jetty.toolchain.test.jupiter.WorkDir;
|
||||
import org.eclipse.jetty.toolchain.test.jupiter.WorkDirExtension;
|
||||
import org.eclipse.jetty.util.IO;
|
||||
import org.eclipse.jetty.util.resource.FileSystemPool;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Tag;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.condition.DisabledOnOs;
|
||||
import org.junit.jupiter.api.condition.OS;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
|
@ -42,9 +37,6 @@ import static org.hamcrest.Matchers.empty;
|
|||
import static org.hamcrest.Matchers.is;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
@ExtendWith(WorkDirExtension.class)
|
||||
|
@ -92,35 +84,6 @@ public class TempDirTest
|
|||
assertThat(FileSystemPool.INSTANCE.mounts(), empty());
|
||||
}
|
||||
|
||||
/**
|
||||
* ServletContext.TEMPDIR has <code>null</code> value
|
||||
* so webappContent#tempDirectory is created under <code>java.io.tmpdir</code>
|
||||
*/
|
||||
@Test
|
||||
public void attributeWithNullValue() throws Exception
|
||||
{
|
||||
WebInfConfiguration webInfConfiguration = new WebInfConfiguration();
|
||||
WebAppContext webAppContext = new WebAppContext();
|
||||
webAppContext.setAttribute(ServletContext.TEMPDIR, null);
|
||||
webInfConfiguration.resolveTempDirectory(webAppContext);
|
||||
Path webappTempDir = webAppContext.getTempDirectory().toPath();
|
||||
Path javaIoTmpDir = Paths.get(System.getProperty("java.io.tmpdir"));
|
||||
assertEquals(javaIoTmpDir, webappTempDir.getParent());
|
||||
}
|
||||
|
||||
/**
|
||||
* ServletContext.TEMPDIR has <code>""</code> value
|
||||
* IllegalStateException
|
||||
*/
|
||||
@Test
|
||||
public void attributeWithEmptyStringValue()
|
||||
{
|
||||
WebInfConfiguration webInfConfiguration = new WebInfConfiguration();
|
||||
WebAppContext webAppContext = new WebAppContext();
|
||||
webAppContext.setAttribute(ServletContext.TEMPDIR, "");
|
||||
assertThrows(IllegalStateException.class, () -> webInfConfiguration.resolveTempDirectory(webAppContext));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test ServletContext.TEMPDIR as valid directory with types File, String and Path.
|
||||
*/
|
||||
|
@ -133,17 +96,10 @@ public class TempDirTest
|
|||
FS.ensureDirExists(tmpDir);
|
||||
switch (type)
|
||||
{
|
||||
case "File":
|
||||
webAppContext.setAttribute(ServletContext.TEMPDIR, tmpDir.toFile());
|
||||
break;
|
||||
case "String":
|
||||
webAppContext.setAttribute(ServletContext.TEMPDIR, tmpDir.toString());
|
||||
break;
|
||||
case "Path":
|
||||
webAppContext.setAttribute(ServletContext.TEMPDIR, tmpDir);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException();
|
||||
case "File" -> webAppContext.setAttribute(ServletContext.TEMPDIR, tmpDir.toFile());
|
||||
case "String" -> webAppContext.setAttribute(ServletContext.TEMPDIR, tmpDir.toString());
|
||||
case "Path" -> webAppContext.setAttribute(ServletContext.TEMPDIR, tmpDir);
|
||||
default -> throw new IllegalStateException();
|
||||
}
|
||||
|
||||
// Test we have correct value as the webapp temp directory.
|
||||
|
@ -160,23 +116,18 @@ public class TempDirTest
|
|||
@ValueSource(strings = {"File", "String", "Path"})
|
||||
public void attributeWithNonExistentDirectory(String type) throws Exception
|
||||
{
|
||||
Server server = new Server();
|
||||
WebAppContext webAppContext = new WebAppContext();
|
||||
Path tmpDir = workDir.getPath().resolve("foo_does_not_exist");
|
||||
server.setHandler(webAppContext);
|
||||
Path tmpDir = workDir.getPath().resolve("foo_did_not_exist");
|
||||
assertFalse(Files.exists(tmpDir));
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case "File":
|
||||
webAppContext.setAttribute(ServletContext.TEMPDIR, tmpDir.toFile());
|
||||
break;
|
||||
case "String":
|
||||
webAppContext.setAttribute(ServletContext.TEMPDIR, tmpDir.toString());
|
||||
break;
|
||||
case "Path":
|
||||
webAppContext.setAttribute(ServletContext.TEMPDIR, tmpDir);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException();
|
||||
case "File" -> webAppContext.setAttribute(ServletContext.TEMPDIR, tmpDir.toFile());
|
||||
case "String" -> webAppContext.setAttribute(ServletContext.TEMPDIR, tmpDir.toString());
|
||||
case "Path" -> webAppContext.setAttribute(ServletContext.TEMPDIR, tmpDir);
|
||||
default -> throw new IllegalStateException();
|
||||
}
|
||||
|
||||
// Test we have correct value as the webapp temp directory.
|
||||
|
@ -184,60 +135,20 @@ public class TempDirTest
|
|||
webInfConfiguration.resolveTempDirectory(webAppContext);
|
||||
Path webappTmpDir = webAppContext.getTempDirectory().toPath();
|
||||
assertThat(webappTmpDir, is(tmpDir));
|
||||
assertTrue(Files.exists(webappTmpDir));
|
||||
}
|
||||
|
||||
/**
|
||||
* WebAppContext.BASETEMPDIR has <code>null</code> value
|
||||
* so webappContent#tempDirectory is created under <code>java.io.tmpdir</code>
|
||||
* Test Server.setTempDirectory as valid directory
|
||||
*/
|
||||
@Test
|
||||
public void baseTempDirAttributeWithNullValue() throws Exception
|
||||
{
|
||||
WebInfConfiguration webInfConfiguration = new WebInfConfiguration();
|
||||
WebAppContext webAppContext = new WebAppContext();
|
||||
webAppContext.setAttribute(WebAppContext.BASETEMPDIR, null);
|
||||
webInfConfiguration.resolveTempDirectory(webAppContext);
|
||||
assertThat(webAppContext.getTempDirectory().getParent(), is(System.getProperty("java.io.tmpdir")));
|
||||
}
|
||||
|
||||
/**
|
||||
* WebAppContext.BASETEMPDIR has <code>""</code> value
|
||||
* IllegalStateException
|
||||
*/
|
||||
@Test
|
||||
public void baseTempDirAttributeWithEmptyStringValue()
|
||||
{
|
||||
WebInfConfiguration webInfConfiguration = new WebInfConfiguration();
|
||||
WebAppContext webAppContext = new WebAppContext();
|
||||
webAppContext.setAttribute(WebAppContext.BASETEMPDIR, "");
|
||||
assertThrows(IllegalStateException.class, () -> webInfConfiguration.resolveTempDirectory(webAppContext));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test WebAppContext.BASETEMPDIR as valid directory with types File, String and Path.
|
||||
*/
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings = {"File", "String", "Path"})
|
||||
public void baseTempDirAttributeWithValidDirectory(String type) throws Exception
|
||||
public void serverTempDirAttributeWithValidDirectory() throws Exception
|
||||
{
|
||||
WebAppContext webAppContext = new WebAppContext();
|
||||
Server server = new Server();
|
||||
webAppContext.setServer(server);
|
||||
Path tmpDir = workDir.getPath().resolve("temp_test");
|
||||
FS.ensureDirExists(tmpDir);
|
||||
switch (type)
|
||||
{
|
||||
case "File":
|
||||
webAppContext.setAttribute(WebAppContext.BASETEMPDIR, tmpDir.toFile());
|
||||
break;
|
||||
case "String":
|
||||
webAppContext.setAttribute(WebAppContext.BASETEMPDIR, tmpDir.toString());
|
||||
break;
|
||||
case "Path":
|
||||
webAppContext.setAttribute(WebAppContext.BASETEMPDIR, tmpDir);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
server.setTempDirectory(tmpDir.toFile());
|
||||
|
||||
// Test we have correct value as the webapp temp directory.
|
||||
WebInfConfiguration webInfConfiguration = new WebInfConfiguration();
|
||||
|
@ -247,53 +158,6 @@ public class TempDirTest
|
|||
assertThat(tempDirectory.getParentFile().toPath(), is(tmpDir));
|
||||
}
|
||||
|
||||
/**
|
||||
* WebAppContext.BASETEMPDIR as File to a non existent directory.
|
||||
*/
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings = {"File", "String", "Path"})
|
||||
public void baseTempDirAttributeWithNonExistentDirectory(String type) throws Exception
|
||||
{
|
||||
WebAppContext webAppContext = new WebAppContext();
|
||||
Path tmpDir = workDir.getPath().resolve("does_not_exists");
|
||||
Files.deleteIfExists(tmpDir);
|
||||
assertFalse(Files.exists(tmpDir));
|
||||
switch (type)
|
||||
{
|
||||
case "File":
|
||||
webAppContext.setAttribute(WebAppContext.BASETEMPDIR, tmpDir.toFile());
|
||||
break;
|
||||
case "String":
|
||||
webAppContext.setAttribute(WebAppContext.BASETEMPDIR, tmpDir.toString());
|
||||
break;
|
||||
case "Path":
|
||||
webAppContext.setAttribute(WebAppContext.BASETEMPDIR, tmpDir);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
// The base temp directory must exist for it to be used, if it does not exist or is not writable it will throw ISE.
|
||||
WebInfConfiguration webInfConfiguration = new WebInfConfiguration();
|
||||
assertThrows(IllegalStateException.class, () -> webInfConfiguration.resolveTempDirectory(webAppContext));
|
||||
assertFalse(Files.exists(tmpDir));
|
||||
}
|
||||
|
||||
/**
|
||||
* <code>${jetty.base}</code> exists but has no work subdirectory called work
|
||||
* so webappContent#tempDirectory is created under <code>java.io.tmpdir</code>
|
||||
*/
|
||||
@Test
|
||||
public void jettyBaseWorkDoesNotExist() throws Exception
|
||||
{
|
||||
Path workDir = jettyBase.resolve("work");
|
||||
FS.ensureDeleted(workDir);
|
||||
WebInfConfiguration webInfConfiguration = new WebInfConfiguration();
|
||||
WebAppContext webAppContext = new WebAppContext();
|
||||
webInfConfiguration.resolveTempDirectory(webAppContext);
|
||||
assertThat(webAppContext.getTempDirectory().getParent(), is(System.getProperty("java.io.tmpdir")));
|
||||
}
|
||||
|
||||
/**
|
||||
* <code>${jetty.base}</code> directory exists and has a subdirectory called work
|
||||
* so webappContent#tempDirectory is created under <code>java.io.tmpdir</code>
|
||||
|
@ -304,109 +168,10 @@ public class TempDirTest
|
|||
Path workDir = jettyBase.resolve("work");
|
||||
FS.ensureDirExists(workDir);
|
||||
WebInfConfiguration webInfConfiguration = new WebInfConfiguration();
|
||||
Server server = new Server();
|
||||
WebAppContext webAppContext = new WebAppContext();
|
||||
server.setHandler(webAppContext);
|
||||
webInfConfiguration.resolveTempDirectory(webAppContext);
|
||||
assertThat(webAppContext.getTempDirectory().getParent(), is(workDir.toString()));
|
||||
}
|
||||
|
||||
/**
|
||||
* ServletContext.TEMPDIR has invalid <code>String</code> directory value (wrong permission to write into it)
|
||||
*
|
||||
* Note that if run in the CI environment, the test will fail, because it runs as root,
|
||||
* so we _will_ have permission to write to this directory.
|
||||
*/
|
||||
@Tag("not-on-ci")
|
||||
@DisabledOnOs(value = OS.WINDOWS, disabledReason = "Test/Temp directory is always writable")
|
||||
@Test
|
||||
public void attributeWithInvalidPermissions()
|
||||
{
|
||||
WebInfConfiguration webInfConfiguration = new WebInfConfiguration();
|
||||
WebAppContext webAppContext = new WebAppContext();
|
||||
webAppContext.setAttribute(ServletContext.TEMPDIR, "/var/foo_jetty");
|
||||
assertThrows(IllegalStateException.class, () -> webInfConfiguration.resolveTempDirectory(webAppContext));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(booleans = {true, false})
|
||||
public void testDefaultTempDirectory(boolean persistTempDir) throws Exception
|
||||
{
|
||||
setupServer();
|
||||
webapp.setPersistTempDirectory(persistTempDir);
|
||||
|
||||
// Temp Directory Initially isn't set until started.
|
||||
File tempDirectory = webapp.getTempDirectory();
|
||||
assertNull(tempDirectory);
|
||||
|
||||
// Once server is started the WebApp temp directory exists and is valid directory.
|
||||
server.start();
|
||||
tempDirectory = webapp.getTempDirectory();
|
||||
assertNotNull(tempDirectory);
|
||||
assertTrue(tempDirectory.exists());
|
||||
assertTrue(tempDirectory.isDirectory());
|
||||
|
||||
// Once server is stopped the WebApp temp should be deleted if persistTempDir is false.
|
||||
server.stop();
|
||||
tempDirectory = webapp.getTempDirectory();
|
||||
assertNotNull(tempDirectory, "Temp Directory");
|
||||
if (persistTempDir)
|
||||
{
|
||||
assertTrue(tempDirectory.exists(), "Temp Directory should exist");
|
||||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(booleans = {true, false})
|
||||
public void testPreDefinedTempDirectory(boolean persistTempDir) throws Exception
|
||||
{
|
||||
setupServer();
|
||||
webapp.setPersistTempDirectory(persistTempDir);
|
||||
|
||||
// The temp directory is defined but has not been created.
|
||||
File webappTempDir = MavenTestingUtils.getTargetTestingPath("webappTempDir").toFile();
|
||||
IO.delete(webappTempDir);
|
||||
webapp.setTempDirectory(webappTempDir);
|
||||
assertThat(webapp.getTempDirectory(), is(webappTempDir));
|
||||
assertFalse(webappTempDir.exists());
|
||||
|
||||
// Once server is started the WebApp temp directory exists and is valid directory.
|
||||
server.start();
|
||||
File tempDirectory = webapp.getTempDirectory();
|
||||
assertNotNull(tempDirectory);
|
||||
assertTrue(tempDirectory.exists());
|
||||
assertTrue(tempDirectory.isDirectory());
|
||||
|
||||
// Once server is stopped the WebApp temp should be deleted if persistTempDir is false.
|
||||
server.stop();
|
||||
tempDirectory = webapp.getTempDirectory();
|
||||
assertThat(tempDirectory != null && tempDirectory.exists(), is(persistTempDir));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(booleans = {true, false})
|
||||
public void testPreExistingTempDirectory(boolean persistTempDir) throws Exception
|
||||
{
|
||||
setupServer();
|
||||
webapp.setPersistTempDirectory(persistTempDir);
|
||||
|
||||
// The temp directory is defined and has already been created.
|
||||
File webappTempDir = MavenTestingUtils.getTargetTestingPath("webappTempDir").toFile();
|
||||
IO.delete(webappTempDir);
|
||||
if (!webappTempDir.exists())
|
||||
assertTrue(webappTempDir.mkdir());
|
||||
webapp.setTempDirectory(webappTempDir);
|
||||
assertThat(webapp.getTempDirectory(), is(webappTempDir));
|
||||
assertTrue(webappTempDir.exists());
|
||||
|
||||
// Once server is started the WebApp temp directory exists and is valid directory.
|
||||
server.start();
|
||||
File tempDirectory = webapp.getTempDirectory();
|
||||
assertNotNull(tempDirectory);
|
||||
assertTrue(tempDirectory.exists());
|
||||
assertTrue(tempDirectory.isDirectory());
|
||||
|
||||
// Once server is stopped the WebApp temp should be deleted if persistTempDir is false.
|
||||
server.stop();
|
||||
tempDirectory = webapp.getTempDirectory();
|
||||
assertThat(tempDirectory != null && tempDirectory.exists(), is(persistTempDir));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue