Reformat src code; ensure url caching is controlled by jetty Resource.setDefaultUseCaches

This commit is contained in:
Jan Bartel 2012-04-04 15:13:33 +10:00
parent 792b101639
commit 911643b783
12 changed files with 1084 additions and 1068 deletions

View File

@ -28,98 +28,106 @@ import org.osgi.framework.Bundle;
import org.osgi.framework.FrameworkUtil;
/**
* Plug bundles that contains tld files so that jasper will discover them
* and set them up in jetty.
* Plug bundles that contains tld files so that jasper will discover them and
* set them up in jetty.
*
* For example: -Dorg.eclipse.jetty.osgi.tldbundles=org.springframework.web.servlet,com.opensymphony.module.sitemesh
* Otherwise use an attribute to the WebAppDeployer
* <New class="org.eclipse.jetty.deploy.providers.WebAppProvider">
* ....
* <Set name="tldBundles">&ltProperty name="org.eclipse.jetty.osgi.tldsbundles" default="" /></Set>
* <New>
* For example:
* -Dorg.eclipse.jetty.osgi.tldbundles=org.springframework.web.servlet
* ,com.opensymphony.module.sitemesh Otherwise use an attribute to the
* WebAppDeployer <New
* class="org.eclipse.jetty.deploy.providers.WebAppProvider"> .... <Set
* name="tldBundles">&ltProperty name="org.eclipse.jetty.osgi.tldsbundles"
* default="" /></Set> <New>
*/
public class PluggableWebAppRegistrationCustomizerImpl implements WebappRegistrationCustomizer
{
/**
* To plug into jasper bundles that contain tld files
* please use a list of bundle's symbolic names:
* -Djetty.osgi.tldbundles=org.springframework.web.servlet,com.opensymphony.module.sitemesh
*/
public static final String SYS_PROP_TLD_BUNDLES = "org.eclipse.jetty.osgi.tldbundles";
/**
* Union of the tld bundles defined system wide and the one defines as an attribute of the AppProvider.
* @param provider
* @return
*/
private static Collection<String> getTldBundles(OSGiAppProvider provider)
{
String sysprop = System.getProperty(SYS_PROP_TLD_BUNDLES);
String att = (String)provider.getTldBundles();
if (sysprop == null && att == null)
{
return Collections.emptySet();
}
if (att == null)
{
att = sysprop;
}
else if (sysprop != null)
{
att = att + "," + sysprop;
}
Collection<String> tldbundles = new HashSet<String>();
StringTokenizer tokenizer = new StringTokenizer(att, ", \n\r\t", false);
while (tokenizer.hasMoreTokens())
{
tldbundles.add(tokenizer.nextToken());
}
return tldbundles;
}
/**
* @return The location of the jars that contain tld files.
* Jasper will discover them.
*/
/**
* To plug into jasper bundles that contain tld files please use a list of
* bundle's symbolic names:
* -Djetty.osgi.tldbundles=org.springframework.web.servlet
* ,com.opensymphony.module.sitemesh
*/
public static final String SYS_PROP_TLD_BUNDLES = "org.eclipse.jetty.osgi.tldbundles";
/**
* Union of the tld bundles defined system wide and the one defines as an
* attribute of the AppProvider.
*
* @param provider
* @return
*/
private static Collection<String> getTldBundles(OSGiAppProvider provider)
{
String sysprop = System.getProperty(SYS_PROP_TLD_BUNDLES);
String att = (String) provider.getTldBundles();
if (sysprop == null && att == null) { return Collections.emptySet(); }
if (att == null)
{
att = sysprop;
}
else if (sysprop != null)
{
att = att + "," + sysprop;
}
Collection<String> tldbundles = new HashSet<String>();
StringTokenizer tokenizer = new StringTokenizer(att, ", \n\r\t", false);
while (tokenizer.hasMoreTokens())
{
tldbundles.add(tokenizer.nextToken());
}
return tldbundles;
}
/**
* @return The location of the jars that contain tld files. Jasper will
* discover them.
*/
public URL[] getJarsWithTlds(OSGiAppProvider provider, BundleFileLocatorHelper locatorHelper) throws Exception
{
List<URL> urls = new ArrayList<URL>();
//naive way of finding those bundles.
//lots of assumptions: for example we assume a single version of each bundle that would contain tld files.
//this is probably good enough as those tlds are loaded system-wide on jetty.
//to do better than this we need to do it on a per webapp basis.
//probably using custom properties in the ContextHandler service
//and mirroring those in the MANIFEST.MF
Bundle[] bundles = FrameworkUtil.getBundle(PluggableWebAppRegistrationCustomizerImpl.class).getBundleContext().getBundles();
Collection<String> tldbundles = getTldBundles(provider);
for (Bundle bundle : bundles)
{
if (tldbundles.contains(bundle.getSymbolicName()))
{
registerTldBundle(locatorHelper, bundle, urls);
}
}
return urls.toArray(new URL[urls.size()]);
List<URL> urls = new ArrayList<URL>();
// naive way of finding those bundles.
// lots of assumptions: for example we assume a single version of each
// bundle that would contain tld files.
// this is probably good enough as those tlds are loaded system-wide on
// jetty.
// to do better than this we need to do it on a per webapp basis.
// probably using custom properties in the ContextHandler service
// and mirroring those in the MANIFEST.MF
Bundle[] bundles = FrameworkUtil.getBundle(PluggableWebAppRegistrationCustomizerImpl.class).getBundleContext().getBundles();
Collection<String> tldbundles = getTldBundles(provider);
for (Bundle bundle : bundles)
{
if (tldbundles.contains(bundle.getSymbolicName()))
{
registerTldBundle(locatorHelper, bundle, urls);
}
}
return urls.toArray(new URL[urls.size()]);
}
/**
* Resolves the bundle that contains tld files as a set of URLs that will be
* passed to jasper as a URLClassLoader later on.
* Usually that would be a single URL per bundle.
* But we do some more work if there are jars embedded in the bundle.
* passed to jasper as a URLClassLoader later on. Usually that would be a
* single URL per bundle. But we do some more work if there are jars
* embedded in the bundle.
*
* The jasper TldScanner expects a URLClassloader to parse a jar for the /META-INF/*.tld it may contain. We place the bundles that we know contain such
* tag-libraries. Please note that it will work if and only if the bundle is a jar (!) Currently we just hardcode the bundle that contains the jstl
* implemenation.
* The jasper TldScanner expects a URLClassloader to parse a jar for the
* /META-INF/*.tld it may contain. We place the bundles that we know contain
* such tag-libraries. Please note that it will work if and only if the
* bundle is a jar (!) Currently we just hardcode the bundle that contains
* the jstl implemenation.
*
* A workaround when the tld cannot be parsed with this method is to copy and paste it inside the WEB-INF of the webapplication where it is used.
* A workaround when the tld cannot be parsed with this method is to copy
* and paste it inside the WEB-INF of the webapplication where it is used.
*
* Support only 2 types of packaging for the bundle: - the bundle is a jar (recommended for runtime.) - the bundle is a folder and contain jars in the root
* and/or in the lib folder (nice for PDE developement situations) Unsupported: the bundle is a jar that embeds more jars.
* Support only 2 types of packaging for the bundle: - the bundle is a jar
* (recommended for runtime.) - the bundle is a folder and contain jars in
* the root and/or in the lib folder (nice for PDE developement situations)
* Unsupported: the bundle is a jar that embeds more jars.
*
* @param locatorHelper
* @param bundle
@ -152,9 +160,9 @@ public class PluggableWebAppRegistrationCustomizerImpl implements WebappRegistra
}
else
{
urls.add(jasperLocation.toURI().toURL());
urls.add(jasperLocation.toURI().toURL());
}
}
}

View File

@ -36,48 +36,52 @@ import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
/**
* Fix various shortcomings with the way jasper parses the tld files.
* Plugs the JSTL tlds assuming that they are packaged with the bundle that contains the JSTL classes.
* Fix various shortcomings with the way jasper parses the tld files. Plugs the
* JSTL tlds assuming that they are packaged with the bundle that contains the
* JSTL classes.
* <p>
* Pluggable tlds at the server level are handled by {@link PluggableWebAppRegistrationCustomizerImpl}.
* Pluggable tlds at the server level are handled by
* {@link PluggableWebAppRegistrationCustomizerImpl}.
* </p>
*/
public class WebappRegistrationCustomizerImpl implements WebappRegistrationCustomizer
{
/**
* Default name of a class that belongs to the jstl bundle.
* From that class we locate the corresponding bundle and register it
* as a bundle that contains tld files.
*/
private static String DEFAULT_JSTL_BUNDLE_CLASS = "org.apache.taglibs.standard.tag.el.core.WhenTag";
//used to be "org.apache.jasper.runtime.JspFactoryImpl" but now
//the standard tag library implementation are stored in a separate bundle.
//DISABLED please use the tld bundle argument for the OSGiAppProvider
// /**
// * Default name of a class that belongs to the bundle where the Java server Faces tld files are defined.
// * This is the sun's reference implementation.
// */
// private static String DEFAUT_JSF_IMPL_CLASS = "com.sun.faces.config.ConfigureListener";
/**
* Default jsp factory implementation.
* Idally jasper is osgified and we can use services.
* In the mean time we statically set the jsp factory implementation.
* bug #299733
*/
private static String DEFAULT_JSP_FACTORY_IMPL_CLASS = "org.apache.jasper.runtime.JspFactoryImpl";
/**
* Default name of a class that belongs to the jstl bundle. From that class
* we locate the corresponding bundle and register it as a bundle that
* contains tld files.
*/
private static String DEFAULT_JSTL_BUNDLE_CLASS = "org.apache.taglibs.standard.tag.el.core.WhenTag";
// used to be "org.apache.jasper.runtime.JspFactoryImpl" but now
// the standard tag library implementation are stored in a separate bundle.
// DISABLED please use the tld bundle argument for the OSGiAppProvider
// /**
// * Default name of a class that belongs to the bundle where the Java
// server Faces tld files are defined.
// * This is the sun's reference implementation.
// */
// private static String DEFAUT_JSF_IMPL_CLASS =
// "com.sun.faces.config.ConfigureListener";
/**
* Default jsp factory implementation. Idally jasper is osgified and we can
* use services. In the mean time we statically set the jsp factory
* implementation. bug #299733
*/
private static String DEFAULT_JSP_FACTORY_IMPL_CLASS = "org.apache.jasper.runtime.JspFactoryImpl";
public WebappRegistrationCustomizerImpl()
{
fixupDtdResolution();
try
{
//sanity check:
// sanity check:
Class cl = getClass().getClassLoader().loadClass("org.apache.jasper.servlet.JspServlet");
//System.err.println("found the jsp servlet: " + cl.getName());
// System.err.println("found the jsp servlet: " + cl.getName());
}
catch (Exception e)
{
@ -87,18 +91,18 @@ public class WebappRegistrationCustomizerImpl implements WebappRegistrationCusto
}
try
{
//bug #299733
// bug #299733
JspFactory fact = JspFactory.getDefaultFactory();
if (fact == null)
{ //bug #299733
//JspFactory does a simple Class.getForName("org.apache.jasper.runtime.JspFactoryImpl")
//however its bundles does not import the jasper package
//so it fails. let's help things out:
fact = (JspFactory)JettyBootstrapActivator.class.getClassLoader()
.loadClass(DEFAULT_JSP_FACTORY_IMPL_CLASS).newInstance();
{ // bug #299733
// JspFactory does a simple
// Class.getForName("org.apache.jasper.runtime.JspFactoryImpl")
// however its bundles does not import the jasper package
// so it fails. let's help things out:
fact = (JspFactory) JettyBootstrapActivator.class.getClassLoader().loadClass(DEFAULT_JSP_FACTORY_IMPL_CLASS).newInstance();
JspFactory.setDefaultFactory(fact);
}
}
catch (Exception e)
{
@ -106,85 +110,90 @@ public class WebappRegistrationCustomizerImpl implements WebappRegistrationCusto
e.printStackTrace();
}
}
/**
* The jasper TldScanner expects a URLClassloader to parse a jar for the /META-INF/*.tld it may contain. We place the bundles that we know contain such
* tag-libraries. Please note that it will work if and only if the bundle is a jar (!) Currently we just hardcode the bundle that contains the jstl
* implemenation.
* The jasper TldScanner expects a URLClassloader to parse a jar for the
* /META-INF/*.tld it may contain. We place the bundles that we know contain
* such tag-libraries. Please note that it will work if and only if the
* bundle is a jar (!) Currently we just hardcode the bundle that contains
* the jstl implemenation.
*
* A workaround when the tld cannot be parsed with this method is to copy and paste it inside the WEB-INF of the webapplication where it is used.
* A workaround when the tld cannot be parsed with this method is to copy
* and paste it inside the WEB-INF of the webapplication where it is used.
*
* Support only 2 types of packaging for the bundle: - the bundle is a jar (recommended for runtime.) - the bundle is a folder and contain jars in the root
* and/or in the lib folder (nice for PDE developement situations) Unsupported: the bundle is a jar that embeds more jars.
* Support only 2 types of packaging for the bundle: - the bundle is a jar
* (recommended for runtime.) - the bundle is a folder and contain jars in
* the root and/or in the lib folder (nice for PDE developement situations)
* Unsupported: the bundle is a jar that embeds more jars.
*
* @return array of URLs
* @throws Exception
*/
public URL[] getJarsWithTlds(OSGiAppProvider provider, BundleFileLocatorHelper locatorHelper) throws Exception
{
HashSet<Class<?>> classesToAddToTheTldBundles = new HashSet<Class<?>>();
//Look for the jstl bundle
//We assume the jstl's tlds are defined there.
//We assume that the jstl bundle is imported by this bundle
//So we can look for this class using this bundle's classloader:
Class<?> jstlClass = WebappRegistrationCustomizerImpl.class.getClassLoader().loadClass(DEFAULT_JSTL_BUNDLE_CLASS);
classesToAddToTheTldBundles.add(jstlClass);
HashSet<Class<?>> classesToAddToTheTldBundles = new HashSet<Class<?>>();
// Look for the jstl bundle
// We assume the jstl's tlds are defined there.
// We assume that the jstl bundle is imported by this bundle
// So we can look for this class using this bundle's classloader:
Class<?> jstlClass = WebappRegistrationCustomizerImpl.class.getClassLoader().loadClass(DEFAULT_JSTL_BUNDLE_CLASS);
classesToAddToTheTldBundles.add(jstlClass);
ArrayList<URL> urls = new ArrayList<URL>();
for (Class<?> cl : classesToAddToTheTldBundles)
{
Bundle tldBundle = FrameworkUtil.getBundle(cl);
File tldBundleLocation = locatorHelper.getBundleInstallLocation(tldBundle);
if (tldBundleLocation != null && tldBundleLocation.isDirectory())
{
// try to find the jar files inside this folder
for (File f : tldBundleLocation.listFiles())
{
if (f.getName().endsWith(".jar") && f.isFile())
{
urls.add(f.toURI().toURL());
}
else if (f.isDirectory() && f.getName().equals("lib"))
{
for (File f2 : tldBundleLocation.listFiles())
{
if (f2.getName().endsWith(".jar") && f2.isFile())
{
urls.add(f2.toURI().toURL());
}
}
}
}
}
else if (tldBundleLocation != null)
{
urls.add(tldBundleLocation.toURI().toURL());
}
}
return urls.toArray(new URL[urls.size()]);
for (Class<?> cl : classesToAddToTheTldBundles)
{
Bundle tldBundle = FrameworkUtil.getBundle(cl);
File tldBundleLocation = locatorHelper.getBundleInstallLocation(tldBundle);
if (tldBundleLocation != null && tldBundleLocation.isDirectory())
{
// try to find the jar files inside this folder
for (File f : tldBundleLocation.listFiles())
{
if (f.getName().endsWith(".jar") && f.isFile())
{
urls.add(f.toURI().toURL());
}
else if (f.isDirectory() && f.getName().equals("lib"))
{
for (File f2 : tldBundleLocation.listFiles())
{
if (f2.getName().endsWith(".jar") && f2.isFile())
{
urls.add(f2.toURI().toURL());
}
}
}
}
}
else if (tldBundleLocation != null)
{
urls.add(tldBundleLocation.toURI().toURL());
}
}
return urls.toArray(new URL[urls.size()]);
}
/**
* Jasper resolves the dtd when it parses a taglib descriptor.
* It uses this code to do that: ParserUtils.getClass().getResourceAsStream(resourcePath); where
* resourcePath is for example: /javax/servlet/jsp/resources/web-jsptaglibrary_1_2.dtd Unfortunately,
* the dtd file is not in the exact same classloader as
* ParserUtils class and the dtds are packaged in 2 separate bundles.
* OSGi does not look in the dependencies' classloader when a resource is searched.
* Jasper resolves the dtd when it parses a taglib descriptor. It uses this
* code to do that:
* ParserUtils.getClass().getResourceAsStream(resourcePath); where
* resourcePath is for example:
* /javax/servlet/jsp/resources/web-jsptaglibrary_1_2.dtd Unfortunately, the
* dtd file is not in the exact same classloader as ParserUtils class and
* the dtds are packaged in 2 separate bundles. OSGi does not look in the
* dependencies' classloader when a resource is searched.
* <p>
* The workaround consists of setting the entity resolver. That is a patch
* added to the version of glassfish-jasper-jetty. IT is also present in the latest
* version of glassfish jasper. Could not use introspection to set new value
* on a static friendly field :(
* The workaround consists of setting the entity resolver. That is a patch
* added to the version of glassfish-jasper-jetty. IT is also present in the
* latest version of glassfish jasper. Could not use introspection to set
* new value on a static friendly field :(
* </p>
*/
void fixupDtdResolution()
void fixupDtdResolution()
{
try
{
@ -199,29 +208,23 @@ public class WebappRegistrationCustomizerImpl implements WebappRegistrationCusto
}
/**
* Instead of using the ParserUtil's classloader, we use a class that is indeed next to the resource for sure.
* Instead of using the ParserUtil's classloader, we use a class that is
* indeed next to the resource for sure.
*/
static class MyFixedupEntityResolver implements EntityResolver
{
/**
* Same values than in ParserUtils...
*/
static final String[] CACHED_DTD_PUBLIC_IDS =
{ Constants.TAGLIB_DTD_PUBLIC_ID_11, Constants.TAGLIB_DTD_PUBLIC_ID_12,
Constants.WEBAPP_DTD_PUBLIC_ID_22, Constants.WEBAPP_DTD_PUBLIC_ID_23, };
static final String[] CACHED_DTD_PUBLIC_IDS = { Constants.TAGLIB_DTD_PUBLIC_ID_11, Constants.TAGLIB_DTD_PUBLIC_ID_12,
Constants.WEBAPP_DTD_PUBLIC_ID_22, Constants.WEBAPP_DTD_PUBLIC_ID_23, };
static final String[] CACHED_DTD_RESOURCE_PATHS =
{ Constants.TAGLIB_DTD_RESOURCE_PATH_11,
Constants.TAGLIB_DTD_RESOURCE_PATH_12,
Constants.WEBAPP_DTD_RESOURCE_PATH_22,
Constants.WEBAPP_DTD_RESOURCE_PATH_23, };
static final String[] CACHED_DTD_RESOURCE_PATHS = { Constants.TAGLIB_DTD_RESOURCE_PATH_11, Constants.TAGLIB_DTD_RESOURCE_PATH_12,
Constants.WEBAPP_DTD_RESOURCE_PATH_22, Constants.WEBAPP_DTD_RESOURCE_PATH_23, };
static final String[] CACHED_SCHEMA_RESOURCE_PATHS = { Constants.TAGLIB_SCHEMA_RESOURCE_PATH_20, Constants.TAGLIB_SCHEMA_RESOURCE_PATH_21,
Constants.WEBAPP_SCHEMA_RESOURCE_PATH_24, Constants.WEBAPP_SCHEMA_RESOURCE_PATH_25, };
static final String[] CACHED_SCHEMA_RESOURCE_PATHS = {
Constants.TAGLIB_SCHEMA_RESOURCE_PATH_20,
Constants.TAGLIB_SCHEMA_RESOURCE_PATH_21,
Constants.WEBAPP_SCHEMA_RESOURCE_PATH_24,
Constants.WEBAPP_SCHEMA_RESOURCE_PATH_25,
};
public InputSource resolveEntity(String publicId, String systemId) throws SAXException
{
for (int i = 0; i < CACHED_DTD_PUBLIC_IDS.length; i++)
@ -242,10 +245,7 @@ public class WebappRegistrationCustomizerImpl implements WebappRegistrationCusto
input = this.getClass().getResourceAsStream(resourcePath);
}
}
if (input == null)
{
throw new SAXException(Localizer.getMessage("jsp.error.internal.filenotfound",resourcePath));
}
if (input == null) { throw new SAXException(Localizer.getMessage("jsp.error.internal.filenotfound", resourcePath)); }
InputSource isrc = new InputSource(input);
return isrc;
}
@ -254,5 +254,5 @@ public class WebappRegistrationCustomizerImpl implements WebappRegistrationCusto
return null;
}
}
}

