Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/apache/ajp/tomcat4/config/BaseJkConfig.java


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;
20  import java.io.IOException;
21  import java.io.PrintWriter;
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: 299797 $
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 configHome = null;
100     protected File workersConfig = null;
101 
102     protected File jkLog = null;
103     protected String jkDebug="emerg";
104     protected String jkWorker = "ajp13";
105 
106     protected boolean noRoot=true;
107     protected boolean forwardAll=true;
108 
109     protected String 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 mod_jk = null;
136   try {
137       mod_jk = getWriter();
138   } catch(IOException 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 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 mod_jk)
167     {
168     }
169     /** Generate general options
170      */
171     protected boolean generateJkHead(PrintWriter mod_jk)
172     {
173   return true;
174     }
175     /** Generate general options
176      */
177     protected void generateJkTail(PrintWriter mod_jk)
178     {
179     }
180     /** Generate Virtual Host start
181      */
182     protected void generateVhostHead(Host host, PrintWriter mod_jk) {
183     }
184     /** Generate Virtual Host end
185      */
186     protected void generateVhostTail(Host host, PrintWriter 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 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 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 mod_jk){
222 
223   if(context.getPath().length() > 0 || ! noRoot ) {
224       String 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 mod_jk){
232     }
233     protected void generateContextMappings(Context context, PrintWriter mod_jk){
234     }
235     /** Get the output Writer.  Override with method to generate
236         web server specific configuration.
237      */
238     protected PrintWriter getWriter() throws IOException {
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 dir){
298         if( dir==null ) return;
299         File f=new File(dir);
300         if(!f.isDirectory()){
301             throw new IllegalArgumentException(
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 path){
313         workersConfig= (path==null?null:new File(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 path){
321         jkLog= ( path==null?null:new File(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 level ) {
328         jkDebug=level;
329     }
330 
331     /**
332         Set the AJP worker.
333         @param worker The worker name
334      */
335     public void setJkWorker(String 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 tomcatDir = new File(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 ctxPath, String ext,
359            PrintWriter 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 fullPath, PrintWriter pw ) {
369   return true;
370     }
371 
372     // -------------------- General Utils --------------------
373 
374     protected String getAbsoluteDocBase(Context context)
375     {
376   // Calculate the absolute path of the document base
377   String 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 getConfigFile( File base, File configDir, String defaultF )
388     {
389         if( base==null )
390             base=new File( defaultF );
391         if( ! base.isAbsolute() ) {
392             if( configDir != null )
393                 base=new File( configDir, base.getPath());
394             else
395                 base=new File( base.getAbsolutePath()); //??
396         }
397         File parent=new File(base.getParent());
398         if(!parent.exists()){
399             if(!parent.mkdirs()){
400                 throw new RuntimeException(
401                     "Unable to create path to config file :"+
402                     base.getAbsolutePath());
403             }
404         }
405         return base;
406     }
407     public static String patch(String path) {
408         String 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 sb = new StringBuffer();
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 sb = new StringBuffer();
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 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 msg) {
488         log.info(msg);
489     }
490 }