work in progress... all but OSGi

This commit is contained in:
Greg Wilkins 2016-03-11 12:21:06 +11:00
parent 2f15c3e4f9
commit f19bd2c65a
22 changed files with 729 additions and 717 deletions

View File

@ -0,0 +1,84 @@
//
// ========================================================================
// Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.ant;
import java.io.File;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
import org.apache.tools.ant.AntClassLoader;
import org.eclipse.jetty.util.PatternMatcher;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.webapp.Configuration;
import org.eclipse.jetty.webapp.MetaInfConfiguration;
import org.eclipse.jetty.webapp.WebAppClassLoader;
import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.webapp.WebInfConfiguration;
import org.eclipse.jetty.webapp.WebXmlConfiguration;
public class AntMetaInfConfiguration extends MetaInfConfiguration
{
@Override
public Class<? extends Configuration> replaces()
{
return MetaInfConfiguration.class;
}
/* ------------------------------------------------------------------------------- */
@Override
protected List<URI> getAllContainerJars(final WebAppContext context) throws URISyntaxException
{
List<URI> uris = new ArrayList<>();
if (context.getClassLoader() != null)
{
ClassLoader loader = context.getClassLoader().getParent();
while (loader != null)
{
if (loader instanceof URLClassLoader)
{
URL[] urls = ((URLClassLoader)loader).getURLs();
if (urls != null)
for(URL url:urls)
uris.add(new URI(url.toString().replaceAll(" ","%20")));
}
else if (loader instanceof AntClassLoader)
{
AntClassLoader antLoader = (AntClassLoader)loader;
String[] paths = antLoader.getClasspath().split(new String(new char[]{File.pathSeparatorChar}));
if (paths != null)
{
for (String p:paths)
{
File f = new File(p);
uris.add(f.toURI());
}
}
}
loader = loader.getParent();
}
}
return uris;
}
}

View File

