KickJava   Java API By Example, From Geeks To Geeks.

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


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.FileWriter JavaDoc;
21 import java.io.IOException JavaDoc;
22 import java.io.PrintWriter JavaDoc;
23 import java.util.Date JavaDoc;
24 import java.util.Hashtable JavaDoc;
25
26 import org.apache.catalina.Context;
27 import org.apache.catalina.Host;
28
29 /* The idea is to keep all configuration in server.xml and
30    the normal apache config files. We don't want people to
31    touch apache ( or IIS, NES ) config files unless they
32    want to and know what they're doing ( better than we do :-).
33
34    One nice feature ( if someone sends it ) would be to
35    also edit httpd.conf to add the include.
36
37    We'll generate a number of configuration files - this one
38    is trying to generate a native apache config file.
39
40    Some web.xml mappings do not "map" to server configuration - in
41    this case we need to fallback to forward all requests to tomcat.
42
43    Ajp14 will add to that the posibility to have tomcat and
44    apache on different machines, and many other improvements -
45    but this should also work for Ajp12, Ajp13 and Jni.
46
47 */

48
49 /**
50     Generates automatic apache mod_jk configurations based on
51     the Tomcat server.xml settings and the war contexts
52     initialized during startup.
53     <p>
54     This config interceptor is enabled by inserting an ApacheConfig
55     <code>Listener</code> in
56     the server.xml file like so:
57     <pre>
58     * < Server ... >
59     * ...
60     * <Listener className=<b>org.apache.ajp.tomcat4.config.ApacheConfig</b>
61     * <i>options</i> />
62     * ...
63     * < /Server >
64     </pre>
65     where <i>options</i> can include any of the following attributes:
66     <ul>
67      <li><b>configHome</b> - default parent directory for the following paths.
68                             If not set, this defaults to TOMCAT_HOME. Ignored
69                             whenever any of the following paths is absolute.
70                              </li>
71      <li><b>jkConfig</b> - path to use for writing Apache mod_jk conf file. If
72                             not set, defaults to
73                             "conf/auto/mod_jk.conf".</li>
74      <li><b>workersConfig</b> - path to workers.properties file used by
75                             mod_jk. If not set, defaults to
76                             "conf/jk/workers.properties".</li>
77      <li><b>modJk</b> - path to Apache mod_jk plugin file. If not set,
78                         defaults to "modules/mod_jk.dll" on windows,
79                         "modules/mod_jk.nlm" on netware, and
80                         "libexec/mod_jk.so" everywhere else.</li>
81      <li><b>jkLog</b> - path to log file to be used by mod_jk.</li>
82      <li><b>jkDebug</b> - JK Loglevel setting. May be debug, info, error, or emerg.
83                           If not set, defaults to emerg.</li>
84      <li><b>jkWorker</b> The desired worker. Must be set to one of the workers
85                          defined in the workers.properties file. "ajp12", "ajp13"
86                          or "inprocess" are the workers found in the default
87                          workers.properties file. If not specified, defaults
88                          to "ajp13" if an Ajp13Interceptor is in use, otherwise
89                          it defaults to "ajp12".</li>
90      <li><b>forwardAll</b> - If true, forward all requests to Tomcat. This helps
91                              insure that all the behavior configured in the web.xml
92                              file functions correctly. If false, let Apache serve
93                              static resources. The default is true.
94                              Warning: When false, some configuration in
95                              the web.xml may not be duplicated in Apache.
96                              Review the mod_jk conf file to see what
97                              configuration is actually being set in Apache.</li>
98      <li><b>noRoot</b> - If true, the root context is not mapped to
99                          Tomcat. If false and forwardAll is true, all requests
100                          to the root context are mapped to Tomcat. If false and
101                          forwardAll is false, only JSP and servlets requests to
102                          the root context are mapped to Tomcat. When false,
103                          to correctly serve Tomcat's root context you must also
104                          modify the DocumentRoot setting in Apache's httpd.conf
105                          file to point to Tomcat's root context directory.
106                          Otherwise some content, such as Apache's index.html,
107                          will be served by Apache before mod_jk gets a chance
108                          to claim the request and pass it to Tomcat.
109                          The default is true.</li>
110     </ul>
111     <p>
112     @author Costin Manolache
113     @author Larry Isaacs
114     @author Mel Martinez
115     @author Bill Barker
116  */

