405119 Tidy up comments and code formatting for osgi

This commit is contained in:
Jan Bartel 2013-04-11 10:22:44 +10:00
parent e8d9625dcc
commit 76df005c64
27 changed files with 263 additions and 364 deletions

View File

@ -21,8 +21,6 @@ package org.eclipse.jetty.osgi.boot.jasper;
import java.io.File;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@ -36,61 +34,37 @@ import org.eclipse.jetty.osgi.boot.utils.WebappRegistrationCustomizer;
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.
* PluggableWebAppRegistrationCustomizerImpl
*
* 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>
*
* Use a System property to define bundles that contain tlds that need to
* be treated by jasper as if they were on the jetty container's classpath.
*
* The bundle locations are converted to URLs for jasper's use.
*
* Eg:
* -Dorg.eclipse.jetty.osgi.tldbundles=org.springframework.web.servlet,com.opensymphony.module.sitemesh
*/
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
* Comma separated list of names of bundles that contain tld files that should be
* discoved by jasper as if they were on the container's classpath.
* Eg:
* -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.
* Check the System property "org.eclipse.jetty.osgi.tldbundles" for names of
* bundles that contain tlds and convert to URLs.
*
* @param provider
* @return
*/
private static Collection<String> getTldBundles(DeploymentManager deploymentManager)
{
String sysprop = System.getProperty(SYS_PROP_TLD_BUNDLES);
String att = (String) deploymentManager.getContextAttribute(OSGiWebInfConfiguration.CONTAINER_BUNDLE_PATTERN);
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.
* @return The location of the jars that contain tld files as URLs.
*/
public URL[] getJarsWithTlds(DeploymentManager deploymentManager, BundleFileLocatorHelper locatorHelper) throws Exception
{
@ -118,10 +92,10 @@ public class PluggableWebAppRegistrationCustomizerImpl implements WebappRegistra
for (Bundle bundle : bundles)
{
if (sysNames.contains(bundle.getSymbolicName()))
registerTldBundle(locatorHelper, bundle, urls);
convertBundleLocationToURL(locatorHelper, bundle, urls);
if (pattern != null && pattern.matcher(bundle.getSymbolicName()).matches())
registerTldBundle(locatorHelper, bundle, urls);
convertBundleLocationToURL(locatorHelper, bundle, urls);
}
return urls.toArray(new URL[urls.size()]);
@ -129,19 +103,8 @@ public class PluggableWebAppRegistrationCustomizerImpl implements WebappRegistra
}
/**
* 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.
*
* 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.
* Resolves a bundle that contains tld files as a URL. The URLs are
* used by jasper to discover the tld files.
*
* 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
@ -153,7 +116,7 @@ public class PluggableWebAppRegistrationCustomizerImpl implements WebappRegistra
* @param urls
* @throws Exception
*/
private void registerTldBundle(BundleFileLocatorHelper locatorHelper, Bundle bundle, Set<URL> urls) throws Exception
private void convertBundleLocationToURL(BundleFileLocatorHelper locatorHelper, Bundle bundle, Set<URL> urls) throws Exception
{
File jasperLocation = locatorHelper.getBundleInstallLocation(bundle);
if (jasperLocation.isDirectory())
@ -181,7 +144,5 @@ public class PluggableWebAppRegistrationCustomizerImpl implements WebappRegistra
{
urls.add(jasperLocation.toURI().toURL());
}
}
}

View File

