KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > ajp > tomcat4 > config > BaseJkConfig


1 /*
2  * Copyright 1999-2004 The Apache Software Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.apache.ajp.tomcat4.config;
18
19 import java.io.File JavaDoc;
20 import java.io.IOException JavaDoc;
21 import java.io.PrintWriter JavaDoc;
22
23 import org.apache.catalina.Container;
24 import org.apache.catalina.Context;
25 import org.apache.catalina.Engine;
26 import org.apache.catalina.Host;
27 import org.apache.catalina.Lifecycle;
28 import org.apache.catalina.LifecycleEvent;
29 import org.apache.catalina.LifecycleListener;
30 import org.apache.catalina.Server;
31
32
33 /**
34     Base class for automatic jk based configurations based on
35     the Tomcat server.xml settings and the war contexts
36     initialized during startup.
37     <p>
38     This config interceptor is enabled by inserting a Config
39     element in the <b>&lt;ContextManager&gt;</b> tag body inside
40     the server.xml file like so:
41     <pre>
42     * < ContextManager ... >
43     * ...
44     * <<b>???Config</b> <i>options</i> />
45     * ...
46     * < /ContextManager >
47     </pre>
48     where <i>options</i> can include any of the following attributes:
49     <ul>
50      <li><b>configHome</b> - default parent directory for the following paths.
51                              If not set, this defaults to TOMCAT_HOME. Ignored
52                              whenever any of the following paths is absolute.
53                              </li>
54      <li><b>workersConfig</b> - path to workers.properties file used by
55                                 jk connector. If not set, defaults to
56                                 "conf/jk/workers.properties".</li>
57      <li><b>jkLog</b> - path to log file to be used by jk connector.</li>
58      <li><b>jkDebug</b> - Loglevel setting. May be debug, info, error, or emerg.
59                           If not set, defaults to emerg.</li>
60      <li><b>jkWorker</b> The desired worker. Must be set to one of the workers
61                          defined in the workers.properties file. "ajp12", "ajp13"
62                          or "inprocess" are the workers found in the default
63                          workers.properties file. If not specified, defaults
64                          to "ajp13" if an Ajp13Interceptor is in use, otherwise
65                          it defaults to "ajp12".</li>
66      <li><b>forwardAll</b> - If true, forward all requests to Tomcat. This helps
67                              insure that all the behavior configured in the web.xml
68                              file functions correctly. If false, let Apache serve
69                              static resources. The default is true.
70                              Warning: When false, some configuration in
71                              the web.xml may not be duplicated in Apache.
72                              Review the mod_jk conf file to see what
73                              configuration is actually being set in Apache.</li>
74      <li><b>noRoot</b> - If true, the root context is not mapped to
75                          Tomcat. If false and forwardAll is true, all requests
76                          to the root context are mapped to Tomcat. If false and
77                          forwardAll is false, only JSP and servlets requests to
78                          the root context are mapped to Tomcat. When false,
79                          to correctly serve Tomcat's root context you may also
80                          need to modify the web server to point it's home
81                          directory to Tomcat's root context directory.
82                          Otherwise some content, such as the root index.html,
83                          may be served by the web server before the connector
84                          gets a chance to claim the request and pass it to Tomcat.
85                          The default is true.</li>
86     </ul>
87     <p>
88     @author Costin Manolache
89     @author Larry Isaacs
90     @author Bill Barker
91     @version $Revision: 1.8 $
92  */

