KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > tapestry > parse > SpecificationParser


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

15 package org.apache.tapestry.parse;
16
17 import java.io.BufferedInputStream JavaDoc;
18 import java.io.IOException JavaDoc;
19 import java.io.InputStream JavaDoc;
20 import java.net.URL JavaDoc;
21 import java.util.HashMap JavaDoc;
22 import java.util.Iterator JavaDoc;
23 import java.util.Map JavaDoc;
24
25 import javax.xml.parsers.SAXParser JavaDoc;
26 import javax.xml.parsers.SAXParserFactory JavaDoc;
27
28 import org.apache.commons.logging.Log;
29 import org.apache.commons.logging.LogFactory;
30 import org.apache.hivemind.ClassResolver;
31 import org.apache.hivemind.ErrorHandler;
32 import org.apache.hivemind.HiveMind;
33 import org.apache.hivemind.Location;
34 import org.apache.hivemind.Resource;
35 import org.apache.hivemind.impl.DefaultErrorHandler;
36 import org.apache.hivemind.impl.LocationImpl;
37 import org.apache.hivemind.parse.AbstractParser;
38 import org.apache.tapestry.INamespace;
39 import org.apache.tapestry.Tapestry;
40 import org.apache.tapestry.bean.BindingBeanInitializer;
41 import org.apache.tapestry.bean.LightweightBeanInitializer;
42 import org.apache.tapestry.binding.BindingConstants;
43 import org.apache.tapestry.binding.BindingSource;
44 import org.apache.tapestry.coerce.ValueConverter;
45 import org.apache.tapestry.spec.BeanLifecycle;
46 import org.apache.tapestry.spec.BindingType;
47 import org.apache.tapestry.spec.IApplicationSpecification;
48 import org.apache.tapestry.spec.IAssetSpecification;
49 import org.apache.tapestry.spec.IBeanSpecification;
50 import org.apache.tapestry.spec.IBindingSpecification;
51 import org.apache.tapestry.spec.IComponentSpecification;
52 import org.apache.tapestry.spec.IContainedComponent;
53 import org.apache.tapestry.spec.IExtensionSpecification;
54 import org.apache.tapestry.spec.ILibrarySpecification;
55 import org.apache.tapestry.spec.IListenerBindingSpecification;
56 import org.apache.tapestry.spec.IParameterSpecification;
57 import org.apache.tapestry.spec.IPropertySpecification;
58 import org.apache.tapestry.spec.InjectSpecification;
59 import org.apache.tapestry.spec.SpecFactory;
60 import org.apache.tapestry.util.IPropertyHolder;
61 import org.apache.tapestry.util.RegexpMatcher;
62 import org.apache.tapestry.util.xml.DocumentParseException;
63 import org.apache.tapestry.util.xml.InvalidStringException;
64 import org.xml.sax.InputSource JavaDoc;
65 import org.xml.sax.SAXException JavaDoc;
66 import org.xml.sax.SAXParseException JavaDoc;
67
68 /**
69  * Parses the different types of Tapestry specifications.
70  * <p>
71  * Not threadsafe; it is the callers responsibility to ensure thread safety.
72  *
73  * @author Howard Lewis Ship
74  */