@ -44,6 +44,9 @@ import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
/**
*
* WebappRegistrationCustomizerImpl
*
* 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.

View File

@ -22,14 +22,12 @@ import java.io.File;
import java.net.URL;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.Hashtable;
import org.eclipse.jetty.deploy.App;
import org.eclipse.jetty.deploy.AppProvider;
import org.eclipse.jetty.deploy.DeploymentManager;
import org.eclipse.jetty.osgi.boot.internal.serverfactory.ServerInstanceWrapper;
import org.eclipse.jetty.osgi.boot.internal.webapp.BundleFileLocatorHelperFactory;
import org.eclipse.jetty.osgi.boot.utils.EventSender;
import org.eclipse.jetty.osgi.boot.utils.OSGiClassLoader;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.util.component.AbstractLifeCycle;
@ -37,11 +35,8 @@ import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.resource.JarResource;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.xml.XmlConfiguration;
import org.osgi.framework.Bundle;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.ServiceRegistration;
@ -49,7 +44,9 @@ import org.osgi.framework.ServiceRegistration;
/**
* AbstractContextProvider
*
*
* Base class for DeploymentManager Providers that can deploy ContextHandlers into
* Jetty that have been discovered via OSGI either as bundles or services.
*
*/
public abstract class AbstractContextProvider extends AbstractLifeCycle implements AppProvider
{

View File

@ -32,9 +32,10 @@ import org.osgi.framework.ServiceRegistration;
/**
* AbstractBundleApp
*
* AbstractOSGiApp
*
* Base class representing info about a webapp/ContextHandler that is deployed into Jetty.
*
*/
public abstract class AbstractOSGiApp extends App
{

View File

@ -20,14 +20,9 @@ package org.eclipse.jetty.osgi.boot;
import java.io.File;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import org.eclipse.jetty.deploy.App;
import org.eclipse.jetty.deploy.AppProvider;
@ -35,7 +30,6 @@ import org.eclipse.jetty.deploy.DeploymentManager;
import org.eclipse.jetty.osgi.boot.internal.serverfactory.ServerInstanceWrapper;
import org.eclipse.jetty.osgi.boot.internal.webapp.BundleFileLocatorHelperFactory;
import org.eclipse.jetty.osgi.boot.internal.webapp.OSGiWebappClassLoader;
import org.eclipse.jetty.osgi.boot.utils.EventSender;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.util.component.AbstractLifeCycle;
import org.eclipse.jetty.util.log.Log;
@ -44,9 +38,7 @@ import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.xml.XmlConfiguration;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.packageadmin.PackageAdmin;
@ -55,7 +47,9 @@ import org.osgi.service.packageadmin.PackageAdmin;
/**
* AbstractWebAppProvider
*
*
* Base class for Jetty DeploymentManager Providers that are capable of deploying a webapp,
* either from a bundle or an OSGi service.
*
*/
public abstract class AbstractWebAppProvider extends AbstractLifeCycle implements AppProvider
{

View File

@ -43,7 +43,7 @@ import org.osgi.framework.ServiceRegistration;
/**
* BundleContextProvider
*
* Handles deploying bundles that define a context xml file for configuring them.
* Handles deploying OSGi bundles that define a context xml file for configuring them.
*
*
*/
@ -136,6 +136,7 @@ public class BundleContextProvider extends AbstractContextProvider implements Bu
}
apps.add(app);
getDeploymentManager().addApp(app);
added = true;
}
return added; //true if even 1 context from this bundle was added

View File

@ -20,6 +20,11 @@ package org.eclipse.jetty.osgi.boot;
import org.osgi.framework.Bundle;
/**
* BundleProvider
*
* Jetty DeploymentManager Provider api for webapps or ContextHandlers that are discovered as osgi bundles.
*/
public interface BundleProvider
{
public boolean bundleAdded (Bundle bundle) throws Exception;

View File

@ -21,6 +21,7 @@ package org.eclipse.jetty.osgi.boot;
import java.util.Dictionary;
import java.util.Hashtable;
import org.eclipse.jetty.osgi.boot.internal.serverfactory.DefaultJettyAtJettyHomeHelper;
import org.eclipse.jetty.osgi.boot.internal.serverfactory.JettyServerServiceTracker;
import org.eclipse.jetty.osgi.boot.internal.webapp.IWebBundleDeployerHelper;
@ -29,34 +30,33 @@ import org.eclipse.jetty.osgi.boot.internal.webapp.WebBundleTrackerCustomizer;
import org.eclipse.jetty.osgi.boot.utils.internal.PackageAdminServiceTracker;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.webapp.WebAppContext;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import org.osgi.util.tracker.BundleTracker;
import org.osgi.util.tracker.ServiceTracker;
/**
* JettyBootstrapActivator
*
* Bootstrap jetty and publish a default Server instance as an OSGi service.
*
* Listen for other Server instances to be published as services and support them as deployment targets.
*
* Listen for Bundles to be activated, and deploy those that represent webapps to one of the known Server instances.
* Listen for Bundles to be activated, and deploy those that represent webapps/ContextHandlers to one of the known Server instances.
*
* <ol>
* <li>basic servlet [ok]</li>
* <li>basic jetty.xml [ok]</li>
* <li>basic jetty.xml and jetty-plus.xml [ok]</li>
* <li>basic jsp [ok]</li>
* <li>jsp with tag-libs [ok]</li>
* <li>test-jndi with atomikos and derby inside ${jetty.home}/lib/ext [ok]</li>
* </ul>
*/
public class JettyBootstrapActivator implements BundleActivator
{
private static final Logger LOG = Log.getLogger(JettyBootstrapActivator.class);
private static JettyBootstrapActivator INSTANCE = null;
public static JettyBootstrapActivator getInstance()
@ -84,7 +84,7 @@ public class JettyBootstrapActivator implements BundleActivator
*
* @param context
*/
public void start(BundleContext context) throws Exception
public void start(final BundleContext context) throws Exception
{
INSTANCE = this;
_bundleContext = context;
@ -102,12 +102,14 @@ public class JettyBootstrapActivator implements BundleActivator
context.addServiceListener(_jettyContextHandlerTracker, "(objectclass=" + ContextHandler.class.getName() + ")");
// Create a default jetty instance right now.
DefaultJettyAtJettyHomeHelper.startJettyAtJettyHome(context);
Server defaultServer = DefaultJettyAtJettyHomeHelper.startJettyAtJettyHome(context);
// track Bundles and deploy those that represent webapps to one of the known Servers
WebBundleTrackerCustomizer customizer = new WebBundleTrackerCustomizer();
_webBundleTracker = new BundleTracker(context, Bundle.ACTIVE | Bundle.STOPPING, customizer);
customizer.setAndOpenWebBundleTracker(_webBundleTracker);
//Create a bundle tracker to help deploy webapps and ContextHandlers
WebBundleTrackerCustomizer bundleTrackerCustomizer = new WebBundleTrackerCustomizer();
bundleTrackerCustomizer.setWaitForDefaultServer(defaultServer != null);
_webBundleTracker = new BundleTracker(context, Bundle.ACTIVE | Bundle.STOPPING, bundleTrackerCustomizer);
bundleTrackerCustomizer.setBundleTracker(_webBundleTracker);
bundleTrackerCustomizer.open();
}
/**
@ -120,7 +122,6 @@ public class JettyBootstrapActivator implements BundleActivator
{
try
{
if (_webBundleTracker != null)
{
_webBundleTracker.close();
@ -164,122 +165,4 @@ public class JettyBootstrapActivator implements BundleActivator
INSTANCE = null;
}
}
/**
* Helper method that creates a new org.jetty.webapp.WebAppContext and
* 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 "/"
* @throws Exception
*/
public static void registerWebapplication(Bundle contributor, String webappFolderPath, String contextPath) throws Exception
{
checkBundleActivated();
WebAppContext contextHandler = new WebAppContext();
Dictionary<String,String> dic = new Hashtable<String,String>();
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);
}
/**
* Helper method that creates a new org.jetty.webapp.WebAppContext and
* 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
* @throws Exception
*/
public static void registerWebapplication(Bundle contributor, String webappFolderPath, String contextPath, Dictionary<String, String> dic) throws Exception
{
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);
}
/**
* Helper method that creates a new skeleton of a ContextHandler and
* 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.
* @throws Exception
*/
public static void registerContext(Bundle contributor, String contextFilePath) throws Exception
{
registerContext(contributor, contextFilePath, new Hashtable<String, String>());
}
/**
* Helper method that creates a new skeleton of a ContextHandler and
* 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
* @throws Exception
*/
public static void registerContext(Bundle contributor, String contextFilePath, Dictionary<String, String> dic) throws Exception
{
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);
}
public static void unregister(String contextPath)
{
// todo
}
/**
* Since org.eclipse.jetty.osgi.boot does not have a lazy activation policy
* when one of the static methods to register a webapp is called we should
* make sure that the bundle is started.
*/
private static void checkBundleActivated()
{
if (INSTANCE == null)
{
Bundle thisBundle = FrameworkUtil.getBundle(JettyBootstrapActivator.class);
try
{
thisBundle.start();
}
catch (BundleException e)
{
// nevermind.
}
}
}
/**
* @return The bundle context for this bundle.
*/
public static BundleContext getBundleContext()
{
checkBundleActivated();
return INSTANCE._bundleContext;
}
}