@ -40,13 +40,11 @@ import org.apache.tools.ant.AntClassLoader;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.types.FileSet;
import org.eclipse.jetty.annotations.AnnotationConfiguration;
import org.eclipse.jetty.ant.types.Attribute;
import org.eclipse.jetty.ant.types.Attributes;
import org.eclipse.jetty.ant.types.FileMatchingConfiguration;
import org.eclipse.jetty.ant.utils.TaskLog;
import org.eclipse.jetty.plus.webapp.EnvConfiguration;
import org.eclipse.jetty.plus.webapp.PlusConfiguration;
import org.eclipse.jetty.servlet.FilterHolder;
import org.eclipse.jetty.servlet.FilterMapping;
import org.eclipse.jetty.servlet.Holder;
@ -56,14 +54,9 @@ import org.eclipse.jetty.servlet.ServletMapping;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.webapp.Configuration;
import org.eclipse.jetty.webapp.FragmentConfiguration;
import org.eclipse.jetty.webapp.JettyWebXmlConfiguration;
import org.eclipse.jetty.webapp.MetaInfConfiguration;
import org.eclipse.jetty.webapp.WebAppClassLoader;
import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.webapp.WebInfConfiguration;
import org.eclipse.jetty.webapp.WebXmlConfiguration;
import org.eclipse.jetty.xml.XmlConfiguration;
/**
@ -81,10 +74,10 @@ public class AntWebAppContext extends WebAppContext
private File jettyEnvXml;
/** List of web application libraries. */
private List libraries = new ArrayList();
private List<FileSet> libraries = new ArrayList<>();
/** List of web application class directories. */
private List classes = new ArrayList();
private List<FileSet> classes = new ArrayList<>();
/** context xml file to apply to the webapp */
private File contextXml;
@ -100,11 +93,6 @@ public class AntWebAppContext extends WebAppContext
private List<File> scanFiles;
/** Extra scan targets. */
private FileMatchingConfiguration extraScanTargetsConfiguration;
private FileMatchingConfiguration librariesConfiguration;
@ -409,8 +397,9 @@ public class AntWebAppContext extends WebAppContext
{
super();
this.project = project;
setAttribute(WebInfConfiguration.CONTAINER_JAR_PATTERN, DEFAULT_CONTAINER_INCLUDE_JAR_PATTERN);
setAttribute(MetaInfConfiguration.CONTAINER_JAR_PATTERN, DEFAULT_CONTAINER_INCLUDE_JAR_PATTERN);
setParentLoaderPriority(true);
addConfiguration(new AntWebInfConfiguration(),new AntWebXmlConfiguration(),new AntMetaInfConfiguration());
}
@ -463,7 +452,7 @@ public class AntWebAppContext extends WebAppContext
public List getLibraries()
public List<File> getLibraries()
{
return librariesConfiguration.getBaseDirectories();
}
@ -479,7 +468,7 @@ public class AntWebAppContext extends WebAppContext
this.scanTargets = scanTargets;
}
public List getScanTargetFiles ()
public List<File> getScanTargetFiles ()
{
if (this.scanTargets == null)
return null;
@ -569,7 +558,6 @@ public class AntWebAppContext extends WebAppContext
scanList.addAll(cpFiles);
//any extra scan targets
@SuppressWarnings("unchecked")
List<File> scanFiles = (List<File>)getScanTargetFiles();
if (scanFiles != null)
scanList.addAll(scanFiles);
@ -608,7 +596,6 @@ public class AntWebAppContext extends WebAppContext
try
{
TaskLog.logWithTimestamp("Starting web application "+this.getDescriptor());
addConfiguration(new AntWebInfConfiguration(),new AntWebXmlConfiguration());
if (jettyEnvXml != null && jettyEnvXml.exists())
getConfiguration(EnvConfiguration.class).setJettyEnvXml(Resource.toURL(jettyEnvXml));
@ -674,17 +661,17 @@ public class AntWebAppContext extends WebAppContext
public List<File> getClassPathFiles()
{
List<File> classPathFiles = new ArrayList<File>();
Iterator classesIterator = classes.iterator();
Iterator<FileSet> classesIterator = classes.iterator();
while (classesIterator.hasNext())
{
FileSet clazz = (FileSet) classesIterator.next();
FileSet clazz = classesIterator.next();
classPathFiles.add(clazz.getDirectoryScanner(project).getBasedir());
}
Iterator iterator = libraries.iterator();
Iterator<FileSet> iterator = libraries.iterator();
while (iterator.hasNext())
{
FileSet library = (FileSet) iterator.next();
FileSet library = iterator.next();
String[] includedFiles = library.getDirectoryScanner(project).getIncludedFiles();
File baseDir = library.getDirectoryScanner(project).getBasedir();
@ -708,17 +695,17 @@ public class AntWebAppContext extends WebAppContext
{
FileMatchingConfiguration config = new FileMatchingConfiguration();
Iterator classesIterator = classes.iterator();
Iterator<FileSet> classesIterator = classes.iterator();
while (classesIterator.hasNext())
{
FileSet clazz = (FileSet) classesIterator.next();
FileSet clazz = classesIterator.next();
config.addDirectoryScanner(clazz.getDirectoryScanner(project));
}
Iterator librariesIterator = libraries.iterator();
Iterator<FileSet> librariesIterator = libraries.iterator();
while (librariesIterator.hasNext())
{
FileSet library = (FileSet) librariesIterator.next();
FileSet library = librariesIterator.next();
config.addDirectoryScanner(library.getDirectoryScanner(project));
}

View File

@ -44,112 +44,6 @@ public class AntWebInfConfiguration extends WebInfConfiguration
return WebInfConfiguration.class;
}
@Override
public void preConfigure(final WebAppContext context) throws Exception
{
//Make a temp directory for the webapp if one is not already set
resolveTempDirectory(context);
//Extract webapp if necessary
unpack (context);
//Apply an initial ordering to the jars which governs which will be scanned for META-INF
//info and annotations. The ordering is based on inclusion patterns.
String tmp = (String)context.getAttribute(WEBINF_JAR_PATTERN);
Pattern webInfPattern = (tmp==null?null:Pattern.compile(tmp));
tmp = (String)context.getAttribute(CONTAINER_JAR_PATTERN);
Pattern containerPattern = (tmp==null?null:Pattern.compile(tmp));
//Apply ordering to container jars - if no pattern is specified, we won't
//match any of the container jars
PatternMatcher containerJarNameMatcher = new PatternMatcher ()
{
public void matched(URI uri) throws Exception
{
context.getMetaData().addContainerResource(Resource.newResource(uri));
}
};
ClassLoader loader = context.getClassLoader();
if (loader != null)
{
loader = loader.getParent();
if (loader != null)
{
URI[] containerUris = null;
if (loader instanceof URLClassLoader)
{
URL[] urls = ((URLClassLoader)loader).getURLs();
if (urls != null)
{
containerUris = new URI[urls.length];
int i=0;
for (URL u : urls)
{
try
{
containerUris[i] = u.toURI();
}
catch (URISyntaxException e)
{
containerUris[i] = new URI(u.toString().replaceAll(" ", "%20"));
}
i++;
}
}
}
else if (loader instanceof AntClassLoader)
{
AntClassLoader antLoader = (AntClassLoader)loader;
String[] paths = antLoader.getClasspath().split(new String(new char[]{File.pathSeparatorChar}));
if (paths != null)
{
containerUris = new URI[paths.length];
int i=0;
for (String p:paths)
{
File f = new File(p);
containerUris[i] = f.toURI();
i++;
}
}
}
containerJarNameMatcher.match(containerPattern, containerUris, false);
}
}
//Apply ordering to WEB-INF/lib jars
PatternMatcher webInfJarNameMatcher = new PatternMatcher ()
{
@Override
public void matched(URI uri) throws Exception
{
context.getMetaData().addWebInfJar(Resource.newResource(uri));
}
};
List<Resource> jars = findJars(context);
//Convert to uris for matching
URI[] uris = null;
if (jars != null)
{
uris = new URI[jars.size()];
int i=0;
for (Resource r: jars)
{
uris[i++] = r.getURI();
}
}
webInfJarNameMatcher.match(webInfPattern, uris, true); //null is inclusive, no pattern == all jars match
//No pattern to appy to classes, just add to metadata
context.getMetaData().setWebInfClassesDirs(findClassDirs(context));
}
/**
* Adds classpath files into web application classloader, and
* sets web.xml and base directory for the configured web application.

View File

@ -34,11 +34,11 @@ import org.apache.tools.ant.DirectoryScanner;
public class FileMatchingConfiguration
{
private List directoryScanners;
private List<DirectoryScanner> directoryScanners;
public FileMatchingConfiguration()
{
this.directoryScanners = new ArrayList();
this.directoryScanners = new ArrayList<>();
}
/**
@ -54,10 +54,10 @@ public class FileMatchingConfiguration
* @return a list of base directories denoted by a list of directory
* scanners.
*/
public List getBaseDirectories()
public List<File> getBaseDirectories()
{
List baseDirs = new ArrayList();
Iterator scanners = directoryScanners.iterator();
List<File> baseDirs = new ArrayList<>();
Iterator<DirectoryScanner> scanners = directoryScanners.iterator();
while (scanners.hasNext())
{
DirectoryScanner scanner = (DirectoryScanner) scanners.next();
@ -75,7 +75,7 @@ public class FileMatchingConfiguration
*/
public boolean isIncluded(String pathToFile)
{
Iterator scanners = directoryScanners.iterator();
Iterator<DirectoryScanner> scanners = directoryScanners.iterator();
while (scanners.hasNext())
{
DirectoryScanner scanner = (DirectoryScanner) scanners.next();

View File

@ -21,7 +21,6 @@ package org.eclipse.jetty.deploy.bindings;
import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.isIn;
import static org.hamcrest.Matchers.not;
import java.io.File;
import java.util.List;
@ -87,11 +86,9 @@ public class GlobalWebappConfigBindingTest
WebAppContext context = contexts.get(0);
Assert.assertNotNull("Context should not be null",context);
String defaultClasses[] = context.getDefaultServerClasses();
String currentClasses[] = context.getServerClasses();
String addedClass = "org.eclipse.foo."; // What was added by the binding
Assert.assertThat("Default Server Classes",addedClass,not(isIn(defaultClasses)));
Assert.assertThat("Current Server Classes",addedClass,isIn(currentClasses));
// boolean jndiPackage = false;

View File

@ -119,6 +119,7 @@ public class JettyWebAppContext extends WebAppContext
// Turn off copyWebInf option as it is not applicable for plugin.
super.setCopyWebInf(false);
addConfiguration(new MavenWebInfConfiguration());
addConfiguration(new MavenMetaInfConfiguration());
addConfiguration(new EnvConfiguration());
addConfiguration(new PlusConfiguration());
addConfiguration(new AnnotationConfiguration());

View File

@ -0,0 +1,127 @@
//
// ========================================================================
// Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.maven.plugin;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.webapp.Configuration;
import org.eclipse.jetty.webapp.MetaInfConfiguration;
import org.eclipse.jetty.webapp.WebAppContext;
/**
* MavenWebInfConfiguration
*
* WebInfConfiguration to take account of overlaid wars expressed as project dependencies and
* potential configured via the maven-war-plugin.
*/
public class MavenMetaInfConfiguration extends MetaInfConfiguration
{
private static final Logger LOG = Log.getLogger(MavenMetaInfConfiguration.class);
protected static int COUNTER = 0;
@Override
public Class<? extends Configuration> replaces()
{
return MetaInfConfiguration.class;
}
/**
* Get the jars to examine from the files from which we have
* synthesized the classpath. Note that the classpath is not
* set at this point, so we cannot get them from the classpath.
* @param context the web app context
* @return the list of jars found
*/
@Override
protected List<Resource> findJars (WebAppContext context)
throws Exception
{
List<Resource> list = new ArrayList<Resource>();
JettyWebAppContext jwac = (JettyWebAppContext)context;
if (jwac.getClassPathFiles() != null)
{
for (File f: jwac.getClassPathFiles())
{
if (f.getName().toLowerCase(Locale.ENGLISH).endsWith(".jar"))
{
try
{
list.add(Resource.newResource(f.toURI()));
}
catch (Exception e)
{
LOG.warn("Bad url ", e);
}
}
}
}
List<Resource> superList = super.findJars(context);
if (superList != null)
list.addAll(superList);
return list;
}
/**
* Add in the classes dirs from test/classes and target/classes
* @see org.eclipse.jetty.webapp.WebInfConfiguration#findClassDirs(org.eclipse.jetty.webapp.WebAppContext)
*/
@Override
protected List<Resource> findClassDirs(WebAppContext context) throws Exception
{
List<Resource> list = new ArrayList<Resource>();
JettyWebAppContext jwac = (JettyWebAppContext)context;
if (jwac.getClassPathFiles() != null)
{
for (File f: jwac.getClassPathFiles())
{
if (f.exists() && f.isDirectory())
{
try
{
list.add(Resource.newResource(f.toURI()));
}
catch (Exception e)
{
LOG.warn("Bad url ", e);
}
}
}
}
List<Resource> classesDirs = super.findClassDirs(context);
if (classesDirs != null)
list.addAll(classesDirs);
return list;
}
}

View File

@ -21,10 +21,7 @@ package org.eclipse.jetty.maven.plugin;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
@ -36,7 +33,6 @@ import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.webapp.WebInfConfiguration;
/**
* MavenWebInfConfiguration
*
@ -52,6 +48,16 @@ public class MavenWebInfConfiguration extends WebInfConfiguration
protected Resource _originalResourceBase;
protected List<Resource> _unpackedOverlayResources;
public MavenWebInfConfiguration()
{
super();
addServerClass(
"org.apache.maven.",
"org.codehaus.plexus.");
}
@Override
public Class<? extends Configuration> replaces()
{
@ -66,58 +72,26 @@ public class MavenWebInfConfiguration extends WebInfConfiguration
JettyWebAppContext jwac = (JettyWebAppContext)context;
//put the classes dir and all dependencies into the classpath
if (jwac.getClassPathFiles() != null)
if (jwac.getClassPathFiles() != null && context.getClassLoader() instanceof WebAppClassLoader)
{
if (LOG.isDebugEnabled()) LOG.debug("Setting up classpath ...");
Iterator itor = jwac.getClassPathFiles().iterator();
while (itor.hasNext())
((WebAppClassLoader)context.getClassLoader()).addClassPath(((File)itor.next()).getCanonicalPath());
if (LOG.isDebugEnabled())
LOG.debug("Setting up classpath ...");
WebAppClassLoader loader=(WebAppClassLoader)context.getClassLoader();
for (File classpath:jwac.getClassPathFiles())
loader.addClassPath(classpath.getCanonicalPath());
}
super.configure(context);
// knock out environmental maven and plexus classes from webAppContext
String[] existingServerClasses = context.getServerClasses();
String[] newServerClasses = new String[2+(existingServerClasses==null?0:existingServerClasses.length)];
newServerClasses[0] = "org.apache.maven.";
newServerClasses[1] = "org.codehaus.plexus.";
System.arraycopy( existingServerClasses, 0, newServerClasses, 2, existingServerClasses.length );
if (LOG.isDebugEnabled())
{
LOG.debug("Server classes:");
for (int i=0;i<newServerClasses.length;i++)
LOG.debug(newServerClasses[i]);
}
context.setServerClasses( newServerClasses );
return true;
}
/**
* @see org.eclipse.jetty.webapp.WebInfConfiguration#preConfigure(org.eclipse.jetty.webapp.WebAppContext)
*/
public void preConfigure(WebAppContext context) throws Exception
{
super.preConfigure(context);
}
/**
* @see org.eclipse.jetty.webapp.AbstractConfiguration#postConfigure(org.eclipse.jetty.webapp.WebAppContext)
*/
public void postConfigure(WebAppContext context) throws Exception
{
super.postConfigure(context);
}
/**
* @see org.eclipse.jetty.webapp.WebInfConfiguration#deconfigure(org.eclipse.jetty.webapp.WebAppContext)
@ -193,85 +167,6 @@ public class MavenWebInfConfiguration extends WebInfConfiguration
}
/**
* Get the jars to examine from the files from which we have
* synthesized the classpath. Note that the classpath is not
* set at this point, so we cannot get them from the classpath.
* @param context the web app context
* @return the list of jars found
*/
@Override
protected List<Resource> findJars (WebAppContext context)
throws Exception
{
List<Resource> list = new ArrayList<Resource>();
JettyWebAppContext jwac = (JettyWebAppContext)context;
if (jwac.getClassPathFiles() != null)
{
for (File f: jwac.getClassPathFiles())
{
if (f.getName().toLowerCase(Locale.ENGLISH).endsWith(".jar"))
{
try
{
list.add(Resource.newResource(f.toURI()));
}
catch (Exception e)
{
LOG.warn("Bad url ", e);
}
}
}
}
List<Resource> superList = super.findJars(context);
if (superList != null)
list.addAll(superList);
return list;
}
/**
* Add in the classes dirs from test/classes and target/classes
* @see org.eclipse.jetty.webapp.WebInfConfiguration#findClassDirs(org.eclipse.jetty.webapp.WebAppContext)
*/
@Override
protected List<Resource> findClassDirs(WebAppContext context) throws Exception
{
List<Resource> list = new ArrayList<Resource>();
JettyWebAppContext jwac = (JettyWebAppContext)context;
if (jwac.getClassPathFiles() != null)
{
for (File f: jwac.getClassPathFiles())
{
if (f.exists() && f.isDirectory())
{
try
{
list.add(Resource.newResource(f.toURI()));
}
catch (Exception e)
{
LOG.warn("Bad url ", e);
}
}
}
}
List<Resource> classesDirs = super.findClassDirs(context);
if (classesDirs != null)
list.addAll(classesDirs);
return list;
}
protected Resource unpackOverlay (WebAppContext context, Overlay overlay)
throws IOException
{

View File

@ -36,6 +36,7 @@ import org.eclipse.jetty.server.handler.HandlerCollection;
import org.eclipse.jetty.server.handler.RequestLogHandler;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.webapp.Configuration;
import org.eclipse.jetty.webapp.Configurations;
import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.xml.XmlConfiguration;
@ -50,7 +51,7 @@ public class ServerSupport
public static void configureDefaultConfigurationClasses (Server server)
{
server.setAttribute(Configuration.ATTR, JettyWebAppContext.DEFAULT_CONFIGURATION_CLASSES);
Configurations.setServerDefault(server);
}

View File

@ -40,7 +40,6 @@ import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.resource.JarResource;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.webapp.Configurations;
import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.xml.XmlConfiguration;
import org.osgi.framework.Bundle;
@ -291,9 +290,15 @@ public abstract class AbstractWebAppProvider extends AbstractLifeCycle implement
// Set up what has been configured on the provider
_webApp.setParentLoaderPriority(isParentLoaderPriority());
_webApp.setExtractWAR(isExtract());
_webApp.setConfigurationClasses(getConfigurationClasses());
_webApp.addConfiguration(new OSGiWebInfConfiguration(),new OSGiMetaInfConfiguration());
if (annotationsAvailable())
_webApp.addConfiguration(new AnnotationConfiguration());
//add in EnvConfiguration and PlusConfiguration just after FragmentConfiguration
if (jndiAvailable())
_webApp.addConfiguration(new EnvConfiguration(),new PlusConfiguration());
if (getDefaultsDescriptor() != null)
_webApp.setDefaultsDescriptor(getDefaultsDescriptor());
@ -568,36 +573,6 @@ public abstract class AbstractWebAppProvider extends AbstractLifeCycle implement
return _tldBundles;
}
/* ------------------------------------------------------------ */
/**
* @param configurations The configuration class names.
*/
public void setConfigurationClasses(String[] configurations)
{
_configurationClasses = configurations == null ? null : (String[]) configurations.clone();
}
/* ------------------------------------------------------------ */
public String[] getConfigurationClasses()
{
if (_configurationClasses != null)
return _configurationClasses;
Configurations defaults = Configurations.serverDefault(_serverWrapper.getServer());
//add before JettyWebXmlConfiguration
if (annotationsAvailable())
defaults.add(AnnotationConfiguration.class.getName());
//add in EnvConfiguration and PlusConfiguration just after FragmentConfiguration
if (jndiAvailable())
defaults.add(
EnvConfiguration.class.getName(),
PlusConfiguration.class.getName());
String[] asArray = new String[defaults.size()];
return defaults.toArray(asArray);
}
/* ------------------------------------------------------------ */
public void setServerInstanceWrapper(ServerInstanceWrapper wrapper)

View File

@ -0,0 +1,341 @@
//
// ========================================================================
// Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.osgi.boot;
import java.io.File;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.TreeMap;
import java.util.regex.Pattern;
import org.eclipse.jetty.osgi.boot.utils.BundleFileLocatorHelperFactory;
import org.eclipse.jetty.osgi.boot.utils.Util;
import org.eclipse.jetty.osgi.boot.utils.internal.PackageAdminServiceTracker;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.util.resource.ResourceCollection;
import org.eclipse.jetty.webapp.Configuration;
import org.eclipse.jetty.webapp.MetaInfConfiguration;
import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.webapp.WebInfConfiguration;
import org.osgi.framework.Bundle;
import org.osgi.framework.FrameworkUtil;
/**
* OSGiWebInfConfiguration
*
* Handle adding resources found in bundle fragments, and add them into the
*/
public class OSGiMetaInfConfiguration extends MetaInfConfiguration
{
private static final Logger LOG = Log.getLogger(WebInfConfiguration.class);
/**
* Comma separated list of symbolic names of bundles that contain tlds that should be considered
* as on the container classpath
*/
public static final String SYS_PROP_TLD_BUNDLES = "org.eclipse.jetty.osgi.tldbundles";
/**
* Regex of symbolic names of bundles that should be considered to be on the container classpath
*/
public static final String CONTAINER_BUNDLE_PATTERN = "org.eclipse.jetty.server.webapp.containerIncludeBundlePattern";
public static final String FRAGMENT_AND_REQUIRED_BUNDLES = "org.eclipse.jetty.osgi.fragmentAndRequiredBundles";
public static final String FRAGMENT_AND_REQUIRED_RESOURCES = "org.eclipse.jetty.osgi.fragmentAndRequiredResources";
@Override
public Class<? extends Configuration> replaces()
{
return MetaInfConfiguration.class;
}
/* ------------------------------------------------------------ */
/**
* Check to see if there have been any bundle symbolic names added of bundles that should be
* regarded as being on the container classpath, and scanned for fragments, tlds etc etc.
* This can be defined in:
* <ol>
* <li>SystemProperty SYS_PROP_TLD_BUNDLES</li>
* <li>DeployerManager.setContextAttribute CONTAINER_BUNDLE_PATTERN</li>
* </ol>
*
* We also allow individual bundles to specify particular bundles that might include TLDs via the Require-Tlds
* MANIFEST.MF header.
*
* @see org.eclipse.jetty.webapp.WebInfConfiguration#preConfigure(org.eclipse.jetty.webapp.WebAppContext)
*/
@Override
public void preConfigure(final WebAppContext context) throws Exception
{
super.preConfigure(context);
//Check to see if there have been any bundle symbolic names added of bundles that should be
//regarded as being on the container classpath, and scanned for fragments, tlds etc etc.
//This can be defined in:
// 1. SystemProperty SYS_PROP_TLD_BUNDLES
// 2. DeployerManager.setContextAttribute CONTAINER_BUNDLE_PATTERN
String tmp = (String)context.getAttribute(CONTAINER_BUNDLE_PATTERN);
Pattern pattern = (tmp==null?null:Pattern.compile(tmp));
List<String> names = new ArrayList<String>();
tmp = System.getProperty(SYS_PROP_TLD_BUNDLES);
if (tmp != null)
{
StringTokenizer tokenizer = new StringTokenizer(tmp, ", \n\r\t", false);
while (tokenizer.hasMoreTokens())
names.add(tokenizer.nextToken());
}
HashSet<Resource> matchingResources = new HashSet<Resource>();
if ( !names.isEmpty() || pattern != null)
{
Bundle[] bundles = FrameworkUtil.getBundle(OSGiMetaInfConfiguration.class).getBundleContext().getBundles();
for (Bundle bundle : bundles)
{
LOG.debug("Checking bundle {}:{}", bundle.getBundleId(), bundle.getSymbolicName());
if (pattern != null)
{
// if bundle symbolic name matches the pattern
if (pattern.matcher(bundle.getSymbolicName()).matches())
{
//get the file location of the jar and put it into the list of container jars that will be scanned for stuff (including tlds)
matchingResources.addAll(getBundleAsResource(bundle));
}
}
if (names != null)
{
//if there is an explicit bundle name, then check if it matches
if (names.contains(bundle.getSymbolicName()))
matchingResources.addAll(getBundleAsResource(bundle));
}
}
}
for (Resource r:matchingResources)
{
context.getMetaData().addContainerResource(r);
}
}
@Override
public void postConfigure(WebAppContext context) throws Exception
{
context.setAttribute(FRAGMENT_AND_REQUIRED_BUNDLES, null);
context.setAttribute(FRAGMENT_AND_REQUIRED_RESOURCES, null);
super.postConfigure(context);
}
/* ------------------------------------------------------------ */
/**
* Consider the fragment bundles associated with the bundle of the webapp being deployed.
*
*
* @see org.eclipse.jetty.webapp.WebInfConfiguration#findJars(org.eclipse.jetty.webapp.WebAppContext)
*/
@Override
protected List<Resource> findJars (WebAppContext context)
throws Exception
{
List<Resource> mergedResources = new ArrayList<Resource>();
//get jars from WEB-INF/lib if there are any
List<Resource> webInfJars = super.findJars(context);
if (webInfJars != null)
mergedResources.addAll(webInfJars);
//add fragment jars and any Required-Bundles as if in WEB-INF/lib of the associated webapp
Bundle[] bundles = PackageAdminServiceTracker.INSTANCE.getFragmentsAndRequiredBundles((Bundle)context.getAttribute(OSGiWebappConstants.JETTY_OSGI_BUNDLE));
if (bundles != null && bundles.length > 0)
{
Set<Bundle> fragsAndReqsBundles = (Set<Bundle>)context.getAttribute(FRAGMENT_AND_REQUIRED_BUNDLES);
if (fragsAndReqsBundles == null)
{
fragsAndReqsBundles = new HashSet<Bundle>();
context.setAttribute(FRAGMENT_AND_REQUIRED_BUNDLES, fragsAndReqsBundles);
}
Set<Resource> fragsAndReqsResources = (Set<Resource>)context.getAttribute(FRAGMENT_AND_REQUIRED_RESOURCES);
if (fragsAndReqsResources == null)
{
fragsAndReqsResources = new HashSet<Resource>();
context.setAttribute(FRAGMENT_AND_REQUIRED_RESOURCES, fragsAndReqsResources);
}
for (Bundle b : bundles)
{
//skip bundles that are not installed
if (b.getState() == Bundle.UNINSTALLED)
continue;
//add to context attribute storing associated fragments and required bundles
fragsAndReqsBundles.add(b);
File f = BundleFileLocatorHelperFactory.getFactory().getHelper().getBundleInstallLocation(b);
Resource r = Resource.newResource(f.toURI());
//add to convenience context attribute storing fragments and required bundles as Resources
fragsAndReqsResources.add(r);
mergedResources.add(r);
}
}
return mergedResources;
}
/* ------------------------------------------------------------ */
/**
* Allow fragments to supply some resources that are added to the baseResource of the webapp.
*
* The resources can be either prepended or appended to the baseResource.
*
* @see org.eclipse.jetty.webapp.WebInfConfiguration#configure(org.eclipse.jetty.webapp.WebAppContext)
*/
@Override
public boolean configure(WebAppContext context) throws Exception
{
TreeMap<String, Resource> prependedResourcesPath = new TreeMap<String, Resource>();
TreeMap<String, Resource> appendedResourcesPath = new TreeMap<String, Resource>();
Bundle bundle = (Bundle)context.getAttribute(OSGiWebappConstants.JETTY_OSGI_BUNDLE);
if (bundle != null)
{
Set<Bundle> fragments = (Set<Bundle>)context.getAttribute(FRAGMENT_AND_REQUIRED_BUNDLES);
if (fragments != null && !fragments.isEmpty())
{
// sorted extra resource base found in the fragments.
// the resources are either overriding the resourcebase found in the
// web-bundle
// or appended.
// amongst each resource we sort them according to the alphabetical
// order
// of the name of the internal folder and the symbolic name of the
// fragment.
// this is useful to make sure that the lookup path of those
// resource base defined by fragments is always the same.
// This natural order could be abused to define the order in which
// the base resources are
// looked up.
for (Bundle frag : fragments)
{
String path = Util.getManifestHeaderValue(OSGiWebappConstants.JETTY_WAR_FRAGMENT_FOLDER_PATH,OSGiWebappConstants.JETTY_WAR_FRAGMENT_RESOURCE_PATH,frag.getHeaders());
convertFragmentPathToResource(path, frag, appendedResourcesPath);
path = Util.getManifestHeaderValue(OSGiWebappConstants.JETTY_WAR_PATCH_FRAGMENT_FOLDER_PATH, OSGiWebappConstants.JETTY_WAR_PREPEND_FRAGMENT_RESOURCE_PATH, frag.getHeaders());
convertFragmentPathToResource(path, frag, prependedResourcesPath);
}
if (!appendedResourcesPath.isEmpty())
{
LinkedHashSet<Resource> resources = new LinkedHashSet<Resource>();
//Add in any existing setting of extra resource dirs
Set<Resource> resourceDirs = (Set<Resource>)context.getAttribute(WebInfConfiguration.RESOURCE_DIRS);
if (resourceDirs != null && !resourceDirs.isEmpty())
resources.addAll(resourceDirs);
//Then append the values from JETTY_WAR_FRAGMENT_FOLDER_PATH
resources.addAll(appendedResourcesPath.values());
context.setAttribute(WebInfConfiguration.RESOURCE_DIRS, resources);
}
}
}
super.configure(context);
// place the prepended resources at the beginning of the contexts's resource base
if (!prependedResourcesPath.isEmpty())
{
Resource[] resources = new Resource[1+prependedResourcesPath.size()];
System.arraycopy(prependedResourcesPath.values().toArray(new Resource[prependedResourcesPath.size()]), 0, resources, 0, prependedResourcesPath.size());
resources[resources.length-1] = context.getBaseResource();
context.setBaseResource(new ResourceCollection(resources));
}
return true;
}
/* ------------------------------------------------------------ */
/**
* Resolves the bundle. Usually that would be a single URL per bundle. But we do some more work if there are jars
* embedded in the bundle.
*/
private List<Resource> getBundleAsResource(Bundle bundle)
throws Exception
{
List<Resource> resources = new ArrayList<Resource>();
File file = BundleFileLocatorHelperFactory.getFactory().getHelper().getBundleInstallLocation(bundle);
if (file.isDirectory())
{
for (File f : file.listFiles())
{
if (f.getName().endsWith(".jar") && f.isFile())
{
resources.add(Resource.newResource(f));
}
else if (f.isDirectory() && f.getName().equals("lib"))
{
for (File f2 : file.listFiles())
{
if (f2.getName().endsWith(".jar") && f2.isFile())
{
resources.add(Resource.newResource(f));
}
}
}
}
resources.add(Resource.newResource(file)); //TODO really???
}
else
{
resources.add(Resource.newResource(file));
}
return resources;
}
/**
* Convert a path inside a fragment into a Resource
* @param resourcePath
* @param fragment
* @param resourceMap
* @throws Exception
*/
private void convertFragmentPathToResource (String resourcePath, Bundle fragment, Map<String, Resource> resourceMap )
throws Exception
{
if (resourcePath == null)
return;
URL url = fragment.getEntry(resourcePath);
if (url == null)
{
throw new IllegalArgumentException("Unable to locate " + resourcePath
+ " inside "
+ " the fragment '"
+ fragment.getSymbolicName()
+ "'");
}
url = BundleFileLocatorHelperFactory.getFactory().getHelper().getLocalURL(url);
String key = resourcePath.startsWith("/") ? resourcePath.substring(1) : resourcePath;
resourceMap.put(key + ";" + fragment.getSymbolicName(), Resource.newResource(url));
}
}

View File

@ -18,30 +18,8 @@
package org.eclipse.jetty.osgi.boot;
import java.io.File;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.TreeMap;
import java.util.regex.Pattern;
import org.eclipse.jetty.osgi.boot.utils.BundleFileLocatorHelperFactory;
import org.eclipse.jetty.osgi.boot.utils.Util;
import org.eclipse.jetty.osgi.boot.utils.internal.PackageAdminServiceTracker;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.util.resource.ResourceCollection;
import org.eclipse.jetty.webapp.Configuration;
import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.webapp.WebInfConfiguration;
import org.osgi.framework.Bundle;
import org.osgi.framework.FrameworkUtil;
@ -51,290 +29,19 @@ import org.osgi.framework.FrameworkUtil;
* Handle adding resources found in bundle fragments, and add them into the
*/
public class OSGiWebInfConfiguration extends WebInfConfiguration
{
private static final Logger LOG = Log.getLogger(WebInfConfiguration.class);
/**
* Comma separated list of symbolic names of bundles that contain tlds that should be considered
* as on the container classpath
*/
public static final String SYS_PROP_TLD_BUNDLES = "org.eclipse.jetty.osgi.tldbundles";
/**
* Regex of symbolic names of bundles that should be considered to be on the container classpath
*/
public static final String CONTAINER_BUNDLE_PATTERN = "org.eclipse.jetty.server.webapp.containerIncludeBundlePattern";
public static final String FRAGMENT_AND_REQUIRED_BUNDLES = "org.eclipse.jetty.osgi.fragmentAndRequiredBundles";
public static final String FRAGMENT_AND_REQUIRED_RESOURCES = "org.eclipse.jetty.osgi.fragmentAndRequiredResources";
{
@Deprecated
public static final String SYS_PROP_TLD_BUNDLES = OSGiMetaInfConfiguration.SYS_PROP_TLD_BUNDLES;
@Deprecated
public static final String CONTAINER_BUNDLE_PATTERN = OSGiMetaInfConfiguration.CONTAINER_BUNDLE_PATTERN;
@Deprecated
public static final String FRAGMENT_AND_REQUIRED_BUNDLES = OSGiMetaInfConfiguration.FRAGMENT_AND_REQUIRED_BUNDLES;
@Deprecated
public static final String FRAGMENT_AND_REQUIRED_RESOURCES = OSGiMetaInfConfiguration.FRAGMENT_AND_REQUIRED_RESOURCES;
@Override
public Class<? extends Configuration> replaces()
{
return WebInfConfiguration.class;
}
/* ------------------------------------------------------------ */
/**
* Check to see if there have been any bundle symbolic names added of bundles that should be
* regarded as being on the container classpath, and scanned for fragments, tlds etc etc.
* This can be defined in:
* <ol>
* <li>SystemProperty SYS_PROP_TLD_BUNDLES</li>
* <li>DeployerManager.setContextAttribute CONTAINER_BUNDLE_PATTERN</li>
* </ol>
*
* We also allow individual bundles to specify particular bundles that might include TLDs via the Require-Tlds
* MANIFEST.MF header.
*
* @see org.eclipse.jetty.webapp.WebInfConfiguration#preConfigure(org.eclipse.jetty.webapp.WebAppContext)
*/
@Override
public void preConfigure(final WebAppContext context) throws Exception
{
super.preConfigure(context);
//Check to see if there have been any bundle symbolic names added of bundles that should be
//regarded as being on the container classpath, and scanned for fragments, tlds etc etc.
//This can be defined in:
// 1. SystemProperty SYS_PROP_TLD_BUNDLES
// 2. DeployerManager.setContextAttribute CONTAINER_BUNDLE_PATTERN
String tmp = (String)context.getAttribute(CONTAINER_BUNDLE_PATTERN);
Pattern pattern = (tmp==null?null:Pattern.compile(tmp));
List<String> names = new ArrayList<String>();
tmp = System.getProperty(SYS_PROP_TLD_BUNDLES);
if (tmp != null)
{
StringTokenizer tokenizer = new StringTokenizer(tmp, ", \n\r\t", false);
while (tokenizer.hasMoreTokens())
names.add(tokenizer.nextToken());
}
HashSet<Resource> matchingResources = new HashSet<Resource>();
if ( !names.isEmpty() || pattern != null)
{
Bundle[] bundles = FrameworkUtil.getBundle(OSGiWebInfConfiguration.class).getBundleContext().getBundles();
for (Bundle bundle : bundles)
{
LOG.debug("Checking bundle {}:{}", bundle.getBundleId(), bundle.getSymbolicName());
if (pattern != null)
{
// if bundle symbolic name matches the pattern
if (pattern.matcher(bundle.getSymbolicName()).matches())
{
//get the file location of the jar and put it into the list of container jars that will be scanned for stuff (including tlds)
matchingResources.addAll(getBundleAsResource(bundle));
}
}
if (names != null)
{
//if there is an explicit bundle name, then check if it matches
if (names.contains(bundle.getSymbolicName()))
matchingResources.addAll(getBundleAsResource(bundle));
}
}
}
for (Resource r:matchingResources)
{
context.getMetaData().addContainerResource(r);
}
}
@Override
public void postConfigure(WebAppContext context) throws Exception
{
context.setAttribute(FRAGMENT_AND_REQUIRED_BUNDLES, null);
context.setAttribute(FRAGMENT_AND_REQUIRED_RESOURCES, null);
super.postConfigure(context);
}
/* ------------------------------------------------------------ */
/**
* Consider the fragment bundles associated with the bundle of the webapp being deployed.
*
*
* @see org.eclipse.jetty.webapp.WebInfConfiguration#findJars(org.eclipse.jetty.webapp.WebAppContext)
*/
@Override
protected List<Resource> findJars (WebAppContext context)
throws Exception
{
List<Resource> mergedResources = new ArrayList<Resource>();
//get jars from WEB-INF/lib if there are any
List<Resource> webInfJars = super.findJars(context);
if (webInfJars != null)
mergedResources.addAll(webInfJars);
//add fragment jars and any Required-Bundles as if in WEB-INF/lib of the associated webapp
Bundle[] bundles = PackageAdminServiceTracker.INSTANCE.getFragmentsAndRequiredBundles((Bundle)context.getAttribute(OSGiWebappConstants.JETTY_OSGI_BUNDLE));
if (bundles != null && bundles.length > 0)
{
Set<Bundle> fragsAndReqsBundles = (Set<Bundle>)context.getAttribute(FRAGMENT_AND_REQUIRED_BUNDLES);
if (fragsAndReqsBundles == null)
{
fragsAndReqsBundles = new HashSet<Bundle>();
context.setAttribute(FRAGMENT_AND_REQUIRED_BUNDLES, fragsAndReqsBundles);
}
Set<Resource> fragsAndReqsResources = (Set<Resource>)context.getAttribute(FRAGMENT_AND_REQUIRED_RESOURCES);
if (fragsAndReqsResources == null)
{
fragsAndReqsResources = new HashSet<Resource>();
context.setAttribute(FRAGMENT_AND_REQUIRED_RESOURCES, fragsAndReqsResources);
}
for (Bundle b : bundles)
{
//skip bundles that are not installed
if (b.getState() == Bundle.UNINSTALLED)
continue;
//add to context attribute storing associated fragments and required bundles
fragsAndReqsBundles.add(b);
File f = BundleFileLocatorHelperFactory.getFactory().getHelper().getBundleInstallLocation(b);
Resource r = Resource.newResource(f.toURI());
//add to convenience context attribute storing fragments and required bundles as Resources
fragsAndReqsResources.add(r);
mergedResources.add(r);
}
}
return mergedResources;
}
/* ------------------------------------------------------------ */
/**
* Allow fragments to supply some resources that are added to the baseResource of the webapp.
*
* The resources can be either prepended or appended to the baseResource.
*
* @see org.eclipse.jetty.webapp.WebInfConfiguration#configure(org.eclipse.jetty.webapp.WebAppContext)
*/
@Override
public boolean configure(WebAppContext context) throws Exception
{
TreeMap<String, Resource> prependedResourcesPath = new TreeMap<String, Resource>();
TreeMap<String, Resource> appendedResourcesPath = new TreeMap<String, Resource>();
Bundle bundle = (Bundle)context.getAttribute(OSGiWebappConstants.JETTY_OSGI_BUNDLE);
if (bundle != null)
{
Set<Bundle> fragments = (Set<Bundle>)context.getAttribute(FRAGMENT_AND_REQUIRED_BUNDLES);
if (fragments != null && !fragments.isEmpty())
{
// sorted extra resource base found in the fragments.
// the resources are either overriding the resourcebase found in the
// web-bundle
// or appended.
// amongst each resource we sort them according to the alphabetical
// order
// of the name of the internal folder and the symbolic name of the
// fragment.
// this is useful to make sure that the lookup path of those
// resource base defined by fragments is always the same.
// This natural order could be abused to define the order in which
// the base resources are
// looked up.
for (Bundle frag : fragments)
{
String path = Util.getManifestHeaderValue(OSGiWebappConstants.JETTY_WAR_FRAGMENT_FOLDER_PATH,OSGiWebappConstants.JETTY_WAR_FRAGMENT_RESOURCE_PATH,frag.getHeaders());
convertFragmentPathToResource(path, frag, appendedResourcesPath);
path = Util.getManifestHeaderValue(OSGiWebappConstants.JETTY_WAR_PATCH_FRAGMENT_FOLDER_PATH, OSGiWebappConstants.JETTY_WAR_PREPEND_FRAGMENT_RESOURCE_PATH, frag.getHeaders());
convertFragmentPathToResource(path, frag, prependedResourcesPath);
}
if (!appendedResourcesPath.isEmpty())
{
LinkedHashSet<Resource> resources = new LinkedHashSet<Resource>();
//Add in any existing setting of extra resource dirs
Set<Resource> resourceDirs = (Set<Resource>)context.getAttribute(WebInfConfiguration.RESOURCE_DIRS);
if (resourceDirs != null && !resourceDirs.isEmpty())
resources.addAll(resourceDirs);
//Then append the values from JETTY_WAR_FRAGMENT_FOLDER_PATH
resources.addAll(appendedResourcesPath.values());
context.setAttribute(WebInfConfiguration.RESOURCE_DIRS, resources);
}
}
}
super.configure(context);
// place the prepended resources at the beginning of the contexts's resource base
if (!prependedResourcesPath.isEmpty())
{
Resource[] resources = new Resource[1+prependedResourcesPath.size()];
System.arraycopy(prependedResourcesPath.values().toArray(new Resource[prependedResourcesPath.size()]), 0, resources, 0, prependedResourcesPath.size());
resources[resources.length-1] = context.getBaseResource();
context.setBaseResource(new ResourceCollection(resources));
}
return true;
}
/* ------------------------------------------------------------ */
/**
* Resolves the bundle. Usually that would be a single URL per bundle. But we do some more work if there are jars
* embedded in the bundle.
*/
private List<Resource> getBundleAsResource(Bundle bundle)
throws Exception
{
List<Resource> resources = new ArrayList<Resource>();
File file = BundleFileLocatorHelperFactory.getFactory().getHelper().getBundleInstallLocation(bundle);
if (file.isDirectory())
{
for (File f : file.listFiles())
{
if (f.getName().endsWith(".jar") && f.isFile())
{
resources.add(Resource.newResource(f));
}
else if (f.isDirectory() && f.getName().equals("lib"))
{
for (File f2 : file.listFiles())
{
if (f2.getName().endsWith(".jar") && f2.isFile())
{
resources.add(Resource.newResource(f));
}
}
}
}
resources.add(Resource.newResource(file)); //TODO really???
}
else
{
resources.add(Resource.newResource(file));
}
return resources;
}
/**
* Convert a path inside a fragment into a Resource
* @param resourcePath
* @param fragment
* @param resourceMap
* @throws Exception
*/
private void convertFragmentPathToResource (String resourcePath, Bundle fragment, Map<String, Resource> resourceMap )
throws Exception
{
if (resourcePath == null)
return;
URL url = fragment.getEntry(resourcePath);
if (url == null)
{
throw new IllegalArgumentException("Unable to locate " + resourcePath
+ " inside "
+ " the fragment '"
+ fragment.getSymbolicName()
+ "'");
}
url = BundleFileLocatorHelperFactory.getFactory().getHelper().getLocalURL(url);
String key = resourcePath.startsWith("/") ? resourcePath.substring(1) : resourcePath;
resourceMap.put(key + ";" + fragment.getSymbolicName(), Resource.newResource(url));
}
}

View File

@ -29,11 +29,12 @@ import org.eclipse.jetty.annotations.ServletContainerInitializersStarter;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.webapp.AbstractConfiguration;
import org.eclipse.jetty.webapp.Configuration;
import org.eclipse.jetty.webapp.StandardDescriptorProcessor;
import org.eclipse.jetty.webapp.WebAppClassLoader;
import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.webapp.WebInfConfiguration;
import org.eclipse.jetty.webapp.WebXmlConfiguration;
/**
* QuickStartConfiguration
@ -41,7 +42,7 @@ import org.eclipse.jetty.webapp.WebInfConfiguration;
* Re-inflate a deployable webapp from a saved effective-web.xml
* which combines all pre-parsed web xml descriptors and annotations.
*/
public class QuickStartConfiguration extends WebInfConfiguration
public class QuickStartConfiguration extends AbstractConfiguration
{
private static final Logger LOG = Log.getLogger(QuickStartConfiguration.class);
@ -58,6 +59,16 @@ public class QuickStartConfiguration extends WebInfConfiguration
private Mode _mode=Mode.AUTO;
private boolean _quickStart;
public QuickStartConfiguration()
{
super(false,
new String[]{WebInfConfiguration.class.getName()},
new String[]{WebXmlConfiguration.class.getName()},
null,null
);
}
public void setMode(Mode mode)
{
_mode=mode;
@ -68,11 +79,6 @@ public class QuickStartConfiguration extends WebInfConfiguration
return _mode;
}
@Override
public Class<? extends Configuration> replaces()
{
return WebInfConfiguration.class;
}
@Override
public boolean isAddedByDefault()
@ -86,20 +92,11 @@ public class QuickStartConfiguration extends WebInfConfiguration
@Override
public void preConfigure(WebAppContext context) throws Exception
{
//Make a temp directory for the webapp if one is not already set
resolveTempDirectory(context);
// expand war
if (!context.isExtractWAR() || context.isCopyWebDir() || context.isCopyWebInf())
throw new IllegalStateException("Quickstart must be run is expanded war");
unpack (context);
//check that webapp is suitable for quick start - it is not a packed war
String war = context.getWar();
if (war == null || war.length()<=0 || !context.getBaseResource().isDirectory())
throw new IllegalStateException ("Bad Quickstart location");
//look for quickstart-web.xml in WEB-INF of webapp
Resource quickStartWebXml = getQuickStartWebXml(context);
LOG.debug("quickStartWebXml={} exists={}",quickStartWebXml,quickStartWebXml.exists());
@ -132,7 +129,6 @@ public class QuickStartConfiguration extends WebInfConfiguration
else
throw new IllegalStateException ("No "+quickStartWebXml);
break;
}
}
@ -144,11 +140,11 @@ public class QuickStartConfiguration extends WebInfConfiguration
.filter(c->!__replacedConfigurations.contains(c.replaces())&&!__replacedConfigurations.contains(c.getClass()))
.collect(Collectors.toList()).toArray(new Configuration[]{}));
context.getMetaData().setWebXml(quickStartWebXml);
context.getServletContext().setEffectiveMajorVersion(context.getMetaData().getWebXml().getMajorVersion());
context.getServletContext().setEffectiveMinorVersion(context.getMetaData().getWebXml().getMinorVersion());
}
/**
* @see org.eclipse.jetty.webapp.AbstractConfiguration#configure(org.eclipse.jetty.webapp.WebAppContext)
*/
@ -158,22 +154,6 @@ public class QuickStartConfiguration extends WebInfConfiguration
if (!_quickStart)
return super.configure(context);
//TODO: set up the classpath here. This should be handled by the QuickStartDescriptorProcessor
Resource webInf = context.getWebInf();
if (webInf != null && webInf.isDirectory() && context.getClassLoader() instanceof WebAppClassLoader)
{
// Look for classes directory
Resource classes= webInf.addPath("classes/");
if (classes.exists())
((WebAppClassLoader)context.getClassLoader()).addClassPath(classes);
// Look for jars
Resource lib= webInf.addPath("lib/");
if (lib.exists() || lib.isDirectory())
((WebAppClassLoader)context.getClassLoader()).addJars(lib);
}
//add the processor to handle normal web.xml content
context.getMetaData().addDescriptorProcessor(new StandardDescriptorProcessor());

View File

@ -122,7 +122,7 @@ public class QuickStartGeneratorConfiguration extends AbstractConfiguration
webappAttr.put("xmlns:xsi","http://www.w3.org/2001/XMLSchema-instance");
webappAttr.put("xsi:schemaLocation","http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd");
webappAttr.put("metadata-complete","true");
webappAttr.put("version","3.1");
webappAttr.put("version",_webApp.getServletContext().getEffectiveMajorVersion()+"."+_webApp.getServletContext().getEffectiveMinorVersion());
out.openTag("web-app",webappAttr);
if (_webApp.getDisplayName() != null)

View File

@ -18,6 +18,7 @@
package org.eclipse.jetty.webapp;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@ -74,8 +75,8 @@ public class AbstractConfiguration implements Configuration
_enabledByDefault=enableByDefault;
_after=Collections.unmodifiableList(after==null?Collections.emptyList():Arrays.asList(after).stream().map(Class::getName).collect(Collectors.toList()));
_before=Collections.unmodifiableList(before==null?Collections.emptyList():Arrays.asList(before).stream().map(Class::getName).collect(Collectors.toList()));
_system=Collections.unmodifiableList(systemClasses==null?Collections.emptyList():Arrays.asList(systemClasses));
_server=Collections.unmodifiableList(serverClasses==null?Collections.emptyList():Arrays.asList(serverClasses));
_system=new ArrayList<>(systemClasses==null?Collections.emptyList():Arrays.asList(systemClasses));
_server=new ArrayList<>(serverClasses==null?Collections.emptyList():Arrays.asList(serverClasses));
}
/**
@ -90,8 +91,20 @@ public class AbstractConfiguration implements Configuration
_enabledByDefault=enableByDefault;
_after=Collections.unmodifiableList(after==null?Collections.emptyList():Arrays.asList(after));
_before=Collections.unmodifiableList(before==null?Collections.emptyList():Arrays.asList(before));
_system=Collections.unmodifiableList(systemClasses==null?Collections.emptyList():Arrays.asList(systemClasses));
_server=Collections.unmodifiableList(serverClasses==null?Collections.emptyList():Arrays.asList(serverClasses));
_system=new ArrayList<>(systemClasses==null?Collections.emptyList():Arrays.asList(systemClasses));
_server=new ArrayList<>(serverClasses==null?Collections.emptyList():Arrays.asList(serverClasses));
}
protected void addSystemClass(String... systemClass)
{
for (String s:systemClass)
_system.add(s);
}
protected void addServerClass(String... serverClass)
{
for (String s:serverClass)
_system.add(s);
}
@Override

View File

@ -21,7 +21,6 @@ package org.eclipse.jetty.webapp;
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.ConcurrentModificationException;
import java.util.HashMap;
@ -43,24 +42,27 @@ public class Configurations extends AbstractList<Configuration>
{
private static final Logger LOG = Log.getLogger(Configurations.class);
private static final Map<String,Configuration> __known = new HashMap<>();
private static final List<Configuration> __known = new ArrayList<>();
private static final Map<String,Configuration> __knownByClassName = new HashMap<>();
static
{
ServiceLoader<Configuration> configs = ServiceLoader.load(Configuration.class);
for (Configuration configuration : configs)
__known.put(configuration.getName(),configuration);
__knownByClassName.put(configuration.getName(),configuration);
__known.addAll(__knownByClassName.values());
sort(__known);
if (LOG.isDebugEnabled())
{
for (Map.Entry<String, Configuration> e: __known.entrySet())
LOG.debug("known {}",e);
for (Configuration c: __known)
LOG.debug("known {}",c);
}
LOG.debug("Known Configurations {}",__known.keySet());
LOG.debug("Known Configurations {}",__knownByClassName.keySet());
}
public static Collection<Configuration> getKnown()
public static List<Configuration> getKnown()
{
return Collections.unmodifiableCollection(__known.values());
return __known;
}
/* ------------------------------------------------------------ */
@ -73,7 +75,7 @@ public class Configurations extends AbstractList<Configuration>
* @param server The server the default is for
* @return the server default ClassList instance of the configuration classes for this server. Changes to this list will change the server default instance.
*/
public static Configurations setServerDefault(Server server) throws ClassNotFoundException, InstantiationException, IllegalAccessException
public static Configurations setServerDefault(Server server)
{
Configurations configurations=server.getBean(Configurations.class);
if (configurations!=null)
@ -94,10 +96,8 @@ public class Configurations extends AbstractList<Configuration>
*/
public static Configurations serverDefault(Server server)
{
Configurations configurations;
if (server==null)
configurations=new Configurations(WebAppContext.DEFAULT_CONFIGURATION_CLASSES);
else
Configurations configurations=null;
if (server!=null)
{
configurations= server.getBean(Configurations.class);
if (configurations!=null)
@ -110,11 +110,15 @@ public class Configurations extends AbstractList<Configuration>
configurations = new Configurations((Configurations)attr);
else if (attr instanceof String[])
configurations = new Configurations((String[])attr);
else
configurations=new Configurations(WebAppContext.DEFAULT_CONFIGURATION_CLASSES);
}
}
}
if (configurations==null)
configurations=new Configurations(Configurations.getKnown().stream()
.filter(Configuration::isAddedByDefault)
.map(c->c.getClass().getName())
.toArray(String[]::new));
if (LOG.isDebugEnabled())
LOG.debug("default configurations for {}: {}",server,configurations);
@ -134,7 +138,7 @@ public class Configurations extends AbstractList<Configuration>
protected static Configuration getConfiguration(String classname)
{
Configuration configuration = __known.get(classname);
Configuration configuration = __knownByClassName.get(classname);
if (configuration==null)
{
try
@ -165,7 +169,9 @@ public class Configurations extends AbstractList<Configuration>
public Configurations(Configurations classlist)
{
_configurations.addAll(classlist._configurations);
this(classlist._configurations.stream()
.map(c->c.getClass().getName())
.toArray(String[]::new));
}
public void add(Configuration... configurations)
@ -232,14 +238,24 @@ public class Configurations extends AbstractList<Configuration>
}
public void sort()
{
sort(_configurations);
if (LOG.isDebugEnabled())
{
for (Configuration c: _configurations)
LOG.debug("sorted {}",c);
}
}
public static void sort(List<Configuration> configurations)
{
// Sort the configurations
Map<String,Configuration> map = new HashMap<>();
TopologicalSort<Configuration> sort = new TopologicalSort<>();
for (Configuration c:_configurations)
for (Configuration c:configurations)
map.put(c.getName(),c);
for (Configuration c:_configurations)
for (Configuration c:configurations)
{
for (String b:c.getConfigurationsBeforeThis())
{
@ -255,12 +271,7 @@ public class Configurations extends AbstractList<Configuration>
}
}
sort.sort(_configurations);
if (LOG.isDebugEnabled())
{
for (Configuration c: _configurations)
LOG.debug("sorted {}",c);
}
sort.sort(configurations);
}
public List<Configuration> getConfigurations()
@ -283,7 +294,7 @@ public class Configurations extends AbstractList<Configuration>
private void add(String name,Configuration configuration)
{
// Is this configuration known?
if (!__known.containsKey(name))
if (!__knownByClassName.containsKey(name))
LOG.warn("Unknown configuration {}. Not declared for ServiceLoader!",name);
// Do we need to replace any existing configuration?
@ -321,7 +332,7 @@ public class Configurations extends AbstractList<Configuration>
for (int i=0; i<_configurations.size() ;i++)
{
Configuration configuration=_configurations.get(i);
LOG.debug("preConfigure {} with {}",this,configuration);
LOG.debug("preConfigure with {}",configuration);
configuration.preConfigure(webapp);
if (_configurations.get(i)!=configuration)
@ -334,7 +345,7 @@ public class Configurations extends AbstractList<Configuration>
// Configure webapp
for (Configuration configuration : _configurations)
{
LOG.debug("configure {} with {}",this,configuration);
LOG.debug("configure {}",configuration);
if (!configuration.configure(webapp))
return false;
}
@ -347,7 +358,7 @@ public class Configurations extends AbstractList<Configuration>
// Configure webapp
for (Configuration configuration : _configurations)
{
LOG.debug("postConfigure {} with {}",this,configuration);
LOG.debug("postConfigure {}",configuration);
configuration.postConfigure(webapp);
}
}

View File

@ -23,6 +23,7 @@ import java.io.File;
import java.io.IOException;
import java.net.JarURLConnection;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
@ -98,7 +99,29 @@ public class MetaInfConfiguration extends AbstractConfiguration
{
return true;
}
/* ------------------------------------------------------------------------------- */
protected List<URI> getAllContainerJars(final WebAppContext context) throws URISyntaxException
{
List<URI> uris = new ArrayList<>();
if (context.getClassLoader() != null)
{
ClassLoader loader = context.getClassLoader().getParent();
while (loader != null)
{
if (loader instanceof URLClassLoader)
{
URL[] urls = ((URLClassLoader)loader).getURLs();
if (urls != null)
for(URL url:urls)
uris.add(new URI(url.toString().replaceAll(" ","%20")));
}
loader = loader.getParent();
}
}
return uris;
}
/* ------------------------------------------------------------------------------- */
@Override
public void preConfigure(final WebAppContext context) throws Exception
@ -106,16 +129,7 @@ public class MetaInfConfiguration extends AbstractConfiguration
// discover matching container jars
if (context.getClassLoader() != null)
{
ClassLoader loader = context.getClassLoader().getParent();
List<URI> uris = new ArrayList<>();
while (loader != null && (loader instanceof URLClassLoader))
{
URL[] urls = ((URLClassLoader)loader).getURLs();
if (urls != null)
for(URL url:urls)
uris.add(new URI(url.toString().replaceAll(" ","%20")));
loader = loader.getParent();
}
List<URI> uris = getAllContainerJars(context);
new PatternMatcher ()
{

View File

@ -163,15 +163,6 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
private String[] __dftProtectedTargets = {"/web-inf", "/meta-inf"};
/*
* default configurations.
*/
public static final String[] DEFAULT_CONFIGURATION_CLASSES =
Configurations.getKnown().stream()
.filter(Configuration::isAddedByDefault)
.map(c->c.getClass().getName())
.toArray(String[]::new);
// System classes are classes that cannot be replaced by
// the web application, and they are *always* loaded via
// system classloader.
@ -914,25 +905,6 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
return _parentLoaderPriority;
}
/* ------------------------------------------------------------ */
public static String[] getDefaultConfigurationClasses ()
{
return DEFAULT_CONFIGURATION_CLASSES;
}
/* ------------------------------------------------------------ */
public String[] getDefaultServerClasses ()
{
return __dftServerClasses;
}
/* ------------------------------------------------------------ */
public String[] getDefaultSystemClasses ()
{
return __dftSystemClasses;
}
/* ------------------------------------------------------------ */
protected void loadConfigurations()
{
@ -941,7 +913,6 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
return;
_configurations.add(Configurations.serverDefault(getServer()).toArray());
_configurations.sort();
}
/* ------------------------------------------------------------ */
@ -985,6 +956,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
_configurations.set(configurations);
}
/* ------------------------------------------------------------ */
public void setConfigurationClasses(List<String> configurations)
{
setConfigurationClasses(configurations.toArray(new String[configurations.size()]));

View File

@ -38,7 +38,14 @@ public class WebInfConfiguration extends AbstractConfiguration
private static final Logger LOG = Log.getLogger(WebInfConfiguration.class);
public static final String TEMPDIR_CONFIGURED = "org.eclipse.jetty.tmpdirConfigured";
@Deprecated
public static final String CONTAINER_JAR_PATTERN = MetaInfConfiguration.CONTAINER_JAR_PATTERN;
@Deprecated
public static final String WEBINF_JAR_PATTERN = MetaInfConfiguration.WEBINF_JAR_PATTERN;
@Deprecated
public static final String RESOURCE_DIRS = MetaInfConfiguration.RESOURCE_DIRS;
protected Resource _preUnpackBaseResource;
public WebInfConfiguration()

View File

@ -57,10 +57,16 @@ public class WebAppContextTest
@Test
public void testConfigurationClassesFromDefault ()
{
String[] known_and_enabled=Configurations.getKnown().stream()
.filter(Configuration::isAddedByDefault)
.map(c->c.getClass().getName())
.toArray(String[]::new);
Server server = new Server();
//test if no classnames set, its the defaults
WebAppContext wac = new WebAppContext();
assertThat(Arrays.asList(wac.getConfigurations()).stream().map(c->{return c.getClass().getName();}).collect(Collectors.toList()),Matchers.containsInAnyOrder(WebAppContext.DEFAULT_CONFIGURATION_CLASSES));
assertThat(Arrays.asList(wac.getConfigurations()).stream().map(c->{return c.getClass().getName();}).collect(Collectors.toList()),Matchers.containsInAnyOrder(known_and_enabled));
String[] classNames = wac.getConfigurationClasses();
assertNotNull(classNames);

View File

@ -1,6 +1,6 @@
# Setup default logging implementation for during testing
org.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog
org.eclipse.jetty.LEVEL=INFO
org.eclipse.jetty.webapp.LEVEL=DEBUG
# org.eclipse.jetty.webapp.LEVEL=DEBUG
# org.eclipse.jetty.util.LEVEL=DEBUG
# org.eclipse.jetty.util.PathWatcher.Noisy.LEVEL=OFF

View File

@ -1,7 +1,7 @@
# Setup default logging implementation for during testing
org.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog
org.eclipse.jetty.LEVEL=INFO
#org.eclipse.jetty.webapp.LEVEL=DEBUG
#org.eclipse.jetty.quickstart.LEVEL=DEBUG
org.eclipse.jetty.webapp.LEVEL=DEBUG
org.eclipse.jetty.quickstart.LEVEL=DEBUG
#org.eclipse.jetty.util.LEVEL=DEBUG
#org.eclipse.jetty.util.PathWatcher.Noisy.LEVEL=OFF