93 public class BaseJkConfig implements LifecycleListener {
94
95     private static org.apache.commons.logging.Log log=
96         org.apache.commons.logging.LogFactory.getLog( BaseJkConfig.class );
97     
98     protected int debug=0;
99     protected File JavaDoc configHome = null;
100     protected File JavaDoc workersConfig = null;
101
102     protected File JavaDoc jkLog = null;
103     protected String JavaDoc jkDebug="emerg";
104     protected String JavaDoc jkWorker = "ajp13";
105
106     protected boolean noRoot=true;
107     protected boolean forwardAll=true;
108
109     protected String JavaDoc tomcatHome;
110     protected boolean regenerate=false;
111     protected boolean append=false;
112
113     // -------------------- Tomcat callbacks --------------------
114

115
116     // Auto-config should be able to react to dynamic config changes,
117
// and regenerate the config.
118

119     /** Generate the configuration - only when the server is
120      * completely initialized ( before starting )
121      */

122     public void lifecycleEvent(LifecycleEvent evt)
123     {
124     if(Lifecycle.START_EVENT.equals(evt.getType())) {
125        execute( evt );
126     }
127     }
128
129     /** Generate configuration files. Override with method to generate
130         web server specific configuration.
131      */

132     public void execute(LifecycleEvent evt)
133     {
134     initProperties();
135     PrintWriter JavaDoc mod_jk = null;
136     try {
137         mod_jk = getWriter();
138     } catch(IOException JavaDoc iex) {
139         log.warn("Unable to open config file", iex);
140         return;
141     }
142     Lifecycle who = evt.getLifecycle();
143     if( who instanceof Server ) {
144         executeServer((Server)who, mod_jk);
145     } else if ( who instanceof Host ) {
146         executeHost((Host)who, mod_jk);
147     } else if( who instanceof Context ) {
148         executeContext((Context)who, mod_jk);
149     }
150     mod_jk.close();
151     }
152     /** Generate configuration files. Override with method to generate
153         web server specific configuration.
154      */

155     public void executeServer(Server svr, PrintWriter JavaDoc mod_jk) {
156     if(! append ) {
157         if( ! generateJkHead(mod_jk) )
158         return;
159         generateSSLConfig(mod_jk);
160         generateJkTail(mod_jk);
161     }
162     }
163
164     /** Generate SSL options
165      */

166     protected void generateSSLConfig(PrintWriter JavaDoc mod_jk)
167     {
168     }
169     /** Generate general options
170      */

171     protected boolean generateJkHead(PrintWriter JavaDoc mod_jk)
172     {
173     return true;
174     }
175     /** Generate general options
176      */

177     protected void generateJkTail(PrintWriter JavaDoc mod_jk)
178     {
179     }
180     /** Generate Virtual Host start
181      */

182     protected void generateVhostHead(Host host, PrintWriter JavaDoc mod_jk) {
183     }
184     /** Generate Virtual Host end
185      */

186     protected void generateVhostTail(Host host, PrintWriter JavaDoc mod_jk) {
187     }
188     /** Generate configuration files. Override with method to generate
189         web server specific configuration.
190      */

191     protected void executeEngine(Engine egn, PrintWriter JavaDoc mod_jk) {
192     Container [] children = egn.findChildren();
193     for(int ii=0; ii < children.length; ii++) {
194         if( children[ii] instanceof Host ) {
195         executeHost((Host)children[ii], mod_jk);
196         } else if( children[ii] instanceof Context ) {
197         executeContext((Context)children[ii], mod_jk);
198         }
199     }
200     }
201     /** Generate configuration files. Override with method to generate
202         web server specific configuration.
203      */

204     protected void executeHost(Host hst, PrintWriter JavaDoc mod_jk) {
205     generateVhostHead(hst, mod_jk);
206     Container [] children = hst.findChildren();
207     for(int ii=0; ii < children.length; ii++) {
208         if(children[ii] instanceof Context) {
209         executeContext((Context)children[ii],mod_jk);
210         }
211     }
212     generateVhostTail(hst, mod_jk);
213     }
214     /**
215         executes the ApacheConfig interceptor. This method generates apache
216         configuration files for use with mod_jk.
217         <p>
218         @param context a Context object.
219     @param mod_jk Writer for output.
220     */

221     public void executeContext(Context context, PrintWriter JavaDoc mod_jk){
222
223     if(context.getPath().length() > 0 || ! noRoot ) {
224         String JavaDoc docRoot = context.getServletContext().getRealPath("/");
225         if( forwardAll || docRoot == null)
226         generateStupidMappings( context, mod_jk );
227         else
228         generateContextMappings( context, mod_jk);
229     }
230     }
231     protected void generateStupidMappings(Context context, PrintWriter JavaDoc mod_jk){
232     }
233     protected void generateContextMappings(Context context, PrintWriter JavaDoc mod_jk){
234     }
235     /** Get the output Writer. Override with method to generate
236         web server specific configuration.
237      */

238     protected PrintWriter JavaDoc getWriter() throws IOException JavaDoc {
239     return null;
240     }
241     /** Get the host associated with this Container (if any).
242      */

243     protected Host getHost(Container child) {
244     while(child != null && ! (child instanceof Host) ) {
245         child = child.getParent();
246     }
247     return (Host)child;
248     }
249
250     //-------------------- Properties --------------------
251

252     /** Append to config file.
253      * Set to <code>true</code> if the config information should be
254      * appended.
255      */

256     public void setAppend(boolean apnd) {
257     append = apnd;
258     }
259     /** If false, we'll try to generate a config that will
260      * let apache serve static files.
261      * The default is true, forward all requests in a context
262      * to tomcat.
263      */

264     public void setForwardAll( boolean b ) {
265         forwardAll=b;
266     }
267
268     /** Special option - do not generate mappings for the ROOT
269         context. The default is true, and will not generate the mappings,
270         not redirecting all pages to tomcat (since /* matches everything).
271         This means that the web server's root remains intact but isn't
272         completely servlet/JSP enabled. If the ROOT webapp can be configured
273         with the web server serving static files, there's no problem setting
274         this option to false. If not, then setting it true means the web
275         server will be out of picture for all requests.
276     */

277     public void setNoRoot( boolean b ) {
278         noRoot=b;
279     }
280     
281     /**
282         set a path to the parent directory of the
283         conf folder. That is, the parent directory
284         within which path setters would be resolved against,
285         if relative. For example if ConfigHome is set to "/home/tomcat"
286         and regConfig is set to "conf/mod_jk.conf" then the resulting
287         path used would be:
288         "/home/tomcat/conf/mod_jk.conf".</p>
289         <p>
290         However, if the path is set to an absolute path,
291         this attribute is ignored.
292         <p>
293         If not set, execute() will set this to TOMCAT_HOME.
294         <p>
295         @param dir - path to a directory
296     */

297     public void setConfigHome(String JavaDoc dir){
298         if( dir==null ) return;
299         File JavaDoc f=new File JavaDoc(dir);
300         if(!f.isDirectory()){
301             throw new IllegalArgumentException JavaDoc(
302                 "BaseConfig.setConfigHome(): "+
303                 "Configuration Home must be a directory! : "+dir);
304         }
305         configHome = f;
306     }
307
308     /**
309         set a path to the workers.properties file.
310         @param path String path to workers.properties file
311     */

312     public void setWorkersConfig(String JavaDoc path){
313         workersConfig= (path==null?null:new File JavaDoc(path));
314     }
315
316     /**
317         set the path to the log file
318         @param path String path to a file
319     */

320     public void setJkLog(String JavaDoc path){
321         jkLog= ( path==null?null:new File JavaDoc(path));
322     }
323
324     /** Set the verbosity level
325         ( use debug, error, etc. ) If not set, no log is written.
326      */

327     public void setJkDebug( String JavaDoc level ) {
328         jkDebug=level;
329     }
330
331     /**
332         Set the AJP worker.
333         @param worker The worker name
334      */

335     public void setJkWorker(String JavaDoc worker){
336         jkWorker = worker;
337     }
338
339     // -------------------- Initialize/guess defaults --------------------
340

341     /** Initialize defaults for properties that are not set
342         explicitely
343     */

344     protected void initProperties() {
345         tomcatHome = System.getProperty("catalina.home");
346         File JavaDoc tomcatDir = new File JavaDoc(tomcatHome);
347         if(configHome==null){
348             configHome=tomcatDir;
349         }
350     }
351
352     // -------------------- Config Utils --------------------
353

354
355     /** Add an extension mapping. Override with method to generate
356         web server specific configuration
357      */

358     protected boolean addExtensionMapping( String JavaDoc ctxPath, String JavaDoc ext,
359                      PrintWriter JavaDoc pw )
360     {
361     return true;
362     }
363     
364     
365     /** Add a fulling specified mapping. Override with method to generate
366         web server specific configuration
367      */

368     protected boolean addMapping( String JavaDoc fullPath, PrintWriter JavaDoc pw ) {
369     return true;
370     }
371
372     // -------------------- General Utils --------------------
373

374     protected String JavaDoc getAbsoluteDocBase(Context context)
375     {
376     // Calculate the absolute path of the document base
377
String JavaDoc docBase = context.getServletContext().getRealPath("/");
378     docBase = docBase.substring(0,docBase.length()-1);
379     if (!isAbsolute(docBase)){
380         docBase = tomcatHome + "/" + docBase;
381     }
382     docBase = patch(docBase);
383         return docBase;
384     }
385
386     // ------------------ Grabbed from FileUtil -----------------
387
public static File JavaDoc getConfigFile( File JavaDoc base, File JavaDoc configDir, String JavaDoc defaultF )
388     {
389         if( base==null )
390             base=new File JavaDoc( defaultF );
391         if( ! base.isAbsolute() ) {
392             if( configDir != null )
393                 base=new File JavaDoc( configDir, base.getPath());
394             else
395                 base=new File JavaDoc( base.getAbsolutePath()); //??
396
}
397         File JavaDoc parent=new File JavaDoc(base.getParent());
398         if(!parent.exists()){
399             if(!parent.mkdirs()){
400                 throw new RuntimeException JavaDoc(
401                     "Unable to create path to config file :"+
402                     base.getAbsolutePath());
403             }
404         }
405         return base;
406     }
407     public static String JavaDoc patch(String JavaDoc path) {
408         String JavaDoc patchPath = path;
409
410         // Move drive spec to the front of the path
411
if (patchPath.length() >= 3 &&
412             patchPath.charAt(0) == '/' &&
413             Character.isLetter(patchPath.charAt(1)) &&
414             patchPath.charAt(2) == ':') {
415             patchPath=patchPath.substring(1,3)+"/"+patchPath.substring(3);
416         }
417
418         // Eliminate consecutive slashes after the drive spec
419
if (patchPath.length() >= 2 &&
420             Character.isLetter(patchPath.charAt(0)) &&
421             patchPath.charAt(1) == ':') {
422             char[] ca = patchPath.replace('/', '\\').toCharArray();
423             char c;
424             StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
425
426             for (int i = 0; i < ca.length; i++) {
427                 if ((ca[i] != '\\') ||
428                     (ca[i] == '\\' &&
429                         i > 0 &&
430                         ca[i - 1] != '\\')) {
431                     if (i == 0 &&
432                         Character.isLetter(ca[i]) &&
433                         i < ca.length - 1 &&
434                         ca[i + 1] == ':') {
435                         c = Character.toUpperCase(ca[i]);
436                     } else {
437                         c = ca[i];
438                     }
439
440                     sb.append(c);
441                 }
442             }
443
444             patchPath = sb.toString();
445         }
446
447     // fix path on NetWare - all '/' become '\\' and remove duplicate '\\'
448
if (System.getProperty("os.name").startsWith("NetWare") &&
449         path.length() >=3 &&
450         path.indexOf(':') > 0) {
451         char[] ca = patchPath.replace('/', '\\').toCharArray();
452         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
453
454         for (int i = 0; i < ca.length; i++) {
455         if ((ca[i] != '\\') ||
456             (ca[i] == '\\' && i > 0 && ca[i - 1] != '\\')) {
457             sb.append(ca[i]);
458         }
459         }
460         patchPath = sb.toString();
461     }
462
463         return patchPath;
464     }
465
466     public static boolean isAbsolute( String JavaDoc path ) {
467     // normal file
468
if( path.startsWith("/" ) ) return true;
469
470     if( path.startsWith(File.separator ) ) return true;
471
472     // win c:
473
if (path.length() >= 3 &&
474             Character.isLetter(path.charAt(0)) &&
475             path.charAt(1) == ':')
476         return true;
477
478     // NetWare volume:
479
if (System.getProperty("os.name").startsWith("NetWare") &&
480         path.length() >=3 &&
481         path.indexOf(':') > 0)
482         return true;
483
484     return false;
485     }
486
487     protected void log(String JavaDoc msg) {
488         log.info(msg);
489     }
490 }
491
Popular Tags