View File

@ -27,7 +27,9 @@ import org.eclipse.jetty.osgi.boot.utils.EventSender;
/**
* OSGiDeployer
*
*
* Extension of standard Jetty deployer that emits OSGi EventAdmin
* events whenever a webapp is deployed into OSGi via Jetty.
*
*/
public class OSGiDeployer extends StandardDeployer
{

View File

@ -32,6 +32,13 @@ import org.eclipse.jetty.webapp.MetaInfConfiguration;
import org.eclipse.jetty.webapp.WebAppContext;
import org.osgi.framework.Bundle;
/**
* OSGiMetaInfConfiguration
*
* Extension of standard Jetty MetaInfConfiguration class to handle OSGi bundle
* fragments that may also need to be scanned for META-INF info.
*
*/
public class OSGiMetaInfConfiguration extends MetaInfConfiguration
{
private static final Logger LOG = Log.getLogger(OSGiMetaInfConfiguration.class);

View File

@ -19,6 +19,8 @@
package org.eclipse.jetty.osgi.boot;
/**
* OSGiServerConstants
*
* Name of the properties that configure a jetty Server OSGi service.
*/
public class OSGiServerConstants

View File

@ -29,7 +29,9 @@ import org.eclipse.jetty.osgi.boot.utils.EventSender;
/**
* OSGiUndeployer
*
*
* Extension of the Jetty Undeployer which emits OSGi EventAdmin events
* whenever a webapp is undeployed from Jetty.
*
*/
public class OSGiUndeployer extends StandardUndeployer
{

View File

@ -19,7 +19,12 @@
package org.eclipse.jetty.osgi.boot;
/**
* Name of the service properties for a ContextHandler that configure a webapp deployed on jetty OSGi.
* OSGiWebappConstants
*
*
* Constants (MANIFEST headers, service properties etc) associated with deploying
* webapps into OSGi via Jetty.
*
*/
public class OSGiWebappConstants
{

View File

@ -38,7 +38,9 @@ import org.osgi.framework.ServiceRegistration;
/**
* ServiceContextProvider
*
*
* Jetty DeploymentManager Provider that is able to deploy ContextHandlers discovered via OSGi as services.
*
*
*/
public class ServiceContextProvider extends AbstractContextProvider implements ServiceProvider
{

View File

@ -21,6 +21,11 @@ package org.eclipse.jetty.osgi.boot;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.osgi.framework.ServiceReference;
/**
* ServiceProvider
*
* Jetty DeploymentManager Provider api for webapps or ContextHandlers that are discovered as OSGi services.
*/
public interface ServiceProvider
{
public boolean serviceAdded (ServiceReference ref, ContextHandler handler) throws Exception;

View File

@ -27,7 +27,6 @@ import org.eclipse.jetty.deploy.App;
import org.eclipse.jetty.deploy.AppProvider;
import org.eclipse.jetty.deploy.DeploymentManager;
import org.eclipse.jetty.osgi.boot.internal.serverfactory.ServerInstanceWrapper;
import org.eclipse.jetty.osgi.boot.utils.EventSender;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;

View File

@ -29,7 +29,6 @@ import java.util.StringTokenizer;
import org.eclipse.jetty.osgi.boot.JettyBootstrapActivator;
import org.eclipse.jetty.osgi.boot.OSGiServerConstants;
import org.eclipse.jetty.osgi.boot.internal.webapp.BundleFileLocatorHelperFactory;
import org.eclipse.jetty.osgi.boot.utils.BundleFileLocatorHelper;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
@ -40,9 +39,12 @@ import org.osgi.framework.BundleContext;
* DefaultJettyAtJettyHomeHelper
*
*
* Creates a default instance of Jetty, based on the values of the
* System properties "jetty.home" or "jetty.home.bundle", one of which
* must be specified in order to create the default instance.
*
* Called by the {@link JettyBootstrapActivator} during the starting of the
* bundle. If the system property 'jetty.home' is defined and points to a
* folder, then setup the corresponding jetty server.
* bundle.
*/
public class DefaultJettyAtJettyHomeHelper
{
@ -87,7 +89,7 @@ public class DefaultJettyAtJettyHomeHelper
* as part of their properties.
* </p>
*/
public static void startJettyAtJettyHome(BundleContext bundleContext) throws Exception
public static Server startJettyAtJettyHome(BundleContext bundleContext) throws Exception
{
String jettyHomeSysProp = System.getProperty(OSGiServerConstants.JETTY_HOME);
String jettyHomeBundleSysProp = System.getProperty(OSGiServerConstants.JETTY_HOME_BUNDLE);
@ -109,7 +111,7 @@ public class DefaultJettyAtJettyHomeHelper
if (!jettyHome.exists() || !jettyHome.isDirectory())
{
LOG.warn("Unable to locate the jetty.home folder " + jettyHomeSysProp);
return;
return null;
}
}
else if (jettyHomeBundleSysProp != null)
@ -126,14 +128,14 @@ public class DefaultJettyAtJettyHomeHelper
if (jettyHomeBundle == null)
{
LOG.warn("Unable to find the jetty.home.bundle named " + jettyHomeSysProp);
return;
return null;
}
}
if (jettyHome == null && jettyHomeBundle == null)
{
LOG.warn("No default jetty created.");
return;
return null;
}
Server server = new Server();
@ -152,8 +154,11 @@ public class DefaultJettyAtJettyHomeHelper
setProperty(properties, OSGiServerConstants.JETTY_PORT, System.getProperty(OSGiServerConstants.JETTY_PORT));
setProperty(properties, OSGiServerConstants.JETTY_PORT_SSL, System.getProperty(OSGiServerConstants.JETTY_PORT_SSL));
//register the Server instance as an OSGi service.
//Register the default Server instance as an OSGi service.
//The JettyServerServiceTracker will notice it and configure it.
bundleContext.registerService(Server.class.getName(), server, properties);
return server;
}

View File

@ -32,8 +32,11 @@ import org.osgi.framework.ServiceListener;
import org.osgi.framework.ServiceReference;
/**
* Deploy the jetty server instances when they are registered as an OSGi
* service.
* JettyServerServiceTracker
*
* Tracks instances of Jetty Servers, and configures them so that they can deploy
* webapps or ContextHandlers discovered from the OSGi environment.
*
*/
public class JettyServerServiceTracker implements ServiceListener, IManagedJettyServerRegistry
{

View File

@ -18,28 +18,18 @@
package org.eclipse.jetty.osgi.boot.internal.webapp;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.eclipse.jetty.osgi.boot.BundleWebAppProvider;
import org.eclipse.jetty.osgi.boot.JettyBootstrapActivator;
import org.eclipse.jetty.osgi.boot.OSGiServerConstants;
import org.eclipse.jetty.osgi.boot.OSGiWebappConstants;
import org.eclipse.jetty.osgi.boot.ServiceProvider;
import org.eclipse.jetty.osgi.boot.internal.serverfactory.DefaultJettyAtJettyHomeHelper;
import org.eclipse.jetty.osgi.boot.internal.serverfactory.IManagedJettyServerRegistry;
import org.eclipse.jetty.osgi.boot.internal.serverfactory.ServerInstanceWrapper;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.Scanner;
import org.eclipse.jetty.webapp.WebAppContext;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.FrameworkUtil;
@ -195,6 +185,7 @@ public class JettyContextHandlerServiceTracker implements ServiceListener
try
{
added = e.getValue().serviceAdded(sr, contextHandler);
System.err.println(serverName+" deployed "+contextHandler+": "+added);
if (added && LOG.isDebugEnabled())
LOG.debug("Provider "+e.getValue()+" deployed "+contextHandler);
}

View File

@ -33,6 +33,9 @@ import java.util.Set;
import org.eclipse.jetty.server.Server;
/**
* LibExtClassLoaderHelper
*
*
* Helper to create a URL class-loader with the jars inside
* ${jetty.home}/lib/ext and ${jetty.home}/resources. In an ideal world, every
* library is an OSGi bundle that does loads nicely. To support standard jars or
@ -40,41 +43,18 @@ import org.eclipse.jetty.server.Server;
* inserting the jars in the usual jetty/lib/ext folders in the proper classpath
* for the webapps.
* <p>
* Also the folder resources typically contains central configuration files for
* things like: log config and others. We enable fragments to register classes
* that are called back and passed those resources to do what they need to do.
* The drawback is that those jars will not be available in the OSGi
* classloader.
* </p>
* <p>
* For example the test-jndi webapplication depends on derby, derbytools,
* atomikos none of them are osgi bundles. we can either re-package them or we
* can place them in the usual lib/ext. <br/>
* In fact jasper's jsp libraries should maybe place in lib/ext too.
* </p>
* <p>
* The drawback is that those libraries will not be available in the OSGi
* classloader. Note that we could have setup those jars as embedded jars of the
* current bundle. However, we would need to know in advance what are those jars
* which was not acceptable. Also having those jars in a URLClassLoader seem to
* be required for some cases. For example jaspers' TldLocationsCache (replaced
* by TldScanner for servlet-3.0). <br/>
* Also all the dependencies of those libraries must be resolvable directly from
* the JettyBootstrapActivator bundle as it is set as the parent classloader. For
* example: if atomikos is placed in lib/ext it will work if and only if
* JettyBootstrapActivator import the necessary packages from javax.naming*,
* javax.transaction*, javax.mail* etc Most of the common cases of javax are
* added as optional import packages into jetty bootstrapper plugin. When there
* are not covered: please make a request or create a fragment or register a
* bundle with a buddy-policy onto the jetty bootstrapper..
* </p>
* <p>
* Alternatives to placing jars in lib/ext
* Alternatives to placing jars in lib/ext:
* <ol>
* <li>Bundle the jars in an osgi bundle. Have the webapp(s) that context
* depends on them depend on that bundle. Things will go well for jetty.</li>
* <li>Bundle the jars in an osgi bundle. Have the webapp(s) that need these jars
* depend on that bundle.</li>
* <li>Bundle those jars in an osgi bundle-fragment that targets the
* jetty-bootstrap bundle</li>
* <li>Use equinox Buddy-Policy: register a buddy of the jetty bootstrapper
* bundle. (least favorite: it will work only on equinox)</li>
* bundle. (Note: it will work only on equinox)</li>
* </ol>
* </p>
*/

View File

@ -33,7 +33,6 @@ import java.util.jar.JarFile;
import javax.servlet.http.HttpServlet;
import org.eclipse.jetty.osgi.boot.utils.BundleClassLoaderHelper;
import org.eclipse.jetty.osgi.boot.utils.BundleClassLoaderHelperFactory;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
@ -44,8 +43,10 @@ import org.osgi.framework.Bundle;
import org.osgi.framework.BundleReference;
/**
* Extends the webappclassloader to insert the classloader provided by the osgi
* bundle at the same level than any other jars palced in the webappclassloader.
* OSGiWebappClassLoader
*
*
* Extends the webapp classloader to also use the classloader of the Bundle defining the webapp.
*/
public class OSGiWebappClassLoader extends WebAppClassLoader implements BundleReference
{
@ -79,10 +80,9 @@ public class OSGiWebappClassLoader extends WebAppClassLoader implements BundleRe
private boolean _lookInOsgiFirst = true;
private Set<String> _libsAlreadyInManifest = new HashSet<String>();
/**
* @param parent The parent classloader. In this case
* @param parent The parent classloader.
* @param context The WebAppContext
* @param contributor The bundle that defines this web-application.
* @throws IOException
@ -106,16 +106,6 @@ public class OSGiWebappClassLoader extends WebAppClassLoader implements BundleRe
return _contributor;
}
/**
* Reads the manifest. If the manifest is already configured to loads a few
* libs we should not add them to the classpath of the webapp. Not really
* important as we resolve classes through the osgi classloader first and
* then default on the libs of the webapp.
*/
private void computeLibsAlreadyInOSGiClassLoader()
{
// TODO
}
@Override
public Enumeration<URL> getResources(String name) throws IOException

View File

@ -21,6 +21,10 @@ package org.eclipse.jetty.osgi.boot.internal.webapp;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import org.eclipse.jetty.osgi.boot.BundleProvider;
import org.eclipse.jetty.osgi.boot.OSGiServerConstants;
@ -39,12 +43,9 @@ import org.osgi.util.tracker.ServiceTracker;
* WebBundleTrackerCustomizer
*
*
* Support bundles that declare a webpp or context directly through headers in their
* manifest. They will be deployed to the default jetty Server instance.
*
* If you wish to deploy a context or webapp to a different jetty Server instance,
* register your context/webapp as an osgi service, and set the property OSGiServerConstants.MANAGED_JETTY_SERVER_NAME
* with the name of the Server instance you wish to depoy to.
* Tracks the installation and removal of Bundles in the OSGi environment. Any bundles
* that are added are passed to the set of Jetty DeploymentManager providers to see if
* the bundle should be deployed as a webapp or ContextHandler into Jetty.
*
* @author hmalphettes
*/
@ -53,35 +54,109 @@ public class WebBundleTrackerCustomizer implements BundleTrackerCustomizer
private static final Logger LOG = Log.getLogger(WebBundleTrackerCustomizer.class);
public static Collection<WebappRegistrationCustomizer> JSP_REGISTRATION_HELPERS = new ArrayList<WebappRegistrationCustomizer>();
public static final String FILTER = "(&(objectclass=" + BundleProvider.class.getName() + ")"+
"("+OSGiServerConstants.MANAGED_JETTY_SERVER_NAME+"="+OSGiServerConstants.MANAGED_JETTY_SERVER_DEFAULT_NAME+"))";
public static final String FILTER = "(objectclass=" + BundleProvider.class.getName() + ")";
private ServiceTracker _serviceTracker;
private BundleTracker _bundleTracker;
private boolean _waitForDefaultServer = true;
private boolean _defaultServerReady = false;
private Bundle _bundle = null;
/* ------------------------------------------------------------ */
/**
* @throws Exception
*/
public WebBundleTrackerCustomizer ()
throws Exception
public WebBundleTrackerCustomizer() throws Exception
{
Bundle myBundle = FrameworkUtil.getBundle(this.getClass());
//track all instances of deployers of webapps/contexts as bundles
_serviceTracker = new ServiceTracker(myBundle.getBundleContext(), FrameworkUtil.createFilter(FILTER),null) {
public Object addingService(ServiceReference reference) {
Object object = super.addingService(reference);
LOG.debug("Deployer registered {}", reference);
openBundleTracker();
return object;
}
};
_bundle = FrameworkUtil.getBundle(this.getClass());
//Track all BundleProviders (Jetty DeploymentManager Providers that can deploy bundles)
_serviceTracker = new ServiceTracker(_bundle.getBundleContext(), FrameworkUtil.createFilter(FILTER),null);
_serviceTracker.open();
}
public boolean isWaitForDefaultServer()
{
return _waitForDefaultServer;
}
public void setWaitForDefaultServer(boolean waitForDefaultServer)
{
_waitForDefaultServer = waitForDefaultServer;
}
public void setBundleTracker (BundleTracker bundleTracker)
{
_bundleTracker = bundleTracker;
}
public void open () throws Exception
{
if (_waitForDefaultServer && !_defaultServerReady)
{
String filter = "(&(objectclass=" + BundleProvider.class.getName() + ")"+
"("+OSGiServerConstants.MANAGED_JETTY_SERVER_NAME+"="+OSGiServerConstants.MANAGED_JETTY_SERVER_DEFAULT_NAME+"))";
ServiceTracker defaultServerTracker = new ServiceTracker(_bundle.getBundleContext(),
FrameworkUtil.createFilter(filter),null)
{
public Object addingService(ServiceReference reference)
{
try
{
Object object = super.addingService(reference);
LOG.debug("Default Jetty Server registered {}", reference);
_defaultServerReady = true;
openBundleTracker();
return object;
}
catch (Exception e)
{
throw new IllegalStateException(e);
}
}
};
defaultServerTracker.open();
}
else
openBundleTracker();
}
/* ------------------------------------------------------------ */
/**
* @param managedServerName
* @return
*/
public Map<ServiceReference, BundleProvider> getDeployers(String managedServerName)
{
if (managedServerName == null)
managedServerName = OSGiServerConstants.MANAGED_JETTY_SERVER_DEFAULT_NAME;
Map<ServiceReference, BundleProvider> candidates = new HashMap<ServiceReference, BundleProvider>();
ServiceReference[] references = _serviceTracker.getServiceReferences();
if (references != null)
{
for (ServiceReference ref:references)
{
String name = (String)ref.getProperty(OSGiServerConstants.MANAGED_JETTY_SERVER_NAME);
if (managedServerName.equalsIgnoreCase(name))
{
BundleProvider candidate = (BundleProvider)_serviceTracker.getService(ref);
if (candidate != null)
candidates.put(ref, candidate);
}
}
}
return candidates;
}
/* ------------------------------------------------------------ */
/**
* A bundle is being added to the <code>BundleTracker</code>.
@ -138,8 +213,6 @@ public class WebBundleTrackerCustomizer implements BundleTrackerCustomizer
*/
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);
@ -171,35 +244,40 @@ public class WebBundleTrackerCustomizer implements BundleTrackerCustomizer
}
protected void openBundleTracker()
{
_bundleTracker.open();
}
/* ------------------------------------------------------------ */
/**
* @param bundle
* @return true if this bundle in indeed a web-bundle.
* @return true if this bundle can be deployed into Jetty
*/
private boolean register(Bundle bundle)
{
if (bundle == null)
return false;
//It might be a bundle that we can deploy to our default jetty server instance
//It might be a bundle that is deployable by Jetty.
//Use any named Server instance provided, defaulting to the default Server instance if none supplied
boolean deployed = false;
Object[] deployers = _serviceTracker.getServices();
if (deployers != null)
String serverName = (String)bundle.getHeaders().get(OSGiServerConstants.MANAGED_JETTY_SERVER_NAME);
Map<ServiceReference, BundleProvider> candidates = getDeployers(serverName);
if (candidates != null)
{
int i=0;
while (!deployed && i<deployers.length)
Iterator<Entry<ServiceReference, BundleProvider>> itor = candidates.entrySet().iterator();
while (!deployed && itor.hasNext())
{
BundleProvider p = (BundleProvider)deployers[i];
Entry<ServiceReference, BundleProvider> e = itor.next();
try
{
deployed = p.bundleAdded(bundle);
{
deployed = e.getValue().bundleAdded(bundle);
}
catch (Exception x)
{
LOG.warn("Error deploying bundle for jetty context", x);
}
i++;
}
}
@ -212,39 +290,24 @@ public class WebBundleTrackerCustomizer implements BundleTrackerCustomizer
*/
private void unregister(Bundle bundle)
{
Object[] deployers = _serviceTracker.getServices();
boolean undeployed = false;
if (deployers != null)
String serverName = (String)bundle.getHeaders().get(OSGiServerConstants.MANAGED_JETTY_SERVER_NAME);
Map<ServiceReference, BundleProvider> candidates = getDeployers(serverName);
if (candidates != null)
{
int i=0;
while (!undeployed && i<deployers.length)
Iterator<Entry<ServiceReference, BundleProvider>> itor = candidates.entrySet().iterator();
while (!undeployed && itor.hasNext())
{
Entry<ServiceReference, BundleProvider> e = itor.next();
try
{
undeployed = ((BundleProvider)deployers[i++]).bundleRemoved(bundle);
undeployed = e.getValue().bundleRemoved(bundle);
}
catch (Exception x)
{
LOG.warn("Error undeploying bundle for jetty context", x);
LOG.warn("Error undeploying Bundle representing jetty deployable ", x);
}
}
}
}
public void setAndOpenWebBundleTracker(BundleTracker bundleTracker) {
if(_bundleTracker == null) {
_bundleTracker = bundleTracker;
LOG.debug("Bundle tracker is set");
openBundleTracker();
}
}
private void openBundleTracker() {
if(_bundleTracker != null && _serviceTracker.getServices() != null &&
_serviceTracker.getServices().length > 0) {
_bundleTracker.open();
LOG.debug("Bundle tracker has been opened");
}
}
}

View File

@ -78,8 +78,7 @@ public class OSGiClassLoader extends URLClassLoader
}
if (url == null)
{
{
url = _osgiBundleClassLoader.getResource(name);
if (url == null && name.startsWith("/"))

View File

@ -24,7 +24,9 @@ import org.eclipse.jetty.deploy.DeploymentManager;
/**
* Fix various shortcomings with the way jasper parses the tld files.
* WebappRegistrationCustomizer
*
* Convert bundles that contain tlds into URL locations for consumption by jasper.
*/
public interface WebappRegistrationCustomizer
{
@ -35,25 +37,13 @@ public interface WebappRegistrationCustomizer
*/
public static final String CLASS_NAME = "org.eclipse.jetty.osgi.boot.jasper.WebappRegistrationCustomizerImpl";
/**
* TODO: right now only the jetty-jsp bundle is scanned for common taglibs.
* Should support a way to plug more bundles that contain taglibs.
* Find bundles that contain tlds and convert into URL references to their location.
*
* 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.
*
* 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
* @param manager
* @param fileLocator
* @return array of URLs representing locations of tld containing bundles
* @throws Exception
*/
URL[] getJarsWithTlds(DeploymentManager manager, BundleFileLocatorHelper fileLocator) throws Exception;

View File

@ -28,6 +28,9 @@ import org.eclipse.jetty.util.log.Logger;
import org.osgi.framework.Bundle;
/**
* DefaultBundleClassLoaderHelper
*
*
* Default implementation of the BundleClassLoaderHelper. Uses introspection to
* support equinox-3.5 and felix-2.0.0
*/

View File

@ -36,6 +36,9 @@ import org.eclipse.jetty.util.resource.FileResource;
import org.osgi.framework.Bundle;
/**
* DefaultFileLocatorHelper
*
*
* From a bundle to its location on the filesystem. Assumes the bundle is not a
* jar.
*

View File

@ -35,6 +35,9 @@ import org.osgi.service.packageadmin.PackageAdmin;
import org.osgi.service.startlevel.StartLevel;
/**
* PackageAdminServiceTracker
*
*
* When the PackageAdmin service is activated we can look for the fragments
* attached to this bundle and "activate" them.
*/