75 public class SpecificationParser extends AbstractParser implements ISpecificationParser
76 {
77     private static final String JavaDoc IDENTIFIER_PATTERN = "_?[a-zA-Z]\\w*";
78
79     private static final String JavaDoc EXTENDED_IDENTIFIER_PATTERN = "_?[a-zA-Z](\\w|-)*";
80
81     /**
82      * Perl5 pattern for asset names. Letter, followed by letter, number or underscore. Also allows
83      * the special "$template" value.
84      *
85      * @since 2.2
86      */

87
88     public static final String JavaDoc ASSET_NAME_PATTERN = "(\\$template)|("
89             + Tapestry.SIMPLE_PROPERTY_NAME_PATTERN + ")";
90
91     /**
92      * Perl5 pattern for helper bean names. Letter, followed by letter, number or underscore.
93      *
94      * @since 2.2
95      */

96
97     public static final String JavaDoc BEAN_NAME_PATTERN = Tapestry.SIMPLE_PROPERTY_NAME_PATTERN;
98
99     /**
100      * Perl5 pattern for component alias. Letter, followed by letter, number, or underscore. This is
101      * used to validate component types registered in the application or library specifications.
102      *
103      * @since 2.2
104      */

105
106     public static final String JavaDoc COMPONENT_ALIAS_PATTERN = Tapestry.SIMPLE_PROPERTY_NAME_PATTERN;
107
108     /**
109      * Perl5 pattern for component ids. Letter, followed by letter, number or underscore.
110      *
111      * @since 2.2
112      */

113
114     public static final String JavaDoc COMPONENT_ID_PATTERN = Tapestry.SIMPLE_PROPERTY_NAME_PATTERN;
115
116     /**
117      * Perl5 pattern for component types. Component types are an optional namespace prefix followed
118      * by a normal identifier.
119      *
120      * @since 2.2
121      */

122
123     public static final String JavaDoc COMPONENT_TYPE_PATTERN = "^(" + IDENTIFIER_PATTERN + ":)?"
124             + IDENTIFIER_PATTERN + "$";
125
126     /**
127      * We can share a single map for all the XML attribute to object conversions, since the keys are
128      * unique.
129      */

130
131     private final Map JavaDoc CONVERSION_MAP = new HashMap JavaDoc();
132
133     /**
134      * Extended version of {@link Tapestry.SIMPLE_PROPERTY_NAME_PATTERN}, but allows a series of
135      * individual property names, seperated by periods. In addition, each name within the dotted
136      * sequence is allowed to contain dashes.
137      *
138      * @since 2.2
139      */

140
141     public static final String JavaDoc EXTENDED_PROPERTY_NAME_PATTERN = "^" + EXTENDED_IDENTIFIER_PATTERN
142             + "(\\." + EXTENDED_IDENTIFIER_PATTERN + ")*$";
143
144     /**
145      * Per5 pattern for extension names. Letter followed by letter, number, dash, period or
146      * underscore.
147      *
148      * @since 2.2
149      */

150
151     public static final String JavaDoc EXTENSION_NAME_PATTERN = EXTENDED_PROPERTY_NAME_PATTERN;
152
153     /**
154      * Perl5 pattern for library ids. Letter followed by letter, number or underscore.
155      *
156      * @since 2.2
157      */

158
159     public static final String JavaDoc LIBRARY_ID_PATTERN = Tapestry.SIMPLE_PROPERTY_NAME_PATTERN;
160
161     /** @since 4.0 */
162     private final Log _log;
163
164     /** @since 4.0 */
165     private final ErrorHandler _errorHandler;
166
167     /**
168      * Set to true if parsing the 4.0 DTD.
169      *
170      * @since 4.0
171      */

172
173     private boolean _DTD_4_0;
174
175     /**
176      * Perl5 pattern for page names. Page names appear in library and application specifications, in
177      * the &lt;page&gt; element. Starting with 4.0, the page name may look more like a path name,
178      * consisting of a number of ids seperated by slashes. This is used to determine the folder
179      * which contains the page specification or the page's template.
180      *
181      * @since 2.2
182      */

183
184     public static final String JavaDoc PAGE_NAME_PATTERN = "^" + IDENTIFIER_PATTERN + "(/"
185             + IDENTIFIER_PATTERN + ")*$";
186
187     /**
188      * Perl5 pattern that parameter names must conform to. Letter, followed by letter, number or
189      * underscore.
190      *
191      * @since 2.2
192      */

193
194     public static final String JavaDoc PARAMETER_NAME_PATTERN = Tapestry.SIMPLE_PROPERTY_NAME_PATTERN;
195
196     /**
197      * Perl5 pattern that property names (that can be connected to parameters) must conform to.
198      * Letter, followed by letter, number or underscore.
199      *
200      * @since 2.2
201      */

202
203     public static final String JavaDoc PROPERTY_NAME_PATTERN = Tapestry.SIMPLE_PROPERTY_NAME_PATTERN;
204
205     /**
206      * Perl5 pattern for service names. Letter followed by letter, number, dash, underscore or
207      * period.
208      *
209      * @since 2.2
210      * @deprecated As of release 4.0, the &lt;service&gt; element (in 3.0 DTDs) is no longer
211      * supported.
212      */

213
214     public static final String JavaDoc SERVICE_NAME_PATTERN = EXTENDED_PROPERTY_NAME_PATTERN;
215
216     private static final int STATE_ALLOW_DESCRIPTION = 2000;
217
218     private static final int STATE_ALLOW_PROPERTY = 2001;
219
220     private static final int STATE_APPLICATION_SPECIFICATION_INITIAL = 1002;
221
222     private static final int STATE_BEAN = 4;
223
224     /** Very different between 3.0 and 4.0 DTD */
225
226     private static final int STATE_BINDING_3_0 = 7;
227
228     /** @since 4.0 */
229
230     private static final int STATE_BINDING = 100;
231
232     private static final int STATE_COMPONENT = 6;
233
234     private static final int STATE_COMPONENT_SPECIFICATION = 1;
235
236     private static final int STATE_COMPONENT_SPECIFICATION_INITIAL = 1000;
237
238     private static final int STATE_CONFIGURE = 14;
239
240     private static final int STATE_DESCRIPTION = 2;
241
242     private static final int STATE_EXTENSION = 13;
243
244     private static final int STATE_LIBRARY_SPECIFICATION = 12;
245
246     private static final int STATE_LIBRARY_SPECIFICATION_INITIAL = 1003;
247
248     private static final int STATE_LISTENER_BINDING = 8;
249
250     private static final int STATE_NO_CONTENT = 3000;
251
252     private static final int STATE_PAGE_SPECIFICATION = 11;
253
254     private static final int STATE_PAGE_SPECIFICATION_INITIAL = 1001;
255
256     private static final int STATE_META = 3;
257
258     private static final int STATE_PROPERTY = 10;
259
260     private static final int STATE_SET = 5;
261
262     /** 3.0 DTD only */
263     private static final int STATE_STATIC_BINDING = 9;
264
265     /** @since 3.0 */
266
267     public static final String JavaDoc TAPESTRY_DTD_3_0_PUBLIC_ID = "-//Apache Software Foundation//Tapestry Specification 3.0//EN";
268
269     /** @since 4.0 */
270
271     public static final String JavaDoc TAPESTRY_DTD_4_0_PUBLIC_ID = "-//Apache Software Foundation//Tapestry Specification 4.0//EN";
272
273     /**
274      * The attributes of the current element, as a map (string keyed on string).
275      */

276
277     private Map JavaDoc _attributes;
278
279     /**
280      * The name of the current element.
281      */

282
283     private String JavaDoc _elementName;
284
285     /** @since 1.0.9 */
286
287     private final SpecFactory _factory;
288
289     private RegexpMatcher _matcher = new RegexpMatcher();
290
291     private SAXParser JavaDoc _parser;
292
293     private SAXParserFactory JavaDoc _parserFactory = SAXParserFactory.newInstance();
294
295     /**
296      * @since 3.0
297      */

298
299     private final ClassResolver _resolver;
300
301     /** @since 4.0 */
302
303     private BindingSource _bindingSource;
304
305     /**
306      * The root object parsed: a component or page specification, a library specification, or an
307      * application specification.
308      */

309     private Object JavaDoc _rootObject;
310
311     /** @since 4.0 */
312
313     private ValueConverter _valueConverter;
314
315     // Identify all the different acceptible values.
316
// We continue to sneak by with a single map because
317
// there aren't conflicts; when we have 'foo' meaning
318
// different things in different places in the DTD, we'll
319
// need multiple maps.
320

321     {
322
323         CONVERSION_MAP.put("true", Boolean.TRUE);
324         CONVERSION_MAP.put("t", Boolean.TRUE);
325         CONVERSION_MAP.put("1", Boolean.TRUE);
326         CONVERSION_MAP.put("y", Boolean.TRUE);
327         CONVERSION_MAP.put("yes", Boolean.TRUE);
328         CONVERSION_MAP.put("on", Boolean.TRUE);
329         CONVERSION_MAP.put("aye", Boolean.TRUE);
330
331         CONVERSION_MAP.put("false", Boolean.FALSE);
332         CONVERSION_MAP.put("f", Boolean.FALSE);
333         CONVERSION_MAP.put("0", Boolean.FALSE);
334         CONVERSION_MAP.put("off", Boolean.FALSE);
335         CONVERSION_MAP.put("no", Boolean.FALSE);
336         CONVERSION_MAP.put("n", Boolean.FALSE);
337         CONVERSION_MAP.put("nay", Boolean.FALSE);
338
339         CONVERSION_MAP.put("none", BeanLifecycle.NONE);
340         CONVERSION_MAP.put("request", BeanLifecycle.REQUEST);
341         CONVERSION_MAP.put("page", BeanLifecycle.PAGE);
342         CONVERSION_MAP.put("render", BeanLifecycle.RENDER);
343
344         _parserFactory.setNamespaceAware(false);
345         _parserFactory.setValidating(true);
346     }
347
348     /**
349      * This constructor is a convienience used by some tests.
350      */

351     public SpecificationParser(ClassResolver resolver)
352     {
353         this(resolver, new SpecFactory());
354     }
355
356     /**
357      * Create a new instance with resolver and a provided SpecFactory (used by Spindle).
358      *
359      * @deprecated to be removed in release 4.1
360      */

361     public SpecificationParser(ClassResolver resolver, SpecFactory factory)
362     {
363         this(new DefaultErrorHandler(), LogFactory.getLog(SpecificationParser.class), resolver,
364                 factory);
365     }
366
367     /**
368      * The full constructor, used within Tapestry.
369      */

370     public SpecificationParser(ErrorHandler errorHandler, Log log, ClassResolver resolver,
371             SpecFactory factory)
372     {
373         _errorHandler = errorHandler;
374         _log = log;
375         _resolver = resolver;
376         _factory = factory;
377     }
378
379     protected void begin(String JavaDoc elementName, Map JavaDoc attributes)
380     {
381         _elementName = elementName;
382         _attributes = attributes;
383
384         switch (getState())
385         {
386             case STATE_COMPONENT_SPECIFICATION_INITIAL:
387
388                 beginComponentSpecificationInitial();
389                 break;
390
391             case STATE_PAGE_SPECIFICATION_INITIAL:
392
393                 beginPageSpecificationInitial();
394                 break;
395
396             case STATE_APPLICATION_SPECIFICATION_INITIAL:
397
398                 beginApplicationSpecificationInitial();
399                 break;
400
401             case STATE_LIBRARY_SPECIFICATION_INITIAL:
402
403                 beginLibrarySpecificationInitial();
404                 break;
405
406             case STATE_COMPONENT_SPECIFICATION:
407
408                 beginComponentSpecification();
409                 break;
410
411             case STATE_PAGE_SPECIFICATION:
412
413                 beginPageSpecification();
414                 break;
415
416             case STATE_ALLOW_DESCRIPTION:
417
418                 beginAllowDescription();
419                 break;
420
421             case STATE_ALLOW_PROPERTY:
422
423                 allowMetaData();
424                 break;
425
426             case STATE_BEAN:
427
428                 beginBean();
429                 break;
430
431             case STATE_COMPONENT:
432
433                 beginComponent();
434                 break;
435
436             case STATE_LIBRARY_SPECIFICATION:
437
438                 beginLibrarySpecification();
439                 break;
440
441             case STATE_EXTENSION:
442
443                 beginExtension();
444                 break;
445
446             default:
447
448                 unexpectedElement(_elementName);
449         }
450     }
451
452     /**
453      * Special state for a number of specification types that can support the &lt;description&gt;
454      * element.
455      */

456
457     private void beginAllowDescription()
458     {
459         if (_elementName.equals("description"))
460         {
461             enterDescription();
462             return;
463         }
464
465         unexpectedElement(_elementName);
466     }
467
468     /**
469      * Special state for a number of elements that can support the nested &lt;meta&gt; meta data
470      * element (&lt;property&gt; in 3.0 DTD).
471      */

472
473     private void allowMetaData()
474     {
475         if (_DTD_4_0)
476         {
477             if (_elementName.equals("meta"))
478             {
479                 enterMeta();
480                 return;
481             }
482         }
483         else if (_elementName.equals("property"))
484         {
485             enterProperty_3_0();
486             return;
487         }
488
489         unexpectedElement(_elementName);
490     }
491
492     private void beginApplicationSpecificationInitial()
493     {
494         expectElement("application");
495
496         String JavaDoc name = getAttribute("name");
497         String JavaDoc engineClassName = getAttribute("engine-class");
498
499         IApplicationSpecification as = _factory.createApplicationSpecification();
500
501         as.setName(name);
502
503         if (HiveMind.isNonBlank(engineClassName))
504             as.setEngineClassName(engineClassName);
505
506         _rootObject = as;
507
508         push(_elementName, as, STATE_LIBRARY_SPECIFICATION);
509     }
510
511     private void beginBean()
512     {
513         if (_elementName.equals("set"))
514         {
515             enterSet();
516             return;
517         }
518
519         if (_elementName.equals("set-property"))
520         {
521             enterSetProperty_3_0();
522             return;
523         }
524
525         if (_elementName.equals("set-message-property"))
526         {
527             enterSetMessage_3_0();
528             return;
529         }
530
531         if (_elementName.equals("description"))
532         {
533             enterDescription();
534             return;
535         }
536
537         allowMetaData();
538     }
539
540     private void beginComponent()
541     {
542         // <binding> has changed between 3.0 and 4.0
543

544         if (_elementName.equals("binding"))
545         {
546             enterBinding();
547             return;
548         }
549
550         if (_elementName.equals("static-binding"))
551         {
552             enterStaticBinding_3_0();
553             return;
554         }
555
556         if (_elementName.equals("message-binding"))
557         {
558             enterMessageBinding_3_0();
559             return;
560         }
561
562         if (_elementName.equals("inherited-binding"))
563         {
564             enterInheritedBinding_3_0();
565             return;
566         }
567
568         if (_elementName.equals("listener-binding"))
569         {
570             enterListenerBinding();
571             return;
572         }
573
574         allowMetaData();
575     }
576
577     private void beginComponentSpecification()
578     {
579         if (_elementName.equals("reserved-parameter"))
580         {
581             enterReservedParameter();
582             return;
583         }
584
585         if (_elementName.equals("parameter"))
586         {
587             enterParameter();
588             return;
589         }
590
591         // The remainder are common to both <component-specification> and
592
// <page-specification>
593

594         beginPageSpecification();
595     }
596
597     private void beginComponentSpecificationInitial()
598     {
599         expectElement("component-specification");
600
601         IComponentSpecification cs = _factory.createComponentSpecification();
602
603         cs.setAllowBody(getBooleanAttribute("allow-body", true));
604         cs.setAllowInformalParameters(getBooleanAttribute("allow-informal-parameters", true));
605         cs.setDeprecated(getBooleanAttribute("deprecated", false));
606
607         String JavaDoc className = getAttribute("class");
608
609         if (className != null)
610             cs.setComponentClassName(className);
611
612         cs.setSpecificationLocation(getResource());
613
614         _rootObject = cs;
615
616         push(_elementName, cs, STATE_COMPONENT_SPECIFICATION);
617     }
618
619     private void beginExtension()
620     {
621         if (_elementName.equals("configure"))
622         {
623             enterConfigure();
624             return;
625         }
626
627         allowMetaData();
628     }
629
630     private void beginLibrarySpecification()
631     {
632         if (_elementName.equals("description"))
633         {
634             enterDescription();
635             return;
636         }
637
638         if (_elementName.equals("page"))
639         {
640             enterPage();
641             return;
642         }
643
644         if (_elementName.equals("component-type"))
645         {
646             enterComponentType();
647             return;
648         }
649
650         // Holdover from the 3.0 DTD, now ignored.
651

652         if (_elementName.equals("service"))
653         {
654             enterService_3_0();
655             return;
656         }
657
658         if (_elementName.equals("library"))
659         {
660             enterLibrary();
661             return;
662         }
663
664         if (_elementName.equals("extension"))
665         {
666             enterExtension();
667             return;
668         }
669
670         allowMetaData();
671     }
672
673     private void beginLibrarySpecificationInitial()
674     {
675         expectElement("library-specification");
676
677         ILibrarySpecification ls = _factory.createLibrarySpecification();
678
679         _rootObject = ls;
680
681         push(_elementName, ls, STATE_LIBRARY_SPECIFICATION);
682     }
683
684     private void beginPageSpecification()
685     {
686         if (_elementName.equals("component"))
687         {
688             enterComponent();
689             return;
690         }
691
692         if (_elementName.equals("bean"))
693         {
694             enterBean();
695             return;
696         }
697
698         // <property-specification> in 3.0, <property> in 4.0
699
// Have to be careful, because <meta> in 4.0 was <property> in 3.0
700

701         if (_elementName.equals("property-specification")
702                 || (_DTD_4_0 && _elementName.equals("property")))
703         {
704             enterProperty();
705             return;
706         }
707
708         if (_elementName.equals("inject"))
709         {
710             enterInject();
711             return;
712         }
713
714         // <asset> is new in 4.0
715

716         if (_elementName.equals("asset"))
717         {
718             enterAsset();
719             return;
720         }
721
722         // <context-asset>, <external-asset>, and <private-asset>
723
// are all throwbacks to the 3.0 DTD and don't exist
724
// in the 4.0 DTD.
725

726         if (_elementName.equals("context-asset"))
727         {
728             enterContextAsset_3_0();
729             return;
730         }
731
732         if (_elementName.equals("private-asset"))
733         {
734             enterPrivateAsset_3_0();
735             return;
736         }
737
738         if (_elementName.equals("external-asset"))
739         {
740             enterExternalAsset_3_0();
741             return;
742
743         }
744
745         if (_elementName.equals("description"))
746         {
747             enterDescription();
748             return;
749         }
750
751         allowMetaData();
752     }
753
754     private void beginPageSpecificationInitial()
755     {
756         expectElement("page-specification");
757
758         IComponentSpecification cs = _factory.createComponentSpecification();
759
760         String JavaDoc className = getAttribute("class");
761
762         if (className != null)
763             cs.setComponentClassName(className);
764
765         cs.setSpecificationLocation(getResource());
766         cs.setPageSpecification(true);
767
768         _rootObject = cs;
769
770         push(_elementName, cs, STATE_PAGE_SPECIFICATION);
771     }
772
773     /**
774      * Close a stream (if not null), ignoring any errors.
775      */

776     private void close(InputStream JavaDoc stream)
777     {
778         try
779         {
780             if (stream != null)
781                 stream.close();
782         }
783         catch (IOException JavaDoc ex)
784         {
785             // ignore
786
}
787     }
788
789     private void copyBindings(String JavaDoc sourceComponentId, IComponentSpecification cs,
790             IContainedComponent target)
791     {
792         IContainedComponent source = cs.getComponent(sourceComponentId);
793         if (source == null)
794             throw new DocumentParseException(ParseMessages.unableToCopy(sourceComponentId),
795                     getLocation(), null);
796
797         Iterator JavaDoc i = source.getBindingNames().iterator();
798         while (i.hasNext())
799         {
800             String JavaDoc bindingName = (String JavaDoc) i.next();
801             IBindingSpecification binding = source.getBinding(bindingName);
802             target.setBinding(bindingName, binding);
803         }
804
805         target.setType(source.getType());
806     }
807
808     protected void end(String JavaDoc elementName)
809     {
810         _elementName = elementName;
811
812         switch (getState())
813         {
814             case STATE_DESCRIPTION:
815
816                 endDescription();
817                 break;
818
819             case STATE_META:
820
821                 endProperty();
822                 break;
823
824             case STATE_SET:
825
826                 endSetProperty();
827                 break;
828
829             case STATE_BINDING_3_0:
830
831                 endBinding_3_0();
832                 break;
833
834             case STATE_BINDING:
835
836                 endBinding();
837                 break;
838
839             case STATE_LISTENER_BINDING:
840
841                 endListenerBinding();
842                 break;
843
844             case STATE_STATIC_BINDING:
845
846                 endStaticBinding();
847                 break;
848
849             case STATE_PROPERTY:
850
851                 endPropertySpecification();
852                 break;
853
854             case STATE_LIBRARY_SPECIFICATION:
855
856                 endLibrarySpecification();
857                 break;
858
859             case STATE_CONFIGURE:
860
861                 endConfigure();
862                 break;
863
864             default:
865                 break;
866         }
867
868         // Pop the top element of the stack and continue processing from there.
869

870         pop();
871     }
872
873     private void endBinding_3_0()
874     {
875         BindingSetter bs = (BindingSetter) peekObject();
876
877         String JavaDoc expression = getExtendedValue(bs.getValue(), "expression", true);
878
879         IBindingSpecification spec = _factory.createBindingSpecification();
880
881         spec.setType(BindingType.PREFIXED);
882         spec.setValue(BindingConstants.OGNL_PREFIX + ":" + expression);
883
884         bs.apply(spec);
885     }
886
887     private void endConfigure()
888     {
889         ExtensionConfigurationSetter setter = (ExtensionConfigurationSetter) peekObject();
890
891         String JavaDoc finalValue = getExtendedValue(setter.getValue(), "value", true);
892
893         setter.apply(finalValue);
894     }
895
896     private void endDescription()
897     {
898         DescriptionSetter setter = (DescriptionSetter) peekObject();
899
900         String JavaDoc description = peekContent();
901
902         setter.apply(description);
903     }
904
905     private void endLibrarySpecification()
906     {
907         ILibrarySpecification spec = (ILibrarySpecification) peekObject();
908
909         spec.setSpecificationLocation(getResource());
910
911         spec.instantiateImmediateExtensions();
912     }
913
914     private void endListenerBinding()
915     {
916         BindingSetter bs = (BindingSetter) peekObject();
917
918         IListenerBindingSpecification lbs = _factory.createListenerBindingSpecification();
919
920         lbs.setLanguage(bs.getValue());
921
922         // Do we need a check for no body content?
923

924         lbs.setValue(peekContent());
925         lbs.setLocation(getLocation());
926
927         bs.apply(lbs);
928     }
929
930     private void endProperty()
931     {
932         PropertyValueSetter pvs = (PropertyValueSetter) peekObject();
933
934         String JavaDoc finalValue = getExtendedValue(pvs.getPropertyValue(), "value", true);
935
936         pvs.applyValue(finalValue);
937     }
938
939     private void endPropertySpecification()
940     {
941         IPropertySpecification ps = (IPropertySpecification) peekObject();
942
943         String JavaDoc initialValue = getExtendedValue(ps.getInitialValue(), "initial-value", false);
944
945         // In the 3.0 DTD, the initial value was always an OGNL expression.
946
// In the 4.0 DTD, it is a binding reference, qualified with a prefix.
947

948         if (initialValue != null && !_DTD_4_0)
949             initialValue = BindingConstants.OGNL_PREFIX + ":" + initialValue;
950
951         ps.setInitialValue(initialValue);
952     }
953
954     private void endSetProperty()
955     {
956         BeanSetPropertySetter bs = (BeanSetPropertySetter) peekObject();
957
958         String JavaDoc finalValue = getExtendedValue(bs.getBindingReference(), "expression", true);
959
960         bs.applyBindingReference(finalValue);
961     }
962
963     private void endStaticBinding()
964     {
965         BindingSetter bs = (BindingSetter) peekObject();
966
967         String JavaDoc literalValue = getExtendedValue(bs.getValue(), "value", true);
968
969         IBindingSpecification spec = _factory.createBindingSpecification();
970
971         spec.setType(BindingType.PREFIXED);
972         spec.setValue(BindingConstants.LITERAL_PREFIX + ":" + literalValue);
973
974         bs.apply(spec);
975     }
976
977     private void enterAsset(String JavaDoc pathAttributeName, String JavaDoc prefix)
978     {
979         String JavaDoc name = getValidatedAttribute("name", ASSET_NAME_PATTERN, "invalid-asset-name");
980         String JavaDoc path = getAttribute(pathAttributeName);
981         String JavaDoc propertyName = getValidatedAttribute(
982                 "property",
983                 PROPERTY_NAME_PATTERN,
984                 "invalid-property-name");
985
986         IAssetSpecification ia = _factory.createAssetSpecification();
987
988         ia.setPath(prefix == null ? path : prefix + path);
989         ia.setPropertyName(propertyName);
990
991         IComponentSpecification cs = (IComponentSpecification) peekObject();
992
993         cs.addAsset(name, ia);
994
995         push(_elementName, ia, STATE_ALLOW_PROPERTY);
996     }
997
998     private void enterBean()
999     {
1000        String JavaDoc name = getValidatedAttribute("name", BEAN_NAME_PATTERN, "invalid-bean-name");
1001
1002        String JavaDoc classAttribute = getAttribute("class");
1003
1004        // Look for the lightweight initialization
1005

1006        int commax = classAttribute.indexOf(',');
1007
1008        String JavaDoc className = commax < 0 ? classAttribute : classAttribute.substring(0, commax);
1009
1010        BeanLifecycle lifecycle = (BeanLifecycle) getConvertedAttribute(
1011                "lifecycle",
1012                BeanLifecycle.REQUEST);
1013        String JavaDoc propertyName = getValidatedAttribute(
1014                "property",
1015                PROPERTY_NAME_PATTERN,
1016                "invalid-property-name");
1017
1018        IBeanSpecification bs = _factory.createBeanSpecification();
1019
1020        bs.setClassName(className);
1021        bs.setLifecycle(lifecycle);
1022        bs.setPropertyName(propertyName);
1023
1024        if (commax > 0)
1025        {
1026            String JavaDoc initializer = classAttribute.substring(commax + 1);
1027            bs.addInitializer(new LightweightBeanInitializer(initializer));
1028        }
1029
1030        IComponentSpecification cs = (IComponentSpecification) peekObject();
1031
1032        cs.addBeanSpecification(name, bs);
1033
1034        push(_elementName, bs, STATE_BEAN);
1035    }
1036
1037    private void enterBinding()
1038    {
1039        if (!_DTD_4_0)
1040        {
1041            enterBinding_3_0();
1042            return;
1043        }
1044
1045        // 4.0 stuff
1046

1047        String JavaDoc name = getValidatedAttribute(
1048                "name",
1049                PARAMETER_NAME_PATTERN,
1050                "invalid-parameter-name");
1051        String JavaDoc value = getAttribute("value");
1052
1053        IContainedComponent cc = (IContainedComponent) peekObject();
1054
1055        BindingSetter bs = new BindingSetter(cc, name, value);
1056
1057        push(_elementName, bs, STATE_BINDING, false);
1058    }
1059
1060    private void endBinding()
1061    {
1062        BindingSetter bs = (BindingSetter) peekObject();
1063
1064        String JavaDoc value = getExtendedValue(bs.getValue(), "value", true);
1065
1066        IBindingSpecification spec = _factory.createBindingSpecification();
1067
1068        spec.setType(BindingType.PREFIXED);
1069        spec.setValue(value);
1070
1071        bs.apply(spec);
1072    }
1073
1074    /**
1075     * Handles a binding in a 3.0 DTD.
1076     */

1077
1078    private void enterBinding_3_0()
1079    {
1080        String JavaDoc name = getAttribute("name");
1081        String JavaDoc expression = getAttribute("expression");
1082
1083        IContainedComponent cc = (IContainedComponent) peekObject();
1084
1085        BindingSetter bs = new BindingSetter(cc, name, expression);
1086
1087        push(_elementName, bs, STATE_BINDING_3_0, false);
1088    }
1089
1090    private void enterComponent()
1091    {
1092        String JavaDoc id = getValidatedAttribute("id", COMPONENT_ID_PATTERN, "invalid-component-id");
1093
1094        String JavaDoc type = getValidatedAttribute(
1095                "type",
1096                COMPONENT_TYPE_PATTERN,
1097                "invalid-component-type");
1098        String JavaDoc copyOf = getAttribute("copy-of");
1099        boolean inherit = getBooleanAttribute("inherit-informal-parameters", false);
1100        String JavaDoc propertyName = getValidatedAttribute(
1101                "property",
1102                PROPERTY_NAME_PATTERN,
1103                "invalid-property-name");
1104
1105        // Check that either copy-of or type, but not both
1106

1107        boolean hasCopyOf = HiveMind.isNonBlank(copyOf);
1108
1109        if (hasCopyOf)
1110        {
1111            if (HiveMind.isNonBlank(type))
1112                throw new DocumentParseException(ParseMessages.bothTypeAndCopyOf(id),
1113                        getLocation(), null);
1114        }
1115        else
1116        {
1117            if (HiveMind.isBlank(type))
1118                throw new DocumentParseException(ParseMessages.missingTypeOrCopyOf(id),
1119                        getLocation(), null);
1120        }
1121
1122        IContainedComponent cc = _factory.createContainedComponent();
1123        cc.setType(type);
1124        cc.setCopyOf(copyOf);
1125        cc.setInheritInformalParameters(inherit);
1126        cc.setPropertyName(propertyName);
1127
1128        IComponentSpecification cs = (IComponentSpecification) peekObject();
1129
1130        cs.addComponent(id, cc);
1131
1132        if (hasCopyOf)
1133            copyBindings(copyOf, cs, cc);
1134
1135        push(_elementName, cc, STATE_COMPONENT);
1136    }
1137
1138    private void enterComponentType()
1139    {
1140        String JavaDoc type = getValidatedAttribute(
1141                "type",
1142                COMPONENT_ALIAS_PATTERN,
1143                "invalid-component-type");
1144        String JavaDoc path = getAttribute("specification-path");
1145
1146        ILibrarySpecification ls = (ILibrarySpecification) peekObject();
1147
1148        ls.setComponentSpecificationPath(type, path);
1149
1150        push(_elementName, null, STATE_NO_CONTENT);
1151    }
1152
1153    private void enterConfigure()
1154    {
1155        String JavaDoc attributeName = _DTD_4_0 ? "property" : "property-name";
1156
1157        String JavaDoc propertyName = getValidatedAttribute(
1158                attributeName,
1159                PROPERTY_NAME_PATTERN,
1160                "invalid-property-name");
1161
1162        String JavaDoc value = getAttribute("value");
1163
1164        IExtensionSpecification es = (IExtensionSpecification) peekObject();
1165
1166        ExtensionConfigurationSetter setter = new ExtensionConfigurationSetter(es, propertyName,
1167                value);
1168
1169        push(_elementName, setter, STATE_CONFIGURE, false);
1170    }
1171
1172    private void enterContextAsset_3_0()
1173    {
1174        enterAsset("path", "context:");
1175    }
1176
1177    /**
1178     * New in the 4.0 DTD. When using the 4.0 DTD, you must explicitly specify prefix if the asset
1179     * is not stored in the same domain as the specification file.
1180     *
1181     * @since 4.0
1182     */

1183
1184    private void enterAsset()
1185    {
1186        enterAsset("path", null);
1187    }
1188
1189    private void enterDescription()
1190    {
1191        push(_elementName, new DescriptionSetter(peekObject()), STATE_DESCRIPTION, false);
1192    }
1193
1194    private void enterExtension()
1195    {
1196        String JavaDoc name = getValidatedAttribute(
1197                "name",
1198                EXTENSION_NAME_PATTERN,
1199                "invalid-extension-name");
1200
1201        boolean immediate = getBooleanAttribute("immediate", false);
1202        String JavaDoc className = getAttribute("class");
1203
1204        IExtensionSpecification es = _factory.createExtensionSpecification(
1205                _resolver,
1206                _valueConverter);
1207
1208        es.setClassName(className);
1209        es.setImmediate(immediate);
1210
1211        ILibrarySpecification ls = (ILibrarySpecification) peekObject();
1212
1213        ls.addExtensionSpecification(name, es);
1214
1215        push(_elementName, es, STATE_EXTENSION);
1216    }
1217
1218    private void enterExternalAsset_3_0()
1219    {
1220        // External URLs get no prefix, but will have a scheme (i.e., "http:") that
1221
// fulfils much the same purpose.
1222

1223        enterAsset("URL", null);
1224    }
1225
1226    /** A throwback to the 3.0 DTD */
1227
1228    private void enterInheritedBinding_3_0()
1229    {
1230        String JavaDoc name = getAttribute("name");
1231        String JavaDoc parameterName = getAttribute("parameter-name");
1232
1233        IBindingSpecification bs = _factory.createBindingSpecification();
1234        bs.setType(BindingType.INHERITED);
1235        bs.setValue(parameterName);
1236
1237        IContainedComponent cc = (IContainedComponent) peekObject();
1238
1239        cc.setBinding(name, bs);
1240
1241        push(_elementName, null, STATE_NO_CONTENT);
1242    }
1243
1244    private void enterLibrary()
1245    {
1246        String JavaDoc libraryId = getValidatedAttribute("id", LIBRARY_ID_PATTERN, "invalid-library-id");
1247        String JavaDoc path = getAttribute("specification-path");
1248
1249        if (libraryId.equals(INamespace.FRAMEWORK_NAMESPACE))
1250            throw new DocumentParseException(ParseMessages
1251                    .frameworkLibraryIdIsReserved(INamespace.FRAMEWORK_NAMESPACE), getLocation(),
1252                    null);
1253
1254        ILibrarySpecification ls = (ILibrarySpecification) peekObject();
1255
1256        ls.setLibrarySpecificationPath(libraryId, path);
1257
1258        push(_elementName, null, STATE_NO_CONTENT);
1259    }
1260
1261    private void enterListenerBinding()
1262    {
1263        String JavaDoc name = getAttribute("name");
1264        String JavaDoc language = getAttribute("language");
1265
1266        IContainedComponent cc = (IContainedComponent) peekObject();
1267        BindingSetter bs = new BindingSetter(cc, name, language);
1268
1269        push(_elementName, bs, STATE_LISTENER_BINDING, false);
1270    }
1271
1272    private void enterMessageBinding_3_0()
1273    {
1274        String JavaDoc name = getAttribute("name");
1275        String JavaDoc key = getAttribute("key");
1276
1277        IBindingSpecification bs = _factory.createBindingSpecification();
1278        bs.setType(BindingType.PREFIXED);
1279        bs.setValue(BindingConstants.MESSAGE_PREFIX + ":" + key);
1280        bs.setLocation(getLocation());
1281
1282        IContainedComponent cc = (IContainedComponent) peekObject();
1283
1284        cc.setBinding(name, bs);
1285
1286        push(_elementName, null, STATE_NO_CONTENT);
1287    }
1288
1289    private void enterPage()
1290    {
1291        String JavaDoc name = getValidatedAttribute("name", PAGE_NAME_PATTERN, "invalid-page-name");
1292        String JavaDoc path = getAttribute("specification-path");
1293
1294        ILibrarySpecification ls = (ILibrarySpecification) peekObject();
1295
1296        ls.setPageSpecificationPath(name, path);
1297
1298        push(_elementName, null, STATE_NO_CONTENT);
1299    }
1300
1301    private void enterParameter()
1302    {
1303        IParameterSpecification ps = _factory.createParameterSpecification();
1304
1305        String JavaDoc name = getValidatedAttribute(
1306                "name",
1307                PARAMETER_NAME_PATTERN,
1308                "invalid-parameter-name");
1309
1310        String JavaDoc attributeName = _DTD_4_0 ? "property" : "property-name";
1311
1312        String JavaDoc propertyName = getValidatedAttribute(
1313                attributeName,
1314                PROPERTY_NAME_PATTERN,
1315                "invalid-property-name");
1316
1317        if (propertyName == null)
1318            propertyName = name;
1319
1320        ps.setParameterName(name);
1321        ps.setPropertyName(propertyName);
1322
1323        ps.setRequired(getBooleanAttribute("required", false));
1324
1325        // In the 3.0 DTD, default-value was always an OGNL expression.
1326
// Starting with 4.0, it's like a binding (prefixed). For a 3.0
1327
// DTD, we supply the "ognl:" prefix.
1328

1329        String JavaDoc defaultValue = getAttribute("default-value");
1330
1331        if (defaultValue != null && !_DTD_4_0)
1332            defaultValue = BindingConstants.OGNL_PREFIX + ":" + defaultValue;
1333
1334        ps.setDefaultValue(defaultValue);
1335
1336        ps.setDefaultBindingType(getAttribute("default-binding"));
1337
1338        if (!_DTD_4_0)
1339        {
1340            String JavaDoc direction = getAttribute("direction");
1341            ps.setCache(!"auto".equals(direction));
1342        }
1343        else
1344        {
1345            boolean cache = getBooleanAttribute("cache", true);
1346            ps.setCache(cache);
1347        }
1348
1349        // type will only be specified in a 3.0 DTD.
1350

1351        String JavaDoc type = getAttribute("type");
1352
1353        if (type != null)
1354            ps.setType(type);
1355
1356        // aliases is new in the 4.0 DTD
1357

1358        String JavaDoc aliases = getAttribute("aliases");
1359
1360        ps.setAliases(aliases);
1361        ps.setDeprecated(getBooleanAttribute("deprecated", false));
1362
1363        IComponentSpecification cs = (IComponentSpecification) peekObject();
1364
1365        cs.addParameter(ps);
1366
1367        push(_elementName, ps, STATE_ALLOW_DESCRIPTION);
1368    }
1369
1370    private void enterPrivateAsset_3_0()
1371    {
1372        enterAsset("resource-path", "classpath:");
1373    }
1374
1375    /** @since 4.0 */
1376    private void enterMeta()
1377    {
1378        String JavaDoc key = getAttribute("key");
1379        String JavaDoc value = getAttribute("value");
1380
1381        // Value may be null, in which case the value is set from the element content
1382

1383        IPropertyHolder ph = (IPropertyHolder) peekObject();
1384
1385        push(_elementName, new PropertyValueSetter(ph, key, value), STATE_META, false);
1386    }
1387
1388    private void enterProperty_3_0()
1389    {
1390        String JavaDoc name = getAttribute("name");
1391        String JavaDoc value = getAttribute("value");
1392
1393        // Value may be null, in which case the value is set from the element content
1394

1395        IPropertyHolder ph = (IPropertyHolder) peekObject();
1396
1397        push(_elementName, new PropertyValueSetter(ph, name, value), STATE_META, false);
1398    }
1399
1400    /**
1401     * &tl;property&gt; in 4.0, or &lt;property-specification&gt; in 3.0
1402     */

1403
1404    private void enterProperty()
1405    {
1406        String JavaDoc name = getValidatedAttribute("name", PROPERTY_NAME_PATTERN, "invalid-property-name");
1407        String JavaDoc type = getAttribute("type");
1408
1409        String JavaDoc persistence = null;
1410
1411        if (_DTD_4_0)
1412            persistence = getAttribute("persist");
1413        else
1414            persistence = getBooleanAttribute("persistent", false) ? "session" : null;
1415
1416        String JavaDoc initialValue = getAttribute("initial-value");
1417
1418        IPropertySpecification ps = _factory.createPropertySpecification();
1419        ps.setName(name);
1420
1421        if (HiveMind.isNonBlank(type))
1422            ps.setType(type);
1423
1424        ps.setPersistence(persistence);
1425        ps.setInitialValue(initialValue);
1426
1427        IComponentSpecification cs = (IComponentSpecification) peekObject();
1428        cs.addPropertySpecification(ps);
1429
1430        push(_elementName, ps, STATE_PROPERTY, false);
1431    }
1432
1433    /**
1434     * @since 4.0
1435     */

1436
1437    private void enterInject()
1438    {
1439        String JavaDoc property = getValidatedAttribute(
1440                "property",
1441                PROPERTY_NAME_PATTERN,
1442                "invalid-property-name");
1443        String JavaDoc type = getAttribute("type");
1444        String JavaDoc objectReference = getAttribute("object");
1445
1446        InjectSpecification spec = _factory.createInjectSpecification();
1447
1448        spec.setProperty(property);
1449        spec.setType(type);
1450        spec.setObject(objectReference);
1451        IComponentSpecification cs = (IComponentSpecification) peekObject();
1452
1453        cs.addInjectSpecification(spec);
1454
1455        push(_elementName, spec, STATE_NO_CONTENT);
1456    }
1457
1458    private void enterReservedParameter()
1459    {
1460        String JavaDoc name = getAttribute("name");
1461        IComponentSpecification cs = (IComponentSpecification) peekObject();
1462
1463        cs.addReservedParameterName(name);
1464
1465        push(_elementName, null, STATE_NO_CONTENT);
1466    }
1467
1468    private void enterService_3_0()
1469    {
1470        _errorHandler.error(_log, ParseMessages.serviceElementNotSupported(), getLocation(), null);
1471
1472        push(_elementName, null, STATE_NO_CONTENT);
1473    }
1474
1475    private void enterSetMessage_3_0()
1476    {
1477        String JavaDoc name = getAttribute("name");
1478        String JavaDoc key = getAttribute("key");
1479
1480        BindingBeanInitializer bi = _factory.createBindingBeanInitializer(_bindingSource);
1481
1482        bi.setPropertyName(name);
1483        bi.setBindingReference(BindingConstants.MESSAGE_PREFIX + ":" + key);
1484        bi.setLocation(getLocation());
1485
1486        IBeanSpecification bs = (IBeanSpecification) peekObject();
1487
1488        bs.addInitializer(bi);
1489
1490        push(_elementName, null, STATE_NO_CONTENT);
1491    }
1492
1493    private void enterSet()
1494    {
1495        String JavaDoc name = getAttribute("name");
1496        String JavaDoc reference = getAttribute("value");
1497
1498        BindingBeanInitializer bi = _factory.createBindingBeanInitializer(_bindingSource);
1499
1500        bi.setPropertyName(name);
1501
1502        IBeanSpecification bs = (IBeanSpecification) peekObject();
1503
1504        push(_elementName, new BeanSetPropertySetter(bs, bi, null, reference), STATE_SET, false);
1505    }
1506
1507    private void enterSetProperty_3_0()
1508    {
1509        String JavaDoc name = getAttribute("name");
1510        String JavaDoc expression = getAttribute("expression");
1511
1512        BindingBeanInitializer bi = _factory.createBindingBeanInitializer(_bindingSource);
1513
1514        bi.setPropertyName(name);
1515
1516        IBeanSpecification bs = (IBeanSpecification) peekObject();
1517
1518        push(_elementName, new BeanSetPropertySetter(bs, bi, BindingConstants.OGNL_PREFIX + ":",
1519                expression), STATE_SET, false);
1520    }
1521
1522    private void enterStaticBinding_3_0()
1523    {
1524        String JavaDoc name = getAttribute("name");
1525        String JavaDoc expression = getAttribute("value");
1526
1527        IContainedComponent cc = (IContainedComponent) peekObject();
1528
1529        BindingSetter bs = new BindingSetter(cc, name, expression);
1530
1531        push(_elementName, bs, STATE_STATIC_BINDING, false);
1532    }
1533
1534    private void expectElement(String JavaDoc elementName)
1535    {
1536        if (_elementName.equals(elementName))
1537            return;
1538
1539        throw new DocumentParseException(ParseMessages.incorrectDocumentType(
1540                _elementName,
1541                elementName), getLocation(), null);
1542
1543    }
1544
1545    private String JavaDoc getAttribute(String JavaDoc name)
1546    {
1547        return (String JavaDoc) _attributes.get(name);
1548    }
1549
1550    private boolean getBooleanAttribute(String JavaDoc name, boolean defaultValue)
1551    {
1552        String JavaDoc value = getAttribute(name);
1553
1554        if (value == null)
1555            return defaultValue;
1556
1557        Boolean JavaDoc b = (Boolean JavaDoc) CONVERSION_MAP.get(value);
1558
1559        return b.booleanValue();
1560    }
1561
1562    private Object JavaDoc getConvertedAttribute(String JavaDoc name, Object JavaDoc defaultValue)
1563    {
1564        String JavaDoc key = getAttribute(name);
1565
1566        if (key == null)
1567            return defaultValue;
1568
1569        return CONVERSION_MAP.get(key);
1570    }
1571
1572    private InputSource JavaDoc getDTDInputSource(String JavaDoc name)
1573    {
1574        InputStream JavaDoc stream = getClass().getResourceAsStream(name);
1575
1576        return new InputSource JavaDoc(stream);
1577    }
1578
1579    private String JavaDoc getExtendedValue(String JavaDoc attributeValue, String JavaDoc attributeName, boolean required)
1580    {
1581        String JavaDoc contentValue = peekContent();
1582
1583        boolean asAttribute = HiveMind.isNonBlank(attributeValue);
1584        boolean asContent = HiveMind.isNonBlank(contentValue);
1585
1586        if (asAttribute && asContent)
1587        {
1588            throw new DocumentParseException(ParseMessages.noAttributeAndBody(
1589                    attributeName,
1590                    _elementName), getLocation(), null);
1591        }
1592
1593        if (required && !(asAttribute || asContent))
1594        {
1595            throw new DocumentParseException(ParseMessages.requiredExtendedAttribute(
1596                    _elementName,
1597                    attributeName), getLocation(), null);
1598        }
1599
1600        if (asAttribute)
1601            return attributeValue;
1602
1603        return contentValue;
1604    }
1605
1606    private String JavaDoc getValidatedAttribute(String JavaDoc name, String JavaDoc pattern, String JavaDoc errorKey)
1607    {
1608        String JavaDoc value = getAttribute(name);
1609
1610        if (value == null)
1611            return null;
1612
1613        if (_matcher.matches(pattern, value))
1614            return value;
1615
1616        throw new InvalidStringException(ParseMessages.invalidAttribute(errorKey, value), value,
1617                getLocation());
1618    }
1619
1620    protected void initializeParser(Resource resource, int startState)
1621    {
1622        super.initializeParser(resource, startState);
1623
1624        _rootObject = null;
1625        _attributes = new HashMap JavaDoc();
1626    }
1627
1628    public IApplicationSpecification parseApplicationSpecification(Resource resource)
1629    {
1630        initializeParser(resource, STATE_APPLICATION_SPECIFICATION_INITIAL);
1631
1632        try
1633        {
1634            parseDocument();
1635
1636            return (IApplicationSpecification) _rootObject;
1637        }
1638        finally
1639        {
1640            resetParser();
1641        }
1642    }
1643
1644    public IComponentSpecification parseComponentSpecification(Resource resource)
1645    {
1646        initializeParser(resource, STATE_COMPONENT_SPECIFICATION_INITIAL);
1647
1648        try
1649        {
1650            parseDocument();
1651
1652            return (IComponentSpecification) _rootObject;
1653        }
1654        finally
1655        {
1656            resetParser();
1657        }
1658    }
1659
1660    private void parseDocument()
1661    {
1662        InputStream JavaDoc stream = null;
1663
1664        Resource resource = getResource();
1665
1666        boolean success = false;
1667
1668        try
1669        {
1670            if (_parser == null)
1671                _parser = _parserFactory.newSAXParser();
1672
1673            URL JavaDoc resourceURL = resource.getResourceURL();
1674
1675            if (resourceURL == null)
1676                throw new DocumentParseException(ParseMessages.missingResource(resource), resource,
1677                        null);
1678
1679            InputStream JavaDoc rawStream = resourceURL.openStream();
1680            stream = new BufferedInputStream JavaDoc(rawStream);
1681
1682            _parser.parse(stream, this, resourceURL.toExternalForm());
1683
1684            stream.close();
1685            stream = null;
1686
1687            success = true;
1688        }
1689        catch (SAXParseException JavaDoc ex)
1690        {
1691            _parser = null;
1692
1693            Location location = new LocationImpl(resource, ex.getLineNumber(), ex.getColumnNumber());
1694
1695            throw new DocumentParseException(ParseMessages.errorReadingResource(resource, ex),
1696                    location, ex);
1697        }
1698        catch (Exception JavaDoc ex)
1699        {
1700            _parser = null;
1701
1702            throw new DocumentParseException(ParseMessages.errorReadingResource(resource, ex),
1703                    resource, ex);
1704        }
1705        finally
1706        {
1707            if (!success)
1708                _parser = null;
1709
1710            close(stream);
1711        }
1712    }
1713
1714    public ILibrarySpecification parseLibrarySpecification(Resource resource)
1715    {
1716        initializeParser(resource, STATE_LIBRARY_SPECIFICATION_INITIAL);
1717
1718        try
1719        {
1720            parseDocument();
1721
1722            return (ILibrarySpecification) _rootObject;
1723        }
1724        finally
1725        {
1726            resetParser();
1727        }
1728    }
1729
1730    public IComponentSpecification parsePageSpecification(Resource resource)
1731    {
1732        initializeParser(resource, STATE_PAGE_SPECIFICATION_INITIAL);
1733
1734        try
1735        {
1736            parseDocument();
1737
1738            return (IComponentSpecification) _rootObject;
1739        }
1740        finally
1741        {
1742            resetParser();
1743        }
1744    }
1745
1746    protected String JavaDoc peekContent()
1747    {
1748        String JavaDoc content = super.peekContent();
1749
1750        if (content == null)
1751            return null;
1752
1753        return content.trim();
1754    }
1755
1756    protected void resetParser()
1757    {
1758        _rootObject = null;
1759        _DTD_4_0 = false;
1760
1761        _attributes.clear();
1762    }
1763
1764    /**
1765     * Resolved an external entity, which is assumed to be the doctype. Might need a check to ensure
1766     * that specs without a doctype fail.
1767     */

1768    public InputSource JavaDoc resolveEntity(String JavaDoc publicId, String JavaDoc systemId) throws SAXException JavaDoc
1769    {
1770        if (TAPESTRY_DTD_4_0_PUBLIC_ID.equals(publicId))
1771        {
1772            _DTD_4_0 = true;
1773            return getDTDInputSource("Tapestry_4_0.dtd");
1774        }
1775
1776        if (TAPESTRY_DTD_3_0_PUBLIC_ID.equals(publicId))
1777            return getDTDInputSource("Tapestry_3_0.dtd");
1778
1779        throw new DocumentParseException(ParseMessages.unknownPublicId(getResource(), publicId),
1780                new LocationImpl(getResource()), null);
1781    }
1782
1783    /** @since 4.0 */
1784    public void setBindingSource(BindingSource bindingSource)
1785    {
1786        _bindingSource = bindingSource;
1787    }
1788
1789    /** @since 4.0 */
1790    public void setValueConverter(ValueConverter valueConverter)
1791    {
1792        _valueConverter = valueConverter;
1793    }
1794}
Popular Tags