KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > catalina > core > StandardHost


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 JavaDoc;
23 import javax.management.ObjectName JavaDoc;
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: 467222 $ $Date: 2006-10-24 05:17:11 +0200 (mar., 24 oct. 2006) $
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.commons.logging.Log log=
52         org.apache.commons.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 JavaDoc[] aliases = new String JavaDoc[0];
75
76
77     /**
78      * The application root for this Host.
79      */

80     private String JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc errorReportValveClass =
122         "org.apache.catalina.valves.ErrorReportValve";
123
124     /**
125      * The object name for the errorReportValve.
126      */

127     private ObjectName JavaDoc errorReportValveObjectName = null;
128
129     /**
130      * The descriptive information string for this implementation.
131      */

132     private static final String JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc appBase) {
187
188         String JavaDoc 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 JavaDoc 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 JavaDoc configClass) {
239
240         String JavaDoc 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 JavaDoc 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 JavaDoc contextClass) {
266
267         String JavaDoc 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 JavaDoc 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 JavaDoc errorReportValveClass) {
362
363         String JavaDoc 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 JavaDoc 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 JavaDoc name) {
392
393         if (name == null)
394             throw new IllegalArgumentException JavaDoc
395                 (sm.getString("standardHost.nullName"));
396
397         name = name.toLowerCase(); // Internally all names are lower case
398

399         String JavaDoc 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 JavaDoc getWorkDir() {
468
469         return (workDir);
470     }
471
472
473     /**
474      * Host work directory base.
475      */

476     public void setWorkDir(String JavaDoc 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 JavaDoc 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 JavaDoc newAliases[] = new String JavaDoc[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 JavaDoc
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 JavaDoc[] 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 JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc results[] = new String JavaDoc[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 JavaDoc toString() {
645
646         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
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 JavaDoc realmName=null;
676             try {
677                 realmName=new ObjectName JavaDoc( domain + ":type=Realm,host=" + getName());
678                 if( mserver.isRegistered(realmName ) ) {
679                     mserver.invoke(realmName, "init",
680                             new Object JavaDoc[] {},
681                             new String JavaDoc[] {}
682                     );
683                 }
684             } catch( Throwable JavaDoc 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 JavaDoc[] 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 JavaDoc t) {
708                 log.error(sm.getString
709                     ("standardHost.invalidErrorReportValveClass",
710                      errorReportValveClass));
711             }
712         }
713         if(log.isInfoEnabled()) {
714             if (xmlValidation)
715                 log.info( sm.getString("standardHost.validationEnabled"));
716             else
717                 log.info( 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 JavaDoc [] getValveNames()
731          throws Exception JavaDoc
732     {
733          Valve [] valves = this.getValves();
734          String JavaDoc [] mbeanNames = new String JavaDoc[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 JavaDoc[] 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 JavaDoc serviceName=new ObjectName JavaDoc(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 JavaDoc[] { this },
769                             new String JavaDoc[] { "org.apache.catalina.Container" } );
770                 }
771             } catch( Exception JavaDoc 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 JavaDoc(domain + ":type=Host,host=" +
784                         this.getName());
785                 controller = oname;
786                 Registry.getRegistry(null, null)
787                     .registerComponent(this, oname, null);
788             } catch( Throwable JavaDoc t ) {
789                 log.error("Host registering failed!", t );
790             }
791         }
792     }
793
794     public void destroy() throws Exception JavaDoc {
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 JavaDoc preRegister(MBeanServer JavaDoc server, ObjectName JavaDoc oname )
806         throws Exception JavaDoc
807     {
808         ObjectName JavaDoc res=super.preRegister(server, oname);
809         String JavaDoc name=oname.getKeyProperty("host");
810         if( name != null )
811             setName( name );
812         return res;
813     }
814     
815     public ObjectName JavaDoc createObjectName(String JavaDoc domain, ObjectName JavaDoc parent)
816         throws Exception JavaDoc
817     {
818         if( log.isDebugEnabled())
819             log.debug("Create ObjectName " + domain + " " + parent );
820         return new ObjectName JavaDoc( domain + ":type=Host,host=" + getName());
821     }
822
823 }
824
Popular Tags