JettyJWebContainerServiceImpl.java

00001 
00027 package org.objectweb.jonas.web.jetty50;
00028 
00029 import java.io.File;
00030 import java.io.IOException;
00031 import java.net.URL;
00032 import java.net.URLClassLoader;
00033 import java.util.Map;
00034 import java.util.StringTokenizer;
00035 import java.util.Vector;
00036 
00037 import javax.management.ObjectName;
00038 import javax.naming.Context;
00039 import javax.naming.NamingException;
00040 
00041 import org.objectweb.util.monolog.api.BasicLevel;
00042 
00043 import org.objectweb.jonas.jmx.JmxService;
00044 import org.objectweb.jonas.jmx.JonasObjectName;
00045 import org.objectweb.jonas.service.ServiceException;
00046 import org.objectweb.jonas.service.ServiceManager;
00047 import org.objectweb.jonas.web.AbsJWebContainerServiceImpl;
00048 import org.objectweb.jonas.web.JWebContainerServiceException;
00049 
00050 import org.mortbay.http.HttpContext;
00051 import org.mortbay.http.HttpListener;
00052 import org.mortbay.jetty.Server;
00053 import org.mortbay.jetty.servlet.WebApplicationContext;
00054 
00061 public class JettyJWebContainerServiceImpl extends AbsJWebContainerServiceImpl {
00062 
00066     private static final String JETTY_DEFAULT_WEB_XML_FILE = AbsJWebContainerServiceImpl.JONAS_BASE + File.separator + "conf" + File.separator + "jetty5-webdefault.xml";
00067 
00071     private static String config = null;
00072 
00076     private static final String JETTY_CONFIG = "config";
00077 
00081     private Server jettyServer = null;
00082 
00088     protected void doInit(javax.naming.Context ctx) throws ServiceException {
00089 
00090         super.doInit(ctx);
00091 
00092         String strJettyHome = System.getProperty("jetty.home");
00093         if (strJettyHome != null) {
00094             getLogger().log(BasicLevel.DEBUG, "");
00095 
00096             try {
00097                 config = (String) ctx.lookup(JETTY_CONFIG);
00098             } catch (NamingException neExc) {
00099                 // by default we take jetty5.xml under JONAS_BASE/conf
00100                 String jonasbase = System.getProperties().getProperty("jonas.base");
00101                 config = jonasbase + "/conf/jetty5.xml";
00102             }
00103             getLogger().log(BasicLevel.LEVEL_DEBUG, "using configuration file " + config);
00104 
00105             jettyServer = new Server();
00106         }
00107 
00108     }
00109 
00114     public void doStart() throws ServiceException {
00115         getLogger().log(BasicLevel.DEBUG, "");
00116 
00117         if (jettyServer != null) {
00118             JmxService srvcJMX = null;
00119 
00120             // Start Jetty directly and just pass it to JMX if available
00121             if (config != null) {
00122                 try {
00123                     jettyServer.configure(config);
00124                     jettyServer.start();
00125                 } catch (Exception eExc) {
00126                     getLogger().log(BasicLevel.LEVEL_ERROR,
00127                             "error has occured while starting Jetty server using configuration file " + config, eExc);
00128                 }
00129             }
00130 
00131             ServiceManager sm = null;
00132             try {
00133                 sm = ServiceManager.getInstance();
00134             } catch (Exception e) {
00135                 String err = "Cannot get ServiceManager instance.";
00136                 getLogger().log(BasicLevel.ERROR, err);
00137                 throw new ServiceException(err, e);
00138             }
00139 
00140             try {
00141                 srvcJMX = (JmxService) sm.getJmxService();
00142                 if (srvcJMX != null) {
00143                     // Register JettyService MBean : JettyService
00144                     Object obj;
00145                     ObjectName objname;
00146                     // Once we register this bean, it will start Jetty using
00147                     // given configuration
00148                     // file. That's why we have to do it in run() instead in
00149                     // doStart()
00150                     obj = new JettyJonasServerMBean(jettyServer);
00151                     objname = JonasObjectName.wwwService();
00152                     srvcJMX.getJmxServer().registerMBean(obj, objname);
00153                 }
00154             } catch (ServiceException seExc) {
00155                 // Jmx Service not available, do nothing
00156                 getLogger().log(
00157                         BasicLevel.LEVEL_DEBUG,
00158                         "cannot start Jetty server using configuration file " + config
00159                                 + " using JMX. Will start without JMX.", seExc);
00160             } catch (Exception eExc) {
00161                 getLogger().log(BasicLevel.LEVEL_ERROR, "cannot start Jetty server using configuration file " + config,
00162                         eExc);
00163                 throw new ServiceException("Cannot start Jetty server using configuration file " + config, eExc);
00164             }
00165 
00166             // ... and deploy wars of the jonas.properties
00167             super.doStart();
00168         } else {
00169             throw new ServiceException("Cannot start Jetty server.");
00170         }
00171     }
00172 
00177     protected void doStop() throws ServiceException {
00178         // Undeploy the wars ...
00179         super.doStop();
00180 
00181         // ... and shut down embedded jetty
00182         getLogger().log(BasicLevel.DEBUG, "");
00183         if (isStarted()) {
00184             JmxService srvcJMX = null;
00185 
00186             ServiceManager sm = null;
00187             try {
00188                 sm = ServiceManager.getInstance();
00189             } catch (Exception e) {
00190                 String err = "Cannot get ServiceManager instance.";
00191                 getLogger().log(BasicLevel.ERROR, err);
00192                 throw new ServiceException(err, e);
00193             }
00194 
00195             try {
00196                 srvcJMX = (JmxService) sm.getJmxService();
00197                 if (srvcJMX != null) {
00198                     ObjectName objname;
00199 
00200                     objname = new ObjectName("jonas:type=service,name=jetty");
00201                     srvcJMX.getJmxServer().unregisterMBean(objname);
00202                     jettyServer = null;
00203                     objname = new ObjectName("jonas:type=jetty,name=jettylog");
00204                     srvcJMX.getJmxServer().unregisterMBean(objname);
00205                     objname = new ObjectName("jonas:type=jetty,name=jettycode");
00206                     srvcJMX.getJmxServer().unregisterMBean(objname);
00207                 }
00208             } catch (ServiceException seExc) {
00209                 getLogger().log(BasicLevel.LEVEL_ERROR, "JMX Service not available", seExc);
00210             } catch (Exception eExc) {
00211                 getLogger().log(BasicLevel.LEVEL_ERROR, "Cannot stop Jetty server", eExc);
00212                 throw new ServiceException("Cannot stop Jetty server", eExc);
00213             }
00214 
00215             if (jettyServer != null) {
00216                 try {
00217                     jettyServer.stop();
00218                     jettyServer.destroy();
00219                     jettyServer = null;
00220                 } catch (Exception eExc) {
00221                     getLogger().log(BasicLevel.LEVEL_ERROR,
00222                             "error has occured while stopping Jetty server using configuration file " + config, eExc);
00223                 }
00224             }
00225         }
00226     }
00227 
00236     protected void doRegisterWar(Context ctx) throws JWebContainerServiceException {
00237         // Get the 5 parameters :
00238         //   - warURL is the URL of the war to register (required param).
00239         //   - contextRoot is the context root to which this application
00240         // should be installed (must be unique) (required param).
00241         //   - hostName is the name of the host on which deploy the war
00242         // (optional param taken into account only if no <context> element
00243         //  was declared in server.xml for this web application) .
00244         //   - java2DelegationModel the compliance to java2 delegation model
00245         //   - parentCL the war classloader of this war.
00246         //URL warURL = null;
00247         URL unpackedWarURL = null;
00248         String contextRoot = null;
00249         boolean java2DelegationModel = true;
00250         try {
00251             unpackedWarURL = (URL) ctx.lookup("unpackedWarURL");
00252             contextRoot = (String) ctx.lookup("contextRoot");
00253             Boolean bool = (Boolean) ctx.lookup("java2DelegationModel");
00254             java2DelegationModel = bool.booleanValue();
00255         } catch (NamingException e) {
00256             String err = "Error while getting parameter from context param ";
00257             getLogger().log(BasicLevel.ERROR, err + e.getMessage());
00258             throw new JWebContainerServiceException(err, e);
00259         }
00260 
00261         ClassLoader webClassLoader = null;
00262         try {
00263             webClassLoader = (ClassLoader) ctx.lookup("parentCL");
00264         } catch (NamingException e) {
00265             String err = "error while getting parameter from context param ";
00266             getLogger().log(BasicLevel.ERROR, err + e.getMessage());
00267             throw new JWebContainerServiceException(err, e);
00268         }
00269 
00270         String hostName = null;
00271         try {
00272             hostName = (String) ctx.lookup("hostName");
00273         } catch (NamingException e) {
00274             hostName = "";
00275         }
00276 
00277         // Install a new web application, whose web application archive is
00278         // at the specified URL, into this container with the specified
00279         // context root.
00280         // A context root of "" (the empty string) should be used for the root
00281         // application for this container. Otherwise, the context root must
00282         // start with a slash.
00283 
00284         if (contextRoot.equals("/")) {
00285             contextRoot = "";
00286         } else if (contextRoot.equalsIgnoreCase("ROOT")) {
00287             // Jetty uses ROOT.war and ROOT directory to as root context
00288             contextRoot = "";
00289         }
00290 
00291         // install the war.
00292         File fWar = new File(unpackedWarURL.getFile());
00293         String fileName = fWar.getAbsolutePath();
00294 
00295         if (jettyServer != null) {
00296             try {
00297                 WebApplicationContext contextWebApp;
00298 
00299                 if ((hostName == null) || (hostName.length() == 0)) {
00300                     // There is no host
00301                     getLogger().log(BasicLevel.DEBUG,
00302                             "Jetty server installing web app " + fileName + " and context " + contextRoot);
00303                     contextWebApp = jettyServer.addWebApplication(contextRoot, fileName);
00304                 } else {
00305                     // Host was specified
00306                     getLogger().log(
00307                             BasicLevel.DEBUG,
00308                             "Jetty server installing web app " + fileName + " on host " + hostName + " and context "
00309                                     + contextRoot);
00310                     contextWebApp = jettyServer.addWebApplication(hostName, contextRoot, fileName);
00311                 }
00312 
00313                 // Add default xml descriptor
00314                 if (new File(JETTY_DEFAULT_WEB_XML_FILE).exists()) {
00315                     contextWebApp.setDefaultsDescriptor(JETTY_DEFAULT_WEB_XML_FILE);
00316                 } else {
00317                     getLogger().log(BasicLevel.WARN, "The file '" + JETTY_DEFAULT_WEB_XML_FILE + "' is not present. Check that your JONAS_BASE is up-to-date.");
00318                 }
00319 
00320                 // Specifying the jsp class path used by jasper
00321                 contextWebApp.setAttribute("org.apache.catalina.jsp_classpath", getJOnASClassPath(webClassLoader));
00322 
00323                 // Set the parent class loader
00324                 contextWebApp.setParentClassLoader(webClassLoader);
00325 
00326                 // Set this classloader to the Java2 compliant mode ?
00327                 contextWebApp.setClassLoaderJava2Compliant(java2DelegationModel);
00328 
00329                 getLogger().log(BasicLevel.DEBUG,
00330                         "Webapp class loader java 2 delegation model set to " + java2DelegationModel);
00331 
00332                 getLogger().log(BasicLevel.DEBUG, "Jetty server starting web app " + fileName);
00333                 contextWebApp.start();
00334                 getLogger().log(BasicLevel.DEBUG, "Jetty server is running web app " + fileName);
00335 
00336             } catch (IOException ioeExc) {
00337                 String err = "Cannot install this web application " + ioeExc;
00338                 getLogger().log(BasicLevel.ERROR, err);
00339                 throw new JWebContainerServiceException(err, ioeExc);
00340             } catch (Exception eExc) {
00341                 String err = "Cannot start this web application " + eExc;
00342                 getLogger().log(BasicLevel.ERROR, err);
00343                 throw new JWebContainerServiceException(err, eExc);
00344             }
00345         } else {
00346             getLogger().log(BasicLevel.DEBUG, "No Jetty server to install web app " + fileName);
00347         }
00348     }
00349 
00356     public String getJOnASClassPath(ClassLoader webClassLoader) {
00357 
00358         StringBuffer classpath = new StringBuffer();
00359         int n = 0;
00360         while (webClassLoader != null) {
00361             if (!(webClassLoader instanceof URLClassLoader)) {
00362                 break;
00363             }
00364             URL[] repositories = ((URLClassLoader) webClassLoader).getURLs();
00365             for (int i = 0; i < repositories.length; i++) {
00366                 String repository = repositories[i].toString();
00367                 if (repository.startsWith("file://")) {
00368                     repository = repository.substring("file://".length());
00369                 } else if (repository.startsWith("file:")) {
00370                     repository = repository.substring("file:".length());
00371                 } else {
00372                     continue;
00373                 }
00374                 if (repository == null) {
00375                     continue;
00376                 }
00377                 if (n > 0) {
00378                     classpath.append(File.pathSeparator);
00379                 }
00380                 classpath.append(repository);
00381                 n++;
00382             }
00383             webClassLoader = webClassLoader.getParent();
00384         }
00385 
00386         return classpath.toString();
00387     }
00388 
00395     protected void doUnRegisterWar(Context ctx) throws JWebContainerServiceException {
00396         // Get the 2 parameters :
00397         //   - contextRoot is the context root to be removed (required param).
00398         //   - hostName is the name of the host to remove the war (optional).
00399         String contextRoot = null;
00400         try {
00401             contextRoot = (String) ctx.lookup("contextRoot");
00402         } catch (NamingException e) {
00403             String err = "Error while getting parameter from context param ";
00404             getLogger().log(BasicLevel.ERROR, err + e.getMessage());
00405             throw new JWebContainerServiceException(err, e);
00406         }
00407 
00408         String hostName = null;
00409         try {
00410             hostName = (String) ctx.lookup("hostName");
00411         } catch (NamingException e) {
00412             hostName = "";
00413         }
00414         // A context root of "" (the empty string) should be used for the root
00415         // application for this container. Otherwise, the context root must
00416         // start with a slash.
00417 
00418         if (contextRoot.equals("/")) {
00419             contextRoot = "";
00420         } else if (contextRoot.equalsIgnoreCase("ROOT")) {
00421             // Jetty uses ROOT.war and ROOT directory to as root context
00422             contextRoot = "";
00423         }
00424 
00425         if (jettyServer != null) {
00426             HttpContext contextWebApp;
00427 
00428             if ((hostName == null) || (hostName.length() == 0)) {
00429                 // There is no host
00430                 getLogger().log(BasicLevel.DEBUG, "Jetty server looking upweb app " + " from context " + contextRoot);
00431                 contextWebApp = jettyServer.getContext(contextRoot);
00432             } else {
00433                 // Host was specified
00434                 getLogger().log(BasicLevel.DEBUG,
00435                         "Jetty server looking up web app " + " on host " + hostName + " and context " + contextRoot);
00436                 contextWebApp = jettyServer.getContext(hostName, contextRoot);
00437             }
00438 
00439             if (contextWebApp != null) {
00440                 getLogger().log(BasicLevel.DEBUG,
00441                         "Jetty server found and is stopping web app at context " + contextRoot);
00442 
00443                 // Stop it gracefully
00444                 try {
00445                     contextWebApp.stop(true);
00446                 } catch (InterruptedException ieExc) {
00447                     getLogger().log(BasicLevel.LEVEL_DEBUG,
00448                             "Jetty server encoutered exception while stopping web application ", ieExc);
00449                 }
00450 
00451                 getLogger().log(BasicLevel.DEBUG,
00452                         "Jetty server stopped and is removing web app at context " + contextRoot);
00453 
00454                 jettyServer.removeContext(contextWebApp);
00455 
00456                 getLogger().log(BasicLevel.DEBUG,
00457                         "Jetty server removed and is destroying web app at context " + contextRoot);
00458 
00459                 contextWebApp.destroy();
00460 
00461                 getLogger().log(BasicLevel.DEBUG, "Jetty server unloaded web app at context " + contextRoot);
00462 
00463             } else {
00464                 getLogger().log(BasicLevel.DEBUG, "Jetty server didn't find web app at context " + contextRoot);
00465             }
00466 
00467         } else {
00468             getLogger().log(BasicLevel.DEBUG, "No Jetty server to install web app at context " + contextRoot);
00469         }
00470     }
00471 
00475     protected void updateServerInfos() {
00476         String infos = org.mortbay.http.Version.getImplVersion();
00477 
00478         StringTokenizer st = new StringTokenizer(infos, "/");
00479         if (st.countTokens() != 2) {
00480             setServerName(infos);
00481             setServerVersion("");
00482         } else {
00483             setServerName(st.nextToken());
00484             setServerVersion(st.nextToken());
00485         }
00486     }
00487 
00494     public String getDefaultHost() throws JWebContainerServiceException {
00495         Map hosts = jettyServer.getHostMap();
00496         // If we have more than 1 host, we cannot determine default host!
00497         if (hosts.size() != 1) {
00498             String err = "Cannot determine default host :" + " Jetty server has more than 1 host";
00499             throw new JWebContainerServiceException(err);
00500         }
00501         String vHost = (String) hosts.keySet().iterator().next();
00502         if (vHost == null) {
00503             return "localhost";
00504         } else {
00505             return vHost;
00506         }
00507     }
00508 
00516     public String getDefaultHttpPort() throws JWebContainerServiceException {
00517         HttpListener[] listeners = jettyServer.getListeners();
00518         Vector http = new Vector();
00519         for (int i = 0; i < listeners.length; i++) {
00520             String scheme = listeners[i].getDefaultScheme();
00521             if (scheme.equalsIgnoreCase("http")) {
00522                 http.add(listeners[i]);
00523             }
00524         }
00525 
00526         if (http.size() != 1) {
00527             String err = "Cannot determine default http port :" + " Jetty server has more (or zero) HTTP Listener";
00528             throw new JWebContainerServiceException(err);
00529         }
00530 
00531         return new String("" + ((HttpListener) http.get(0)).getPort());
00532     }
00533 
00541     public String getDefaultHttpsPort() throws JWebContainerServiceException {
00542         HttpListener[] listeners = jettyServer.getListeners();
00543         Vector http = new Vector();
00544         for (int i = 0; i < listeners.length; i++) {
00545             String scheme = listeners[i].getDefaultScheme();
00546             if (scheme.equalsIgnoreCase("https")) {
00547                 http.add(listeners[i]);
00548             }
00549         }
00550 
00551         if (http.size() != 1) {
00552             String err = "Cannot determine default http port :" + " Jetty server has more (or zero) HTTPS Listener";
00553             throw new JWebContainerServiceException(err);
00554         }
00555 
00556         return new String("" + ((HttpListener) http.get(0)).getPort());
00557     }
00558 
00559 }
00560 

Generated on Tue Feb 15 15:05:25 2005 for JOnAS by  doxygen 1.3.9.1