311550 The WebAppProvider should allow setTempDirectory

git-svn-id: svn+ssh://dev.eclipse.org/svnroot/rt/org.eclipse.jetty/jetty/trunk@2000 7e9141cc-0065-0410-87d8-b60c137991c4
This commit is contained in:
Joakim Erdfelt 2010-06-14 22:19:08 +00:00
parent 02b3db3727
commit c9db2c9620
7 changed files with 247 additions and 65 deletions

View File

@ -1,4 +1,5 @@
jetty-7.1.5-SNAPSHOT
+ 311550 The WebAppProvider should allow setTempDirectory
+ 316449 Websocket disconnect fix
jetty-7.1.4.v20100610
@ -27,7 +28,7 @@ jetty-7.1.4.v20100610
+ 316334 Breaking change on org.eclipse.jetty.client.HttpExchange
+ 316399 Debug output in MultiPartFilter
+ 316413 Restarting webapp for packed war fails
+ 316557 OSGi HttpService is not available because context handlers files are not deployed
+ 316557 OSGi HttpService failure due to undeployed context handlers
+ JETTY-547 Delay close after shutdown until request read
+ JETTY-1231 Support context request log handler

View File

@ -12,6 +12,7 @@ import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.util.URIUtil;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.webapp.WebInfConfiguration;
/* ------------------------------------------------------------ */
@ -27,6 +28,7 @@ public class WebAppProvider extends ScanningAppProvider
private boolean _parentLoaderPriority = false;
private String _defaultsDescriptor;
private Filter _filter;
private File _tempDirectory;
private String[] _configurationClasses;
private static class Filter implements FilenameFilter
@ -36,13 +38,17 @@ public class WebAppProvider extends ScanningAppProvider
public boolean accept(File dir, String name)
{
if (!dir.exists())
{
return false;
}
String lowername = name.toLowerCase();
File file = new File(dir,name);
// is it not a directory and not a war ?
if (!file.isDirectory() && !lowername.endsWith(".war"))
{
return false;
}
// is it a directory for an existing war file?
if (file.isDirectory() &&
@ -57,7 +63,9 @@ public class WebAppProvider extends ScanningAppProvider
{
String context=name;
if (!file.isDirectory())
{
context=context.substring(0,context.length()-4);
}
if (new File(_contexts,context+".xml").exists() ||
new File(_contexts,context+".XML").exists() )
{
@ -112,7 +120,7 @@ public class WebAppProvider extends ScanningAppProvider
{
_parentLoaderPriority = parentLoaderPriority;
}
/* ------------------------------------------------------------ */
/** Get the defaultsDescriptor.
* @return the defaultsDescriptor
@ -156,7 +164,7 @@ public class WebAppProvider extends ScanningAppProvider
}
catch (MalformedURLException e)
{
e.printStackTrace();
throw new RuntimeException(e);
}
catch (IOException e)
{
@ -183,6 +191,27 @@ public class WebAppProvider extends ScanningAppProvider
return _configurationClasses;
}
/**
* Set the Work directory where unpacked WAR files are managed from.
* <p>
* Default is the same as the <code>java.io.tmpdir</code> System Property.
*
* @param directory the new work directory
*/
public void setTempDir(File directory)
{
_tempDirectory = directory;
}
/**
* Get the user supplied Work Directory.
*
* @return the user supplied work directory (null if user has not set Temp Directory yet)
*/
public File getTempDir()
{
return _tempDirectory;
}
/* ------------------------------------------------------------ */
public ContextHandler createContextHandler(final App app) throws Exception
@ -203,31 +232,54 @@ public class WebAppProvider extends ScanningAppProvider
// Context Path is the same as the archive.
context = context.substring(0,context.length() - 4);
}
else
else
{
throw new IllegalStateException("unable to create ContextHandler for "+app);
}
// special case of archive (or dir) named "root" is / context
if (context.equalsIgnoreCase("root") || context.equalsIgnoreCase("root/"))
if (context.equalsIgnoreCase("root") || context.equalsIgnoreCase("root/"))
{
context = URIUtil.SLASH;
}
// Ensure "/" is Prepended to all context paths.
if (context.charAt(0) != '/')
if (context.charAt(0) != '/')
{
context = "/" + context;
}
// Ensure "/" is Not Trailing in context paths.
if (context.endsWith("/") && context.length() > 0)
if (context.endsWith("/") && context.length() > 0)
{
context = context.substring(0,context.length() - 1);
}
WebAppContext wah = new WebAppContext();
wah.setContextPath(context);
wah.setWar(file.getAbsolutePath());
if (_defaultsDescriptor != null)
if (_defaultsDescriptor != null)
{
wah.setDefaultsDescriptor(_defaultsDescriptor);
}
wah.setExtractWAR(_extractWars);
wah.setParentLoaderPriority(_parentLoaderPriority);
if (_configurationClasses != null)
if (_configurationClasses != null)
{
wah.setConfigurationClasses(_configurationClasses);
}
if (_tempDirectory != null)
{
/* Since the Temp Dir is really a context base temp directory,
* Lets set the Temp Directory in a way similar to how WebInfConfiguration does it,
* instead of setting the
* WebAppContext.setTempDirectory(File).
* If we used .setTempDirectory(File) all webapps will wind up in the
* same temp / work directory, overwriting each others work.
*/
wah.setAttribute(WebAppContext.BASETEMPDIR,_tempDirectory);
}
return wah;
}

View File

@ -0,0 +1,76 @@
package org.eclipse.jetty.deploy.providers;
import java.io.File;
import org.eclipse.jetty.deploy.test.XmlConfiguredJetty;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
public class WebAppProviderTest
{
private static XmlConfiguredJetty jetty;
@BeforeClass
public static void setupEnvironment() throws Exception
{
jetty = new XmlConfiguredJetty();
jetty.addConfiguration("jetty.xml");
jetty.addConfiguration("jetty-deploy-wars.xml");
// Setup initial context
jetty.copyContext("foo.xml","foo.xml");
jetty.copyWebapp("foo-webapp-1.war","foo.war");
// Should not throw an Exception
jetty.load();
// Start it
jetty.start();
}
@AfterClass
public static void teardownEnvironment() throws Exception
{
// Stop jetty.
jetty.stop();
}
@Test
public void testStartupContext()
{
// Check Server for Handlers
jetty.printHandlers(System.out);
jetty.assertWebAppContextsExists("/foo");
File workDir = jetty.getJettyDir("workish");
// Test for regressions
assertDirNotExists("root of work directory",workDir,"webinf");
assertDirNotExists("root of work directory",workDir,"jsp");
// Test for correct behavior
Assert.assertTrue("Should have generated directory in work directory: " + workDir,hasJettyGeneratedPath(workDir,"foo.war"));
}
private static boolean hasJettyGeneratedPath(File basedir, String expectedWarFilename)
{
for (File path : basedir.listFiles())
{
if (path.exists() && path.isDirectory() && path.getName().startsWith("Jetty_") && path.getName().contains(expectedWarFilename))
{
System.out.println("Found expected generated directory: " + path);
return true;
}
}
return false;
}
public static void assertDirNotExists(String msg, File workDir, String subdir)
{
File dir = new File(workDir,subdir);
Assert.assertFalse("Should not have " + subdir + " in " + msg + " - " + workDir,dir.exists());
}
}

View File

@ -59,7 +59,7 @@ public class XmlConfiguredJetty
{
this(MavenTestingUtils.getTestID());
}
public XmlConfiguredJetty(String testname) throws IOException
{
xmlConfigurations = new ArrayList<URL>();
@ -69,9 +69,10 @@ public class XmlConfiguredJetty
// Ensure we have a new (pristene) directory to work with.
int idx = 0;
jettyHome = new File(jettyHomeBase + "#" + idx);
while(jettyHome.exists()) {
idx++;
jettyHome = new File(jettyHomeBase + "#" + idx);
while (jettyHome.exists())
{
idx++;
jettyHome = new File(jettyHomeBase + "#" + idx);
}
deleteContents(jettyHome);
// Prepare Jetty.Home (Test) dir
@ -91,23 +92,37 @@ public class XmlConfiguredJetty
deleteContents(contextsDir);
}
contextsDir.mkdirs();
File webappsDir = new File(jettyHome,"webapps");
if (webappsDir.exists())
{
deleteContents(webappsDir);
}
webappsDir.mkdirs();
File tmpDir = new File(jettyHome,"tmp");
if (tmpDir.exists())
{
deleteContents(tmpDir);
}
tmpDir.mkdirs();
File workishDir = new File(jettyHome,"workish");
if (workishDir.exists())
{
deleteContents(workishDir);
}
workishDir.mkdirs();
// Setup properties
System.setProperty("java.io.tmpdir",tmpDir.getAbsolutePath());
properties.setProperty("jetty.home",jettyHome.getAbsolutePath());
System.setProperty("jetty.home",jettyHome.getAbsolutePath());
properties.setProperty("test.basedir",MavenTestingUtils.getBasedir().getAbsolutePath());
properties.setProperty("test.resourcesdir",MavenTestingUtils.getTestResourcesDir().getAbsolutePath());
properties.setProperty("test.webapps",webappsDir.getAbsolutePath());
properties.setProperty("test.webapps",workishDir.getAbsolutePath());
properties.setProperty("test.targetdir",MavenTestingUtils.getTargetDir().getAbsolutePath());
properties.setProperty("test.workdir",workishDir.getAbsolutePath());
// Write out configuration for use by ConfigurationManager.
File testConfig = MavenTestingUtils.getTargetFile("xml-configured-jetty.properties");
@ -238,11 +253,11 @@ public class XmlConfiguredJetty
private void deleteContents(File dir)
{
System.out.printf("Delete (dir) %s/%n",dir);
if(!dir.exists())
if (!dir.exists())
{
return;
return;
}
for (File file : dir.listFiles())
{
// Safety measure. only recursively delete within target directory.

View File

@ -0,0 +1,29 @@
<?xml version="1.0"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">
<Configure id="Server" class="org.eclipse.jetty.server.Server">
<Call name="addLifeCycle">
<Arg>
<New id="DeploymentManager" class="org.eclipse.jetty.deploy.DeploymentManager">
<Set name="contexts">
<Ref id="Contexts" />
</Set>
<!-- Providers of Apps -->
<Set name="appProviders">
<Array type="org.eclipse.jetty.deploy.AppProvider">
<Item>
<New class="org.eclipse.jetty.deploy.providers.WebAppProvider">
<Set name="monitoredDir"><SystemProperty name="jetty.home" />/webapps</Set>
<Set name="scanInterval">1</Set>
<Set name="tempDir"><Property name="jetty.home" default="target" />/workish</Set>
</New>
</Item>
</Array>
</Set>
</New>
</Arg>
</Call>
</Configure>

View File

@ -20,9 +20,7 @@ import java.net.URL;
import java.security.PermissionCollection;
import java.util.EventListener;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.jar.JarFile;
import javax.servlet.http.HttpSessionActivationListener;
import javax.servlet.http.HttpSessionAttributeListener;
@ -65,6 +63,7 @@ import org.eclipse.jetty.util.resource.ResourceCollection;
public class WebAppContext extends ServletContextHandler
{
public static final String TEMPDIR = "javax.servlet.context.tempdir";
public static final String BASETEMPDIR = "org.eclipse.jetty.webapp.basetempdir";
public final static String WEB_DEFAULTS_XML="org/eclipse/jetty/webapp/webdefault.xml";
public final static String ERROR_PAGE="org.eclipse.jetty.server.error_page";
public final static String SERVER_CONFIG = "org.eclipse.jetty.webapp.configuration";

View File

@ -221,61 +221,47 @@ public class WebInfConfiguration implements Configuration
{
//If a tmp directory is already set, we're done
File tmpDir = context.getTempDirectory();
if (tmpDir!=null && tmpDir.isDirectory() && tmpDir.canWrite())
return; //Already have a suitable tmp dir configured
if (tmpDir != null && tmpDir.isDirectory() && tmpDir.canWrite())
{
return; // Already have a suitable tmp dir configured
}
//None configured, try and come up with one
//First ... see if one is configured in a context attribute
//either as a File or name of a file
Object t = context.getAttribute(WebAppContext.TEMPDIR);
if (t != null)
// No temp directory configured, try to establish one.
// First we check the context specific, javax.servlet specified, temp directory attribute
File servletTmpDir = asFile(context.getAttribute(WebAppContext.TEMPDIR));
if (servletTmpDir != null && servletTmpDir.isDirectory() && servletTmpDir.canWrite())
{
//Is it a File?
if (t instanceof File)
{
tmpDir=(File)t;
if (tmpDir.isDirectory() && tmpDir.canWrite())
{
context.setTempDirectory(tmpDir);
return;
}
}
// The context attribute specified a name not a File
if (t instanceof String)
{
try
{
tmpDir=new File((String)t);
if (tmpDir.isDirectory() && tmpDir.canWrite())
{
context.setAttribute(context.TEMPDIR,tmpDir);
context.setTempDirectory(tmpDir);
return;
}
}
catch(Exception e)
{
Log.warn(Log.EXCEPTION,e);
}
}
// Use as tmpDir
tmpDir = servletTmpDir;
// Ensure Attribute has File object
context.setAttribute(WebAppContext.TEMPDIR,tmpDir);
// Set as TempDir in context.
context.setTempDirectory(tmpDir);
return;
}
// Second ... make a tmp directory, in a work directory if one exists
String temp = getCanonicalNameForWebAppTmpDir(context);
try
{
//Put the tmp dir in the work directory if we had one
// Put the tmp dir in the work directory if we had one
File work = new File(System.getProperty("jetty.home"),"work");
if (!work.exists() || !work.canWrite() || !work.isDirectory())
work = null;
if (work!=null)
if (work.exists() && work.canWrite() && work.isDirectory())
{
makeTempDirectory(work, context, false); //make a tmp dir inside work, don't delete if it exists
}
else
makeTempDirectory(new File(System.getProperty("java.io.tmpdir")), context, true); //make a tmpdir, delete if it already exists
{
File baseTemp = asFile(context.getAttribute(WebAppContext.BASETEMPDIR));
if (baseTemp != null && baseTemp.isDirectory() && baseTemp.canWrite())
{
// Use baseTemp directory (allow the funky Jetty_0_0_0_0.. subdirectory logic to kick in
makeTempDirectory(baseTemp,context,false);
}
else
{
makeTempDirectory(new File(System.getProperty("java.io.tmpdir")),context,true); //make a tmpdir, delete if it already exists
}
}
}
catch(Exception e)
{
@ -304,7 +290,31 @@ public class WebInfConfiguration implements Configuration
}
}
/**
* 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 and type String, all others return null)
* @return the File object, null if null, or null if not a File or String
*/
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);
}
return null;
}
public void makeTempDirectory (File parent, WebAppContext context, boolean deleteExisting)
throws IOException
{