View File

@ -19,15 +19,14 @@ import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
/**
* Pseudo fragment activator.
* Called by the main org.eclipse.jetty.osgi.boot bundle.
* Please note: this is not a real BundleActivator. Simply something called back by
* the host bundle.
* Pseudo fragment activator. Called by the main org.eclipse.jetty.osgi.boot
* bundle. Please note: this is not a real BundleActivator. Simply something
* called back by the host bundle.
* <p>
* It must be placed in the org.eclipse.jetty.osgi.boot.jsp package:
* this is because org.eclipse.jetty.osgi.boot.jsp is the sympbolic-name
* of this fragment. From that name, the PackageadminTracker will call
* this class. IN a different package it won't be called.
* It must be placed in the org.eclipse.jetty.osgi.boot.jsp package: this is
* because org.eclipse.jetty.osgi.boot.jsp is the sympbolic-name of this
* fragment. From that name, the PackageadminTracker will call this class. IN a
* different package it won't be called.
* </p>
*/
public class FragmentActivator implements BundleActivator
@ -35,7 +34,8 @@ public class FragmentActivator implements BundleActivator
/**
*
*/
public void start(BundleContext context) throws Exception {
public void start(BundleContext context) throws Exception
{
System.setProperty("org.apache.jasper.compiler.disablejsr199", Boolean.TRUE.toString());
WebBundleDeployerHelper.JSP_REGISTRATION_HELPERS.add(new WebappRegistrationCustomizerImpl());
WebBundleDeployerHelper.JSP_REGISTRATION_HELPERS.add(new PluggableWebAppRegistrationCustomizerImpl());
@ -44,7 +44,8 @@ public class FragmentActivator implements BundleActivator
/**
*
*/
public void stop(BundleContext context) throws Exception {
public void stop(BundleContext context) throws Exception
{
}
}

View File

@ -35,123 +35,120 @@ import org.osgi.util.tracker.ServiceTracker;
* Replacement for {@link TagLibConfiguration} for the OSGi integration.
* </p>
* <p>
* In the case of a WAB, tlds can be located in OSGi bundles that are dependencies
* of the WAB.
* It is expected that each WAB lists the symbolic-names of the bundles that contain
* tld files. The list is defined as the value of the header 'Require-TldBundle'
* In the case of a WAB, tlds can be located in OSGi bundles that are
* dependencies of the WAB. It is expected that each WAB lists the
* symbolic-names of the bundles that contain tld files. The list is defined as
* the value of the header 'Require-TldBundle'
* </p>
* <p>
* Discussions about this are logged in https://bugs.eclipse.org/bugs/show_bug.cgi?id=306971
* Discussions about this are logged in
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=306971
* </p>
*/
public class TagLibOSGiConfiguration extends TagLibConfiguration
{
private static final Logger LOG = Log.getLogger(TagLibOSGiConfiguration.class);
private ServiceTracker packageAdminServiceTracker = null;
/**
* Override the preConfigure; locates the bundles that contain
* tld files according to the value of the manifest header Require-TldBundle.
* <p>
* Set or add to the property TldProcessor.TLDResources the list of located jars
* so that the super class will scan those.
* </p>
*/
private ServiceTracker packageAdminServiceTracker = null;
/**
* Override the preConfigure; locates the bundles that contain tld files
* according to the value of the manifest header Require-TldBundle.
* <p>
* Set or add to the property TldProcessor.TLDResources the list of located
* jars so that the super class will scan those.
* </p>
*/
public void preConfigure(WebAppContext context) throws Exception
{
String requireTldBundle = (String)context.getAttribute(OSGiWebappConstants.REQUIRE_TLD_BUNDLE);
if (requireTldBundle != null)
{
Collection<Resource> resources = getRequireTldBundleAsJettyResources(context, requireTldBundle);
if (resources != null && !resources.isEmpty())
{
Collection<Resource> previouslySet = (Collection<Resource>)
context.getAttribute(TagLibConfiguration.TLD_RESOURCES);
if (previouslySet != null)
{
resources.addAll(previouslySet);
}
context.setAttribute(TagLibConfiguration.TLD_RESOURCES, resources);
}
}
super.preConfigure(context);
String requireTldBundle = (String) context.getAttribute(OSGiWebappConstants.REQUIRE_TLD_BUNDLE);
if (requireTldBundle != null)
{
Collection<Resource> resources = getRequireTldBundleAsJettyResources(context, requireTldBundle);
if (resources != null && !resources.isEmpty())
{
Collection<Resource> previouslySet = (Collection<Resource>) context.getAttribute(TagLibConfiguration.TLD_RESOURCES);
if (previouslySet != null)
{
resources.addAll(previouslySet);
}
context.setAttribute(TagLibConfiguration.TLD_RESOURCES, resources);
}
}
super.preConfigure(context);
}
/**
* @param requireTldBundle The comma separated list of bundles' symbolic names
* that contain tld for this osgi webapp.
* @param requireTldBundle The comma separated list of bundles' symbolic
* names that contain tld for this osgi webapp.
* @return The collection of jars or folders that match those bundles.
*/
private Collection<Resource> getRequireTldBundleAsJettyResources(
WebAppContext context, String requireTldBundle)
private Collection<Resource> getRequireTldBundleAsJettyResources(WebAppContext context, String requireTldBundle)
{
Bundle bundle = (Bundle)
context.getAttribute(OSGiWebappConstants.JETTY_OSGI_BUNDLE);
PackageAdmin packAdmin = getBundleAdmin();
String[] symbNames = requireTldBundle.split(", ");
Collection<Resource> tlds = new LinkedHashSet<Resource>();
for (String symbName : symbNames)
{
Bundle[] bs = packAdmin.getBundles(symbName, null);
if (bs == null || bs.length == 0)
{
throw new IllegalArgumentException("Unable to locate the bundle '"
+ symbName + "' specified in the "
+ OSGiWebappConstants.REQUIRE_TLD_BUNDLE
+ " of the manifest of "
+ bundle.getSymbolicName());
}
//take the first one as it is the most recent version?
Enumeration<URL> en = bs[0].findEntries("META-INF", "*.tld", false);
boolean atLeastOneTldFound = false;
while (en.hasMoreElements())
{
atLeastOneTldFound = true;
URL oriUrl = en.nextElement();
URL url = DefaultFileLocatorHelper.getLocalURL(oriUrl);
Resource tldResource;
try
{
tldResource = Resource.newResource(url);
}
catch (IOException e)
{
throw new IllegalArgumentException("Unable to locate the "
+ "tld resource in '"
+ url.toString()
+ "' in the bundle '" + bs[0].getSymbolicName()
+ "' while registering the "
+ OSGiWebappConstants.REQUIRE_TLD_BUNDLE
+ " of the manifest of "
+ bundle.getSymbolicName(), e);
}
tlds.add(tldResource);
}
if (!atLeastOneTldFound)
{
LOG.warn("No '/META-INF/*.tld' resources were found "
+ " in the bundle '" + bs[0].getSymbolicName()
+ "' while registering the "
+ OSGiWebappConstants.REQUIRE_TLD_BUNDLE
+ " of the manifest of "
+ bundle.getSymbolicName());
}
}
return tlds;
Bundle bundle = (Bundle) context.getAttribute(OSGiWebappConstants.JETTY_OSGI_BUNDLE);
PackageAdmin packAdmin = getBundleAdmin();
String[] symbNames = requireTldBundle.split(", ");
Collection<Resource> tlds = new LinkedHashSet<Resource>();
for (String symbName : symbNames)
{
Bundle[] bs = packAdmin.getBundles(symbName, null);
if (bs == null || bs.length == 0)
{
throw new IllegalArgumentException("Unable to locate the bundle '" + symbName
+ "' specified in the "
+ OSGiWebappConstants.REQUIRE_TLD_BUNDLE
+ " of the manifest of "
+ bundle.getSymbolicName());
}
// take the first one as it is the most recent version?
Enumeration<URL> en = bs[0].findEntries("META-INF", "*.tld", false);
boolean atLeastOneTldFound = false;
while (en.hasMoreElements())
{
atLeastOneTldFound = true;
URL oriUrl = en.nextElement();
URL url = DefaultFileLocatorHelper.getLocalURL(oriUrl);
Resource tldResource;
try
{
tldResource = Resource.newResource(url);
}
catch (IOException e)
{
throw new IllegalArgumentException("Unable to locate the " + "tld resource in '"
+ url.toString()
+ "' in the bundle '"
+ bs[0].getSymbolicName()
+ "' while registering the "
+ OSGiWebappConstants.REQUIRE_TLD_BUNDLE
+ " of the manifest of "
+ bundle.getSymbolicName(), e);
}
tlds.add(tldResource);
}
if (!atLeastOneTldFound)
{
LOG.warn("No '/META-INF/*.tld' resources were found " + " in the bundle '"
+ bs[0].getSymbolicName()
+ "' while registering the "
+ OSGiWebappConstants.REQUIRE_TLD_BUNDLE
+ " of the manifest of "
+ bundle.getSymbolicName());
}
}
return tlds;
}
private PackageAdmin getBundleAdmin()
{
if (packageAdminServiceTracker == null)
{
Bundle bootBundle = ((BundleReference)OSGiWebappConstants.class.getClassLoader()).getBundle();
packageAdminServiceTracker = new ServiceTracker(bootBundle.getBundleContext(),
PackageAdmin.class.getName(), null);
packageAdminServiceTracker.open();
}
return (PackageAdmin) packageAdminServiceTracker.getService();
}
private PackageAdmin getBundleAdmin()
{
if (packageAdminServiceTracker == null)
{
Bundle bootBundle = ((BundleReference) OSGiWebappConstants.class.getClassLoader()).getBundle();
packageAdminServiceTracker = new ServiceTracker(bootBundle.getBundleContext(), PackageAdmin.class.getName(), null);
packageAdminServiceTracker.open();
}
return (PackageAdmin) packageAdminServiceTracker.getService();
}
}

View File

@ -24,12 +24,13 @@ import java.util.jar.Manifest;
import org.eclipse.jetty.osgi.boot.warurl.internal.WarBundleManifestGenerator;
import org.eclipse.jetty.osgi.boot.warurl.internal.WarURLConnection;
import org.eclipse.jetty.util.URIUtil;
import org.eclipse.jetty.util.resource.Resource;
import org.osgi.service.url.AbstractURLStreamHandlerService;
/**
* RFC-66: support for the "war" protocol
* We are reusing the parsing of the query string from jetty.
* If we wanted to not depend on jetty at all we could duplicate that method here
* RFC-66: support for the "war" protocol We are reusing the parsing of the
* query string from jetty. If we wanted to not depend on jetty at all we could
* duplicate that method here
*/
public class WarUrlStreamHandler extends AbstractURLStreamHandlerService
{
@ -40,11 +41,11 @@ public class WarUrlStreamHandler extends AbstractURLStreamHandlerService
@Override
public URLConnection openConnection(URL url) throws IOException
{
//remove the war scheme.
// remove the war scheme.
URL actual = new URL(url.toString().substring("war:".length()));
//let's do some basic tests: see if this is a folder or not.
//if it is a folder. we will try to support it.
// let's do some basic tests: see if this is a folder or not.
// if it is a folder. we will try to support it.
if (actual.getProtocol().equals("file"))
{
File file = new File(URIUtil.encodePath(actual.getPath()));
@ -52,34 +53,48 @@ public class WarUrlStreamHandler extends AbstractURLStreamHandlerService
{
if (file.isDirectory())
{
//TODO (not mandatory for rfc66 though)
// TODO (not mandatory for rfc66 though)
}
}
}
// if (actual.toString().startsWith("file:/") && ! actual.to)
// if (actual.toString().startsWith("file:/") && ! actual.to)
URLConnection ori = (URLConnection) actual.openConnection();
ori.setDefaultUseCaches(Resource.getDefaultUseCaches());
JarURLConnection jarOri = null;
try {
try
{
if (ori instanceof JarURLConnection)
{
jarOri = (JarURLConnection)ori;
jarOri = (JarURLConnection) ori;
}
else
{
jarOri = (JarURLConnection) new URL("jar:"+actual.toString() + "!/").openConnection();
jarOri = (JarURLConnection) new URL("jar:" + actual.toString() + "!/").openConnection();
jarOri.setDefaultUseCaches(Resource.getDefaultUseCaches());
}
Manifest mf = WarBundleManifestGenerator.createBundleManifest(
jarOri.getManifest(), url, jarOri.getJarFile());
try { jarOri.getJarFile().close(); jarOri = null; } catch (Throwable t) {}
return new WarURLConnection(actual,mf);
Manifest mf = WarBundleManifestGenerator.createBundleManifest(jarOri.getManifest(), url, jarOri.getJarFile());
try
{
jarOri.getJarFile().close();
jarOri = null;
}
catch (Throwable t)
{
}
return new WarURLConnection(actual, mf);
}
finally
{
if (jarOri != null) try { jarOri.getJarFile().close(); } catch (Throwable t) {}
if (jarOri != null) try
{
jarOri.getJarFile().close();
}
catch (Throwable t)
{
}
}
}
}

View File

@ -31,6 +31,7 @@ import java.util.jar.Manifest;
import java.util.zip.ZipEntry;
import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.resource.Resource;
/**
* Facade for a URLConnection that will read a jar and substitute its
@ -106,6 +107,7 @@ public class WarURLConnection extends URLConnection
{
super(url);
_conn = url.openConnection();
_conn.setDefaultUseCaches(Resource.getDefaultUseCaches());
_mf = mf;
}
@Override

View File

@ -66,15 +66,19 @@ public class JettyBootstrapActivator implements BundleActivator
}
private ServiceRegistration _registeredServer;
private Server _server;
private JettyContextHandlerServiceTracker _jettyContextHandlerTracker;
private PackageAdminServiceTracker _packageAdminServiceTracker;
private BundleTracker _webBundleTracker;
private BundleContext _bundleContext;
// private ServiceRegistration _jettyServerFactoryService;
// private ServiceRegistration _jettyServerFactoryService;
private JettyServerServiceTracker _jettyServerServiceTracker;
/**
* Setup a new jetty Server, registers it as a service. Setup the Service
@ -93,30 +97,31 @@ public class JettyBootstrapActivator implements BundleActivator
// should activate.
_packageAdminServiceTracker = new PackageAdminServiceTracker(context);
_jettyServerServiceTracker = new JettyServerServiceTracker();
context.addServiceListener(_jettyServerServiceTracker,"(objectclass=" + Server.class.getName() + ")");
_jettyServerServiceTracker = new JettyServerServiceTracker();
context.addServiceListener(_jettyServerServiceTracker, "(objectclass=" + Server.class.getName() + ")");
// Register the Jetty Server Factory as a ManagedServiceFactory:
// Properties jettyServerMgdFactoryServiceProps = new Properties();
// jettyServerMgdFactoryServiceProps.put("pid",
// OSGiWebappConstants.MANAGED_JETTY_SERVER_FACTORY_PID);
// _jettyServerFactoryService = context.registerService(
// ManagedServiceFactory.class.getName(), new
// JettyServersManagedFactory(),
// jettyServerMgdFactoryServiceProps);
//Register the Jetty Server Factory as a ManagedServiceFactory:
// Properties jettyServerMgdFactoryServiceProps = new Properties();
// jettyServerMgdFactoryServiceProps.put("pid", OSGiWebappConstants.MANAGED_JETTY_SERVER_FACTORY_PID);
// _jettyServerFactoryService = context.registerService(
// ManagedServiceFactory.class.getName(), new JettyServersManagedFactory(),
// jettyServerMgdFactoryServiceProps);
_jettyContextHandlerTracker = new JettyContextHandlerServiceTracker(_jettyServerServiceTracker);
// the tracker in charge of the actual deployment
// and that will configure and start the jetty server.
context.addServiceListener(_jettyContextHandlerTracker,"(objectclass=" + ContextHandler.class.getName() + ")");
context.addServiceListener(_jettyContextHandlerTracker, "(objectclass=" + ContextHandler.class.getName() + ")");
//see if we shoult start a default jetty instance right now.
// see if we shoult start a default jetty instance right now.
DefaultJettyAtJettyHomeHelper.startJettyAtJettyHome(context);
// now ready to support the Extender pattern:
_webBundleTracker = new BundleTracker(context,
Bundle.ACTIVE | Bundle.STOPPING, new WebBundleTrackerCustomizer());
// now ready to support the Extender pattern:
_webBundleTracker = new BundleTracker(context, Bundle.ACTIVE | Bundle.STOPPING, new WebBundleTrackerCustomizer());
_webBundleTracker.open();
}
/*
@ -129,12 +134,12 @@ public class JettyBootstrapActivator implements BundleActivator
{
try
{
if (_webBundleTracker != null)
{
_webBundleTracker.close();
_webBundleTracker = null;
}
if (_webBundleTracker != null)
{
_webBundleTracker.close();
_webBundleTracker = null;
}
if (_jettyContextHandlerTracker != null)
{
_jettyContextHandlerTracker.stop();
@ -143,7 +148,7 @@ public class JettyBootstrapActivator implements BundleActivator
}
if (_jettyServerServiceTracker != null)
{
_jettyServerServiceTracker.stop();
_jettyServerServiceTracker.stop();
context.removeServiceListener(_jettyServerServiceTracker);
_jettyServerServiceTracker = null;
}
@ -165,31 +170,31 @@ public class JettyBootstrapActivator implements BundleActivator
}
finally
{
_registeredServer = null;
_registeredServer = null;
}
}
// if (_jettyServerFactoryService != null)
// {
// try
// {
// _jettyServerFactoryService.unregister();
// }
// catch (IllegalArgumentException ill)
// {
// // already unregistered.
// }
// finally
// {
// _jettyServerFactoryService = null;
// }
// }
// if (_jettyServerFactoryService != null)
// {
// try
// {
// _jettyServerFactoryService.unregister();
// }
// catch (IllegalArgumentException ill)
// {
// // already unregistered.
// }
// finally
// {
// _jettyServerFactoryService = null;
// }
// }
}
finally
{
if (_server != null)
{
_server.stop();
_server.stop();
}
INSTANCE = null;
}
@ -200,27 +205,25 @@ public class JettyBootstrapActivator implements BundleActivator
* registers it as an OSGi service. The tracker
* {@link JettyContextHandlerServiceTracker} will do the actual deployment.
*
* @param contributor
* The bundle
* @param webappFolderPath
* The path to the root of the webapp. Must be a path relative to
* bundle; either an absolute path.
* @param contextPath
* The context path. Must start with "/"
* @param contributor The bundle
* @param webappFolderPath The path to the root of the webapp. Must be a
* path relative to bundle; either an absolute path.
* @param contextPath The context path. Must start with "/"
* @throws Exception
*/
public static void registerWebapplication(Bundle contributor, String webappFolderPath, String contextPath) throws Exception
{
checkBundleActivated();
WebAppContext contextHandler = new WebAppContext();
checkBundleActivated();
WebAppContext contextHandler = new WebAppContext();
Dictionary dic = new Hashtable();
dic.put(OSGiWebappConstants.SERVICE_PROP_WAR,webappFolderPath);
dic.put(OSGiWebappConstants.SERVICE_PROP_CONTEXT_PATH,contextPath);
String requireTldBundle = (String)contributor.getHeaders().get(OSGiWebappConstants.REQUIRE_TLD_BUNDLE);
if (requireTldBundle != null) {
dic.put(OSGiWebappConstants.SERVICE_PROP_REQUIRE_TLD_BUNDLE, requireTldBundle);
dic.put(OSGiWebappConstants.SERVICE_PROP_WAR, webappFolderPath);
dic.put(OSGiWebappConstants.SERVICE_PROP_CONTEXT_PATH, contextPath);
String requireTldBundle = (String) contributor.getHeaders().get(OSGiWebappConstants.REQUIRE_TLD_BUNDLE);
if (requireTldBundle != null)
{
dic.put(OSGiWebappConstants.SERVICE_PROP_REQUIRE_TLD_BUNDLE, requireTldBundle);
}
contributor.getBundleContext().registerService(ContextHandler.class.getName(),contextHandler,dic);
contributor.getBundleContext().registerService(ContextHandler.class.getName(), contextHandler, dic);
}
/**
@ -228,24 +231,20 @@ public class JettyBootstrapActivator implements BundleActivator
* registers it as an OSGi service. The tracker
* {@link JettyContextHandlerServiceTracker} will do the actual deployment.
*
* @param contributor
* The bundle
* @param webappFolderPath
* The path to the root of the webapp. Must be a path relative to
* bundle; either an absolute path.
* @param contextPath
* The context path. Must start with "/"
* @param dic
* TODO: parameter description
* @param contributor The bundle
* @param webappFolderPath The path to the root of the webapp. Must be a
* path relative to bundle; either an absolute path.
* @param contextPath The context path. Must start with "/"
* @param dic TODO: parameter description
* @throws Exception
*/
public static void registerWebapplication(Bundle contributor, String webappFolderPath, String contextPath, Dictionary<String, String> dic) throws Exception
{
checkBundleActivated();
checkBundleActivated();
WebAppContext contextHandler = new WebAppContext();
dic.put(OSGiWebappConstants.SERVICE_PROP_WAR,webappFolderPath);
dic.put(OSGiWebappConstants.SERVICE_PROP_CONTEXT_PATH,contextPath);
contributor.getBundleContext().registerService(ContextHandler.class.getName(),contextHandler,dic);
dic.put(OSGiWebappConstants.SERVICE_PROP_WAR, webappFolderPath);
dic.put(OSGiWebappConstants.SERVICE_PROP_CONTEXT_PATH, contextPath);
contributor.getBundleContext().registerService(ContextHandler.class.getName(), contextHandler, dic);
}
/**
@ -253,16 +252,14 @@ public class JettyBootstrapActivator implements BundleActivator
* registers it as an OSGi service. The tracker
* {@link JettyContextHandlerServiceTracker} will do the actual deployment.
*
* @param contributor
* The bundle that registers a new context
* @param contextFilePath
* The path to the file inside the bundle that defines the
* context.
* @param contributor The bundle that registers a new context
* @param contextFilePath The path to the file inside the bundle that
* defines the context.
* @throws Exception
*/
public static void registerContext(Bundle contributor, String contextFilePath) throws Exception
{
registerContext(contributor,contextFilePath,new Hashtable<String, String>());
registerContext(contributor, contextFilePath, new Hashtable<String, String>());
}
/**
@ -270,33 +267,30 @@ public class JettyBootstrapActivator implements BundleActivator
* registers it as an OSGi service. The tracker
* {@link JettyContextHandlerServiceTracker} will do the actual deployment.
*
* @param contributor
* The bundle that registers a new context
* @param contextFilePath
* The path to the file inside the bundle that defines the
* context.
* @param dic
* TODO: parameter description
* @param contributor The bundle that registers a new context
* @param contextFilePath The path to the file inside the bundle that
* defines the context.
* @param dic TODO: parameter description
* @throws Exception
*/
public static void registerContext(Bundle contributor, String contextFilePath, Dictionary<String, String> dic) throws Exception
{
checkBundleActivated();
checkBundleActivated();
ContextHandler contextHandler = new ContextHandler();
dic.put(OSGiWebappConstants.SERVICE_PROP_CONTEXT_FILE_PATH,contextFilePath);
dic.put(IWebBundleDeployerHelper.INTERNAL_SERVICE_PROP_UNKNOWN_CONTEXT_HANDLER_TYPE,Boolean.TRUE.toString());
contributor.getBundleContext().registerService(ContextHandler.class.getName(),contextHandler,dic);
dic.put(OSGiWebappConstants.SERVICE_PROP_CONTEXT_FILE_PATH, contextFilePath);
dic.put(IWebBundleDeployerHelper.INTERNAL_SERVICE_PROP_UNKNOWN_CONTEXT_HANDLER_TYPE, Boolean.TRUE.toString());
contributor.getBundleContext().registerService(ContextHandler.class.getName(), contextHandler, dic);
}
public static void unregister(String contextPath)
{
// todo
}
/**
* Since org.eclipse.jetty.osgi.boot does not have a lazy activation policy
* when one fo the static methods to register a webapp is called we should make sure that
* the bundle is started.
* when one fo the static methods to register a webapp is called we should
* make sure that the bundle is started.
*/
private static void checkBundleActivated()
{
@ -313,7 +307,7 @@ public class JettyBootstrapActivator implements BundleActivator
}
}
}
/**
* @return The bundle context for this bundle.
*/
@ -322,6 +316,5 @@ public class JettyBootstrapActivator implements BundleActivator
checkBundleActivated();
return INSTANCE._bundleContext;
}
}

