Save This Page
Home » apache-tomcat-6.0.16-src » org.apache » catalina » core » [javadoc | source]
    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one or more
    3    * contributor license agreements.  See the NOTICE file distributed with
    4    * this work for additional information regarding copyright ownership.
    5    * The ASF licenses this file to You under the Apache License, Version 2.0
    6    * (the "License"); you may not use this file except in compliance with
    7    * the License.  You may obtain a copy of the License at
    8    * 
    9    *      http://www.apache.org/licenses/LICENSE-2.0
   10    * 
   11    * Unless required by applicable law or agreed to in writing, software
   12    * distributed under the License is distributed on an "AS IS" BASIS,
   13    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   14    * See the License for the specific language governing permissions and
   15    * limitations under the License.
   16    */
   17   
   18   
   19   package org.apache.catalina.core;
   20   
   21   
   22   import javax.management.MBeanServer;
   23   import javax.management.ObjectName;
   24   
   25   import org.apache.catalina.Container;
   26   import org.apache.catalina.Context;
   27   import org.apache.catalina.Host;
   28   import org.apache.catalina.LifecycleException;
   29   import org.apache.catalina.Valve;
   30   import org.apache.catalina.startup.HostConfig;
   31   import org.apache.catalina.valves.ValveBase;
   32   import org.apache.tomcat.util.modeler.Registry;
   33   
   34   
   35   /**
   36    * Standard implementation of the <b>Host</b> interface.  Each
   37    * child container must be a Context implementation to process the
   38    * requests directed to a particular web application.
   39    *
   40    * @author Craig R. McClanahan
   41    * @author Remy Maucherat
   42    * @version $Revision: 497521 $ $Date: 2007-01-18 19:24:17 +0100 (jeu., 18 janv. 2007) $
   43    */
   44   
   45   public class StandardHost
   46       extends ContainerBase
   47       implements Host  
   48    {
   49       /* Why do we implement deployer and delegate to deployer ??? */
   50   
   51       private static org.apache.juli.logging.Log log=
   52           org.apache.juli.logging.LogFactory.getLog( StandardHost.class );
   53       
   54       // ----------------------------------------------------------- Constructors
   55   
   56   
   57       /**
   58        * Create a new StandardHost component with the default basic Valve.
   59        */
   60       public StandardHost() {
   61   
   62           super();
   63           pipeline.setBasic(new StandardHostValve());
   64   
   65       }
   66   
   67   
   68       // ----------------------------------------------------- Instance Variables
   69   
   70   
   71       /**
   72        * The set of aliases for this Host.
   73        */
   74       private String[] aliases = new String[0];
   75   
   76   
   77       /**
   78        * The application root for this Host.
   79        */
   80       private String appBase = ".";
   81   
   82   
   83       /**
   84        * The auto deploy flag for this Host.
   85        */
   86       private boolean autoDeploy = true;
   87   
   88   
   89       /**
   90        * The Java class name of the default context configuration class
   91        * for deployed web applications.
   92        */
   93       private String configClass =
   94           "org.apache.catalina.startup.ContextConfig";
   95   
   96   
   97       /**
   98        * The Java class name of the default Context implementation class for
   99        * deployed web applications.
  100        */
  101       private String contextClass =
  102           "org.apache.catalina.core.StandardContext";
  103   
  104   
  105       /**
  106        * The deploy on startup flag for this Host.
  107        */
  108       private boolean deployOnStartup = true;
  109   
  110   
  111       /**
  112        * deploy Context XML config files property.
  113        */
  114       private boolean deployXML = true;
  115   
  116   
  117       /**
  118        * The Java class name of the default error reporter implementation class 
  119        * for deployed web applications.
  120        */
  121       private String errorReportValveClass =
  122           "org.apache.catalina.valves.ErrorReportValve";
  123   
  124       /**
  125        * The object name for the errorReportValve.
  126        */
  127       private ObjectName errorReportValveObjectName = null;
  128   
  129       /**
  130        * The descriptive information string for this implementation.
  131        */
  132       private static final String info =
  133           "org.apache.catalina.core.StandardHost/1.0";
  134   
  135   
  136       /**
  137        * The live deploy flag for this Host.
  138        */
  139       private boolean liveDeploy = true;
  140   
  141   
  142       /**
  143        * Unpack WARs property.
  144        */
  145       private boolean unpackWARs = true;
  146   
  147   
  148       /**
  149        * Work Directory base for applications.
  150        */
  151       private String workDir = null;
  152   
  153   
  154       /**
  155        * Attribute value used to turn on/off XML validation
  156        */
  157        private boolean xmlValidation = false;
  158   
  159   
  160       /**
  161        * Attribute value used to turn on/off XML namespace awarenes.
  162        */
  163        private boolean xmlNamespaceAware = false;
  164   
  165   
  166       // ------------------------------------------------------------- Properties
  167   
  168   
  169       /**
  170        * Return the application root for this Host.  This can be an absolute
  171        * pathname, a relative pathname, or a URL.
  172        */
  173       public String getAppBase() {
  174   
  175           return (this.appBase);
  176   
  177       }
  178   
  179   
  180       /**
  181        * Set the application root for this Host.  This can be an absolute
  182        * pathname, a relative pathname, or a URL.
  183        *
  184        * @param appBase The new application root
  185        */
  186       public void setAppBase(String appBase) {
  187   
  188           String oldAppBase = this.appBase;
  189           this.appBase = appBase;
  190           support.firePropertyChange("appBase", oldAppBase, this.appBase);
  191   
  192       }
  193   
  194   
  195       /**
  196        * Return the value of the auto deploy flag.  If true, it indicates that 
  197        * this host's child webapps will be dynamically deployed.
  198        */
  199       public boolean getAutoDeploy() {
  200   
  201           return (this.autoDeploy);
  202   
  203       }
  204   
  205   
  206       /**
  207        * Set the auto deploy flag value for this host.
  208        * 
  209        * @param autoDeploy The new auto deploy flag
  210        */
  211       public void setAutoDeploy(boolean autoDeploy) {
  212   
  213           boolean oldAutoDeploy = this.autoDeploy;
  214           this.autoDeploy = autoDeploy;
  215           support.firePropertyChange("autoDeploy", oldAutoDeploy, 
  216                                      this.autoDeploy);
  217   
  218       }
  219   
  220   
  221       /**
  222        * Return the Java class name of the context configuration class
  223        * for new web applications.
  224        */
  225       public String getConfigClass() {
  226   
  227           return (this.configClass);
  228   
  229       }
  230   
  231   
  232       /**
  233        * Set the Java class name of the context configuration class
  234        * for new web applications.
  235        *
  236        * @param configClass The new context configuration class
  237        */
  238       public void setConfigClass(String configClass) {
  239   
  240           String oldConfigClass = this.configClass;
  241           this.configClass = configClass;
  242           support.firePropertyChange("configClass",
  243                                      oldConfigClass, this.configClass);
  244   
  245       }
  246   
  247   
  248       /**
  249        * Return the Java class name of the Context implementation class
  250        * for new web applications.
  251        */
  252       public String getContextClass() {
  253   
  254           return (this.contextClass);
  255   
  256       }
  257   
  258   
  259       /**
  260        * Set the Java class name of the Context implementation class
  261        * for new web applications.
  262        *
  263        * @param contextClass The new context implementation class
  264        */
  265       public void setContextClass(String contextClass) {
  266   
  267           String oldContextClass = this.contextClass;
  268           this.contextClass = contextClass;
  269           support.firePropertyChange("contextClass",
  270                                      oldContextClass, this.contextClass);
  271   
  272       }
  273   
  274   
  275       /**
  276        * Return the value of the deploy on startup flag.  If true, it indicates 
  277        * that this host's child webapps should be discovred and automatically 
  278        * deployed at startup time.
  279        */
  280       public boolean getDeployOnStartup() {
  281   
  282           return (this.deployOnStartup);
  283   
  284       }
  285   
  286   
  287       /**
  288        * Set the deploy on startup flag value for this host.
  289        * 
  290        * @param deployOnStartup The new deploy on startup flag
  291        */
  292       public void setDeployOnStartup(boolean deployOnStartup) {
  293   
  294           boolean oldDeployOnStartup = this.deployOnStartup;
  295           this.deployOnStartup = deployOnStartup;
  296           support.firePropertyChange("deployOnStartup", oldDeployOnStartup, 
  297                                      this.deployOnStartup);
  298   
  299       }
  300   
  301   
  302       /**
  303        * Deploy XML Context config files flag accessor.
  304        */
  305       public boolean isDeployXML() {
  306   
  307           return (deployXML);
  308   
  309       }
  310   
  311   
  312       /**
  313        * Deploy XML Context config files flag mutator.
  314        */
  315       public void setDeployXML(boolean deployXML) {
  316   
  317           this.deployXML = deployXML;
  318   
  319       }
  320   
  321   
  322       /**
  323        * Return the value of the live deploy flag.  If true, it indicates that 
  324        * a background thread should be started that looks for web application
  325        * context files, WAR files, or unpacked directories being dropped in to
  326        * the <code>appBase</code> directory, and deploys new ones as they are
  327        * encountered.
  328        */
  329       public boolean getLiveDeploy() {
  330           return (this.autoDeploy);
  331       }
  332   
  333   
  334       /**
  335        * Set the live deploy flag value for this host.
  336        * 
  337        * @param liveDeploy The new live deploy flag
  338        */
  339       public void setLiveDeploy(boolean liveDeploy) {
  340           setAutoDeploy(liveDeploy);
  341       }
  342   
  343   
  344       /**
  345        * Return the Java class name of the error report valve class
  346        * for new web applications.
  347        */
  348       public String getErrorReportValveClass() {
  349   
  350           return (this.errorReportValveClass);
  351   
  352       }
  353   
  354   
  355       /**
  356        * Set the Java class name of the error report valve class
  357        * for new web applications.
  358        *
  359        * @param errorReportValveClass The new error report valve class
  360        */
  361       public void setErrorReportValveClass(String errorReportValveClass) {
  362   
  363           String oldErrorReportValveClassClass = this.errorReportValveClass;
  364           this.errorReportValveClass = errorReportValveClass;
  365           support.firePropertyChange("errorReportValveClass",
  366                                      oldErrorReportValveClassClass, 
  367                                      this.errorReportValveClass);
  368   
  369       }
  370   
  371   
  372       /**
  373        * Return the canonical, fully qualified, name of the virtual host
  374        * this Container represents.
  375        */
  376       public String getName() {
  377   
  378           return (name);
  379   
  380       }
  381   
  382   
  383       /**
  384        * Set the canonical, fully qualified, name of the virtual host
  385        * this Container represents.
  386        *
  387        * @param name Virtual host name
  388        *
  389        * @exception IllegalArgumentException if name is null
  390        */
  391       public void setName(String name) {
  392   
  393           if (name == null)
  394               throw new IllegalArgumentException
  395                   (sm.getString("standardHost.nullName"));
  396   
  397           name = name.toLowerCase();      // Internally all names are lower case
  398   
  399           String oldName = this.name;
  400           this.name = name;
  401           support.firePropertyChange("name", oldName, this.name);
  402   
  403       }
  404   
  405   
  406       /**
  407        * Unpack WARs flag accessor.
  408        */
  409       public boolean isUnpackWARs() {
  410   
  411           return (unpackWARs);
  412   
  413       }
  414   
  415   
  416       /**
  417        * Unpack WARs flag mutator.
  418        */
  419       public void setUnpackWARs(boolean unpackWARs) {
  420   
  421           this.unpackWARs = unpackWARs;
  422   
  423       }
  424   
  425        /**
  426        * Set the validation feature of the XML parser used when
  427        * parsing xml instances.
  428        * @param xmlValidation true to enable xml instance validation
  429        */
  430       public void setXmlValidation(boolean xmlValidation){
  431           
  432           this.xmlValidation = xmlValidation;
  433   
  434       }
  435   
  436       /**
  437        * Get the server.xml <host> attribute's xmlValidation.
  438        * @return true if validation is enabled.
  439        *
  440        */
  441       public boolean getXmlValidation(){
  442           return xmlValidation;
  443       }
  444   
  445       /**
  446        * Get the server.xml <host> attribute's xmlNamespaceAware.
  447        * @return true if namespace awarenes is enabled.
  448        *
  449        */
  450       public boolean getXmlNamespaceAware(){
  451           return xmlNamespaceAware;
  452       }
  453   
  454   
  455       /**
  456        * Set the namespace aware feature of the XML parser used when
  457        * parsing xml instances.
  458        * @param xmlNamespaceAware true to enable namespace awareness
  459        */
  460       public void setXmlNamespaceAware(boolean xmlNamespaceAware){
  461           this.xmlNamespaceAware=xmlNamespaceAware;
  462       }    
  463       
  464       /**
  465        * Host work directory base.
  466        */
  467       public String getWorkDir() {
  468   
  469           return (workDir);
  470       }
  471   
  472   
  473       /**
  474        * Host work directory base.
  475        */
  476       public void setWorkDir(String workDir) {
  477   
  478           this.workDir = workDir;
  479       }
  480   
  481   
  482       // --------------------------------------------------------- Public Methods
  483   
  484   
  485       /**
  486        * Add an alias name that should be mapped to this same Host.
  487        *
  488        * @param alias The alias to be added
  489        */
  490       public void addAlias(String alias) {
  491   
  492           alias = alias.toLowerCase();
  493   
  494           // Skip duplicate aliases
  495           for (int i = 0; i < aliases.length; i++) {
  496               if (aliases[i].equals(alias))
  497                   return;
  498           }
  499   
  500           // Add this alias to the list
  501           String newAliases[] = new String[aliases.length + 1];
  502           for (int i = 0; i < aliases.length; i++)
  503               newAliases[i] = aliases[i];
  504           newAliases[aliases.length] = alias;
  505   
  506           aliases = newAliases;
  507   
  508           // Inform interested listeners
  509           fireContainerEvent(ADD_ALIAS_EVENT, alias);
  510   
  511       }
  512   
  513   
  514       /**
  515        * Add a child Container, only if the proposed child is an implementation
  516        * of Context.
  517        *
  518        * @param child Child container to be added
  519        */
  520       public void addChild(Container child) {
  521   
  522           if (!(child instanceof Context))
  523               throw new IllegalArgumentException
  524                   (sm.getString("standardHost.notContext"));
  525           super.addChild(child);
  526   
  527       }
  528   
  529   
  530       /**
  531        * Return the set of alias names for this Host.  If none are defined,
  532        * a zero length array is returned.
  533        */
  534       public String[] findAliases() {
  535   
  536           return (this.aliases);
  537   
  538       }
  539   
  540   
  541       /**
  542        * Return descriptive information about this Container implementation and
  543        * the corresponding version number, in the format
  544        * <code>&lt;description&gt;/&lt;version&gt;</code>.
  545        */
  546       public String getInfo() {
  547   
  548           return (info);
  549   
  550       }
  551   
  552   
  553       /**
  554        * Return the Context that would be used to process the specified
  555        * host-relative request URI, if any; otherwise return <code>null</code>.
  556        *
  557        * @param uri Request URI to be mapped
  558        */
  559       public Context map(String uri) {
  560   
  561           if (log.isDebugEnabled())
  562               log.debug("Mapping request URI '" + uri + "'");
  563           if (uri == null)
  564               return (null);
  565   
  566           // Match on the longest possible context path prefix
  567           if (log.isTraceEnabled())
  568               log.trace("  Trying the longest context path prefix");
  569           Context context = null;
  570           String mapuri = uri;
  571           while (true) {
  572               context = (Context) findChild(mapuri);
  573               if (context != null)
  574                   break;
  575               int slash = mapuri.lastIndexOf('/');
  576               if (slash < 0)
  577                   break;
  578               mapuri = mapuri.substring(0, slash);
  579           }
  580   
  581           // If no Context matches, select the default Context
  582           if (context == null) {
  583               if (log.isTraceEnabled())
  584                   log.trace("  Trying the default context");
  585               context = (Context) findChild("");
  586           }
  587   
  588           // Complain if no Context has been selected
  589           if (context == null) {
  590               log.error(sm.getString("standardHost.mappingError", uri));
  591               return (null);
  592           }
  593   
  594           // Return the mapped Context (if any)
  595           if (log.isDebugEnabled())
  596               log.debug(" Mapped to context '" + context.getPath() + "'");
  597           return (context);
  598   
  599       }
  600   
  601   
  602       /**
  603        * Remove the specified alias name from the aliases for this Host.
  604        *
  605        * @param alias Alias name to be removed
  606        */
  607       public void removeAlias(String alias) {
  608   
  609           alias = alias.toLowerCase();
  610   
  611           synchronized (aliases) {
  612   
  613               // Make sure this alias is currently present
  614               int n = -1;
  615               for (int i = 0; i < aliases.length; i++) {
  616                   if (aliases[i].equals(alias)) {
  617                       n = i;
  618                       break;
  619                   }
  620               }
  621               if (n < 0)
  622                   return;
  623   
  624               // Remove the specified alias
  625               int j = 0;
  626               String results[] = new String[aliases.length - 1];
  627               for (int i = 0; i < aliases.length; i++) {
  628                   if (i != n)
  629                       results[j++] = aliases[i];
  630               }
  631               aliases = results;
  632   
  633           }
  634   
  635           // Inform interested listeners
  636           fireContainerEvent(REMOVE_ALIAS_EVENT, alias);
  637   
  638       }
  639   
  640   
  641       /**
  642        * Return a String representation of this component.
  643        */
  644       public String toString() {
  645   
  646           StringBuffer sb = new StringBuffer();
  647           if (getParent() != null) {
  648               sb.append(getParent().toString());
  649               sb.append(".");
  650           }
  651           sb.append("StandardHost[");
  652           sb.append(getName());
  653           sb.append("]");
  654           return (sb.toString());
  655   
  656       }
  657   
  658   
  659       /**
  660        * Start this host.
  661        *
  662        * @exception LifecycleException if this component detects a fatal error
  663        *  that prevents it from being started
  664        */
  665       public synchronized void start() throws LifecycleException {
  666           if( started ) {
  667               return;
  668           }
  669           if( ! initialized )
  670               init();
  671   
  672           // Look for a realm - that may have been configured earlier. 
  673           // If the realm is added after context - it'll set itself.
  674           if( realm == null ) {
  675               ObjectName realmName=null;
  676               try {
  677                   realmName=new ObjectName( domain + ":type=Realm,host=" + getName());
  678                   if( mserver.isRegistered(realmName ) ) {
  679                       mserver.invoke(realmName, "init", 
  680                               new Object[] {},
  681                               new String[] {}
  682                       );            
  683                   }
  684               } catch( Throwable t ) {
  685                   log.debug("No realm for this host " + realmName);
  686               }
  687           }
  688               
  689           // Set error report valve
  690           if ((errorReportValveClass != null)
  691               && (!errorReportValveClass.equals(""))) {
  692               try {
  693                   boolean found = false;
  694                   if(errorReportValveObjectName != null) {
  695                       ObjectName[] names = 
  696                           ((StandardPipeline)pipeline).getValveObjectNames();
  697                       for (int i=0; !found && i<names.length; i++)
  698                           if(errorReportValveObjectName.equals(names[i]))
  699                               found = true ;
  700                       }
  701                       if(!found) {          	
  702                           Valve valve = (Valve) Class.forName(errorReportValveClass)
  703                           .newInstance();
  704                           addValve(valve);
  705                           errorReportValveObjectName = ((ValveBase)valve).getObjectName() ;
  706                       }
  707               } catch (Throwable t) {
  708                   log.error(sm.getString
  709                       ("standardHost.invalidErrorReportValveClass", 
  710                        errorReportValveClass));
  711               }
  712           }
  713           if(log.isDebugEnabled()) {
  714               if (xmlValidation)
  715                   log.debug(sm.getString("standardHost.validationEnabled"));
  716               else
  717                   log.debug(sm.getString("standardHost.validationDisabled"));
  718           }
  719           super.start();
  720   
  721       }
  722   
  723   
  724       // -------------------- JMX  --------------------
  725       /**
  726         * Return the MBean Names of the Valves assoicated with this Host
  727         *
  728         * @exception Exception if an MBean cannot be created or registered
  729         */
  730        public String [] getValveNames()
  731            throws Exception
  732       {
  733            Valve [] valves = this.getValves();
  734            String [] mbeanNames = new String[valves.length];
  735            for (int i = 0; i < valves.length; i++) {
  736                if( valves[i] == null ) continue;
  737                if( ((ValveBase)valves[i]).getObjectName() == null ) continue;
  738                mbeanNames[i] = ((ValveBase)valves[i]).getObjectName().toString();
  739            }
  740   
  741            return mbeanNames;
  742   
  743        }
  744   
  745       public String[] getAliases() {
  746           return aliases;
  747       }
  748   
  749       private boolean initialized=false;
  750       
  751       public void init() {
  752           if( initialized ) return;
  753           initialized=true;
  754           
  755           // already registered.
  756           if( getParent() == null ) {
  757               try {
  758                   // Register with the Engine
  759                   ObjectName serviceName=new ObjectName(domain + 
  760                                           ":type=Engine");
  761   
  762                   HostConfig deployer = new HostConfig();
  763                   addLifecycleListener(deployer);                
  764                   if( mserver.isRegistered( serviceName )) {
  765                       if(log.isDebugEnabled())
  766                           log.debug("Registering "+ serviceName +" with the Engine");
  767                       mserver.invoke( serviceName, "addChild",
  768                               new Object[] { this },
  769                               new String[] { "org.apache.catalina.Container" } );
  770                   }
  771               } catch( Exception ex ) {
  772                   log.error("Host registering failed!",ex);
  773               }
  774           }
  775           
  776           if( oname==null ) {
  777               // not registered in JMX yet - standalone mode
  778               try {
  779                   StandardEngine engine=(StandardEngine)parent;
  780                   domain=engine.getName();
  781                   if(log.isDebugEnabled())
  782                       log.debug( "Register host " + getName() + " with domain "+ domain );
  783                   oname=new ObjectName(domain + ":type=Host,host=" +
  784                           this.getName());
  785                   controller = oname;
  786                   Registry.getRegistry(null, null)
  787                       .registerComponent(this, oname, null);
  788               } catch( Throwable t ) {
  789                   log.error("Host registering failed!", t );
  790               }
  791           }
  792       }
  793   
  794       public void destroy() throws Exception {
  795           // destroy our child containers, if any
  796           Container children[] = findChildren();
  797           super.destroy();
  798           for (int i = 0; i < children.length; i++) {
  799               if(children[i] instanceof StandardContext)
  800                   ((StandardContext)children[i]).destroy();
  801           }
  802         
  803       }
  804       
  805       public ObjectName preRegister(MBeanServer server, ObjectName oname ) 
  806           throws Exception
  807       {
  808           ObjectName res=super.preRegister(server, oname);
  809           String name=oname.getKeyProperty("host");
  810           if( name != null )
  811               setName( name );
  812           return res;        
  813       }
  814       
  815       public ObjectName createObjectName(String domain, ObjectName parent)
  816           throws Exception
  817       {
  818           if( log.isDebugEnabled())
  819               log.debug("Create ObjectName " + domain + " " + parent );
  820           return new ObjectName( domain + ":type=Host,host=" + getName());
  821       }
  822   
  823   }

Save This Page
Home » apache-tomcat-6.0.16-src » org.apache » catalina » core » [javadoc | source]