KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > jk > config > WebXml2Jk


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.jk.config;
18
19 import java.io.File JavaDoc;
20 import java.io.IOException JavaDoc;
21 import java.io.StringReader JavaDoc;
22 import java.util.Hashtable JavaDoc;
23 import java.util.Vector JavaDoc;
24
25 import javax.xml.parsers.DocumentBuilder JavaDoc;
26 import javax.xml.parsers.DocumentBuilderFactory JavaDoc;
27 import javax.xml.parsers.ParserConfigurationException JavaDoc;
28
29 import org.apache.tomcat.util.IntrospectionUtils;
30 import org.w3c.dom.Document JavaDoc;
31 import org.w3c.dom.Node JavaDoc;
32 import org.xml.sax.EntityResolver JavaDoc;
33 import org.xml.sax.InputSource JavaDoc;
34 import org.xml.sax.SAXException JavaDoc;
35
36
37 /* Naming conventions:
38
39 JK_CONF_DIR == serverRoot/work ( XXX /jkConfig ? )
40
41 - Each vhost has a sub-dir named after the canonycal name
42
43 - For each webapp in a vhost, there is a separate WEBAPP_NAME.jkmap
44
45 - In httpd.conf ( or equivalent servers ), in each virtual host you
46 should "Include JK_CONF_DIR/VHOST/jk_apache.conf". The config
47 file will contain the Alias declarations and other rules required
48 for apache operation. Same for other servers.
49
50 - WebXml2Jk will be invoked by a config tool or automatically for each
51 webapp - it'll generate the WEBAPP.jkmap files and config fragments.
52
53 WebXml2Jk will _not_ generate anything else but mappings.
54 It should _not_ try to guess locations or anything else - that's
55 another components' job.
56
57 */

58
59 /**
60  * Read a web.xml file and generate the mappings for jk2.
61  * It can be used from the command line or ant.
62  *
63  * In order for the web server to serve static pages, all webapps
64  * must be deployed on the computer that runs Apache, IIS, etc.
65  *
66  * Dynamic pages can be executed on that computer or other servers
67  * in a pool, but even if the main server doesn't run tomcat,
68  * it must have all the static files and WEB-INF/web.xml.
69  * ( you could have a script remove everything else, including jsps - if
70  * security paranoia is present ).
71  *
72  * XXX We could have this in WEB-INF/urimap.properties.
73  *
74  * @author Costin Manolache
75  */