View File

@ -53,14 +53,15 @@ import org.osgi.framework.ServiceReference;
public class JettyContextHandlerServiceTracker implements ServiceListener
{
/** New style: ability to manage multiple jetty instances */
private final IManagedJettyServerRegistry _registry;
/** New style: ability to manage multiple jetty instances */
private final IManagedJettyServerRegistry _registry;
/** The context-handler to deactivate indexed by context handler */
private Map<ServiceReference, ContextHandler> _indexByServiceReference = new HashMap<ServiceReference, ContextHandler>();
/**
* The index is the bundle-symbolic-name/path/to/context/file when there is such thing
* The index is the bundle-symbolic-name/path/to/context/file when there is
* such thing
*/
private Map<String, ServiceReference> _indexByContextFile = new HashMap<String, ServiceReference>();
@ -72,7 +73,7 @@ public class JettyContextHandlerServiceTracker implements ServiceListener
*/
public JettyContextHandlerServiceTracker(IManagedJettyServerRegistry registry) throws Exception
{
_registry = registry;
_registry = registry;
}
public void stop() throws Exception
@ -85,19 +86,16 @@ public class JettyContextHandlerServiceTracker implements ServiceListener
// nothing to stop in the WebappRegistrationHelper
}
/**
* @param contextHome Parent folder where the context files can override the context files
* defined in the web bundles: equivalent to the contexts folder in a traditional
* jetty installation.
* when null, just do nothing.
* @param contextHome Parent folder where the context files can override the
* context files defined in the web bundles: equivalent to the
* contexts folder in a traditional jetty installation. when
* null, just do nothing.
*/
protected void setupContextHomeScanner(File contextHome) throws IOException
{
if (contextHome == null)
{
return;
}
if (contextHome == null) { return; }
final String osgiContextHomeFolderCanonicalPath = contextHome.getCanonicalPath();
_scanner = new Scanner();
_scanner.setRecursive(true);
@ -132,8 +130,7 @@ public class JettyContextHandlerServiceTracker implements ServiceListener
/**
* Receives notification that a service has had a lifecycle change.
*
* @param ev
* The <code>ServiceEvent</code> object.
* @param ev The <code>ServiceEvent</code> object.
*/
public void serviceChanged(ServiceEvent ev)
{
@ -148,7 +145,7 @@ public class JettyContextHandlerServiceTracker implements ServiceListener
{
try
{
getWebBundleDeployerHelp(sr).unregister(ctxtHandler);
getWebBundleDeployerHelp(sr).unregister(ctxtHandler);
}
catch (Exception e)
{
@ -170,30 +167,32 @@ public class JettyContextHandlerServiceTracker implements ServiceListener
{
Bundle contributor = sr.getBundle();
BundleContext context = FrameworkUtil.getBundle(JettyBootstrapActivator.class).getBundleContext();
ContextHandler contextHandler = (ContextHandler)context.getService(sr);
ContextHandler contextHandler = (ContextHandler) context.getService(sr);
if (contextHandler.getServer() != null)
{
// is configured elsewhere.
return;
}
String contextFilePath = (String)sr.getProperty(OSGiWebappConstants.SERVICE_PROP_CONTEXT_FILE_PATH);
String contextFilePath = (String) sr.getProperty(OSGiWebappConstants.SERVICE_PROP_CONTEXT_FILE_PATH);
if (contextHandler instanceof WebAppContext && contextFilePath == null)
//it could be a web-application that will in fact be configured via a context file.
//that case is identified by the fact that the contextFilePath is not null
//in that case we must use the register context methods.
// it could be a web-application that will in fact be configured
// via a context file.
// that case is identified by the fact that the contextFilePath
// is not null
// in that case we must use the register context methods.
{
WebAppContext webapp = (WebAppContext)contextHandler;
String contextPath = (String)sr.getProperty(OSGiWebappConstants.SERVICE_PROP_CONTEXT_PATH);
WebAppContext webapp = (WebAppContext) contextHandler;
String contextPath = (String) sr.getProperty(OSGiWebappConstants.SERVICE_PROP_CONTEXT_PATH);
if (contextPath == null)
{
contextPath = webapp.getContextPath();
}
String webXmlPath = (String)sr.getProperty(OSGiWebappConstants.SERVICE_PROP_WEB_XML_PATH);
String webXmlPath = (String) sr.getProperty(OSGiWebappConstants.SERVICE_PROP_WEB_XML_PATH);
if (webXmlPath == null)
{
webXmlPath = webapp.getDescriptor();
}
String defaultWebXmlPath = (String)sr.getProperty(OSGiWebappConstants.SERVICE_PROP_DEFAULT_WEB_XML_PATH);
String defaultWebXmlPath = (String) sr.getProperty(OSGiWebappConstants.SERVICE_PROP_DEFAULT_WEB_XML_PATH);
if (defaultWebXmlPath == null)
{
String jettyHome = System.getProperty(DefaultJettyAtJettyHomeHelper.SYS_PROP_JETTY_HOME);
@ -202,7 +201,7 @@ public class JettyContextHandlerServiceTracker implements ServiceListener
File etc = new File(jettyHome, "etc");
if (etc.exists() && etc.isDirectory())
{
File webDefault = new File (etc, "webdefault.xml");
File webDefault = new File(etc, "webdefault.xml");
if (webDefault.exists())
defaultWebXmlPath = webDefault.getAbsolutePath();
else
@ -212,27 +211,28 @@ public class JettyContextHandlerServiceTracker implements ServiceListener
defaultWebXmlPath = webapp.getDefaultsDescriptor();
}
}
String war = (String)sr.getProperty("war");
String war = (String) sr.getProperty("war");
try
{
IWebBundleDeployerHelper deployerHelper = getWebBundleDeployerHelp(sr);
if (deployerHelper == null)
{
}
else
{
WebAppContext handler = deployerHelper
.registerWebapplication(contributor,war,contextPath,
(String)sr.getProperty(OSGiWebappConstants.SERVICE_PROP_EXTRA_CLASSPATH),
(String)sr.getProperty(OSGiWebappConstants.SERVICE_PROP_BUNDLE_INSTALL_LOCATION_OVERRIDE),
(String)sr.getProperty(OSGiWebappConstants.SERVICE_PROP_REQUIRE_TLD_BUNDLE),
webXmlPath,defaultWebXmlPath,webapp);
IWebBundleDeployerHelper deployerHelper = getWebBundleDeployerHelp(sr);
if (deployerHelper == null)
{
}
else
{
WebAppContext handler = deployerHelper.registerWebapplication(contributor,
war,
contextPath,
(String) sr.getProperty(OSGiWebappConstants.SERVICE_PROP_EXTRA_CLASSPATH),
(String) sr.getProperty(OSGiWebappConstants.SERVICE_PROP_BUNDLE_INSTALL_LOCATION_OVERRIDE),
(String) sr.getProperty(OSGiWebappConstants.SERVICE_PROP_REQUIRE_TLD_BUNDLE),
webXmlPath, defaultWebXmlPath, webapp);
if (handler != null)
{
registerInIndex(handler,sr);
registerInIndex(handler, sr);
}
}
}
}
catch (Throwable e)
{
@ -242,34 +242,31 @@ public class JettyContextHandlerServiceTracker implements ServiceListener
else
{
// consider this just an empty skeleton:
if (contextFilePath == null)
{
throw new IllegalArgumentException("the property contextFilePath is required");
}
if (contextFilePath == null) { throw new IllegalArgumentException("the property contextFilePath is required"); }
try
{
IWebBundleDeployerHelper deployerHelper = getWebBundleDeployerHelp(sr);
if (deployerHelper == null)
{
//more warnings?
}
else
{
if (Boolean.TRUE.toString().equals(sr.getProperty(
IWebBundleDeployerHelper.INTERNAL_SERVICE_PROP_UNKNOWN_CONTEXT_HANDLER_TYPE)))
{
contextHandler = null;
}
ContextHandler handler = deployerHelper.registerContext(contributor,contextFilePath,
(String)sr.getProperty(OSGiWebappConstants.SERVICE_PROP_EXTRA_CLASSPATH),
(String)sr.getProperty(OSGiWebappConstants.SERVICE_PROP_BUNDLE_INSTALL_LOCATION_OVERRIDE),
(String)sr.getProperty(OSGiWebappConstants.SERVICE_PROP_REQUIRE_TLD_BUNDLE),
contextHandler);
if (handler != null)
{
registerInIndex(handler,sr);
}
}
IWebBundleDeployerHelper deployerHelper = getWebBundleDeployerHelp(sr);
if (deployerHelper == null)
{
// more warnings?
}
else
{
if (Boolean.TRUE.toString().equals(sr.getProperty(IWebBundleDeployerHelper.INTERNAL_SERVICE_PROP_UNKNOWN_CONTEXT_HANDLER_TYPE)))
{
contextHandler = null;
}
ContextHandler handler = deployerHelper.registerContext(contributor,
contextFilePath,
(String) sr.getProperty(OSGiWebappConstants.SERVICE_PROP_EXTRA_CLASSPATH),
(String) sr.getProperty(OSGiWebappConstants.SERVICE_PROP_BUNDLE_INSTALL_LOCATION_OVERRIDE),
(String) sr.getProperty(OSGiWebappConstants.SERVICE_PROP_REQUIRE_TLD_BUNDLE),
contextHandler);
if (handler != null)
{
registerInIndex(handler, sr);
}
}
}
catch (Throwable e)
{
@ -278,17 +275,17 @@ public class JettyContextHandlerServiceTracker implements ServiceListener
}
}
}
break;
break;
}
}
private void registerInIndex(ContextHandler handler, ServiceReference sr)
{
_indexByServiceReference.put(sr,handler);
_indexByServiceReference.put(sr, handler);
String key = getSymbolicNameAndContextFileKey(sr);
if (key != null)
{
_indexByContextFile.put(key,sr);
_indexByContextFile.put(key, sr);
}
}
@ -320,11 +317,8 @@ public class JettyContextHandlerServiceTracker implements ServiceListener
*/
private String getSymbolicNameAndContextFileKey(ServiceReference sr)
{
String contextFilePath = (String)sr.getProperty(OSGiWebappConstants.SERVICE_PROP_CONTEXT_FILE_PATH);
if (contextFilePath != null)
{
return sr.getBundle().getSymbolicName() + "/" + contextFilePath;
}
String contextFilePath = (String) sr.getProperty(OSGiWebappConstants.SERVICE_PROP_CONTEXT_FILE_PATH);
if (contextFilePath != null) { return sr.getBundle().getSymbolicName() + "/" + contextFilePath; }
return null;
}
@ -336,17 +330,14 @@ public class JettyContextHandlerServiceTracker implements ServiceListener
public void reloadJettyContextHandler(String canonicalNameOfFileChanged, String osgiContextHomeFolderCanonicalPath)
{
String key = getNormalizedRelativePath(canonicalNameOfFileChanged, osgiContextHomeFolderCanonicalPath);
if (key == null)
{
return;
}
if (key == null) { return; }
ServiceReference sr = _indexByContextFile.get(key);
if (sr == null)
{
// nothing to do?
return;
}
serviceChanged(new ServiceEvent(ServiceEvent.MODIFIED,sr));
serviceChanged(new ServiceEvent(ServiceEvent.MODIFIED, sr));
}
/**
@ -362,36 +353,31 @@ public class JettyContextHandlerServiceTracker implements ServiceListener
// warning?
return null;
}
return canFilename.substring(osgiContextHomeFolderCanonicalPath.length()).replace('\\','/');
return canFilename.substring(osgiContextHomeFolderCanonicalPath.length()).replace('\\', '/');
}
/**
* @return The server on which this webapp is meant to be deployed
*/
private ServerInstanceWrapper getServerInstanceWrapper(String managedServerName)
{
if (_registry == null)
{
return null;
}
if (managedServerName == null)
{
managedServerName = OSGiServerConstants.MANAGED_JETTY_SERVER_DEFAULT_NAME;
}
ServerInstanceWrapper wrapper = _registry.getServerInstanceWrapper(managedServerName);
//System.err.println("Returning " + managedServerName + " = " + wrapper);
return wrapper;
if (_registry == null) { return null; }
if (managedServerName == null)
{
managedServerName = OSGiServerConstants.MANAGED_JETTY_SERVER_DEFAULT_NAME;
}
ServerInstanceWrapper wrapper = _registry.getServerInstanceWrapper(managedServerName);
// System.err.println("Returning " + managedServerName + " = " +
// wrapper);
return wrapper;
}
private IWebBundleDeployerHelper getWebBundleDeployerHelp(ServiceReference sr)
{
if (_registry == null)
{
return null;
}
String managedServerName = (String)sr.getProperty(OSGiServerConstants.MANAGED_JETTY_SERVER_NAME);
ServerInstanceWrapper wrapper = getServerInstanceWrapper(managedServerName);
return wrapper != null ? wrapper.getWebBundleDeployerHelp() : null;
if (_registry == null) { return null; }
String managedServerName = (String) sr.getProperty(OSGiServerConstants.MANAGED_JETTY_SERVER_NAME);
ServerInstanceWrapper wrapper = getServerInstanceWrapper(managedServerName);
return wrapper != null ? wrapper.getWebBundleDeployerHelp() : null;
}
}

View File

@ -247,7 +247,7 @@ public class OSGiWebappClassLoader extends WebAppClassLoader implements BundleRe
catch (IOException e)
{
// nevermind. just trying our best
e.printStackTrace();
__logger.ignore(e);
}
return true;
}
@ -279,7 +279,7 @@ public class OSGiWebappClassLoader extends WebAppClassLoader implements BundleRe
catch (Throwable t)
{
// humf that will hurt if it does not work.
t.printStackTrace();
__logger.warn("Unable to set webappcontext", t);
}
}
}

