001: /*
002: * Copyright 1999-2001,2004 The Apache Software Foundation.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.apache.catalina.startup;
018:
019: import java.lang.reflect.Method;
020: import org.apache.catalina.Context;
021: import org.apache.catalina.Wrapper;
022: import org.apache.catalina.deploy.SecurityConstraint;
023: import org.apache.commons.digester.Digester;
024: import org.apache.commons.digester.Rule;
025: import org.apache.commons.digester.RuleSetBase;
026: import org.xml.sax.Attributes;
027:
028: /**
029: * <p><strong>RuleSet</strong> for processing the contents of a web application
030: * deployment descriptor (<code>/WEB-INF/web.xml</code>) resource.</p>
031: *
032: * @author Craig R. McClanahan
033: * @version $Revision: 1.12 $ $Date: 2004/05/10 15:43:09 $
034: */
035:
036: public class WebRuleSet extends RuleSetBase {
037:
038: // ----------------------------------------------------- Instance Variables
039:
040: /**
041: * The matching pattern prefix to use for recognizing our elements.
042: */
043: protected String prefix = null;
044:
045: /**
046: * The <code>SetSessionConfig</code> rule used to parse the web.xml
047: */
048: protected SetSessionConfig sessionConfig;
049:
050: /**
051: * The <code>SetLoginConfig</code> rule used to parse the web.xml
052: */
053: protected SetLoginConfig loginConfig;
054:
055: /**
056: * The <code>SetJspConfig</code> rule used to parse the web.xml
057: */
058: protected SetJspConfig jspConfig;
059:
060: // ------------------------------------------------------------ Constructor
061:
062: /**
063: * Construct an instance of this <code>RuleSet</code> with the default
064: * matching pattern prefix.
065: */
066: public WebRuleSet() {
067:
068: this ("");
069:
070: }
071:
072: /**
073: * Construct an instance of this <code>RuleSet</code> with the specified
074: * matching pattern prefix.
075: *
076: * @param prefix Prefix for matching pattern rules (including the
077: * trailing slash character)
078: */
079: public WebRuleSet(String prefix) {
080:
081: super ();
082: this .namespaceURI = null;
083: this .prefix = prefix;
084:
085: }
086:
087: // --------------------------------------------------------- Public Methods
088:
089: /**
090: * <p>Add the set of Rule instances defined in this RuleSet to the
091: * specified <code>Digester</code> instance, associating them with
092: * our namespace URI (if any). This method should only be called
093: * by a Digester instance.</p>
094: *
095: * @param digester Digester instance to which the new Rule instances
096: * should be added.
097: */
098: public void addRuleInstances(Digester digester) {
099: sessionConfig = new SetSessionConfig();
100: jspConfig = new SetJspConfig();
101: loginConfig = new SetLoginConfig();
102:
103: digester.addRule(prefix + "web-app", new SetPublicIdRule(
104: "setPublicId"));
105:
106: digester.addCallMethod(prefix + "web-app/context-param",
107: "addParameter", 2);
108: digester.addCallParam(prefix
109: + "web-app/context-param/param-name", 0);
110: digester.addCallParam(prefix
111: + "web-app/context-param/param-value", 1);
112:
113: digester.addCallMethod(prefix + "web-app/display-name",
114: "setDisplayName", 0);
115:
116: digester.addRule(prefix + "web-app/distributable",
117: new SetDistributableRule());
118:
119: digester.addObjectCreate(prefix + "web-app/ejb-local-ref",
120: "org.apache.catalina.deploy.ContextLocalEjb");
121: digester.addSetNext(prefix + "web-app/ejb-local-ref",
122: "addLocalEjb",
123: "org.apache.catalina.deploy.ContextLocalEjb");
124:
125: digester.addCallMethod(prefix
126: + "web-app/ejb-local-ref/description",
127: "setDescription", 0);
128: digester.addCallMethod(prefix
129: + "web-app/ejb-local-ref/ejb-link", "setLink", 0);
130: digester.addCallMethod(prefix
131: + "web-app/ejb-local-ref/ejb-ref-name", "setName", 0);
132: digester.addCallMethod(prefix
133: + "web-app/ejb-local-ref/ejb-ref-type", "setType", 0);
134: digester.addCallMethod(prefix + "web-app/ejb-local-ref/local",
135: "setLocal", 0);
136: digester.addCallMethod(prefix
137: + "web-app/ejb-local-ref/local-home", "setHome", 0);
138:
139: digester.addObjectCreate(prefix + "web-app/ejb-ref",
140: "org.apache.catalina.deploy.ContextEjb");
141: digester.addSetNext(prefix + "web-app/ejb-ref", "addEjb",
142: "org.apache.catalina.deploy.ContextEjb");
143:
144: digester.addCallMethod(prefix + "web-app/ejb-ref/description",
145: "setDescription", 0);
146: digester.addCallMethod(prefix + "web-app/ejb-ref/ejb-link",
147: "setLink", 0);
148: digester.addCallMethod(prefix + "web-app/ejb-ref/ejb-ref-name",
149: "setName", 0);
150: digester.addCallMethod(prefix + "web-app/ejb-ref/ejb-ref-type",
151: "setType", 0);
152: digester.addCallMethod(prefix + "web-app/ejb-ref/home",
153: "setHome", 0);
154: digester.addCallMethod(prefix + "web-app/ejb-ref/remote",
155: "setRemote", 0);
156:
157: digester.addObjectCreate(prefix + "web-app/env-entry",
158: "org.apache.catalina.deploy.ContextEnvironment");
159: digester.addSetNext(prefix + "web-app/env-entry",
160: "addEnvironment",
161: "org.apache.catalina.deploy.ContextEnvironment");
162:
163: digester.addCallMethod(
164: prefix + "web-app/env-entry/description",
165: "setDescription", 0);
166: digester.addCallMethod(prefix
167: + "web-app/env-entry/env-entry-name", "setName", 0);
168: digester.addCallMethod(prefix
169: + "web-app/env-entry/env-entry-type", "setType", 0);
170: digester.addCallMethod(prefix
171: + "web-app/env-entry/env-entry-value", "setValue", 0);
172:
173: digester.addObjectCreate(prefix + "web-app/error-page",
174: "org.apache.catalina.deploy.ErrorPage");
175: digester.addSetNext(prefix + "web-app/error-page",
176: "addErrorPage", "org.apache.catalina.deploy.ErrorPage");
177:
178: digester.addCallMethod(
179: prefix + "web-app/error-page/error-code",
180: "setErrorCode", 0);
181: digester.addCallMethod(prefix
182: + "web-app/error-page/exception-type",
183: "setExceptionType", 0);
184: digester.addCallMethod(prefix + "web-app/error-page/location",
185: "setLocation", 0);
186:
187: digester.addObjectCreate(prefix + "web-app/filter",
188: "org.apache.catalina.deploy.FilterDef");
189: digester.addSetNext(prefix + "web-app/filter", "addFilterDef",
190: "org.apache.catalina.deploy.FilterDef");
191:
192: digester.addCallMethod(prefix + "web-app/filter/description",
193: "setDescription", 0);
194: digester.addCallMethod(prefix + "web-app/filter/display-name",
195: "setDisplayName", 0);
196: digester.addCallMethod(prefix + "web-app/filter/filter-class",
197: "setFilterClass", 0);
198: digester.addCallMethod(prefix + "web-app/filter/filter-name",
199: "setFilterName", 0);
200: digester.addCallMethod(prefix + "web-app/filter/large-icon",
201: "setLargeIcon", 0);
202: digester.addCallMethod(prefix + "web-app/filter/small-icon",
203: "setSmallIcon", 0);
204:
205: digester.addCallMethod(prefix + "web-app/filter/init-param",
206: "addInitParameter", 2);
207: digester.addCallParam(prefix
208: + "web-app/filter/init-param/param-name", 0);
209: digester.addCallParam(prefix
210: + "web-app/filter/init-param/param-value", 1);
211:
212: digester.addObjectCreate(prefix + "web-app/filter-mapping",
213: "org.apache.catalina.deploy.FilterMap");
214: digester.addSetNext(prefix + "web-app/filter-mapping",
215: "addFilterMap", "org.apache.catalina.deploy.FilterMap");
216:
217: digester.addCallMethod(prefix
218: + "web-app/filter-mapping/filter-name",
219: "setFilterName", 0);
220: digester.addCallMethod(prefix
221: + "web-app/filter-mapping/servlet-name",
222: "setServletName", 0);
223: digester.addCallMethod(prefix
224: + "web-app/filter-mapping/url-pattern",
225: "setURLPattern", 0);
226:
227: digester.addCallMethod(prefix
228: + "web-app/filter-mapping/dispatcher", "setDispatcher",
229: 0);
230:
231: digester.addCallMethod(prefix
232: + "web-app/listener/listener-class",
233: "addApplicationListener", 0);
234:
235: digester.addRule(prefix + "web-app/jsp-config", jspConfig);
236:
237: digester.addCallMethod(prefix
238: + "web-app/jsp-config/jsp-property-group/url-pattern",
239: "addJspMapping", 0);
240:
241: digester.addCallMethod(prefix
242: + "web-app/listener/listener-class",
243: "addApplicationListener", 0);
244:
245: digester.addRule(prefix + "web-app/login-config", loginConfig);
246:
247: digester.addObjectCreate(prefix + "web-app/login-config",
248: "org.apache.catalina.deploy.LoginConfig");
249: digester.addSetNext(prefix + "web-app/login-config",
250: "setLoginConfig",
251: "org.apache.catalina.deploy.LoginConfig");
252:
253: digester.addCallMethod(prefix
254: + "web-app/login-config/auth-method", "setAuthMethod",
255: 0);
256: digester.addCallMethod(prefix
257: + "web-app/login-config/realm-name", "setRealmName", 0);
258: digester
259: .addCallMethod(
260: prefix
261: + "web-app/login-config/form-login-config/form-error-page",
262: "setErrorPage", 0);
263: digester
264: .addCallMethod(
265: prefix
266: + "web-app/login-config/form-login-config/form-login-page",
267: "setLoginPage", 0);
268:
269: digester.addCallMethod(prefix + "web-app/mime-mapping",
270: "addMimeMapping", 2);
271: digester.addCallParam(
272: prefix + "web-app/mime-mapping/extension", 0);
273: digester.addCallParam(
274: prefix + "web-app/mime-mapping/mime-type", 1);
275:
276: digester.addCallMethod(prefix + "web-app/resource-env-ref",
277: "addResourceEnvRef", 2);
278: digester.addCallParam(prefix
279: + "web-app/resource-env-ref/resource-env-ref-name", 0);
280: digester.addCallParam(prefix
281: + "web-app/resource-env-ref/resource-env-ref-type", 1);
282:
283: digester.addObjectCreate(
284: prefix + "web-app/message-destination",
285: "org.apache.catalina.deploy.MessageDestination");
286: digester.addSetNext(prefix + "web-app/message-destination",
287: "addMessageDestination",
288: "org.apache.catalina.deploy.MessageDestination");
289:
290: digester.addCallMethod(prefix
291: + "web-app/message-destination/description",
292: "setDescription", 0);
293: digester.addCallMethod(prefix
294: + "web-app/message-destination/display-name",
295: "setDisplayName", 0);
296: digester.addCallMethod(prefix
297: + "web-app/message-destination/icon/large-icon",
298: "setLargeIcon", 0);
299: digester.addCallMethod(prefix
300: + "web-app/message-destination/icon/small-icon",
301: "setSmallIcon", 0);
302: digester
303: .addCallMethod(
304: prefix
305: + "web-app/message-destination/message-destination-name",
306: "setName", 0);
307:
308: digester.addObjectCreate(prefix
309: + "web-app/message-destination-ref",
310: "org.apache.catalina.deploy.MessageDestinationRef");
311: digester.addSetNext(prefix + "web-app/message-destination-ref",
312: "addMessageDestinationRef",
313: "org.apache.catalina.deploy.MessageDestinationRef");
314:
315: digester.addCallMethod(prefix
316: + "web-app/message-destination-ref/description",
317: "setDescription", 0);
318: digester
319: .addCallMethod(
320: prefix
321: + "web-app/message-destination-ref/message-destination-link",
322: "setLink", 0);
323: digester
324: .addCallMethod(
325: prefix
326: + "web-app/message-destination-ref/message-destination-ref-name",
327: "setName", 0);
328: digester
329: .addCallMethod(
330: prefix
331: + "web-app/message-destination-ref/message-destination-type",
332: "setType", 0);
333: digester
334: .addCallMethod(
335: prefix
336: + "web-app/message-destination-ref/message-destination-usage",
337: "setUsage", 0);
338:
339: digester.addObjectCreate(prefix + "web-app/resource-ref",
340: "org.apache.catalina.deploy.ContextResource");
341: digester.addSetNext(prefix + "web-app/resource-ref",
342: "addResource",
343: "org.apache.catalina.deploy.ContextResource");
344:
345: digester.addCallMethod(prefix
346: + "web-app/resource-ref/description", "setDescription",
347: 0);
348: digester.addCallMethod(
349: prefix + "web-app/resource-ref/res-auth", "setAuth", 0);
350: digester.addCallMethod(prefix
351: + "web-app/resource-ref/res-ref-name", "setName", 0);
352: digester.addCallMethod(prefix
353: + "web-app/resource-ref/res-sharing-scope", "setScope",
354: 0);
355: digester.addCallMethod(
356: prefix + "web-app/resource-ref/res-type", "setType", 0);
357:
358: digester.addObjectCreate(
359: prefix + "web-app/security-constraint",
360: "org.apache.catalina.deploy.SecurityConstraint");
361: digester.addSetNext(prefix + "web-app/security-constraint",
362: "addConstraint",
363: "org.apache.catalina.deploy.SecurityConstraint");
364:
365: digester.addRule(prefix
366: + "web-app/security-constraint/auth-constraint",
367: new SetAuthConstraintRule());
368: digester
369: .addCallMethod(
370: prefix
371: + "web-app/security-constraint/auth-constraint/role-name",
372: "addAuthRole", 0);
373: digester.addCallMethod(prefix
374: + "web-app/security-constraint/display-name",
375: "setDisplayName", 0);
376: digester
377: .addCallMethod(
378: prefix
379: + "web-app/security-constraint/user-data-constraint/transport-guarantee",
380: "setUserConstraint", 0);
381:
382: digester
383: .addObjectCreate(
384: prefix
385: + "web-app/security-constraint/web-resource-collection",
386: "org.apache.catalina.deploy.SecurityCollection");
387: digester
388: .addSetNext(
389: prefix
390: + "web-app/security-constraint/web-resource-collection",
391: "addCollection",
392: "org.apache.catalina.deploy.SecurityCollection");
393: digester
394: .addCallMethod(
395: prefix
396: + "web-app/security-constraint/web-resource-collection/http-method",
397: "addMethod", 0);
398: digester
399: .addCallMethod(
400: prefix
401: + "web-app/security-constraint/web-resource-collection/url-pattern",
402: "addPattern", 0);
403: digester
404: .addCallMethod(
405: prefix
406: + "web-app/security-constraint/web-resource-collection/web-resource-name",
407: "setName", 0);
408:
409: digester.addCallMethod(prefix
410: + "web-app/security-role/role-name", "addSecurityRole",
411: 0);
412:
413: digester.addRule(prefix + "web-app/servlet",
414: new WrapperCreateRule());
415: digester.addSetNext(prefix + "web-app/servlet", "addChild",
416: "org.apache.catalina.Container");
417:
418: digester.addCallMethod(prefix + "web-app/servlet/init-param",
419: "addInitParameter", 2);
420: digester.addCallParam(prefix
421: + "web-app/servlet/init-param/param-name", 0);
422: digester.addCallParam(prefix
423: + "web-app/servlet/init-param/param-value", 1);
424:
425: digester.addCallMethod(prefix + "web-app/servlet/jsp-file",
426: "setJspFile", 0);
427: digester.addCallMethod(prefix
428: + "web-app/servlet/load-on-startup",
429: "setLoadOnStartupString", 0);
430: digester.addCallMethod(prefix
431: + "web-app/servlet/run-as/role-name", "setRunAs", 0);
432:
433: digester.addCallMethod(prefix
434: + "web-app/servlet/security-role-ref",
435: "addSecurityReference", 2);
436: digester.addCallParam(prefix
437: + "web-app/servlet/security-role-ref/role-link", 1);
438: digester.addCallParam(prefix
439: + "web-app/servlet/security-role-ref/role-name", 0);
440:
441: digester.addCallMethod(
442: prefix + "web-app/servlet/servlet-class",
443: "setServletClass", 0);
444: digester.addCallMethod(prefix + "web-app/servlet/servlet-name",
445: "setName", 0);
446:
447: digester.addCallMethod(prefix + "web-app/servlet-mapping",
448: "addServletMapping", 2);
449: digester.addCallParam(prefix
450: + "web-app/servlet-mapping/servlet-name", 1);
451: digester.addCallParam(prefix
452: + "web-app/servlet-mapping/url-pattern", 0);
453:
454: digester.addRule(prefix + "web-app/session-config",
455: sessionConfig);
456:
457: digester.addCallMethod(prefix
458: + "web-app/session-config/session-timeout",
459: "setSessionTimeout", 1, new Class[] { Integer.TYPE });
460: digester.addCallParam(prefix
461: + "web-app/session-config/session-timeout", 0);
462:
463: digester.addCallMethod(prefix + "web-app/taglib", "addTaglib",
464: 2);
465: digester.addCallParam(
466: prefix + "web-app/taglib/taglib-location", 1);
467: digester.addCallParam(prefix + "web-app/taglib/taglib-uri", 0);
468:
469: digester.addCallMethod(prefix
470: + "web-app/welcome-file-list/welcome-file",
471: "addWelcomeFile", 0);
472:
473: digester
474: .addCallMethod(
475: prefix
476: + "web-app/locale-encoding-mapping-list/locale-encoding-mapping",
477: "addLocaleEncodingMappingParameter", 2);
478: digester
479: .addCallParam(
480: prefix
481: + "web-app/locale-encoding-mapping-list/locale-encoding-mapping/locale",
482: 0);
483: digester
484: .addCallParam(
485: prefix
486: + "web-app/locale-encoding-mapping-list/locale-encoding-mapping/encoding",
487: 1);
488:
489: }
490:
491: /**
492: * Reset counter used for validating the web.xml file.
493: */
494: public void recycle() {
495: jspConfig.isJspConfigSet = false;
496: sessionConfig.isSessionConfigSet = false;
497: loginConfig.isLoginConfigSet = false;
498: }
499: }
500:
501: // ----------------------------------------------------------- Private Classes
502:
503: /**
504: * Rule to check that the <code>login-config</code> is occuring
505: * only 1 time within the web.xml
506: */
507: final class SetLoginConfig extends Rule {
508: protected boolean isLoginConfigSet = false;
509:
510: public SetLoginConfig() {
511: }
512:
513: public void begin(String namespace, String name,
514: Attributes attributes) throws Exception {
515: if (isLoginConfigSet) {
516: throw new IllegalArgumentException(
517: "<login-config> element is limited to 1 occurance");
518: }
519: isLoginConfigSet = true;
520: }
521:
522: }
523:
524: /**
525: * Rule to check that the <code>jsp-config</code> is occuring
526: * only 1 time within the web.xml
527: */
528: final class SetJspConfig extends Rule {
529: protected boolean isJspConfigSet = false;
530:
531: public SetJspConfig() {
532: }
533:
534: public void begin(String namespace, String name,
535: Attributes attributes) throws Exception {
536: if (isJspConfigSet) {
537: throw new IllegalArgumentException(
538: "<jsp-config> element is limited to 1 occurance");
539: }
540: isJspConfigSet = true;
541: }
542:
543: }
544:
545: /**
546: * Rule to check that the <code>session-config</code> is occuring
547: * only 1 time within the web.xml
548: */
549: final class SetSessionConfig extends Rule {
550: protected boolean isSessionConfigSet = false;
551:
552: public SetSessionConfig() {
553: }
554:
555: public void begin(String namespace, String name,
556: Attributes attributes) throws Exception {
557: if (isSessionConfigSet) {
558: throw new IllegalArgumentException(
559: "<session-config> element is limited to 1 occurance");
560: }
561: isSessionConfigSet = true;
562: }
563:
564: }
565:
566: /**
567: * A Rule that calls the <code>setAuthConstraint(true)</code> method of
568: * the top item on the stack, which must be of type
569: * <code>org.apache.catalina.deploy.SecurityConstraint</code>.
570: */
571:
572: final class SetAuthConstraintRule extends Rule {
573:
574: public SetAuthConstraintRule() {
575: }
576:
577: public void begin(String namespace, String name,
578: Attributes attributes) throws Exception {
579: SecurityConstraint securityConstraint = (SecurityConstraint) digester
580: .peek();
581: securityConstraint.setAuthConstraint(true);
582: if (digester.getLogger().isDebugEnabled()) {
583: digester
584: .getLogger()
585: .debug(
586: "Calling SecurityConstraint.setAuthConstraint(true)");
587: }
588: }
589:
590: }
591:
592: /**
593: * Class that calls <code>setDistributable(true)</code> for the top object
594: * on the stack, which must be a <code>org.apache.catalina.Context</code>.
595: */
596:
597: final class SetDistributableRule extends Rule {
598:
599: public SetDistributableRule() {
600: }
601:
602: public void begin(String namespace, String name,
603: Attributes attributes) throws Exception {
604: Context context = (Context) digester.peek();
605: context.setDistributable(true);
606: if (digester.getLogger().isDebugEnabled()) {
607: digester.getLogger().debug(
608: context.getClass().getName()
609: + ".setDistributable( true)");
610: }
611: }
612:
613: }
614:
615: /**
616: * Class that calls a property setter for the top object on the stack,
617: * passing the public ID of the entity we are currently processing.
618: */
619:
620: final class SetPublicIdRule extends Rule {
621:
622: public SetPublicIdRule(String method) {
623: this .method = method;
624: }
625:
626: private String method = null;
627:
628: public void begin(String namespace, String name,
629: Attributes attributes) throws Exception {
630:
631: Context context = (Context) digester
632: .peek(digester.getCount() - 1);
633: Object top = digester.peek();
634: Class paramClasses[] = new Class[1];
635: paramClasses[0] = "String".getClass();
636: String paramValues[] = new String[1];
637: paramValues[0] = digester.getPublicId();
638:
639: Method m = null;
640: try {
641: m = top.getClass().getMethod(method, paramClasses);
642: } catch (NoSuchMethodException e) {
643: digester.getLogger().error(
644: "Can't find method " + method + " in " + top
645: + " CLASS " + top.getClass());
646: return;
647: }
648:
649: m.invoke(top, paramValues);
650: if (digester.getLogger().isDebugEnabled())
651: digester.getLogger().debug(
652: "" + top.getClass().getName() + "." + method + "("
653: + paramValues[0] + ")");
654:
655: }
656:
657: }
658:
659: /**
660: * A Rule that calls the factory method on the specified Context to
661: * create the object that is to be added to the stack.
662: */
663:
664: final class WrapperCreateRule extends Rule {
665:
666: public WrapperCreateRule() {
667: }
668:
669: public void begin(String namespace, String name,
670: Attributes attributes) throws Exception {
671: Context context = (Context) digester
672: .peek(digester.getCount() - 1);
673: Wrapper wrapper = context.createWrapper();
674: digester.push(wrapper);
675: if (digester.getLogger().isDebugEnabled())
676: digester.getLogger().debug(
677: "new " + wrapper.getClass().getName());
678: }
679:
680: public void end(String namespace, String name) throws Exception {
681: Wrapper wrapper = (Wrapper) digester.pop();
682: if (digester.getLogger().isDebugEnabled())
683: digester.getLogger().debug(
684: "pop " + wrapper.getClass().getName());
685: }
686:
687: }
|