76 public class WebXml2Jk {
77     String JavaDoc vhost="";
78     String JavaDoc cpath="";
79     String JavaDoc docBase;
80     String JavaDoc file;
81     String JavaDoc worker="lb";
82
83     // -------------------- Settings --------------------
84

85     // XXX We can also generate location-independent mappings.
86

87     /** Set the canonycal name of the virtual host.
88      */

89     public void setHost( String JavaDoc vhost ) {
90         this.vhost=vhost;
91     }
92     
93     /** Set the canonical name of the virtual host.
94      */

95     public void setContext( String JavaDoc contextPath ) {
96         this.cpath=contextPath;
97     }
98
99     
100     /** Set the base directory where the application is
101      * deployed ( on the web server ).
102      */

103     public void setDocBase(String JavaDoc docBase ) {
104         this.docBase=docBase;
105     }
106
107     // Automatically generated.
108
// /** The file where the jk2 mapping will be generated
109
// */
110
// public void setJk2Conf( String outFile ) {
111
// file=outFile;
112
// type=CONFIG_JK2_URIMAP;
113
// }
114

115 // /** Backward compat: generate JkMounts for mod_jk1
116
// */
117
// public void setJkmountFile( String outFile ) {
118
// file=outFile;
119
// type=CONFIG_JK_MOUNT;
120
// }
121

122     /* By default we map to the lb - in jk2 this is automatically
123      * created and includes all tomcat instances.
124      *
125      * This is equivalent to the worker in jk1.
126      */

127     public void setGroup(String JavaDoc route ) {
128         worker=route;
129     }
130
131     // -------------------- Generators --------------------
132
public static interface MappingGenerator {
133         void setWebXmlReader(WebXml2Jk wxml );
134
135         /** Start section( vhost declarations, etc )
136          */

137         void generateStart() throws IOException JavaDoc ;
138
139         void generateEnd() throws IOException JavaDoc ;
140         
141         void generateServletMapping( String JavaDoc servlet, String JavaDoc url )throws IOException JavaDoc ;
142         void generateFilterMapping( String JavaDoc servlet, String JavaDoc url ) throws IOException JavaDoc ;
143
144         void generateLoginConfig( String JavaDoc loginPage,
145                                   String JavaDoc errPage, String JavaDoc authM ) throws IOException JavaDoc ;
146
147         void generateErrorPage( int err, String JavaDoc location ) throws IOException JavaDoc ;
148             
149         void generateConstraints( Vector JavaDoc urls, Vector JavaDoc methods, Vector JavaDoc roles, boolean isSSL ) throws IOException JavaDoc ;
150     }
151     
152     // -------------------- Implementation --------------------
153
Node JavaDoc webN;
154     File JavaDoc jkDir;
155     
156     /** Return the top level node
157      */

158     public Node JavaDoc getWebXmlNode() {
159         return webN;
160     }
161
162     public File JavaDoc getJkDir() {
163         return jkDir;
164     }
165     
166     /** Extract the wellcome files from the web.xml
167      */

168     public Vector JavaDoc getWellcomeFiles() {
169         Node JavaDoc n0=getChild( webN, "welcome-file-list" );
170         Vector JavaDoc wF=new Vector JavaDoc();
171         if( n0!=null ) {
172             for( Node JavaDoc mapN=getChild( webN, "welcome-file" );
173                  mapN != null; mapN = getNext( mapN ) ) {
174                 wF.addElement( getContent(mapN));
175             }
176         }
177         // XXX Add index.html, index.jsp
178
return wF;
179     }
180
181
182     void generate(MappingGenerator gen ) throws IOException JavaDoc {
183         gen.generateStart();
184         log.info("Generating mappings for servlets " );
185         for( Node JavaDoc mapN=getChild( webN, "servlet-mapping" );
186              mapN != null; mapN = getNext( mapN ) ) {
187             
188             String JavaDoc serv=getChildContent( mapN, "servlet-name");
189             String JavaDoc url=getChildContent( mapN, "url-pattern");
190             
191             gen.generateServletMapping( serv, url );
192         }
193
194         log.info("Generating mappings for filters " );
195         for( Node JavaDoc mapN=getChild( webN, "filter-mapping" );
196              mapN != null; mapN = getNext( mapN ) ) {
197             
198             String JavaDoc filter=getChildContent( mapN, "filter-name");
199             String JavaDoc url=getChildContent( mapN, "url-pattern");
200
201             gen.generateFilterMapping( filter, url );
202         }
203
204
205         for( Node JavaDoc mapN=getChild( webN, "error-page" );
206              mapN != null; mapN = getNext( mapN ) ) {
207             String JavaDoc errorCode= getChildContent( mapN, "error-code" );
208             String JavaDoc location= getChildContent( mapN, "location" );
209
210             if( errorCode!=null && ! "".equals( errorCode ) ) {
211                 try {
212                     int err=new Integer JavaDoc( errorCode ).intValue();
213                     gen.generateErrorPage( err, location );
214                 } catch( Exception JavaDoc ex ) {
215                     log.error( "Format error " + location, ex);
216                 }
217             }
218         }
219
220         Node JavaDoc lcN=getChild( webN, "login-config" );
221         if( lcN!=null ) {
222             log.info("Generating mapping for login-config " );
223             
224             String JavaDoc authMeth=getContent( getChild( lcN, "auth-method"));
225             String JavaDoc realm=getContent( getChild( lcN, "realm-name"));
226             if( authMeth == null ) authMeth="BASIC";
227
228             Node JavaDoc n1=getChild( lcN, "form-login-config");
229             String JavaDoc loginPage= getChildContent( n1, "form-login-page");
230             String JavaDoc errPage= getChildContent( n1, "form-error-page");
231
232         if(loginPage != null) {
233         int lpos = loginPage.lastIndexOf("/");
234         String JavaDoc jscurl = loginPage.substring(0,lpos+1) + "j_security_check";
235                 gen.generateLoginConfig( jscurl, errPage, authMeth );
236         }
237         }
238
239         log.info("Generating mappings for security constraints " );
240         for( Node JavaDoc mapN=getChild( webN, "security-constraint" );
241              mapN != null; mapN = getNext( mapN )) {
242
243             Vector JavaDoc methods=new Vector JavaDoc();
244             Vector JavaDoc urls=new Vector JavaDoc();
245             Vector JavaDoc roles=new Vector JavaDoc();
246             boolean isSSL=false;
247             
248             Node JavaDoc wrcN=getChild( mapN, "web-resource-collection");
249             for( Node JavaDoc uN=getChild(wrcN, "http-method");
250                  uN!=null; uN=getNext( uN )) {
251                 methods.addElement( getContent( uN ));
252             }
253             for( Node JavaDoc uN=getChild(wrcN, "url-pattern");
254                  uN!=null; uN=getNext( uN )) {
255                 urls.addElement( getContent( uN ));
256             }
257
258             // Not used at the moment
259
Node JavaDoc acN=getChild( mapN, "auth-constraint");
260             for( Node JavaDoc rN=getChild(acN, "role-name");
261                  rN!=null; rN=getNext( rN )) {
262                 roles.addElement(getContent( rN ));
263             }
264
265             Node JavaDoc ucN=getChild( mapN, "user-data-constraint");
266             String JavaDoc transp=getContent(getChild( ucN, "transport-guarantee"));
267             if( transp!=null ) {
268                 if( "INTEGRAL".equalsIgnoreCase( transp ) ||
269                     "CONFIDENTIAL".equalsIgnoreCase( transp ) ) {
270                     isSSL=true;
271                 }
272             }
273
274             gen.generateConstraints( urls, methods, roles, isSSL );
275         }
276         gen.generateEnd();
277     }
278     
279     // -------------------- Main and ant wrapper --------------------
280

281     public void execute() {
282         try {
283             if( docBase== null) {
284                 log.error("No docbase - please specify the base directory of you web application ( -docBase PATH )");
285                 return;
286             }
287             if( cpath== null) {
288                 log.error("No context - please specify the mount ( -context PATH )");
289                 return;
290             }
291             File JavaDoc docbF=new File JavaDoc(docBase);
292             File JavaDoc wXmlF=new File JavaDoc( docBase, "WEB-INF/web.xml");
293
294             Document JavaDoc wXmlN=readXml(wXmlF);
295             if( wXmlN == null ) return;
296
297             webN = wXmlN.getDocumentElement();
298             if( webN==null ) {
299                 log.error("Can't find web-app");
300                 return;
301             }
302
303             jkDir=new File JavaDoc( docbF, "WEB-INF/jk2" );
304             jkDir.mkdirs();
305             
306             MappingGenerator generator=new GeneratorJk2();
307             generator.setWebXmlReader( this );
308             generate( generator );
309
310             generator=new GeneratorJk1();
311             generator.setWebXmlReader( this );
312             generate( generator );
313
314             generator=new GeneratorApache2();
315             generator.setWebXmlReader( this );
316             generate( generator );
317
318         } catch( Exception JavaDoc ex ) {
319             ex.printStackTrace();
320         }
321     }
322
323
324     public static void main(String JavaDoc args[] ) {
325         try {
326             if( args.length == 1 &&
327                 ( "-?".equals(args[0]) || "-h".equals( args[0])) ) {
328                 System.out.println("Usage: ");
329                 System.out.println(" WebXml2Jk [OPTIONS]");
330                 System.out.println();
331                 System.out.println(" -docBase DIR The location of the webapp. Required");
332                 System.out.println(" -group GROUP Group, if you have multiple tomcats with diffrent content. " );
333                 System.out.println(" The default is 'lb', and should be used in most cases");
334                 System.out.println(" -host HOSTNAME Canonical hostname - for virtual hosts");
335                 System.out.println(" -context /CPATH Context path where the app will be mounted");
336                 return;
337             }
338
339             WebXml2Jk w2jk=new WebXml2Jk();
340
341             /* do ant-style property setting */
342             IntrospectionUtils.processArgs( w2jk, args, new String JavaDoc[] {},
343                                             null, new Hashtable JavaDoc());
344             w2jk.execute();
345         } catch( Exception JavaDoc ex ) {
346             ex.printStackTrace();
347         }
348
349     }
350
351     private static org.apache.commons.logging.Log log=
352         org.apache.commons.logging.LogFactory.getLog( WebXml2Jk.class );
353
354     
355     // -------------------- DOM utils --------------------
356

357     /** Get the content of a node
358      */

359     public static String JavaDoc getContent(Node JavaDoc n ) {
360         if( n==null ) return null;
361         Node JavaDoc n1=n.getFirstChild();
362         // XXX Check if it's a text node
363

364         String JavaDoc s1=n1.getNodeValue();
365         return s1.trim();
366     }
367     
368     /** Get the first child
369      */

370     public static Node JavaDoc getChild( Node JavaDoc parent, String JavaDoc name ) {
371         if( parent==null ) return null;
372         Node JavaDoc first=parent.getFirstChild();
373         if( first==null ) return null;
374         for (Node JavaDoc node = first; node != null;
375              node = node.getNextSibling()) {
376             //System.out.println("getNode: " + name + " " + node.getNodeName());
377
if( name.equals( node.getNodeName() ) ) {
378                 return node;
379             }
380         }
381         return null;
382     }
383
384     /** Get the first child's content ( i.e. it's included TEXT node )
385      */

386     public static String JavaDoc getChildContent( Node JavaDoc parent, String JavaDoc name ) {
387         Node JavaDoc first=parent.getFirstChild();
388         if( first==null ) return null;
389         for (Node JavaDoc node = first; node != null;
390              node = node.getNextSibling()) {
391             //System.out.println("getNode: " + name + " " + node.getNodeName());
392
if( name.equals( node.getNodeName() ) ) {
393                 return getContent( node );
394             }
395         }
396         return null;
397     }
398
399     /** Get the node in the list of siblings
400      */

401     public static Node JavaDoc getNext( Node JavaDoc current ) {
402         Node JavaDoc first=current.getNextSibling();
403         String JavaDoc name=current.getNodeName();
404         if( first==null ) return null;
405         for (Node JavaDoc node = first; node != null;
406              node = node.getNextSibling()) {
407             //System.out.println("getNode: " + name + " " + node.getNodeName());
408
if( name.equals( node.getNodeName() ) ) {
409                 return node;
410             }
411         }
412         return null;
413     }
414
415     public static class NullResolver implements EntityResolver JavaDoc {
416         public InputSource JavaDoc resolveEntity (String JavaDoc publicId,
417                                                    String JavaDoc systemId)
418             throws SAXException JavaDoc, IOException JavaDoc
419         {
420             if (log.isDebugEnabled())
421                 log.debug("ResolveEntity: " + publicId + " " + systemId);
422             return new InputSource JavaDoc(new StringReader JavaDoc(""));
423         }
424     }
425     
426     public static Document JavaDoc readXml(File JavaDoc xmlF)
427         throws SAXException JavaDoc, IOException JavaDoc, ParserConfigurationException JavaDoc
428     {
429         if( ! xmlF.exists() ) {
430             log.error("No xml file " + xmlF );
431             return null;
432         }
433         DocumentBuilderFactory JavaDoc dbf =
434             DocumentBuilderFactory.newInstance();
435
436         dbf.setValidating(false);
437         dbf.setIgnoringComments(false);
438         dbf.setIgnoringElementContentWhitespace(true);
439         //dbf.setCoalescing(true);
440
//dbf.setExpandEntityReferences(true);
441

442         DocumentBuilder JavaDoc db = null;
443         db = dbf.newDocumentBuilder();
444         db.setEntityResolver( new NullResolver() );
445         
446         // db.setErrorHandler( new MyErrorHandler());
447

448         Document JavaDoc doc = db.parse(xmlF);
449         return doc;
450     }
451
452 }
453
Popular Tags