117 public class ApacheConfig extends BaseJkConfig {
118     
119     /** default path to mod_jk .conf location */
120     public static final String JavaDoc MOD_JK_CONFIG = "conf/auto/mod_jk.conf";
121     /** default path to workers.properties file
122     This should be also auto-generated from server.xml.
123     */

124     public static final String JavaDoc WORKERS_CONFIG = "conf/jk/workers.properties";
125     /** default mod_jk log file location */
126     public static final String JavaDoc JK_LOG_LOCATION = "logs/mod_jk.log";
127     /** default location of mod_jk Apache plug-in. */
128     public static final String JavaDoc MOD_JK;
129     
130     //set up some defaults based on OS type
131
static{
132         String JavaDoc os = System.getProperty("os.name").toLowerCase();
133         if(os.indexOf("windows")>=0){
134            MOD_JK = "modules/mod_jk.dll";
135         }else if(os.indexOf("netware")>=0){
136            MOD_JK = "modules/mod_jk.nlm";
137         }else{
138            MOD_JK = "libexec/mod_jk.so";
139         }
140     }
141     
142     private File JavaDoc jkConfig = null;
143     private File JavaDoc modJk = null;
144
145     // ssl settings
146
private boolean sslExtract=true;
147     private String JavaDoc sslHttpsIndicator="HTTPS";
148     private String JavaDoc sslSessionIndicator="SSL_SESSION_ID";
149     private String JavaDoc sslCipherIndicator="SSL_CIPHER";
150     private String JavaDoc sslCertsIndicator="SSL_CLIENT_CERT";
151
152     Hashtable JavaDoc NamedVirtualHosts=null;
153     
154     public ApacheConfig() {
155     }
156
157     //-------------------- Properties --------------------
158

159     /**
160         set the path to the output file for the auto-generated
161         mod_jk configuration file. If this path is relative
162         then it will be resolved absolutely against
163         the getConfigHome() path.
164         <p>
165         @param path String path to a file
166     */

167     public void setJkConfig(String JavaDoc path){
168     jkConfig= (path==null)?null:new File JavaDoc(path);
169     }
170
171     /**
172         set the path to the mod_jk Apache Module
173         @param path String path to a file
174     */

175     public void setModJk(String JavaDoc path){
176         modJk=( path==null?null:new File JavaDoc(path));
177     }
178
179     /** By default mod_jk is configured to collect SSL information from
180     the apache environment and send it to the Tomcat workers. The
181     problem is that there are many SSL solutions for Apache and as
182     a result the environment variable names may change.
183
184     The following JK related SSL configureation
185     can be used to customize mod_jk's SSL behaviour.
186
187     Should mod_jk send SSL information to Tomact (default is On)
188     */

189     public void setExtractSSL( boolean sslMode ) {
190     this.sslExtract=sslMode;
191     }
192
193     /** What is the indicator for SSL (default is HTTPS)
194      */

195     public void setHttpsIndicator( String JavaDoc s ) {
196     sslHttpsIndicator=s;
197     }
198
199     /**What is the indicator for SSL session (default is SSL_SESSION_ID)
200      */

201     public void setSessionIndicator( String JavaDoc s ) {
202     sslSessionIndicator=s;
203     }
204     
205     /**What is the indicator for client SSL cipher suit (default is SSL_CIPHER)
206      */

207     public void setCipherIndicator( String JavaDoc s ) {
208     sslCipherIndicator=s;
209     }
210
211     /** What is the indicator for the client SSL certificated(default
212     is SSL_CLIENT_CERT
213      */

214     public void setCertsIndicator( String JavaDoc s ) {
215     sslCertsIndicator=s;
216     }
217
218     // -------------------- Initialize/guess defaults --------------------
219

220     /** Initialize defaults for properties that are not set
221     explicitely
222     */

223     protected void initProperties() {
224         super.initProperties();
225
226     jkConfig= getConfigFile( jkConfig, configHome, MOD_JK_CONFIG);
227     workersConfig=getConfigFile( workersConfig, configHome,
228                      WORKERS_CONFIG);
229     if( modJk == null )
230         modJk=new File JavaDoc(MOD_JK);
231     else
232         modJk=getConfigFile( modJk, configHome, MOD_JK );
233     jkLog=getConfigFile( jkLog, configHome, JK_LOG_LOCATION);
234     }
235     // -------------------- Generate config --------------------
236

237     protected PrintWriter JavaDoc getWriter() throws IOException JavaDoc {
238     String JavaDoc abJkConfig = jkConfig.getAbsolutePath();
239     return new PrintWriter JavaDoc(new FileWriter JavaDoc(abJkConfig, append));
240     }
241                    
242
243     // -------------------- Config sections --------------------
244

245     /** Generate the loadModule and general options
246      */

247     protected boolean generateJkHead(PrintWriter JavaDoc mod_jk)
248     {
249
250     mod_jk.println("########## Auto generated on " + new Date JavaDoc() +
251                "##########" );
252     mod_jk.println();
253
254     // Fail if mod_jk not found, let the user know the problem
255
// instead of running into problems later.
256
if( ! modJk.exists() ) {
257         log( "mod_jk location: " + modJk );
258         log( "Make sure it is installed corectly or " +
259          " set the config location" );
260         log( "Using <Listener className=\""+getClass().getName()+"\" modJk=\"PATH_TO_MOD_JK.SO_OR_DLL\" />" );
261     }
262             
263     // Verify the file exists !!
264
mod_jk.println("<IfModule !mod_jk.c>");
265     mod_jk.println(" LoadModule jk_module \""+
266                modJk.toString().replace('\\','/') +
267                        "\"");
268     mod_jk.println("</IfModule>");
269     mod_jk.println();
270
271     
272     // Fail if workers file not found, let the user know the problem
273
// instead of running into problems later.
274
if( ! workersConfig.exists() ) {
275         log( "Can't find workers.properties at " + workersConfig );
276         log( "Please install it in the default location or " +
277          " set the config location" );
278         log( "Using <Listener className=\"" + getClass().getName() + "\" workersConfig=\"FULL_PATH\" />" );
279         return false;
280     }
281             
282     mod_jk.println("JkWorkersFile \""
283                + workersConfig.toString().replace('\\', '/')
284                + "\"");
285
286     mod_jk.println("JkLogFile \""
287                + jkLog.toString().replace('\\', '/')
288                + "\"");
289     mod_jk.println();
290
291     if( jkDebug != null ) {
292         mod_jk.println("JkLogLevel " + jkDebug);
293         mod_jk.println();
294     }
295     return true;
296     }
297
298     protected void generateVhostHead(Host host, PrintWriter JavaDoc mod_jk) {
299
300         mod_jk.println();
301         String JavaDoc vhostip = host.getName();
302     String JavaDoc vhost = vhostip;
303     int ppos = vhost.indexOf(":");
304     if(ppos >= 0)
305         vhost = vhost.substring(0,ppos);
306
307         mod_jk.println("<VirtualHost "+ vhostip + ">");
308         mod_jk.println(" ServerName " + vhost );
309         String JavaDoc [] aliases=host.findAliases();
310         if( aliases.length > 0 ) {
311             mod_jk.print(" ServerAlias " );
312             for( int ii=0; ii < aliases.length ; ii++) {
313                 mod_jk.print( aliases[ii] + " " );
314             }
315             mod_jk.println();
316         }
317         indent=" ";
318     }
319
320     protected void generateVhostTail(Host host, PrintWriter JavaDoc mod_jk) {
321         mod_jk.println("</VirtualHost>");
322         indent="";
323     }
324     
325     protected void generateSSLConfig(PrintWriter JavaDoc mod_jk) {
326     if( ! sslExtract ) {
327         mod_jk.println("JkExtractSSL Off");
328     }
329     if( ! "HTTPS".equalsIgnoreCase( sslHttpsIndicator ) ) {
330         mod_jk.println("JkHTTPSIndicator " + sslHttpsIndicator);
331     }
332     if( ! "SSL_SESSION_ID".equalsIgnoreCase( sslSessionIndicator )) {
333         mod_jk.println("JkSESSIONIndicator " + sslSessionIndicator);
334     }
335     if( ! "SSL_CIPHER".equalsIgnoreCase( sslCipherIndicator )) {
336         mod_jk.println("JkCIPHERIndicator " + sslCipherIndicator);
337     }
338     if( ! "SSL_CLIENT_CERT".equalsIgnoreCase( sslCertsIndicator )) {
339         mod_jk.println("JkCERTSIndicator " + sslCertsIndicator);
340     }
341
342     mod_jk.println();
343     }
344
345     // -------------------- Forward all mode --------------------
346
String JavaDoc indent="";
347     
348     /** Forward all requests for a context to tomcat.
349     The default.
350      */

351     protected void generateStupidMappings(Context context,
352                        PrintWriter JavaDoc mod_jk )
353     {
354     String JavaDoc ctxPath = context.getPath();
355     if(ctxPath == null)
356         return;
357
358     String JavaDoc nPath=("".equals(ctxPath)) ? "/" : ctxPath;
359     
360         mod_jk.println();
361     mod_jk.println(indent + "JkMount " + nPath + " " + jkWorker );
362     if( "".equals(ctxPath) ) {
363         mod_jk.println(indent + "JkMount " + nPath + "* " + jkWorker );
364             if ( context.getParent() instanceof Host ) {
365                 mod_jk.println(indent + "DocumentRoot \"" +
366                             getApacheDocBase(context) + "\"");
367             } else {
368                 mod_jk.println(indent +
369                         "# To avoid Apache serving root welcome files from htdocs, update DocumentRoot");
370                 mod_jk.println(indent +
371                         "# to point to: \"" + getApacheDocBase(context) + "\"");
372             }
373
374     } else {
375         mod_jk.println(indent + "JkMount " + nPath + "/* " + jkWorker );
376     }
377     }
378
379     
380     private void generateNameVirtualHost( PrintWriter JavaDoc mod_jk, String JavaDoc ip ) {
381         if( !NamedVirtualHosts.containsKey(ip) ) {
382             mod_jk.println("NameVirtualHost " + ip + "");
383             NamedVirtualHosts.put(ip,ip);
384         }
385     }
386     
387     // -------------------- Apache serves static mode --------------------
388
// This is not going to work for all apps. We fall back to stupid mode.
389

390     protected void generateContextMappings(Context context, PrintWriter JavaDoc mod_jk )
391     {
392     String JavaDoc ctxPath = context.getPath();
393     Host vhost = getHost(context);
394
395         if( noRoot && "".equals(ctxPath) ) {
396             log("Ignoring root context in non-forward-all mode ");
397             return;
398         }
399
400     mod_jk.println();
401     mod_jk.println(indent + "#################### " +
402                ((vhost!=null ) ? vhost.getName() + ":" : "" ) +
403                (("".equals(ctxPath)) ? "/" : ctxPath ) +
404                " ####################" );
405         mod_jk.println();
406     // Dynamic /servet pages go to Tomcat
407

408     generateStaticMappings( context, mod_jk );
409
410     // InvokerInterceptor - it doesn't have a container,
411
// but it's implemented using a special module.
412

413     // XXX we need to better collect all mappings
414

415     if(context.getLoginConfig() != null) {
416         String JavaDoc loginPage = context.getLoginConfig().getLoginPage();
417         if(loginPage != null) {
418         int lpos = loginPage.lastIndexOf("/");
419         String JavaDoc jscurl = loginPage.substring(0,lpos+1) + "j_security_check";
420         addMapping( ctxPath, jscurl, mod_jk);
421         }
422     }
423     String JavaDoc [] servletMaps = context.findServletMappings();
424     for(int ii=0; ii < servletMaps.length; ii++) {
425           addMapping( ctxPath, servletMaps[ii] , mod_jk );
426     }
427     }
428
429     /** Add an Apache extension mapping.
430      */

431     protected boolean addExtensionMapping( String JavaDoc ctxPath, String JavaDoc ext,
432                      PrintWriter JavaDoc mod_jk )
433     {
434         if( debug > 0 )
435             log( "Adding extension map for " + ctxPath + "/*." + ext );
436     mod_jk.println(indent + "JkMount " + ctxPath + "/*." + ext
437                + " " + jkWorker);
438     return true;
439     }
440     
441     
442     /** Add a fulling specified Appache mapping.
443      */

444     protected boolean addMapping( String JavaDoc fullPath, PrintWriter JavaDoc mod_jk ) {
445         if( debug > 0 )
446             log( "Adding map for " + fullPath );
447     mod_jk.println(indent + "JkMount " + fullPath + " " + jkWorker );
448     return true;
449     }
450     /** Add a partially specified Appache mapping.
451      */

452     protected boolean addMapping( String JavaDoc ctxP, String JavaDoc ext, PrintWriter JavaDoc mod_jk ) {
453         if( debug > 0 )
454             log( "Adding map for " + ext );
455     if(! ext.startsWith("/") )
456         ext = "/" + ext;
457     if(ext.length() > 1)
458         mod_jk.println(indent + "JkMount " + ctxP + ext+ " " + jkWorker );
459     return true;
460     }
461
462     private void generateWelcomeFiles(Context context, PrintWriter JavaDoc mod_jk ) {
463     String JavaDoc wf[]=context.findWelcomeFiles();
464     if( wf==null || wf.length == 0 )
465         return;
466     mod_jk.print(indent + " DirectoryIndex ");
467     for( int i=0; i<wf.length ; i++ ) {
468         mod_jk.print( wf[i] + " " );
469     }
470     mod_jk.println();
471     }
472
473     /** Mappings for static content. XXX need to add welcome files,
474      * mime mappings ( all will be handled by Mime and Static modules of
475      * apache ).
476      */

477     private void generateStaticMappings(Context context, PrintWriter JavaDoc mod_jk ) {
478     String JavaDoc ctxPath = context.getPath();
479
480     // Calculate the absolute path of the document base
481
String JavaDoc docBase = getApacheDocBase(context);
482
483         if( !"".equals(ctxPath) ) {
484             // Static files will be served by Apache
485
mod_jk.println(indent + "# Static files ");
486             mod_jk.println(indent + "Alias " + ctxPath + " \"" + docBase + "\"");
487             mod_jk.println();
488         } else {
489             if ( getHost(context) != null ) {
490                 mod_jk.println(indent + "DocumentRoot \"" +
491                             getApacheDocBase(context) + "\"");
492             } else {
493                 // For root context, ask user to update DocumentRoot setting.
494
// Using "Alias / " interferes with the Alias for other contexts.
495
mod_jk.println(indent +
496                         "# Be sure to update DocumentRoot");
497                 mod_jk.println(indent +
498                         "# to point to: \"" + docBase + "\"");
499             }
500         }
501     mod_jk.println(indent + "<Directory \"" + docBase + "\">");
502     mod_jk.println(indent + " Options Indexes FollowSymLinks");
503
504     generateWelcomeFiles(context, mod_jk);
505
506     // XXX XXX Here goes the Mime types and welcome files !!!!!!!!
507
mod_jk.println(indent + "</Directory>");
508     mod_jk.println();
509     
510
511     // Deny serving any files from WEB-INF
512
mod_jk.println();
513     mod_jk.println(indent +
514                "# Deny direct access to WEB-INF and META-INF");
515     mod_jk.println(indent + "#");
516     mod_jk.println(indent + "<Location \"" + ctxPath + "/WEB-INF/*\">");
517     mod_jk.println(indent + " AllowOverride None");
518     mod_jk.println(indent + " deny from all");
519     mod_jk.println(indent + "</Location>");
520     // Deny serving any files from META-INF
521
mod_jk.println();
522     mod_jk.println(indent + "<Location \"" + ctxPath + "/META-INF/*\">");
523     mod_jk.println(indent + " AllowOverride None");
524     mod_jk.println(indent + " deny from all");
525     mod_jk.println(indent + "</Location>");
526     if (File.separatorChar == '\\') {
527         mod_jk.println(indent + "#");
528         mod_jk.println(indent +
529                "# Use Directory too. On Windows, Location doesn't"
530                + " work unless case matches");
531         mod_jk.println(indent + "#");
532         mod_jk.println(indent +
533                "<Directory \"" + docBase + "/WEB-INF/\">");
534         mod_jk.println(indent + " AllowOverride None");
535         mod_jk.println(indent + " deny from all");
536         mod_jk.println(indent + "</Directory>");
537         mod_jk.println();
538         mod_jk.println(indent +
539                "<Directory \"" + docBase + "/META-INF/\">");
540         mod_jk.println(indent + " AllowOverride None");
541         mod_jk.println(indent + " deny from all");
542         mod_jk.println(indent + "</Directory>");
543     }
544     mod_jk.println();
545     }
546
547     // -------------------- Utils --------------------
548

549     private String JavaDoc getApacheDocBase(Context context)
550     {
551     // Calculate the absolute path of the document base
552
String JavaDoc docBase = getAbsoluteDocBase(context);
553     if (File.separatorChar == '\\') {
554         // use separator preferred by Apache
555
docBase = docBase.replace('\\','/');
556     }
557         return docBase;
558     }
559
560     private String JavaDoc getVirtualHostAddress(String JavaDoc vhost, String JavaDoc vhostip) {
561         if( vhostip == null ) {
562             if ( vhost != null && vhost.length() > 0 && Character.isDigit(vhost.charAt(0)) )
563                 vhostip=vhost;
564             else
565                 vhostip="*";
566         }
567         return vhostip;
568     }
569
570 }
571
Popular Tags