View File

@ -78,13 +78,14 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper
private static Logger __logger = Log.getLogger(WebBundleDeployerHelper.class.getName());
private static boolean INITIALIZED = false;
/**
* By default set to: {@link DefaultBundleClassLoaderHelper}. It supports
* equinox and apache-felix fragment bundles that are specific to an OSGi
* implementation should set a different implementation.
*/
public static BundleClassLoaderHelper BUNDLE_CLASS_LOADER_HELPER = null;
/**
* By default set to: {@link DefaultBundleClassLoaderHelper}. It supports
* equinox and apache-felix fragment bundles that are specific to an OSGi
@ -97,8 +98,9 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper
* equinox and apache-felix fragment bundles that are specific to an OSGi
* implementation should set a different implementation.
* <p>
* Several of those objects can be added here: For example we could have an optional fragment that setups
* a specific implementation of JSF for the whole of jetty-osgi.
* Several of those objects can be added here: For example we could have an
* optional fragment that setups a specific implementation of JSF for the
* whole of jetty-osgi.
* </p>
*/
public static Collection<WebappRegistrationCustomizer> JSP_REGISTRATION_HELPERS = new ArrayList<WebappRegistrationCustomizer>();
@ -127,7 +129,7 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper
// setup the custom BundleClassLoaderHelper
try
{
BUNDLE_CLASS_LOADER_HELPER = (BundleClassLoaderHelper)Class.forName(BundleClassLoaderHelper.CLASS_NAME).newInstance();
BUNDLE_CLASS_LOADER_HELPER = (BundleClassLoaderHelper) Class.forName(BundleClassLoaderHelper.CLASS_NAME).newInstance();
}
catch (Throwable t)
{
@ -137,7 +139,7 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper
// setup the custom FileLocatorHelper
try
{
BUNDLE_FILE_LOCATOR_HELPER = (BundleFileLocatorHelper)Class.forName(BundleFileLocatorHelper.CLASS_NAME).newInstance();
BUNDLE_FILE_LOCATOR_HELPER = (BundleFileLocatorHelper) Class.forName(BundleFileLocatorHelper.CLASS_NAME).newInstance();
}
catch (Throwable t)
{
@ -150,34 +152,28 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper
/**
* Deploy a new web application on the jetty server.
*
* @param bundle
* The bundle
* @param webappFolderPath
* The path to the root of the webapp. Must be a path relative to
* bundle; either an absolute path.
* @param contextPath
* The context path. Must start with "/"
* @param bundle The bundle
* @param webappFolderPath The path to the root of the webapp. Must be a
* path relative to bundle; either an absolute path.
* @param contextPath The context path. Must start with "/"
* @param extraClasspath
* @param overrideBundleInstallLocation
* @param requireTldBundle The list of bundles's symbolic names that contain
* tld files that are required by this WAB.
* tld files that are required by this WAB.
* @param webXmlPath
* @param defaultWebXmlPath
* TODO: parameter description
* @param defaultWebXmlPath TODO: parameter description
* @return The contexthandler created and started
* @throws Exception
*/
public WebAppContext registerWebapplication(Bundle bundle,
String webappFolderPath, String contextPath, String extraClasspath,
String overrideBundleInstallLocation,
String requireTldBundle, String webXmlPath,
String defaultWebXmlPath, WebAppContext webAppContext) throws Exception
public WebAppContext registerWebapplication(Bundle bundle, String webappFolderPath, String contextPath, String extraClasspath,
String overrideBundleInstallLocation, String requireTldBundle, String webXmlPath, String defaultWebXmlPath,
WebAppContext webAppContext) throws Exception
{
File bundleInstall = overrideBundleInstallLocation == null?BUNDLE_FILE_LOCATOR_HELPER.getBundleInstallLocation(bundle):new File(
overrideBundleInstallLocation);
File bundleInstall = overrideBundleInstallLocation == null ? BUNDLE_FILE_LOCATOR_HELPER.getBundleInstallLocation(bundle) : new File(
overrideBundleInstallLocation);
File webapp = null;
URL baseWebappInstallURL = null;
if (webappFolderPath != null && webappFolderPath.length() != 0 && !webappFolderPath.equals("."))
{
if (webappFolderPath.startsWith("/") || webappFolderPath.startsWith("file:"))
@ -186,7 +182,7 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper
}
else if (bundleInstall != null && bundleInstall.isDirectory())
{
webapp = new File(bundleInstall,webappFolderPath);
webapp = new File(bundleInstall, webappFolderPath);
}
else if (bundleInstall != null)
{
@ -201,37 +197,43 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper
{
webapp = bundleInstall;
}
if (baseWebappInstallURL == null && (webapp == null || !webapp.exists()))
{
throw new IllegalArgumentException("Unable to locate " + webappFolderPath + " inside "
+ (bundleInstall != null?bundleInstall.getAbsolutePath():"unlocated bundle '" + bundle.getSymbolicName() + "'"));
}
if (baseWebappInstallURL == null && (webapp == null || !webapp.exists())) { throw new IllegalArgumentException(
"Unable to locate " + webappFolderPath
+ " inside "
+ (bundleInstall != null ? bundleInstall.getAbsolutePath() : "unlocated bundle '" + bundle.getSymbolicName()
+ "'")); }
if (baseWebappInstallURL == null && webapp != null)
{
baseWebappInstallURL = webapp.toURI().toURL();
}
return registerWebapplication(bundle,webappFolderPath,baseWebappInstallURL,contextPath,
extraClasspath,bundleInstall,requireTldBundle,webXmlPath,defaultWebXmlPath,webAppContext);
return registerWebapplication(bundle, webappFolderPath, baseWebappInstallURL, contextPath, extraClasspath, bundleInstall, requireTldBundle, webXmlPath,
defaultWebXmlPath, webAppContext);
}
/* (non-Javadoc)
* @see org.eclipse.jetty.osgi.boot.internal.webapp.IWebBundleDeployerHelper#registerWebapplication(org.osgi.framework.Bundle, java.lang.String, java.io.File, java.lang.String, java.lang.String, java.io.File, java.lang.String, java.lang.String)
/*
* (non-Javadoc)
*
* @see
* org.eclipse.jetty.osgi.boot.internal.webapp.IWebBundleDeployerHelper#
* registerWebapplication(org.osgi.framework.Bundle, java.lang.String,
* java.io.File, java.lang.String, java.lang.String, java.io.File,
* java.lang.String, java.lang.String)
*/
private WebAppContext registerWebapplication(Bundle contributor, String pathInBundleToWebApp,
URL baseWebappInstallURL, String contextPath, String extraClasspath, File bundleInstall,
String requireTldBundle, String webXmlPath, String defaultWebXmlPath, WebAppContext context)
throws Exception
private WebAppContext registerWebapplication(Bundle contributor, String pathInBundleToWebApp, URL baseWebappInstallURL, String contextPath,
String extraClasspath, File bundleInstall, String requireTldBundle, String webXmlPath,
String defaultWebXmlPath, WebAppContext context) throws Exception
{
ClassLoader contextCl = Thread.currentThread().getContextClassLoader();
String[] oldServerClasses = null;
try
{
// make sure we provide access to all the jetty bundles by going
// through this bundle.
OSGiWebappClassLoader composite = createWebappClassLoader(contributor);
// configure with access to all jetty classes and also all the classes
// configure with access to all jetty classes and also all the
// classes
// that the contributor gives access to.
Thread.currentThread().setContextClassLoader(composite);
@ -248,7 +250,7 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper
}
else
{
webXml = new File(bundleInstall,webXmlPath);
webXml = new File(bundleInstall, webXmlPath);
}
if (webXml.exists())
{
@ -258,7 +260,7 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper
if (defaultWebXmlPath == null || defaultWebXmlPath.length() == 0)
{
//use the one defined by the OSGiAppProvider.
// use the one defined by the OSGiAppProvider.
defaultWebXmlPath = _wrapper.getOSGiAppProvider().getDefaultsDescriptor();
}
if (defaultWebXmlPath != null && defaultWebXmlPath.length() != 0)
@ -270,20 +272,19 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper
}
else
{
defaultWebXml = new File(bundleInstall,defaultWebXmlPath);
defaultWebXml = new File(bundleInstall, defaultWebXmlPath);
}
if (defaultWebXml.exists())
{
context.setDefaultsDescriptor(defaultWebXml.getAbsolutePath());
}
}
//other parameters that might be defines on the OSGiAppProvider:
// other parameters that might be defines on the OSGiAppProvider:
context.setParentLoaderPriority(_wrapper.getOSGiAppProvider().isParentLoaderPriority());
configureWebappClassLoader(contributor,context,composite, requireTldBundle);
configureWebAppContext(context,contributor,requireTldBundle);
configureWebappClassLoader(contributor, context, composite, requireTldBundle);
configureWebAppContext(context, contributor, requireTldBundle);
// @see
// org.eclipse.jetty.webapp.JettyWebXmlConfiguration#configure(WebAppContext)
@ -292,36 +293,36 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper
// through the webapp classloader.
oldServerClasses = context.getServerClasses();
context.setServerClasses(null);
_wrapper.getOSGiAppProvider().addContext(contributor,pathInBundleToWebApp,context);
//support for patch resources. ideally this should be done inside a configurator.
List<Resource> patchResources =
(List<Resource>)context.getAttribute(WebInfConfiguration.RESOURCE_URLS+".patch");
_wrapper.getOSGiAppProvider().addContext(contributor, pathInBundleToWebApp, context);
// support for patch resources. ideally this should be done inside a
// configurator.
List<Resource> patchResources = (List<Resource>) context.getAttribute(WebInfConfiguration.RESOURCE_URLS + ".patch");
if (patchResources != null)
{
LinkedList<Resource> resourcesPath = new LinkedList<Resource>();
//place the patch resources at the beginning of the lookup path.
resourcesPath.addAll(patchResources);
//then place the ones from the host web bundle.
Resource hostResources = context.getBaseResource();
if (hostResources instanceof ResourceCollection)
{
for (Resource re : ((ResourceCollection)hostResources).getResources())
{
resourcesPath.add(re);
}
}
else
{
resourcesPath.add(hostResources);
}
ResourceCollection rc = new ResourceCollection(resourcesPath.toArray(
new Resource[resourcesPath.size()]));
context.setBaseResource(rc);
LinkedList<Resource> resourcesPath = new LinkedList<Resource>();
// place the patch resources at the beginning of the lookup
// path.
resourcesPath.addAll(patchResources);
// then place the ones from the host web bundle.
Resource hostResources = context.getBaseResource();
if (hostResources instanceof ResourceCollection)
{
for (Resource re : ((ResourceCollection) hostResources).getResources())
{
resourcesPath.add(re);
}
}
else
{
resourcesPath.add(hostResources);
}
ResourceCollection rc = new ResourceCollection(resourcesPath.toArray(new Resource[resourcesPath.size()]));
context.setBaseResource(rc);
}
return context;
}
finally
@ -335,38 +336,41 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper
}
/* (non-Javadoc)
* @see org.eclipse.jetty.osgi.boot.internal.webapp.IWebBundleDeployerHelper#unregister(org.eclipse.jetty.server.handler.ContextHandler)
/*
* (non-Javadoc)
*
* @see
* org.eclipse.jetty.osgi.boot.internal.webapp.IWebBundleDeployerHelper#
* unregister(org.eclipse.jetty.server.handler.ContextHandler)
*/
public void unregister(ContextHandler contextHandler) throws Exception
{
_wrapper.getOSGiAppProvider().removeContext(contextHandler);
}
/* (non-Javadoc)
* @see org.eclipse.jetty.osgi.boot.internal.webapp.IWebBundleDeployerHelper#registerContext(org.osgi.framework.Bundle, java.lang.String, java.lang.String, java.lang.String)
/*
* (non-Javadoc)
*
* @see
* org.eclipse.jetty.osgi.boot.internal.webapp.IWebBundleDeployerHelper#
* registerContext(org.osgi.framework.Bundle, java.lang.String,
* java.lang.String, java.lang.String)
*/
public ContextHandler registerContext(Bundle contributor, String contextFileRelativePath, String extraClasspath,
String overrideBundleInstallLocation, String requireTldBundle, ContextHandler handler)
throws Exception
public ContextHandler registerContext(Bundle contributor, String contextFileRelativePath, String extraClasspath, String overrideBundleInstallLocation,
String requireTldBundle, ContextHandler handler) throws Exception
{
File contextsHome = _wrapper.getOSGiAppProvider().getContextXmlDirAsFile();
if (contextsHome != null)
{
File prodContextFile = new File(contextsHome,contributor.getSymbolicName() + "/" + contextFileRelativePath);
if (prodContextFile.exists())
{
return registerContext(contributor,contextFileRelativePath,prodContextFile,extraClasspath,
overrideBundleInstallLocation,requireTldBundle,handler);
}
File prodContextFile = new File(contextsHome, contributor.getSymbolicName() + "/" + contextFileRelativePath);
if (prodContextFile.exists()) { return registerContext(contributor, contextFileRelativePath, prodContextFile, extraClasspath,
overrideBundleInstallLocation, requireTldBundle, handler); }
}
File rootFolder = overrideBundleInstallLocation != null
? Resource.newResource(overrideBundleInstallLocation).getFile()
: BUNDLE_FILE_LOCATOR_HELPER.getBundleInstallLocation(contributor);
File contextFile = rootFolder != null?new File(rootFolder,contextFileRelativePath):null;
File rootFolder = overrideBundleInstallLocation != null ? Resource.newResource(overrideBundleInstallLocation).getFile() : BUNDLE_FILE_LOCATOR_HELPER.getBundleInstallLocation(contributor);
File contextFile = rootFolder != null ? new File(rootFolder, contextFileRelativePath) : null;
if (contextFile != null && contextFile.exists())
{
return registerContext(contributor,contextFileRelativePath,contextFile,extraClasspath,overrideBundleInstallLocation,requireTldBundle,handler);
return registerContext(contributor, contextFileRelativePath, contextFile, extraClasspath, overrideBundleInstallLocation, requireTldBundle, handler);
}
else
{
@ -378,15 +382,19 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper
{
contextFileRelativePath = "/" + contextFileRelativePath;
}
URL contextURL = contributor.getEntry(contextFileRelativePath);
if (contextURL != null)
{
Resource r = Resource.newResource(contextURL);
return registerContext(contributor,contextFileRelativePath,r.getInputStream(),extraClasspath,overrideBundleInstallLocation,requireTldBundle,handler);
Resource r = Resource.newResource(contextURL);
return registerContext(contributor, contextFileRelativePath, r.getInputStream(), extraClasspath, overrideBundleInstallLocation,
requireTldBundle, handler);
}
throw new IllegalArgumentException("Could not find the context " + "file " + contextFileRelativePath + " for the bundle "
+ contributor.getSymbolicName() + (overrideBundleInstallLocation != null?" using the install location " + overrideBundleInstallLocation:""));
throw new IllegalArgumentException("Could not find the context " + "file "
+ contextFileRelativePath
+ " for the bundle "
+ contributor.getSymbolicName()
+ (overrideBundleInstallLocation != null ? " using the install location " + overrideBundleInstallLocation : ""));
}
}
@ -400,16 +408,14 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper
* @param classInBundle
* @throws Exception
*/
private ContextHandler registerContext(Bundle contributor, String pathInBundle, File contextFile,
String extraClasspath, String overrideBundleInstallLocation,
String requireTldBundle, ContextHandler handler) throws Exception
private ContextHandler registerContext(Bundle contributor, String pathInBundle, File contextFile, String extraClasspath,
String overrideBundleInstallLocation, String requireTldBundle, ContextHandler handler) throws Exception
{
InputStream contextFileInputStream = null;
try
{
contextFileInputStream = new BufferedInputStream(new FileInputStream(contextFile));
return registerContext(contributor, pathInBundle, contextFileInputStream,
extraClasspath,overrideBundleInstallLocation,requireTldBundle,handler);
return registerContext(contributor, pathInBundle, contextFileInputStream, extraClasspath, overrideBundleInstallLocation, requireTldBundle, handler);
}
finally
{
@ -424,11 +430,8 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper
* happen.
* @throws Exception
*/
private ContextHandler registerContext(Bundle contributor,
String pathInsideBundle, InputStream contextFileInputStream,
String extraClasspath, String overrideBundleInstallLocation,
String requireTldBundle, ContextHandler handler)
throws Exception
private ContextHandler registerContext(Bundle contributor, String pathInsideBundle, InputStream contextFileInputStream, String extraClasspath,
String overrideBundleInstallLocation, String requireTldBundle, ContextHandler handler) throws Exception
{
ClassLoader contextCl = Thread.currentThread().getContextClassLoader();
String[] oldServerClasses = null;
@ -442,24 +445,23 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper
// classes
// that the contributor gives access to.
Thread.currentThread().setContextClassLoader(composite);
ContextHandler context = createContextHandler(handler, contributor,
contextFileInputStream,extraClasspath,
overrideBundleInstallLocation,requireTldBundle);
if (context == null)
{
ContextHandler context = createContextHandler(handler, contributor, contextFileInputStream, extraClasspath, overrideBundleInstallLocation,
requireTldBundle);
if (context == null)
{
return null;// did not happen
}
// ok now register this webapp. we checked when we started jetty
// that there
// was at least one such handler for webapps.
//the actual registration must happen via the new Deployment API.
// _ctxtHandler.addHandler(context);
// the actual registration must happen via the new Deployment API.
// _ctxtHandler.addHandler(context);
configureWebappClassLoader(contributor,context,composite, requireTldBundle);
configureWebappClassLoader(contributor, context, composite, requireTldBundle);
if (context instanceof WebAppContext)
{
webAppContext = (WebAppContext)context;
webAppContext = (WebAppContext) context;
// @see
// org.eclipse.jetty.webapp.JettyWebXmlConfiguration#configure(WebAppContext)
oldServerClasses = webAppContext.getServerClasses();
@ -485,53 +487,58 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper
* @see {WebAppDeployer#scan} around the comment
* <code>// configure it</code>
*/
protected void configureWebAppContext(ContextHandler wah, Bundle contributor,
String requireTldBundle) throws IOException
protected void configureWebAppContext(ContextHandler wah, Bundle contributor, String requireTldBundle) throws IOException
{
// rfc66
wah.setAttribute(OSGiWebappConstants.RFC66_OSGI_BUNDLE_CONTEXT,contributor.getBundleContext());
wah.setAttribute(OSGiWebappConstants.RFC66_OSGI_BUNDLE_CONTEXT, contributor.getBundleContext());
//spring-dm-1.2.1 looks for the BundleContext as a different attribute.
//not a spec... but if we want to support
//org.springframework.osgi.web.context.support.OsgiBundleXmlWebApplicationContext
//then we need to do this to:
wah.setAttribute("org.springframework.osgi.web." + BundleContext.class.getName(),
contributor.getBundleContext());
//also pass the bundle directly. sometimes a bundle does not have a bundlecontext.
//it is still useful to have access to the Bundle from the servlet context.
// spring-dm-1.2.1 looks for the BundleContext as a different attribute.
// not a spec... but if we want to support
// org.springframework.osgi.web.context.support.OsgiBundleXmlWebApplicationContext
// then we need to do this to:
wah.setAttribute("org.springframework.osgi.web." + BundleContext.class.getName(), contributor.getBundleContext());
// also pass the bundle directly. sometimes a bundle does not have a
// bundlecontext.
// it is still useful to have access to the Bundle from the servlet
// context.
wah.setAttribute(OSGiWebappConstants.JETTY_OSGI_BUNDLE, contributor);
//pass the value of the require tld bundle so that the TagLibOSGiConfiguration
//can pick it up.
// pass the value of the require tld bundle so that the
// TagLibOSGiConfiguration
// can pick it up.
wah.setAttribute(OSGiWebappConstants.REQUIRE_TLD_BUNDLE, requireTldBundle);
Bundle[] fragments = PackageAdminServiceTracker.INSTANCE.getFragmentsAndRequiredBundles(contributor);
if (fragments != null && fragments.length != 0)
{
//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.
TreeMap<String,Resource> patchResourcesPath = new TreeMap<String,Resource>();
TreeMap<String,Resource> appendedResourcesPath = new TreeMap<String,Resource>();
for (Bundle frag : fragments) {
String fragFolder = (String)frag.getHeaders().get(OSGiWebappConstants.JETTY_WAR_FRAGMENT_FOLDER_PATH);
String patchFragFolder = (String)frag.getHeaders().get(OSGiWebappConstants.JETTY_WAR_PATCH_FRAGMENT_FOLDER_PATH);
// 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.
TreeMap<String, Resource> patchResourcesPath = new TreeMap<String, Resource>();
TreeMap<String, Resource> appendedResourcesPath = new TreeMap<String, Resource>();
for (Bundle frag : fragments)
{
String fragFolder = (String) frag.getHeaders().get(OSGiWebappConstants.JETTY_WAR_FRAGMENT_FOLDER_PATH);
String patchFragFolder = (String) frag.getHeaders().get(OSGiWebappConstants.JETTY_WAR_PATCH_FRAGMENT_FOLDER_PATH);
if (fragFolder != null)
{
URL fragUrl = frag.getEntry(fragFolder);
if (fragUrl == null)
{
throw new IllegalArgumentException("Unable to locate " + fragFolder + " inside "
+ " the fragment '" + frag.getSymbolicName() + "'");
}
if (fragUrl == null) { throw new IllegalArgumentException("Unable to locate " + fragFolder
+ " inside "
+ " the fragment '"
+ frag.getSymbolicName()
+ "'"); }
fragUrl = DefaultFileLocatorHelper.getLocalURL(fragUrl);
String key = fragFolder.startsWith("/") ? fragFolder.substring(1) : fragFolder;
appendedResourcesPath.put(key + ";" + frag.getSymbolicName(), Resource.newResource(fragUrl));
@ -539,11 +546,11 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper
if (patchFragFolder != null)
{
URL patchFragUrl = frag.getEntry(patchFragFolder);
if (patchFragUrl == null)
{
throw new IllegalArgumentException("Unable to locate " + patchFragUrl + " inside "
+ " the fragment '" + frag.getSymbolicName() + "'");
}
if (patchFragUrl == null) { throw new IllegalArgumentException("Unable to locate " + patchFragUrl
+ " inside "
+ " the fragment '"
+ frag.getSymbolicName()
+ "'"); }
patchFragUrl = DefaultFileLocatorHelper.getLocalURL(patchFragUrl);
String key = patchFragFolder.startsWith("/") ? patchFragFolder.substring(1) : patchFragFolder;
patchResourcesPath.put(key + ";" + frag.getSymbolicName(), Resource.newResource(patchFragUrl));
@ -551,92 +558,92 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper
}
if (!appendedResourcesPath.isEmpty())
{
wah.setAttribute(WebInfConfiguration.RESOURCE_URLS, new ArrayList<Resource>(appendedResourcesPath.values()));
wah.setAttribute(WebInfConfiguration.RESOURCE_URLS, new ArrayList<Resource>(appendedResourcesPath.values()));
}
if (!patchResourcesPath.isEmpty())
{
wah.setAttribute(WebInfConfiguration.RESOURCE_URLS + ".patch", new ArrayList<Resource>(patchResourcesPath.values()));
wah.setAttribute(WebInfConfiguration.RESOURCE_URLS + ".patch", new ArrayList<Resource>(patchResourcesPath.values()));
}
if (wah instanceof WebAppContext)
{
//This is the equivalent of what MetaInfConfiguration does. For OSGi bundles without the JarScanner
WebAppContext webappCtxt = (WebAppContext)wah;
//take care of the web-fragments, meta-inf resources and tld resources:
//similar to what MetaInfConfiguration does.
List<Resource> frags = (List<Resource>)wah.getAttribute(FragmentConfiguration.FRAGMENT_RESOURCES);
List<Resource> resfrags = (List<Resource>)wah.getAttribute(WebInfConfiguration.RESOURCE_URLS);
List<Resource> tldfrags = (List<Resource>)wah.getAttribute(TagLibConfiguration.TLD_RESOURCES);
for (Bundle frag : fragments)
{
URL webFrag = frag.getEntry("/META-INF/web-fragment.xml");
Enumeration<URL> resEnum = frag.findEntries("/META-INF/resources", "*", true);
Enumeration<URL> tldEnum = frag.findEntries("/META-INF", "*.tld", false);
if (webFrag != null || (resEnum != null && resEnum.hasMoreElements())
|| (tldEnum != null && tldEnum.hasMoreElements()))
{
try
{
File fragFile = BUNDLE_FILE_LOCATOR_HELPER.getBundleInstallLocation(frag);
//add it to the webinf jars collection:
//no need to check that it was not there yet: it was not there yet for sure.
Resource fragFileAsResource = Resource.newResource(fragFile.toURI());
webappCtxt.getMetaData().addWebInfJar(fragFileAsResource);
if (webFrag != null)
{
if (frags == null)
{
frags = new ArrayList<Resource>();
wah.setAttribute(FragmentConfiguration.FRAGMENT_RESOURCES, frags);
}
frags.add(fragFileAsResource);
}
if (resEnum != null && resEnum.hasMoreElements())
{
URL resourcesEntry = frag.getEntry("/META-INF/resources/");
if (resourcesEntry == null)
{
//probably we found some fragments to a bundle.
//those are already contributed.
//so we skip this.
}
else
{
if (resfrags == null)
{
resfrags = new ArrayList<Resource>();
wah.setAttribute(WebInfConfiguration.RESOURCE_URLS, resfrags);
}
resfrags.add(Resource.newResource(
DefaultFileLocatorHelper.getLocalURL(resourcesEntry)));
}
}
if (tldEnum != null && tldEnum.hasMoreElements())
{
if (tldfrags == null)
{
tldfrags = new ArrayList<Resource>();
wah.setAttribute(TagLibConfiguration.TLD_RESOURCES, tldfrags);
}
while (tldEnum.hasMoreElements())
{
URL tldUrl = tldEnum.nextElement();
tldfrags.add(Resource.newResource(
DefaultFileLocatorHelper.getLocalURL(tldUrl)));
}
}
}
catch (Exception e)
{
__logger.warn("Unable to locate the bundle " + frag.getBundleId(),e);
}
}
}
// This is the equivalent of what MetaInfConfiguration does. For
// OSGi bundles without the JarScanner
WebAppContext webappCtxt = (WebAppContext) wah;
// take care of the web-fragments, meta-inf resources and tld
// resources:
// similar to what MetaInfConfiguration does.
List<Resource> frags = (List<Resource>) wah.getAttribute(FragmentConfiguration.FRAGMENT_RESOURCES);
List<Resource> resfrags = (List<Resource>) wah.getAttribute(WebInfConfiguration.RESOURCE_URLS);
List<Resource> tldfrags = (List<Resource>) wah.getAttribute(TagLibConfiguration.TLD_RESOURCES);
for (Bundle frag : fragments)
{
URL webFrag = frag.getEntry("/META-INF/web-fragment.xml");
Enumeration<URL> resEnum = frag.findEntries("/META-INF/resources", "*", true);
Enumeration<URL> tldEnum = frag.findEntries("/META-INF", "*.tld", false);
if (webFrag != null || (resEnum != null && resEnum.hasMoreElements()) || (tldEnum != null && tldEnum.hasMoreElements()))
{
try
{
File fragFile = BUNDLE_FILE_LOCATOR_HELPER.getBundleInstallLocation(frag);
// add it to the webinf jars collection:
// no need to check that it was not there yet: it
// was not there yet for sure.
Resource fragFileAsResource = Resource.newResource(fragFile.toURI());
webappCtxt.getMetaData().addWebInfJar(fragFileAsResource);
if (webFrag != null)
{
if (frags == null)
{
frags = new ArrayList<Resource>();
wah.setAttribute(FragmentConfiguration.FRAGMENT_RESOURCES, frags);
}
frags.add(fragFileAsResource);
}
if (resEnum != null && resEnum.hasMoreElements())
{
URL resourcesEntry = frag.getEntry("/META-INF/resources/");
if (resourcesEntry == null)
{
// probably we found some fragments to a
// bundle.
// those are already contributed.
// so we skip this.
}
else
{
if (resfrags == null)
{
resfrags = new ArrayList<Resource>();
wah.setAttribute(WebInfConfiguration.RESOURCE_URLS, resfrags);
}
resfrags.add(Resource.newResource(DefaultFileLocatorHelper.getLocalURL(resourcesEntry)));
}
}
if (tldEnum != null && tldEnum.hasMoreElements())
{
if (tldfrags == null)
{
tldfrags = new ArrayList<Resource>();
wah.setAttribute(TagLibConfiguration.TLD_RESOURCES, tldfrags);
}
while (tldEnum.hasMoreElements())
{
URL tldUrl = tldEnum.nextElement();
tldfrags.add(Resource.newResource(DefaultFileLocatorHelper.getLocalURL(tldUrl)));
}
}
}
catch (Exception e)
{
__logger.warn("Unable to locate the bundle " + frag.getBundleId(), e);
}
}
}
}
}
}
/**
@ -644,15 +651,13 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper
* @param contextFile
* @return
*/
protected ContextHandler createContextHandler(ContextHandler handlerToConfigure,
Bundle bundle, File contextFile, String extraClasspath,
String overrideBundleInstallLocation, String requireTldBundle)
protected ContextHandler createContextHandler(ContextHandler handlerToConfigure, Bundle bundle, File contextFile, String extraClasspath,
String overrideBundleInstallLocation, String requireTldBundle)
{
try
{
return createContextHandler(handlerToConfigure,bundle,
new BufferedInputStream(new FileInputStream(contextFile)),
extraClasspath,overrideBundleInstallLocation,requireTldBundle);
return createContextHandler(handlerToConfigure, bundle, new BufferedInputStream(new FileInputStream(contextFile)), extraClasspath,
overrideBundleInstallLocation, requireTldBundle);
}
catch (FileNotFoundException e)
{
@ -667,9 +672,8 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper
* @return
*/
@SuppressWarnings("unchecked")
protected ContextHandler createContextHandler(ContextHandler handlerToConfigure,
Bundle bundle, InputStream contextInputStream, String extraClasspath,
String overrideBundleInstallLocation, String requireTldBundle)
protected ContextHandler createContextHandler(ContextHandler handlerToConfigure, Bundle bundle, InputStream contextInputStream, String extraClasspath,
String overrideBundleInstallLocation, String requireTldBundle)
{
/*
* Do something identical to what the ContextProvider would have done:
@ -686,30 +690,30 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper
{
XmlConfiguration xmlConfiguration = new XmlConfiguration(contextInputStream);
HashMap properties = new HashMap();
properties.put("Server",_wrapper.getServer());
properties.put("Server", _wrapper.getServer());
// insert the bundle's location as a property.
setThisBundleHomeProperty(bundle,properties,overrideBundleInstallLocation);
setThisBundleHomeProperty(bundle, properties, overrideBundleInstallLocation);
xmlConfiguration.getProperties().putAll(properties);
ContextHandler context = null;
if (handlerToConfigure == null)
{
context = (ContextHandler)xmlConfiguration.configure();
context = (ContextHandler) xmlConfiguration.configure();
}
else
{
xmlConfiguration.configure(handlerToConfigure);
context = handlerToConfigure;
}
if (context instanceof WebAppContext)
{
((WebAppContext)context).setExtraClasspath(extraClasspath);
((WebAppContext)context).setParentLoaderPriority(_wrapper.getOSGiAppProvider().isParentLoaderPriority());
((WebAppContext) context).setExtraClasspath(extraClasspath);
((WebAppContext) context).setParentLoaderPriority(_wrapper.getOSGiAppProvider().isParentLoaderPriority());
if (_wrapper.getOSGiAppProvider().getDefaultsDescriptor() != null && _wrapper.getOSGiAppProvider().getDefaultsDescriptor().length() != 0)
{
((WebAppContext)context).setDefaultsDescriptor(_wrapper.getOSGiAppProvider().getDefaultsDescriptor());
((WebAppContext) context).setDefaultsDescriptor(_wrapper.getOSGiAppProvider().getDefaultsDescriptor());
}
}
@ -775,13 +779,12 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper
{
if (context instanceof WebAppContext)
{
WebAppContext webappCtxt = (WebAppContext)context;
WebAppContext webappCtxt = (WebAppContext) context;
context.setClassLoader(webappClassLoader);
webappClassLoader.setWebappContext(webappCtxt);
String pathsToRequiredBundles = getPathsToRequiredBundles(context, requireTldBundle);
if (pathsToRequiredBundles != null)
webappClassLoader.addClassPath(pathsToRequiredBundles);
if (pathsToRequiredBundles != null) webappClassLoader.addClassPath(pathsToRequiredBundles);
}
else
{
@ -797,20 +800,20 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper
// we use a temporary WebAppContext object.
// if this is a real webapp we will set it on it a bit later: once we
// know.
OSGiWebappClassLoader webappClassLoader = new OSGiWebappClassLoader(
_wrapper.getParentClassLoaderForWebapps(),new WebAppContext(),contributor,BUNDLE_CLASS_LOADER_HELPER);
/* DEBUG
try {
Class c = webappClassLoader.loadClass("org.glassfish.jsp.api.ResourceInjector");
System.err.println("LOADED org.glassfish.jsp.api.ResourceInjector from "+c.getClassLoader());
}
catch (Exception e) {e.printStackTrace();}
try {
Class c = webappClassLoader.loadClass("org.apache.jasper.xmlparser.ParserUtils");
System.err.println("LOADED org.apache.jasper.xmlparser.ParserUtils from "+c.getClassLoader());
}
catch (Exception e) {e.printStackTrace();}
*/
OSGiWebappClassLoader webappClassLoader = new OSGiWebappClassLoader(_wrapper.getParentClassLoaderForWebapps(), new WebAppContext(), contributor,
BUNDLE_CLASS_LOADER_HELPER);
/*
* DEBUG try { Class c =
* webappClassLoader.loadClass("org.glassfish.jsp.api.ResourceInjector"
* );
* System.err.println("LOADED org.glassfish.jsp.api.ResourceInjector from "
* +c.getClassLoader()); } catch (Exception e) {e.printStackTrace();}
* try { Class c =
* webappClassLoader.loadClass("org.apache.jasper.xmlparser.ParserUtils"
* );
* System.err.println("LOADED org.apache.jasper.xmlparser.ParserUtils from "
* +c.getClassLoader()); } catch (Exception e) {e.printStackTrace();}
*/
return webappClassLoader;
}
@ -823,10 +826,9 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper
{
try
{
File location = overrideBundleInstallLocation != null?new File(overrideBundleInstallLocation):BUNDLE_FILE_LOCATOR_HELPER
.getBundleInstallLocation(bundle);
properties.put("this.bundle.install",location.getCanonicalPath());
properties.put("this.bundle.install.url",bundle.getEntry("/").toString());
File location = overrideBundleInstallLocation != null ? new File(overrideBundleInstallLocation) : BUNDLE_FILE_LOCATOR_HELPER.getBundleInstallLocation(bundle);
properties.put("this.bundle.install", location.getCanonicalPath());
properties.put("this.bundle.install.url", bundle.getEntry("/").toString());
}
catch (Throwable t)
{
@ -834,36 +836,30 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper
}
}
private String getPathsToRequiredBundles (ContextHandler context, String requireTldBundle) throws Exception
private String getPathsToRequiredBundles(ContextHandler context, String requireTldBundle) throws Exception
{
if (requireTldBundle == null)
return null;
if (requireTldBundle == null) return null;
StringBuilder paths = new StringBuilder();
Bundle bundle = (Bundle)context.getAttribute(OSGiWebappConstants.JETTY_OSGI_BUNDLE);
Bundle bundle = (Bundle) context.getAttribute(OSGiWebappConstants.JETTY_OSGI_BUNDLE);
PackageAdmin packAdmin = getBundleAdmin();
DefaultFileLocatorHelper fileLocatorHelper = new DefaultFileLocatorHelper();
String[] symbNames = requireTldBundle.split(", ");
for (String symbName : symbNames)
{
Bundle[] bs = packAdmin.getBundles(symbName, null);
if (bs == null || bs.length == 0)
{
throw new IllegalArgumentException("Unable to locate the bundle '"
+ symbName + "' specified in the "
+ OSGiWebappConstants.REQUIRE_TLD_BUNDLE
+ " of the manifest of "
+ bundle.getSymbolicName());
}
if (bs == null || bs.length == 0) { throw new IllegalArgumentException("Unable to locate the bundle '" + symbName
+ "' specified in the "
+ OSGiWebappConstants.REQUIRE_TLD_BUNDLE
+ " of the manifest of "
+ bundle.getSymbolicName()); }
File f = fileLocatorHelper.getBundleInstallLocation(bs[0]);
if (paths.length() > 0)
if (paths.length() > 0)
paths.append(", ");
System.err.println("getPathsToRequiredBundles: bundle path="+bs[0].getLocation()+" uri="+f.toURI());
__logger.debug("getPathsToRequiredBundles: bundle path=" + bs[0].getLocation() + " uri=" + f.toURI());
paths.append(f.toURI().toURL().toString());
}
@ -872,12 +868,11 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper
private PackageAdmin getBundleAdmin()
{
Bundle bootBundle = ((BundleReference)OSGiWebappConstants.class.getClassLoader()).getBundle();
Bundle bootBundle = ((BundleReference) OSGiWebappConstants.class.getClassLoader()).getBundle();
ServiceTracker serviceTracker = new ServiceTracker(bootBundle.getBundleContext(), PackageAdmin.class.getName(), null);
serviceTracker.open();
return (PackageAdmin) serviceTracker.getService();
}
}

View File

@ -24,7 +24,6 @@ import org.osgi.framework.BundleEvent;
import org.osgi.util.tracker.BundleTracker;
import org.osgi.util.tracker.BundleTrackerCustomizer;
/**
* Support bundles that declare the webapp directly through headers in their
* manifest.
@ -49,133 +48,132 @@ import org.osgi.util.tracker.BundleTrackerCustomizer;
*
* @author hmalphettes
*/
public class WebBundleTrackerCustomizer implements BundleTrackerCustomizer {
public class WebBundleTrackerCustomizer implements BundleTrackerCustomizer
{
private static final Logger LOG = Log.getLogger(WebBundleTrackerCustomizer.class);
/**
* A bundle is being added to the <code>BundleTracker</code>.
*
* <p>
* This method is called before a bundle which matched the search parameters
* of the <code>BundleTracker</code> is added to the
* <code>BundleTracker</code>. This method should return the object to be
* tracked for the specified <code>Bundle</code>. The returned object is
* stored in the <code>BundleTracker</code> and is available from the
* {@link BundleTracker#getObject(Bundle) getObject} method.
*
* @param bundle The <code>Bundle</code> being added to the
* <code>BundleTracker</code>.
* @param event The bundle event which caused this customizer method to be
* called or <code>null</code> if there is no bundle event
* associated with the call to this method.
* @return The object to be tracked for the specified <code>Bundle</code>
* object or <code>null</code> if the specified <code>Bundle</code>
* object should not be tracked.
*/
public Object addingBundle(Bundle bundle, BundleEvent event)
{
if (bundle.getState() == Bundle.ACTIVE)
{
boolean isWebBundle = register(bundle);
return isWebBundle ? bundle : null;
}
else if (bundle.getState() == Bundle.STOPPING)
{
unregister(bundle);
}
else
{
// we should not be called in that state as
// we are registered only for ACTIVE and STOPPING
}
return null;
}
/**
* A bundle is being added to the <code>BundleTracker</code>.
*
* <p>
* This method is called before a bundle which matched the search parameters
* of the <code>BundleTracker</code> is added to the
* <code>BundleTracker</code>. This method should return the object to be
* tracked for the specified <code>Bundle</code>. The returned object is
* stored in the <code>BundleTracker</code> and is available from the
* {@link BundleTracker#getObject(Bundle) getObject} method.
*
* @param bundle The <code>Bundle</code> being added to the
* <code>BundleTracker</code>.
* @param event The bundle event which caused this customizer method to be
* called or <code>null</code> if there is no bundle event associated
* with the call to this method.
* @return The object to be tracked for the specified <code>Bundle</code>
* object or <code>null</code> if the specified <code>Bundle</code>
* object should not be tracked.
*/
public Object addingBundle(Bundle bundle, BundleEvent event)
{
if (bundle.getState() == Bundle.ACTIVE)
{
boolean isWebBundle = register(bundle);
return isWebBundle ? bundle : null;
}
else if (bundle.getState() == Bundle.STOPPING)
{
unregister(bundle);
}
else
{
//we should not be called in that state as
//we are registered only for ACTIVE and STOPPING
}
return null;
}
/**
* A bundle tracked by the <code>BundleTracker</code> has been modified.
*
* <p>
* This method is called when a bundle being tracked by the
* <code>BundleTracker</code> has had its state modified.
*
* @param bundle The <code>Bundle</code> whose state has been modified.
* @param event The bundle event which caused this customizer method to be
* called or <code>null</code> if there is no bundle event
* associated with the call to this method.
* @param object The tracked object for the specified bundle.
*/
public void modifiedBundle(Bundle bundle, BundleEvent event, Object object)
{
// nothing the web-bundle was already track. something changed.
// we only reload the webapps if the bundle is stopped and restarted.
if (bundle.getState() == Bundle.STOPPING || bundle.getState() == Bundle.ACTIVE)
{
unregister(bundle);
}
if (bundle.getState() == Bundle.ACTIVE)
{
register(bundle);
}
}
/**
* A bundle tracked by the <code>BundleTracker</code> has been modified.
*
* <p>
* This method is called when a bundle being tracked by the
* <code>BundleTracker</code> has had its state modified.
*
* @param bundle The <code>Bundle</code> whose state has been modified.
* @param event The bundle event which caused this customizer method to be
* called or <code>null</code> if there is no bundle event associated
* with the call to this method.
* @param object The tracked object for the specified bundle.
*/
public void modifiedBundle(Bundle bundle, BundleEvent event,
Object object)
{
//nothing the web-bundle was already track. something changed.
//we only reload the webapps if the bundle is stopped and restarted.
// System.err.println(bundle.getSymbolicName());
if (bundle.getState() == Bundle.STOPPING || bundle.getState() == Bundle.ACTIVE)
{
unregister(bundle);
}
if (bundle.getState() == Bundle.ACTIVE)
{
register(bundle);
}
}
/**
* A bundle tracked by the <code>BundleTracker</code> has been removed.
*
* <p>
* This method is called after a bundle is no longer being tracked by the
* <code>BundleTracker</code>.
*
* @param bundle The <code>Bundle</code> that has been removed.
* @param event The bundle event which caused this customizer method to be
* called or <code>null</code> if there is no bundle event
* associated with the call to this method.
* @param object The tracked object for the specified bundle.
*/
public void removedBundle(Bundle bundle, BundleEvent event, Object object)
{
unregister(bundle);
}
/**
* A bundle tracked by the <code>BundleTracker</code> has been removed.
*
* <p>
* This method is called after a bundle is no longer being tracked by the
* <code>BundleTracker</code>.
*
* @param bundle The <code>Bundle</code> that has been removed.
* @param event The bundle event which caused this customizer method to be
* called or <code>null</code> if there is no bundle event associated
* with the call to this method.
* @param object The tracked object for the specified bundle.
*/
public void removedBundle(Bundle bundle, BundleEvent event,
Object object)
{
unregister(bundle);
}
/**
* @param bundle
* @return true if this bundle in indeed a web-bundle.
*/
/**
* @param bundle
* @return true if this bundle in indeed a web-bundle.
*/
private boolean register(Bundle bundle)
{
Dictionary<?, ?> dic = bundle.getHeaders();
String warFolderRelativePath = (String)dic.get(OSGiWebappConstants.JETTY_WAR_FOLDER_PATH);
String warFolderRelativePath = (String) dic.get(OSGiWebappConstants.JETTY_WAR_FOLDER_PATH);
if (warFolderRelativePath != null)
{
String contextPath = getWebContextPath(bundle, dic, false);//(String)dic.get(OSGiWebappConstants.RFC66_WEB_CONTEXTPATH);
String contextPath = getWebContextPath(bundle, dic, false);// (String)dic.get(OSGiWebappConstants.RFC66_WEB_CONTEXTPATH);
if (contextPath == null || !contextPath.startsWith("/"))
{
LOG.warn("The manifest header '" + OSGiWebappConstants.JETTY_WAR_FOLDER_PATH +
": " + warFolderRelativePath + "' in the bundle " + bundle.getSymbolicName() +
" is not valid: there is no Web-ContextPath defined in the manifest.");
return false;
LOG.warn("The manifest header '" + OSGiWebappConstants.JETTY_WAR_FOLDER_PATH
+ ": "
+ warFolderRelativePath
+ "' in the bundle "
+ bundle.getSymbolicName()
+ " is not valid: there is no Web-ContextPath defined in the manifest.");
return false;
}
// create the corresponding service and publish it in the context of
// the contributor bundle.
try
{
JettyBootstrapActivator.registerWebapplication(bundle,warFolderRelativePath,contextPath);
JettyBootstrapActivator.registerWebapplication(bundle, warFolderRelativePath, contextPath);
return true;
}
catch (Throwable e)
{
LOG.warn("Starting the web-bundle " + bundle.getSymbolicName() + " threw an exception.", e);
return true;//maybe it did not work maybe it did. safer to track this bundle.
LOG.warn("Starting the web-bundle " + bundle.getSymbolicName() + " threw an exception.", e);
return true;// maybe it did not work maybe it did. safer to
// track this bundle.
}
}
else if (dic.get(OSGiWebappConstants.JETTY_CONTEXT_FILE_PATH) != null)
{
String contextFileRelativePath = (String)dic.get(OSGiWebappConstants.JETTY_CONTEXT_FILE_PATH);
String contextFileRelativePath = (String) dic.get(OSGiWebappConstants.JETTY_CONTEXT_FILE_PATH);
if (contextFileRelativePath == null)
{
// nothing to register here.
@ -187,7 +185,7 @@ public class WebBundleTrackerCustomizer implements BundleTrackerCustomizer {
{
try
{
JettyBootstrapActivator.registerContext(bundle,path.trim());
JettyBootstrapActivator.registerContext(bundle, path.trim());
}
catch (Throwable e)
{
@ -203,8 +201,8 @@ public class WebBundleTrackerCustomizer implements BundleTrackerCustomizer {
// (draft) of the spec: just a couple of posts on the
// world-wide-web.
URL rfc66Webxml = bundle.getEntry("/WEB-INF/web.xml");
if (rfc66Webxml == null && dic.get(OSGiWebappConstants.RFC66_WEB_CONTEXTPATH) == null)
{
if (rfc66Webxml == null && dic.get(OSGiWebappConstants.RFC66_WEB_CONTEXTPATH) == null)
{
return false;// no webapp in here
}
// this is risky: should we make sure that there is no classes and
@ -215,42 +213,41 @@ public class WebBundleTrackerCustomizer implements BundleTrackerCustomizer {
// pointing to files and folders inside WEB-INF. We should
// filter-out
// META-INF too
String rfc66ContextPath = getWebContextPath(bundle,dic,rfc66Webxml==null);
String rfc66ContextPath = getWebContextPath(bundle, dic, rfc66Webxml == null);
try
{
JettyBootstrapActivator.registerWebapplication(bundle,".",rfc66ContextPath);
JettyBootstrapActivator.registerWebapplication(bundle, ".", rfc66ContextPath);
return true;
}
catch (Throwable e)
{
// TODO Auto-generated catch block
e.printStackTrace();
return true;//maybe it did not work maybe it did. safer to track this bundle.
return true;// maybe it did not work maybe it did. safer to
// track this bundle.
}
}
}
private String getWebContextPath(Bundle bundle, Dictionary<?, ?> dic, boolean webinfWebxmlExists)
{
String rfc66ContextPath = (String)dic.get(OSGiWebappConstants.RFC66_WEB_CONTEXTPATH);
String rfc66ContextPath = (String) dic.get(OSGiWebappConstants.RFC66_WEB_CONTEXTPATH);
if (rfc66ContextPath == null)
{
if (!webinfWebxmlExists) {
return null;
}
if (!webinfWebxmlExists) { return null; }
// extract from the last token of the bundle's location:
// (really ?
// could consider processing the symbolic name as an alternative
// the location will often reflect the version.
// maybe this is relevant when the file is a war)
String location = bundle.getLocation();
String toks[] = location.replace('\\','/').split("/");
String toks[] = location.replace('\\', '/').split("/");
rfc66ContextPath = toks[toks.length - 1];
// remove .jar, .war etc:
int lastDot = rfc66ContextPath.lastIndexOf('.');
if (lastDot != -1)
{
rfc66ContextPath = rfc66ContextPath.substring(0,lastDot);
rfc66ContextPath = rfc66ContextPath.substring(0, lastDot);
}
}
if (!rfc66ContextPath.startsWith("/"))
@ -259,7 +256,7 @@ public class WebBundleTrackerCustomizer implements BundleTrackerCustomizer {
}
return rfc66ContextPath;
}
private void unregister(Bundle bundle)
{
// nothing to do: when the bundle is stopped, each one of its service
@ -268,7 +265,4 @@ public class WebBundleTrackerCustomizer implements BundleTrackerCustomizer {
// webapps registered in that bundle.
}
}

View File

@ -25,6 +25,7 @@ import java.util.zip.ZipFile;
import org.eclipse.jetty.osgi.boot.utils.BundleFileLocatorHelper;
import org.eclipse.jetty.util.URIUtil;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.util.resource.FileResource;
import org.osgi.framework.Bundle;
@ -43,11 +44,13 @@ public class DefaultFileLocatorHelper implements BundleFileLocatorHelper
// The url nuxeo and felix return is created directly from the File so it
// should work.
private static Field BUNDLE_ENTRY_FIELD = null;
private static Field FILE_FIELD = null;
private static Field BUNDLE_FILE_FIELD_FOR_DIR_ZIP_BUNDLE_ENTRY = null;// ZipBundleFile
// inside
// DirZipBundleEntry
// inside
// DirZipBundleEntry
private static Field ZIP_FILE_FILED_FOR_ZIP_BUNDLE_FILE = null;// ZipFile
@ -56,8 +59,7 @@ public class DefaultFileLocatorHelper implements BundleFileLocatorHelper
* spirit of OSGi but quite necessary to support self-contained webapps and
* other situations.
*
* @param bundle
* The bundle
* @param bundle The bundle
* @return Its installation location as a file.
* @throws Exception
*/
@ -67,19 +69,23 @@ public class DefaultFileLocatorHelper implements BundleFileLocatorHelper
// grab the MANIFEST.MF's url
// and then do what it takes.
URL url = bundle.getEntry("/META-INF/MANIFEST.MF");
// System.err.println(url.toString() + " " + url.toURI() + " " + url.getProtocol());
//System.err.println(url.toString() + " " + url.toURI() + " " + url.getProtocol());
if (url.getProtocol().equals("file"))
{
// some osgi frameworks do use the file protocole directly in some
// situations. Do use the FileResource to transform the URL into a File: URL#toURI is broken
return new FileResource(url).getFile().getParentFile().getParentFile();
// situations. Do use the FileResource to transform the URL into a
// File: URL#toURI is broken
return new FileResource(url).getFile().getParentFile().getParentFile();
}
else if (url.getProtocol().equals("bundleentry"))
{
// say hello to equinox who has its own protocol.
// we use introspection like there is no tomorrow to get access to
// the File
URLConnection con = url.openConnection();
con.setUseCaches(Resource.getDefaultUseCaches()); //work around problems where url connections cache references to jars
if (BUNDLE_ENTRY_FIELD == null)
{
BUNDLE_ENTRY_FIELD = con.getClass().getDeclaredField("bundleEntry");
@ -93,13 +99,16 @@ public class DefaultFileLocatorHelper implements BundleFileLocatorHelper
FILE_FIELD = bundleEntry.getClass().getDeclaredField("file");
FILE_FIELD.setAccessible(true);
}
File f = (File)FILE_FIELD.get(bundleEntry);
File f = (File) FILE_FIELD.get(bundleEntry);
return f.getParentFile().getParentFile();
}
else if (bundleEntry.getClass().getName().equals("org.eclipse.osgi.baseadaptor.bundlefile.ZipBundleEntry"))
{
url = bundle.getEntry("/");
con = url.openConnection();
con.setDefaultUseCaches(Resource.getDefaultUseCaches());
if (BUNDLE_ENTRY_FIELD == null)
{// this one will be a DirZipBundleEntry
BUNDLE_ENTRY_FIELD = con.getClass().getDeclaredField("bundleEntry");
@ -117,7 +126,7 @@ public class DefaultFileLocatorHelper implements BundleFileLocatorHelper
ZIP_FILE_FILED_FOR_ZIP_BUNDLE_FILE = zipBundleFile.getClass().getDeclaredField("zipFile");
ZIP_FILE_FILED_FOR_ZIP_BUNDLE_FILE.setAccessible(true);
}
ZipFile zipFile = (ZipFile)ZIP_FILE_FILED_FOR_ZIP_BUNDLE_FILE.get(zipBundleFile);
ZipFile zipFile = (ZipFile) ZIP_FILE_FILED_FOR_ZIP_BUNDLE_FILE.get(zipBundleFile);
return new File(zipFile.getName());
}
else if (bundleEntry.getClass().getName().equals("org.eclipse.osgi.baseadaptor.bundlefile.DirZipBundleEntry"))
@ -130,7 +139,7 @@ public class DefaultFileLocatorHelper implements BundleFileLocatorHelper
{
// observed this on felix-2.0.0
String location = bundle.getLocation();
// System.err.println("location " + location);
// System.err.println("location " + location);
if (location.startsWith("file:/"))
{
URI uri = new URI(URIUtil.encodePath(location));
@ -138,27 +147,32 @@ public class DefaultFileLocatorHelper implements BundleFileLocatorHelper
}
else if (location.startsWith("file:"))
{
//location defined in the BundleArchive m_bundleArchive
//it is relative to relative to the BundleArchive's m_archiveRootDir
File res = new File(location.substring("file:".length()));
if (!res.exists())
{
return null;
// Object bundleArchive = getFelixBundleArchive(bundle);
// File archiveRoot = getFelixBundleArchiveRootDir(bundleArchive);
// String currentLocation = getFelixBundleArchiveCurrentLocation(bundleArchive);
// System.err.println("Got the archive root " + archiveRoot.getAbsolutePath()
// + " current location " + currentLocation + " is directory ?");
// res = new File(archiveRoot, currentLocation != null
// ? currentLocation : location.substring("file:".length()));
}
return res;
// location defined in the BundleArchive m_bundleArchive
// it is relative to relative to the BundleArchive's
// m_archiveRootDir
File res = new File(location.substring("file:".length()));
if (!res.exists())
{
return null;
// Object bundleArchive = getFelixBundleArchive(bundle);
// File archiveRoot =
// getFelixBundleArchiveRootDir(bundleArchive);
// String currentLocation =
// getFelixBundleArchiveCurrentLocation(bundleArchive);
// System.err.println("Got the archive root " +
// archiveRoot.getAbsolutePath()
// + " current location " + currentLocation +
// " is directory ?");
// res = new File(archiveRoot, currentLocation != null
// ? currentLocation : location.substring("file:".length()));
}
return res;
}
else if (location.startsWith("reference:file:"))
{
location = URLDecoder.decode(location.substring("reference:".length()), "UTF-8");
File file = new File(location.substring("file:".length()));
return file;
location = URLDecoder.decode(location.substring("reference:".length()), "UTF-8");
File file = new File(location.substring("file:".length()));
return file;
}
}
return null;
@ -179,37 +193,40 @@ public class DefaultFileLocatorHelper implements BundleFileLocatorHelper
path = path.substring(1);
}
File bundleInstall = getBundleInstallLocation(bundle);
File webapp = path != null && path.length() != 0?new File(bundleInstall,path):bundleInstall;
if (!webapp.exists())
{
throw new IllegalArgumentException("Unable to locate " + path + " inside " + bundle.getSymbolicName() + " ("
+ (bundleInstall != null?bundleInstall.getAbsolutePath():" no_bundle_location ") + ")");
File webapp = path != null && path.length() != 0 ? new File(bundleInstall, path) : bundleInstall;
if (!webapp.exists())
{
throw new IllegalArgumentException("Unable to locate " + path
+ " inside "
+ bundle.getSymbolicName()
+ " ("
+ (bundleInstall != null ? bundleInstall.getAbsolutePath() : " no_bundle_location ")
+ ")");
}
return webapp;
}
/**
* Helper method equivalent to Bundle#getEntry(String entryPath) except that
* it searches for entries in the fragments by using the Bundle#findEntries method.
*
* @param bundle
* @param entryPath
* @return null or all the entries found for that path.
*/
public Enumeration<URL> findEntries(Bundle bundle, String entryPath)
{
int last = entryPath.lastIndexOf('/');
String path = last != -1 && last < entryPath.length() -2
? entryPath.substring(0, last) : "/";
if (!path.startsWith("/"))
{
path = "/" + path;
}
String pattern = last != -1 && last < entryPath.length() -2
? entryPath.substring(last+1) : entryPath;
Enumeration<URL> enUrls = bundle.findEntries(path, pattern, false);
return enUrls;
}
* Helper method equivalent to Bundle#getEntry(String entryPath) except that
* it searches for entries in the fragments by using the Bundle#findEntries
* method.
*
* @param bundle
* @param entryPath
* @return null or all the entries found for that path.
*/
public Enumeration<URL> findEntries(Bundle bundle, String entryPath)
{
int last = entryPath.lastIndexOf('/');
String path = last != -1 && last < entryPath.length() - 2 ? entryPath.substring(0, last) : "/";
if (!path.startsWith("/"))
{
path = "/" + path;
}
String pattern = last != -1 && last < entryPath.length() - 2 ? entryPath.substring(last + 1) : entryPath;
Enumeration<URL> enUrls = bundle.findEntries(path, pattern, false);
return enUrls;
}
/**
* If the bundle is a jar, returns the jar. If the bundle is a folder, look
@ -256,76 +273,84 @@ public class DefaultFileLocatorHelper implements BundleFileLocatorHelper
return new File[] { jasperLocation };
}
}
//introspection on equinox to invoke the getLocalURL method on BundleURLConnection
//equivalent to using the FileLocator without depending on an equinox class.
private static Method BUNDLE_URL_CONNECTION_getLocalURL = null;
private static Method BUNDLE_URL_CONNECTION_getFileURL = null;
/**
* Only useful for equinox: on felix we get the file:// or jar:// url already.
* Other OSGi implementations have not been tested
* <p>
* Get a URL to the bundle entry that uses a common protocol (i.e. file:
* jar: or http: etc.).
* </p>
* @return a URL to the bundle entry that uses a common protocol
*/
public static URL getLocalURL(URL url) {
if ("bundleresource".equals(url.getProtocol()) || "bundleentry".equals(url.getProtocol())) {
try {
URLConnection conn = url.openConnection();
if (BUNDLE_URL_CONNECTION_getLocalURL == null &&
conn.getClass().getName().equals(
"org.eclipse.osgi.framework.internal.core.BundleURLConnection")) {
BUNDLE_URL_CONNECTION_getLocalURL = conn.getClass().getMethod("getLocalURL", null);
BUNDLE_URL_CONNECTION_getLocalURL.setAccessible(true);
}
if (BUNDLE_URL_CONNECTION_getLocalURL != null) {
return (URL)BUNDLE_URL_CONNECTION_getLocalURL.invoke(conn, null);
}
} catch (Throwable t) {
System.err.println("Unable to locate the OSGi url: '" + url + "'.");
t.printStackTrace();
}
}
return url;
}
/**
* Only useful for equinox: on felix we get the file:// url already.
* Other OSGi implementations have not been tested
* <p>
* Get a URL to the content of the bundle entry that uses the file: protocol.
* The content of the bundle entry may be downloaded or extracted to the local
* file system in order to create a file: URL.
* @return a URL to the content of the bundle entry that uses the file: protocol
* </p>
*/
public static URL getFileURL(URL url)
{
if ("bundleresource".equals(url.getProtocol()) || "bundleentry".equals(url.getProtocol()))
{
try
{
URLConnection conn = url.openConnection();
if (BUNDLE_URL_CONNECTION_getFileURL == null &&
conn.getClass().getName().equals(
"org.eclipse.osgi.framework.internal.core.BundleURLConnection"))
{
BUNDLE_URL_CONNECTION_getFileURL = conn.getClass().getMethod("getFileURL", null);
BUNDLE_URL_CONNECTION_getFileURL.setAccessible(true);
}
if (BUNDLE_URL_CONNECTION_getFileURL != null)
{
return (URL)BUNDLE_URL_CONNECTION_getFileURL.invoke(conn, null);
}
}
catch (Throwable t)
{
t.printStackTrace();
}
}
return url;
}
// introspection on equinox to invoke the getLocalURL method on
// BundleURLConnection
// equivalent to using the FileLocator without depending on an equinox
// class.
private static Method BUNDLE_URL_CONNECTION_getLocalURL = null;
private static Method BUNDLE_URL_CONNECTION_getFileURL = null;
/**
* Only useful for equinox: on felix we get the file:// or jar:// url
* already. Other OSGi implementations have not been tested
* <p>
* Get a URL to the bundle entry that uses a common protocol (i.e. file:
* jar: or http: etc.).
* </p>
*
* @return a URL to the bundle entry that uses a common protocol
*/
public static URL getLocalURL(URL url)
{
if ("bundleresource".equals(url.getProtocol()) || "bundleentry".equals(url.getProtocol()))
{
try
{
URLConnection conn = url.openConnection();
conn.setDefaultUseCaches(Resource.getDefaultUseCaches());
if (BUNDLE_URL_CONNECTION_getLocalURL == null && conn.getClass().getName()
.equals("org.eclipse.osgi.framework.internal.core.BundleURLConnection"))
{
BUNDLE_URL_CONNECTION_getLocalURL = conn.getClass().getMethod("getLocalURL", null);
BUNDLE_URL_CONNECTION_getLocalURL.setAccessible(true);
}
if (BUNDLE_URL_CONNECTION_getLocalURL != null) { return (URL) BUNDLE_URL_CONNECTION_getLocalURL.invoke(conn, null); }
}
catch (Throwable t)
{
System.err.println("Unable to locate the OSGi url: '" + url + "'.");
t.printStackTrace();
}
}
return url;
}
/**
* Only useful for equinox: on felix we get the file:// url already. Other
* OSGi implementations have not been tested
* <p>
* Get a URL to the content of the bundle entry that uses the file:
* protocol. The content of the bundle entry may be downloaded or extracted
* to the local file system in order to create a file: URL.
*
* @return a URL to the content of the bundle entry that uses the file:
* protocol
* </p>
*/
public static URL getFileURL(URL url)
{
if ("bundleresource".equals(url.getProtocol()) || "bundleentry".equals(url.getProtocol()))
{
try
{
URLConnection conn = url.openConnection();
conn.setDefaultUseCaches(Resource.getDefaultUseCaches());
if (BUNDLE_URL_CONNECTION_getFileURL == null && conn.getClass().getName()
.equals("org.eclipse.osgi.framework.internal.core.BundleURLConnection"))
{
BUNDLE_URL_CONNECTION_getFileURL = conn.getClass().getMethod("getFileURL", null);
BUNDLE_URL_CONNECTION_getFileURL.setAccessible(true);
}
if (BUNDLE_URL_CONNECTION_getFileURL != null) { return (URL) BUNDLE_URL_CONNECTION_getFileURL.invoke(conn, null); }
}
catch (Throwable t)
{
t.printStackTrace();
}
}
return url;
}
}