KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > hivemind > parse > DescriptorParser


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.hivemind.parse;
16
17 import java.io.BufferedInputStream JavaDoc;
18 import java.io.IOException JavaDoc;
19 import java.io.InputStream JavaDoc;
20 import java.util.Enumeration JavaDoc;
21 import java.util.HashMap JavaDoc;
22 import java.util.Iterator JavaDoc;
23 import java.util.List JavaDoc;
24 import java.util.Map JavaDoc;
25 import java.util.Properties JavaDoc;
26
27 import org.apache.commons.logging.Log;
28 import org.apache.commons.logging.LogFactory;
29 import org.apache.hivemind.ApplicationRuntimeException;
30 import org.apache.hivemind.Attribute;
31 import org.apache.hivemind.ClassResolver;
32 import org.apache.hivemind.ErrorHandler;
33 import org.apache.hivemind.Resource;
34 import org.apache.hivemind.definition.Occurances;
35 import org.apache.hivemind.definition.Visibility;
36 import org.apache.hivemind.impl.AttributeImpl;
37 import org.apache.hivemind.impl.ElementImpl;
38 import org.apache.hivemind.schema.ElementModel;
39 import org.apache.hivemind.schema.Rule;
40 import org.apache.hivemind.schema.impl.AttributeModelImpl;
41 import org.apache.hivemind.schema.impl.ElementModelImpl;
42 import org.apache.hivemind.schema.impl.SchemaImpl;
43 import org.apache.hivemind.schema.rules.CreateObjectRule;
44 import org.apache.hivemind.schema.rules.InvokeParentRule;
45 import org.apache.hivemind.schema.rules.PushAttributeRule;
46 import org.apache.hivemind.schema.rules.PushContentRule;
47 import org.apache.hivemind.schema.rules.ReadAttributeRule;
48 import org.apache.hivemind.schema.rules.ReadContentRule;
49 import org.apache.hivemind.schema.rules.SetModuleRule;
50 import org.apache.hivemind.schema.rules.SetParentRule;
51 import org.apache.hivemind.schema.rules.SetPropertyRule;
52 import org.apache.hivemind.util.IdUtils;
53 import org.apache.oro.text.regex.MalformedPatternException;
54 import org.apache.oro.text.regex.Pattern;
55 import org.apache.oro.text.regex.Perl5Compiler;
56 import org.apache.oro.text.regex.Perl5Matcher;
57
58 /**
59  * Used to parse HiveMind module deployment descriptors.
60  * <p>
61  * TODO: The parser ignores element content except inside &lt;contribution&gt; and
62  * &lt;invoke-factory&gt; ... it probably should forbid non-whitespace content.
63  *
64  * @author Howard Lewis Ship
65  */

66 public final class DescriptorParser extends AbstractParser
67 {
68     private static final String JavaDoc DEFAULT_SERVICE_MODEL = "singleton";
69
70     private static final Log LOG = LogFactory.getLog(DescriptorParser.class);
71
72     /**
73      * States used while parsing the document. Most states correspond to a particular XML element in
74      * the document. STATE_START is the initial state, before the &lt;module&gt; element is reached.
75      */

76     private static final int STATE_START = 0;
77
78     private static final int STATE_MODULE = 1;
79
80     // private static final int STATE_DESCRIPTION = 2;
81
private static final int STATE_CONFIGURATION_POINT = 3;
82
83     private static final int STATE_CONTRIBUTION = 4;
84
85     private static final int STATE_SERVICE_POINT = 5;
86
87     private static final int STATE_CREATE_INSTANCE = 6;
88
89     private static final int STATE_IMPLEMENTATION = 8;
90
91     /**
92      * Used for both &lt;schema&;gt; within a &lt;extension-point&gt;, and for
93      * &lt;parameters-schema&gt; within a &lt;service&gt;.
94      */

95     private static final int STATE_SCHEMA = 9;
96
97     private static final int STATE_ELEMENT = 10;
98
99     private static final int STATE_RULES = 11;
100
101     /**
102      * Used with &lt;invoke-factory&gt; and &lt;interceptor&gt; to collect parameters that will be
103      * passed to the implementation or interceptor factory service.
104      */

105     private static final int STATE_COLLECT_SERVICE_PARAMETERS = 12;
106
107     /**
108      * Used with the &lt;conversion&gt; element (an alternative to using &lt;rules&gt;. Finds
109      * &lt;map&gt; elements.
110      */

111     private static final int STATE_CONVERSION = 13;
112     
113     private static final int STATE_SCHEMA_ASSIGNMENT = 14;
114
115     /**
116      * Represents building Element hierarchy as a light-wieght DOM.
117      */

118
119     private static final int STATE_LWDOM = 100;
120
121     /**
122      * Special state for elements that are not allowed to contain any other elements.
123      */

124
125     private static final int STATE_NO_CONTENT = 300;
126
127     private static final String JavaDoc SIMPLE_ID = "[a-zA-Z0-9_]+";
128
129     /**
130      * Format for configuration point ids, service point ids and schema ids. Consists of an optional
131      * leading underscore, followed by alphanumerics and underscores. Normal naming convention is to
132      * use a single CamelCase word, like a Java class name.
133      */

134     public static final String JavaDoc ID_PATTERN = "^" + SIMPLE_ID + "$";
135
136     /**
137      * Module ids are a sequence of simple ids seperated by periods. In practice, they look like
138      * Java package names.
139      */

140     public static final String JavaDoc MODULE_ID_PATTERN = "^" + SIMPLE_ID + "(\\." + SIMPLE_ID + ")*$";
141
142     public static final String JavaDoc VERSION_PATTERN = "[0-9]+(\\.[0-9]+){2}$";
143
144     /**
145      * Temporary storage of the current {@link org.xml.sax.Attributes}.
146      */

147     private Map JavaDoc _attributes = new HashMap JavaDoc();
148
149     /**
150      * Built from DescriptorParser.properties. Key is element name, value is an instance of
151      * {@link ElementParseInfo}.
152      */

153
154     private Map JavaDoc _elementParseInfo = new HashMap JavaDoc();
155
156     private ModuleDescriptor _moduleDescriptor;
157
158     private ErrorHandler _errorHandler;
159
160     private ClassResolver _resolver;
161
162     private Perl5Compiler _compiler;
163
164     private Perl5Matcher _matcher;
165
166     private Map JavaDoc _compiledPatterns;
167
168     /**
169      * Map of Rule keyed on class name, used with &lt;custom&gt; rules.
170      */

171     private final Map JavaDoc _ruleMap = new HashMap JavaDoc();
172
173     private final Map JavaDoc OCCURS_MAP = new HashMap JavaDoc();
174
175     {
176         OCCURS_MAP.put("0..1", Occurances.OPTIONAL);
177         OCCURS_MAP.put("1", Occurances.REQUIRED);
178         OCCURS_MAP.put("1..n", Occurances.ONE_PLUS);
179         OCCURS_MAP.put("0..n", Occurances.UNBOUNDED);
180         OCCURS_MAP.put("none", Occurances.NONE);
181     }
182
183     private final Map JavaDoc VISIBILITY_MAP = new HashMap JavaDoc();
184
185     {
186         VISIBILITY_MAP.put("public", Visibility.PUBLIC);
187         VISIBILITY_MAP.put("private", Visibility.PRIVATE);
188     }
189
190     public DescriptorParser(ErrorHandler errorHandler)
191     {
192         _errorHandler = errorHandler;
193
194         initializeFromPropertiesFile();
195     }
196
197     public void begin(String JavaDoc elementName, Map JavaDoc attributes)
198     {
199         _attributes = attributes;
200
201         switch (getState())
202         {
203             case STATE_START:
204
205                 beginStart(elementName);
206                 break;
207
208             case STATE_MODULE:
209
210                 beginModule(elementName);
211                 break;
212
213             case STATE_CONFIGURATION_POINT:
214
215                 beginConfigurationPoint(elementName);
216                 break;
217
218             case STATE_CONTRIBUTION:
219
220                 beginContribution(elementName);
221                 break;
222
223             case STATE_LWDOM:
224
225                 beginLWDom(elementName);
226                 break;
227
228             case STATE_SERVICE_POINT:
229
230                 beginServicePoint(elementName);
231                 break;
232
233             case STATE_IMPLEMENTATION:
234
235                 beginImplementation(elementName);
236                 break;
237
238             case STATE_SCHEMA:
239
240                 beginSchema(elementName);
241                 break;
242
243             case STATE_ELEMENT:
244
245                 beginElement(elementName);
246                 break;
247
248             case STATE_RULES:
249
250                 beginRules(elementName);
251                 break;
252
253             case STATE_COLLECT_SERVICE_PARAMETERS:
254
255                 beginCollectServiceParameters(elementName);
256                 break;
257
258             case STATE_CONVERSION:
259
260                 beginConversion(elementName);
261                 break;
262
263             default:
264
265                 unexpectedElement(elementName);
266                 break;
267         }
268     }
269
270     /**
271      * Very similar to {@link #beginContribution(String)}, in that it creates an
272      * {@link ElementImpl}, adds it as a parameter to the
273      * {@link AbstractServiceInvocationDescriptor}, then enters STATE_LWDOM to fill in its
274      * attributes and content.
275      */

276
277     private void beginCollectServiceParameters(String JavaDoc elementName)
278     {
279         ElementImpl element = buildLWDomElement(elementName);
280
281         AbstractServiceInvocationDescriptor sid = (AbstractServiceInvocationDescriptor) peekObject();
282
283         sid.addParameter(element);
284
285         push(elementName, element, STATE_LWDOM, false);
286     }
287
288     /**
289      * Invoked when a new element starts within STATE_CONFIGURATION_POINT.
290      */

291     private void beginConfigurationPoint(String JavaDoc elementName)
292     {
293         if (elementName.equals("schema"))
294         {
295             enterEmbeddedConfigurationPointSchema(elementName);
296             return;
297         }
298
299         unexpectedElement(elementName);
300     }
301
302     private void beginContribution(String JavaDoc elementName)
303     {
304         // This is where things get tricky, the point where we outgrew Jakarta Digester.
305

306         ElementImpl element = buildLWDomElement(elementName);
307
308         ContributionDescriptor ed = (ContributionDescriptor) peekObject();
309         ed.addElement(element);
310
311         push(elementName, element, STATE_LWDOM, false);
312     }
313
314     private void beginConversion(String JavaDoc elementName)
315     {
316         if (elementName.equals("map"))
317         {
318             ConversionDescriptor cd = (ConversionDescriptor) peekObject();
319
320             AttributeMappingDescriptor amd = new AttributeMappingDescriptor();
321
322             push(elementName, amd, STATE_NO_CONTENT);
323
324             checkAttributes();
325
326             amd.setAttributeName(getAttribute("attribute"));
327             amd.setPropertyName(getAttribute("property"));
328
329             cd.addAttributeMapping(amd);
330
331             return;
332         }
333
334         unexpectedElement(elementName);
335     }
336
337     private void beginElement(String JavaDoc elementName)
338     {
339         if (elementName.equals("attribute"))
340         {
341             enterAttribute(elementName);
342             return;
343         }
344
345         if (elementName.equals("conversion"))
346         {
347             enterConversion(elementName);
348             return;
349         }
350
351         if (elementName.equals("rules"))
352         {
353             enterRules(elementName);
354             return;
355         }
356
357         // <element> is recursive ... possible, but tricky, if using Digester.
358

359         if (elementName.equals("element"))
360         {
361             ElementModelImpl elementModel = (ElementModelImpl) peekObject();
362
363             elementModel.addElementModel(enterElement(elementName));
364             return;
365         }
366
367         unexpectedElement(elementName);
368     }
369
370     private void beginImplementation(String JavaDoc elementName)
371     {
372
373         if (elementName.equals("create-instance"))
374         {
375             enterCreateInstance(elementName);
376             return;
377         }
378
379         if (elementName.equals("invoke-factory"))
380         {
381             enterInvokeFactory(elementName);
382             return;
383         }
384
385         if (elementName.equals("interceptor"))
386         {
387             enterInterceptor(elementName);
388             return;
389         }
390
391         unexpectedElement(elementName);
392     }
393
394     private void beginLWDom(String JavaDoc elementName)
395     {
396         ElementImpl element = buildLWDomElement(elementName);
397
398         ElementImpl parent = (ElementImpl) peekObject();
399         parent.addElement(element);
400
401         push(elementName, element, STATE_LWDOM, false);
402     }
403
404     /**
405      * Invoked when a new element occurs while in STATE_MODULE.
406      */

407     private void beginModule(String JavaDoc elementName)
408     {
409         if (elementName.equals("configuration-point"))
410         {
411             enterConfigurationPoint(elementName);
412
413             return;
414         }
415
416         if (elementName.equals("contribution"))
417         {
418             enterContribution(elementName);
419             return;
420         }
421
422         if (elementName.equals("service-point"))
423         {
424             enterServicePoint(elementName);
425
426             return;
427         }
428
429         if (elementName.equals("implementation"))
430         {
431             enterImplementation(elementName);
432
433             return;
434         }
435
436         if (elementName.equals("schema"))
437         {
438             enterSchema(elementName);
439             return;
440         }
441
442         if (elementName.equals("sub-module"))
443         {
444             enterSubModule(elementName);
445
446             return;
447         }
448
449         if (elementName.equals("dependency"))
450         {
451             enterDependency(elementName);
452
453             return;
454         }
455         
456         if (elementName.equals("schema-assignment"))
457         {
458             enterSchemaAssignment(elementName);
459             return;
460         }
461
462         unexpectedElement(elementName);
463     }
464
465     private void beginRules(String JavaDoc elementName)
466     {
467
468         if (elementName.equals("create-object"))
469         {
470             enterCreateObject(elementName);
471             return;
472         }
473
474         if (elementName.equals("invoke-parent"))
475         {
476             enterInvokeParent(elementName);
477             return;
478         }
479
480         if (elementName.equals("read-attribute"))
481         {
482             enterReadAttribute(elementName);
483             return;
484         }
485
486         if (elementName.equals("read-content"))
487         {
488             enterReadContent(elementName);
489             return;
490         }
491
492         if (elementName.equals("set-module"))
493         {
494             enterSetModule(elementName);
495             return;
496         }
497
498         if (elementName.equals("set-property"))
499         {
500             enterSetProperty(elementName);
501             return;
502         }
503
504         if (elementName.equals("push-attribute"))
505         {
506             enterPushAttribute(elementName);
507             return;
508         }
509
510         if (elementName.equals("push-content"))
511         {
512             enterPushContent(elementName);
513             return;
514         }
515
516         if (elementName.equals("set-parent"))
517         {
518             enterSetParent(elementName);
519             return;
520         }
521
522         if (elementName.equals("custom"))
523         {
524             enterCustom(elementName);
525
526             return;
527         }
528
529         unexpectedElement(elementName);
530     }
531
532     private void beginSchema(String JavaDoc elementName)
533     {
534         if (elementName.equals("element"))
535         {
536             SchemaImpl schema = (SchemaImpl) peekObject();
537
538             schema.addElementModel(enterElement(elementName));
539             return;
540         }
541
542         unexpectedElement(elementName);
543     }
544
545     private void beginServicePoint(String JavaDoc elementName)
546     {
547         if (elementName.equals("parameters-schema"))
548         {
549             enterParametersSchema(elementName);
550             return;
551         }
552
553         // <service-point> allows an super-set of <implementation>.
554

555         beginImplementation(elementName);
556     }
557
558     /**
559      * begin outermost element, expect "module".
560      */

561     private void beginStart(String JavaDoc elementName)
562     {
563         if (!elementName.equals("module"))
564             throw new ApplicationRuntimeException(ParseMessages.notModule(
565                     elementName,
566                     getLocation()), getLocation(), null);
567
568         ModuleDescriptor md = new ModuleDescriptor(_resolver, _errorHandler);
569
570         push(elementName, md, STATE_MODULE);
571
572         checkAttributes();
573
574         md.setModuleId(getValidatedAttribute("id", MODULE_ID_PATTERN, "module-id-format"));
575         md.setVersion(getValidatedAttribute("version", VERSION_PATTERN, "version-format"));
576
577         String JavaDoc packageName = getAttribute("package");
578         if (packageName == null)
579             packageName = md.getModuleId();
580
581         md.setPackageName(packageName);
582
583         // And, this is what we ultimately return from the parse.
584

585         _moduleDescriptor = md;
586     }
587
588     protected void push(String JavaDoc elementName, Object JavaDoc object, int state)
589     {
590         if (object instanceof AnnotationHolder)
591             super.push(elementName, object, state, false);
592         else
593             super.push(elementName, object, state, true);
594     }
595
596     private ElementImpl buildLWDomElement(String JavaDoc elementName)
597     {
598         ElementImpl result = new ElementImpl();
599         result.setElementName(elementName);
600
601         Iterator JavaDoc i = _attributes.entrySet().iterator();
602         while (i.hasNext())
603         {
604             Map.Entry JavaDoc entry = (Map.Entry JavaDoc) i.next();
605
606             String JavaDoc name = (String JavaDoc) entry.getKey();
607             String JavaDoc value = (String JavaDoc) entry.getValue();
608
609             Attribute a = new AttributeImpl(name, value);
610
611             result.addAttribute(a);
612         }
613
614         return result;
615     }
616
617     private void checkAttributes()
618     {
619         checkAttributes(peekElementName());
620     }
621
622     /**
623      * Checks that only known attributes are specified. Checks that all required attribute are
624      * specified.
625      */

626     private void checkAttributes(String JavaDoc elementName)
627     {
628         Iterator JavaDoc i = _attributes.keySet().iterator();
629
630         ElementParseInfo epi = (ElementParseInfo) _elementParseInfo.get(elementName);
631
632         // A few elements have no attributes at all.
633

634         if (epi == null)
635         {
636             epi = new ElementParseInfo();
637             _elementParseInfo.put(elementName, epi);
638         }
639
640         // First, check that each attribute is in the set of expected attributes.
641

642         while (i.hasNext())
643         {
644             String JavaDoc name = (String JavaDoc) i.next();
645
646             if (!epi.isKnown(name))
647                 _errorHandler.error(
648                         LOG,
649                         ParseMessages.unknownAttribute(name, getElementPath()),
650                         getLocation(),
651                         null);
652         }
653
654         // Now check that all required attributes have been specified.
655

656         i = epi.getRequiredNames();
657         while (i.hasNext())
658         {
659             String JavaDoc name = (String JavaDoc) i.next();
660
661             if (!_attributes.containsKey(name))
662                 throw new ApplicationRuntimeException(ParseMessages.requiredAttribute(
663                         name,
664                         getElementPath(),
665                         getLocation()));
666         }
667
668     }
669
670     public void end(String JavaDoc elementName)
671     {
672         switch (getState())
673         {
674             case STATE_LWDOM:
675
676                 endLWDom();
677                 break;
678
679             case STATE_CONVERSION:
680
681                 endConversion();
682                 break;
683
684             case STATE_SCHEMA:
685
686                 endSchema();
687                 break;
688
689             default:
690
691                 String JavaDoc content = peekContent();
692
693                 if (content != null && (peekObject() instanceof AnnotationHolder))
694                     ((AnnotationHolder) peekObject()).setAnnotation(content);
695
696                 break;
697         }
698
699         // Pop the top item off the stack.
700

701         pop();
702     }
703
704     private void endSchema()
705     {
706         SchemaImpl schema = (SchemaImpl) peekObject();
707
708         schema.setAnnotation(peekContent());
709         
710         try
711         {
712             schema.validateKeyAttributes();
713         }
714         catch (ApplicationRuntimeException e)
715         {
716             _errorHandler.error(LOG, ParseMessages.invalidElementKeyAttribute(schema.getId(), e), e
717                     .getLocation(), e);
718         }
719
720     }
721
722     private void endConversion()
723     {
724         ConversionDescriptor cd = (ConversionDescriptor) peekObject();
725
726         cd.addRulesForModel();
727     }
728
729     private void endLWDom()
730     {
731         ElementImpl element = (ElementImpl) peekObject();
732         element.setContent(peekContent());
733     }
734
735     private void enterAttribute(String JavaDoc elementName)
736     {
737         ElementModelImpl elementModel = (ElementModelImpl) peekObject();
738
739         AttributeModelImpl attributeModel = new AttributeModelImpl();
740
741         push(elementName, attributeModel, STATE_NO_CONTENT);
742
743         checkAttributes();
744
745         attributeModel.setName(getAttribute("name"));
746         attributeModel.setRequired(getBooleanAttribute("required", false));
747         attributeModel.setUnique(getBooleanAttribute("unique", false));
748         attributeModel.setTranslator(getAttribute("translator", "smart"));
749         attributeModel.setDefault(getAttribute("default"));
750
751         elementModel.addAttributeModel(attributeModel);
752     }
753
754     private void enterConfigurationPoint(String JavaDoc elementName)
755     {
756         ModuleDescriptor md = (ModuleDescriptor) peekObject();
757
758         ConfigurationPointDescriptor cpd = new ConfigurationPointDescriptor();
759
760         push(elementName, cpd, STATE_CONFIGURATION_POINT);
761
762         checkAttributes();
763
764         String JavaDoc id = getValidatedAttribute("id", ID_PATTERN, "id-format");
765         cpd.setId(id);
766
767         Occurances count = (Occurances) getEnumAttribute("occurs", OCCURS_MAP);
768
769         if (count != null)
770             cpd.setCount(count);
771
772         Visibility visibility = (Visibility) getEnumAttribute("visibility", VISIBILITY_MAP);
773
774         if (visibility != null)
775             cpd.setVisibility(visibility);
776
777         cpd.setContributionsSchemaId(getAttribute("schema-id"));
778
779         // Get the type of the configuration container
780
// For backward compatibility, List is the default
781
String JavaDoc typeName = getAttribute("type", List JavaDoc.class.getName());
782
783         // Qualify the interface name with the defined package name (which will
784
// often implicitly or explicitly match the module id).
785

786         String JavaDoc fullContainerTypeName = IdUtils.qualify(
787                 _moduleDescriptor.getPackageName(),
788                 typeName);
789         cpd.setType(fullContainerTypeName);
790
791         md.addConfigurationPoint(cpd);
792     }
793
794     private void enterContribution(String JavaDoc elementName)
795     {
796         ModuleDescriptor md = (ModuleDescriptor) peekObject();
797
798         ContributionDescriptor cd = new ContributionDescriptor();
799
800         push(elementName, cd, STATE_CONTRIBUTION);
801
802         checkAttributes();
803
804         cd.setConfigurationId(getAttribute("configuration-id"));
805         cd.setConditionalExpression(getAttribute("if"));
806
807         md.addContribution(cd);
808     }
809
810     private void enterSchemaAssignment(String JavaDoc elementName)
811     {
812         ModuleDescriptor md = (ModuleDescriptor) peekObject();
813
814         SchemaAssignmentDescriptor sad = new SchemaAssignmentDescriptor();
815
816         push(elementName, sad, STATE_SCHEMA_ASSIGNMENT);
817
818         checkAttributes();
819
820         sad.setConfigurationId(getAttribute("configuration-id"));
821         sad.setSchemaId(getAttribute("schema-id"));
822
823         md.addSchemaAssignment(sad);
824     }
825
826     private void enterConversion(String JavaDoc elementName)
827     {
828         ElementModelImpl elementModel = (ElementModelImpl) peekObject();
829
830         ConversionDescriptor cd = new ConversionDescriptor(_errorHandler, elementModel);
831
832         push(elementName, cd, STATE_CONVERSION);
833
834         checkAttributes();
835
836         cd.setClassName(getAttribute("class"));
837
838         String JavaDoc methodName = getAttribute("parent-method");
839
840         if (methodName != null)
841             cd.setParentMethodName(methodName);
842
843         elementModel.addRule(cd);
844     }
845
846     private void enterCreateInstance(String JavaDoc elementName)
847     {
848         AbstractServiceDescriptor sd = (AbstractServiceDescriptor) peekObject();
849         CreateInstanceDescriptor cid = new CreateInstanceDescriptor();
850
851         push(elementName, cid, STATE_CREATE_INSTANCE);
852
853         checkAttributes();
854
855         cid.setInstanceClassName(getAttribute("class"));
856
857         String JavaDoc model = getAttribute("model", DEFAULT_SERVICE_MODEL);
858
859         cid.setServiceModel(model);
860
861         sd.setInstanceBuilder(cid);
862
863     }
864
865     private void enterCreateObject(String JavaDoc elementName)
866     {
867         ElementModelImpl elementModel = (ElementModelImpl) peekObject();
868         CreateObjectRule rule = new CreateObjectRule();
869         push(elementName, rule, STATE_NO_CONTENT);
870
871         checkAttributes();
872
873         rule.setClassName(getAttribute("class"));
874
875         elementModel.addRule(rule);
876     }
877
878     private void enterCustom(String JavaDoc elementName)
879     {
880         ElementModelImpl elementModel = (ElementModelImpl) peekObject();
881
882         // Don't know what it is going to be, yet.
883

884         push(elementName, null, STATE_NO_CONTENT);
885
886         checkAttributes();
887
888         String JavaDoc ruleClassName = getAttribute("class");
889
890         Rule rule = getCustomRule(ruleClassName);
891
892         elementModel.addRule(rule);
893     }
894
895     /**
896      * Pushes STATE_ELEMENT onto the stack and creates and returns the {@link ElementModelImpl} it
897      * creates.
898      */

899     private ElementModel enterElement(String JavaDoc elementName)
900     {
901         ElementModelImpl result = new ElementModelImpl(_moduleDescriptor.getModuleId());
902
903         push(elementName, result, STATE_ELEMENT);
904
905         checkAttributes();
906
907         result.setElementName(getAttribute("name"));
908         result.setContentTranslator(getAttribute("content-translator"));
909         result.setKeyAttribute(getAttribute("key-attribute"));
910
911         return result;
912     }
913
914     private void enterEmbeddedConfigurationPointSchema(String JavaDoc elementName)
915     {
916         ConfigurationPointDescriptor cpd = (ConfigurationPointDescriptor) peekObject();
917
918         SchemaImpl schema = new SchemaImpl(_moduleDescriptor.getModuleId());
919
920         processRootElementClassName(schema);
921
922         push(elementName, schema, STATE_SCHEMA);
923
924         if (cpd.getContributionsSchemaId() != null)
925         {
926             cpd.setContributionsSchemaId(null);
927             cpd.setContributionsSchema(schema);
928             _errorHandler.error(LOG, ParseMessages.multipleContributionsSchemas(cpd.getId(), schema
929                     .getLocation()), schema.getLocation(), null);
930         }
931         else
932             cpd.setContributionsSchema(schema);
933
934         checkAttributes("schema{embedded}");
935     }
936
937     private void processRootElementClassName(SchemaImpl schema)
938     {
939         // Get the type of the root element
940
String JavaDoc rootElementClassName = getAttribute("root-element-class");
941
942         // Qualify the interface name with the defined package name (which will
943
// often implicitly or explicitly match the module id).
944

945         if (rootElementClassName != null) {
946             String JavaDoc fullRootElementClassName = IdUtils.qualify(
947                     _moduleDescriptor.getPackageName(),
948                     rootElementClassName);
949             schema.setRootElementClassName(fullRootElementClassName);
950         }
951     }
952
953     private void enterParametersSchema(String JavaDoc elementName)
954     {
955         ServicePointDescriptor spd = (ServicePointDescriptor) peekObject();
956         SchemaImpl schema = new SchemaImpl(_moduleDescriptor.getModuleId());
957         
958         processRootElementClassName(schema);
959
960         push(elementName, schema, STATE_SCHEMA);
961
962         checkAttributes();
963
964         if (spd.getParametersSchemaId() != null)
965         {
966             spd.setParametersSchemaId(null);
967             spd.setParametersSchema(schema);
968             _errorHandler.error(LOG, ParseMessages.multipleParametersSchemas(spd.getId(), schema
969                     .getLocation()), schema.getLocation(), null);
970         }
971         else
972             spd.setParametersSchema(schema);
973     }
974
975     private void enterImplementation(String JavaDoc elementName)
976     {
977         ModuleDescriptor md = (ModuleDescriptor) peekObject();
978
979         ImplementationDescriptor id = new ImplementationDescriptor();
980
981         push(elementName, id, STATE_IMPLEMENTATION);
982
983         checkAttributes();
984
985         id.setServiceId(getAttribute("service-id"));
986         id.setConditionalExpression(getAttribute("if"));
987
988         md.addImplementation(id);
989     }
990
991     private void enterInterceptor(String JavaDoc elementName)
992     {
993         AbstractServiceDescriptor sd = (AbstractServiceDescriptor) peekObject();
994         InterceptorDescriptor id = new InterceptorDescriptor();
995
996         push(elementName, id, STATE_COLLECT_SERVICE_PARAMETERS);
997
998         checkAttributes();
999
1000        id.setFactoryServiceId(getAttribute("service-id"));
1001
1002        id.setBefore(getAttribute("before"));
1003        id.setAfter(getAttribute("after"));
1004        id.setName(getAttribute("name"));
1005        sd.addInterceptor(id);
1006
1007    }
1008
1009    private void enterInvokeFactory(String JavaDoc elementName)
1010    {
1011        AbstractServiceDescriptor sd = (AbstractServiceDescriptor) peekObject();
1012        InvokeFactoryDescriptor ifd = new InvokeFactoryDescriptor();
1013
1014        push(elementName, ifd, STATE_COLLECT_SERVICE_PARAMETERS);
1015
1016        checkAttributes();
1017
1018        ifd.setFactoryServiceId(getAttribute("service-id", "hivemind.BuilderFactory"));
1019
1020        String JavaDoc model = getAttribute("model", DEFAULT_SERVICE_MODEL);
1021
1022        ifd.setServiceModel(model);
1023
1024        // TODO: Check if instanceBuilder already set
1025

1026        sd.setInstanceBuilder(ifd);
1027
1028    }
1029
1030    private void enterInvokeParent(String JavaDoc elementName)
1031    {
1032        ElementModelImpl elementModel = (ElementModelImpl) peekObject();
1033        InvokeParentRule rule = new InvokeParentRule();
1034
1035        push(elementName, rule, STATE_NO_CONTENT);
1036
1037        checkAttributes();
1038
1039        rule.setMethodName(getAttribute("method"));
1040        
1041        if (_attributes.containsKey("parameter-count")) {
1042            rule.setParameterCount(getIntAttribute("parameter-count"));
1043        }
1044
1045        if (_attributes.containsKey("depth"))
1046            rule.setDepth(getIntAttribute("depth"));
1047
1048        elementModel.addRule(rule);
1049    }
1050
1051    private void enterReadAttribute(String JavaDoc elementName)
1052    {
1053        ElementModelImpl elementModel = (ElementModelImpl) peekObject();
1054        ReadAttributeRule rule = new ReadAttributeRule();
1055
1056        push(elementName, rule, STATE_NO_CONTENT);
1057
1058        checkAttributes();
1059
1060        rule.setPropertyName(getAttribute("property"));
1061        rule.setAttributeName(getAttribute("attribute"));
1062        rule.setSkipIfNull(getBooleanAttribute("skip-if-null", true));
1063        rule.setTranslator(getAttribute("translator"));
1064
1065        elementModel.addRule(rule);
1066    }
1067
1068    private void enterReadContent(String JavaDoc elementName)
1069    {
1070        ElementModelImpl elementModel = (ElementModelImpl) peekObject();
1071        ReadContentRule rule = new ReadContentRule();
1072
1073        push(elementName, rule, STATE_NO_CONTENT);
1074
1075        checkAttributes();
1076
1077        rule.setPropertyName(getAttribute("property"));
1078
1079        elementModel.addRule(rule);
1080    }
1081
1082    private void enterRules(String JavaDoc elementName)
1083    {
1084        ElementModelImpl elementModel = (ElementModelImpl) peekObject();
1085
1086        push(elementName, elementModel, STATE_RULES);
1087
1088    }
1089
1090    private void enterSchema(String JavaDoc elementName)
1091    {
1092        SchemaImpl schema = new SchemaImpl(_moduleDescriptor.getModuleId());
1093
1094        push(elementName, schema, STATE_SCHEMA);
1095
1096        checkAttributes();
1097
1098        String JavaDoc id = getValidatedAttribute("id", ID_PATTERN, "id-format");
1099
1100        schema.setId(id);
1101
1102        Visibility visibility = (Visibility) getEnumAttribute("visibility", VISIBILITY_MAP);
1103
1104        if (visibility != null)
1105            schema.setVisibility(visibility);
1106        
1107        processRootElementClassName(schema);
1108
1109        _moduleDescriptor.addSchema(schema);
1110    }
1111
1112    private void enterServicePoint(String JavaDoc elementName)
1113    {
1114        ModuleDescriptor md = (ModuleDescriptor) peekObject();
1115
1116        ServicePointDescriptor spd = new ServicePointDescriptor();
1117
1118        push(elementName, spd, STATE_SERVICE_POINT);
1119
1120        checkAttributes();
1121
1122        String JavaDoc id = getValidatedAttribute("id", ID_PATTERN, "id-format");
1123
1124        // Get the interface name, and default it to the service id if omitted.
1125

1126        String JavaDoc interfaceAttribute = getAttribute("interface", id);
1127
1128        // Qualify the interface name with the defined package name (which will
1129
// often implicitly or explicitly match the module id).
1130

1131        String JavaDoc interfaceName = IdUtils.qualify(
1132                _moduleDescriptor.getPackageName(),
1133                interfaceAttribute);
1134
1135        spd.setId(id);
1136
1137        spd.setInterfaceClassName(interfaceName);
1138
1139        spd.setParametersSchemaId(getAttribute("parameters-schema-id"));
1140
1141        Occurances count = (Occurances) getEnumAttribute("parameters-occurs", OCCURS_MAP);
1142
1143        if (count != null)
1144            spd.setParametersCount(count);
1145
1146        Visibility visibility = (Visibility) getEnumAttribute("visibility", VISIBILITY_MAP);
1147
1148        if (visibility != null)
1149            spd.setVisibility(visibility);
1150
1151        md.addServicePoint(spd);
1152    }
1153
1154    private void enterSetModule(String JavaDoc elementName)
1155    {
1156        ElementModelImpl elementModel = (ElementModelImpl) peekObject();
1157        SetModuleRule rule = new SetModuleRule();
1158
1159        push(elementName, rule, STATE_NO_CONTENT);
1160
1161        checkAttributes();
1162
1163        rule.setPropertyName(getAttribute("property"));
1164
1165        elementModel.addRule(rule);
1166    }
1167
1168    private void enterSetParent(String JavaDoc elementName)
1169    {
1170        ElementModelImpl elementModel = (ElementModelImpl) peekObject();
1171        SetParentRule rule = new SetParentRule();
1172
1173        push(elementName, rule, STATE_NO_CONTENT);
1174
1175        checkAttributes();
1176
1177        rule.setPropertyName(getAttribute("property"));
1178
1179        elementModel.addRule(rule);
1180    }
1181
1182    private void enterSetProperty(String JavaDoc elementName)
1183    {
1184        ElementModelImpl elementModel = (ElementModelImpl) peekObject();
1185
1186        SetPropertyRule rule = new SetPropertyRule();
1187
1188        push(elementName, rule, STATE_NO_CONTENT);
1189
1190        checkAttributes();
1191
1192        rule.setPropertyName(getAttribute("property"));
1193        rule.setValue(getAttribute("value"));
1194
1195        elementModel.addRule(rule);
1196    }
1197
1198    private void enterPushAttribute(String JavaDoc elementName)
1199    {
1200        ElementModelImpl elementModel = (ElementModelImpl) peekObject();
1201
1202        PushAttributeRule rule = new PushAttributeRule();
1203
1204        push(elementName, rule, STATE_NO_CONTENT);
1205
1206        checkAttributes();
1207
1208        rule.setAttributeName(getAttribute("attribute"));
1209
1210        elementModel.addRule(rule);
1211    }
1212
1213    private void enterPushContent(String JavaDoc elementName)
1214    {
1215        ElementModelImpl elementModel = (ElementModelImpl) peekObject();
1216
1217        PushContentRule rule = new PushContentRule();
1218
1219        push(elementName, rule, STATE_NO_CONTENT);
1220
1221        checkAttributes();
1222
1223        elementModel.addRule(rule);
1224    }
1225
1226    private void enterSubModule(String JavaDoc elementName)
1227    {
1228        ModuleDescriptor md = (ModuleDescriptor) peekObject();
1229
1230        SubModuleDescriptor smd = new SubModuleDescriptor();
1231
1232        push(elementName, smd, STATE_NO_CONTENT);
1233
1234        checkAttributes();
1235
1236        Resource descriptor = getResource().getRelativeResource(getAttribute("descriptor"));
1237
1238        smd.setDescriptor(descriptor);
1239
1240        md.addSubModule(smd);
1241    }
1242
1243    private void enterDependency(String JavaDoc elementName)
1244    {
1245        ModuleDescriptor md = (ModuleDescriptor) peekObject();
1246
1247        DependencyDescriptor dd = new DependencyDescriptor();
1248
1249        push(elementName, dd, STATE_NO_CONTENT);
1250
1251        checkAttributes();
1252
1253        dd.setModuleId(getAttribute("module-id"));
1254        dd.setVersion(getAttribute("version"));
1255
1256        md.addDependency(dd);
1257    }
1258
1259    private String JavaDoc getAttribute(String JavaDoc name)
1260    {
1261        return (String JavaDoc) _attributes.get(name);
1262    }
1263
1264    private String JavaDoc getAttribute(String JavaDoc name, String JavaDoc defaultValue)
1265    {
1266        String JavaDoc result = (String JavaDoc) _attributes.get(name);
1267
1268        if (result == null)
1269            result = defaultValue;
1270
1271        return result;
1272    }
1273
1274    private String JavaDoc getValidatedAttribute(String JavaDoc name, String JavaDoc pattern, String JavaDoc formatKey)
1275    {
1276        String JavaDoc result = getAttribute(name);
1277
1278        if (!validateFormat(result, pattern))
1279            _errorHandler.error(LOG, ParseMessages.invalidAttributeFormat(
1280                    name,
1281                    result,
1282                    getElementPath(),
1283                    formatKey), getLocation(), null);
1284
1285        return result;
1286    }
1287
1288    private boolean validateFormat(String JavaDoc input, String JavaDoc pattern)
1289    {
1290        if (_compiler == null)
1291        {
1292            _compiler = new Perl5Compiler();
1293            _matcher = new Perl5Matcher();
1294            _compiledPatterns = new HashMap JavaDoc();
1295        }
1296
1297        Pattern compiled = (Pattern) _compiledPatterns.get(pattern);
1298        if (compiled == null)
1299        {
1300
1301            try
1302            {
1303                compiled = _compiler.compile(pattern);
1304            }
1305            catch (MalformedPatternException ex)
1306            {
1307                throw new ApplicationRuntimeException(ex);
1308            }
1309
1310            _compiledPatterns.put(pattern, compiled);
1311        }
1312
1313        return _matcher.matches(input, compiled);
1314    }
1315
1316    private boolean getBooleanAttribute(String JavaDoc name, boolean defaultValue)
1317    {
1318        String JavaDoc value = getAttribute(name);
1319
1320        if (value == null)
1321            return defaultValue;
1322
1323        if (value.equals("true"))
1324            return true;
1325
1326        if (value.equals("false"))
1327            return false;
1328
1329        _errorHandler.error(
1330                LOG,
1331                ParseMessages.booleanAttribute(value, name, getElementPath()),
1332                getLocation(),
1333                null);
1334
1335        return defaultValue;
1336    }
1337
1338    private Rule getCustomRule(String JavaDoc ruleClassName)
1339    {
1340        Rule result = (Rule) _ruleMap.get(ruleClassName);
1341
1342        if (result == null)
1343        {
1344            result = instantiateRule(ruleClassName);
1345
1346            _ruleMap.put(ruleClassName, result);
1347        }
1348
1349        return result;
1350    }
1351
1352    /**
1353     * Gets the value for the attribute and uses the Map to translate it to an object value. Returns
1354     * the object value if succesfully translated. Returns null if unsuccesful. If a value is
1355     * provided that isn't a key of the map, and error is logged and null is returned.
1356     */

1357    private Object JavaDoc getEnumAttribute(String JavaDoc name, Map JavaDoc translations)
1358    {
1359        String JavaDoc value = getAttribute(name);
1360
1361        if (value == null)
1362            return null;
1363
1364        Object JavaDoc result = translations.get(value);
1365
1366        if (result == null)
1367            _errorHandler.error(LOG, ParseMessages.invalidAttributeValue(
1368                    value,
1369                    name,
1370                    getElementPath()), getLocation(), null);
1371
1372        return result;
1373    }
1374
1375    private int getIntAttribute(String JavaDoc name)
1376    {
1377        String JavaDoc value = getAttribute(name);
1378
1379        try
1380        {
1381            return Integer.parseInt(value);
1382        }
1383        catch (NumberFormatException JavaDoc ex)
1384        {
1385            _errorHandler.error(LOG, ParseMessages.invalidNumericValue(
1386                    value,
1387                    name,
1388                    getElementPath()), getLocation(), ex);
1389
1390            return 0;
1391        }
1392    }
1393
1394    private void initializeFromProperties(Properties JavaDoc p)
1395    {
1396        Enumeration JavaDoc e = p.propertyNames();
1397
1398        while (e.hasMoreElements())
1399        {
1400            String JavaDoc key = (String JavaDoc) e.nextElement();
1401            String JavaDoc value = p.getProperty(key);
1402
1403            initializeFromProperty(key, value);
1404        }
1405    }
1406
1407    /**
1408     * Invoked from the constructor to read the properties file that defines certain aspects of the
1409     * operation of the parser.
1410     */

1411    private void initializeFromPropertiesFile()
1412    {
1413        Properties JavaDoc p = new Properties JavaDoc();
1414
1415        try
1416        {
1417
1418            InputStream JavaDoc propertiesIn = getClass()
1419                    .getResourceAsStream("DescriptorParser.properties");
1420            InputStream JavaDoc bufferedIn = new BufferedInputStream JavaDoc(propertiesIn);
1421
1422            p.load(bufferedIn);
1423
1424            bufferedIn.close();
1425        }
1426        catch (IOException JavaDoc ex)
1427        {
1428            _errorHandler.error(LOG, ParseMessages.unableToInitialize(ex), null, ex);
1429        }
1430
1431        initializeFromProperties(p);
1432    }
1433
1434    private void initializeFromProperty(String JavaDoc key, String JavaDoc value)
1435    {
1436        if (key.startsWith("required."))
1437        {
1438            initializeRequired(key, value);
1439            return;
1440        }
1441
1442    }
1443
1444    private void initializeRequired(String JavaDoc key, String JavaDoc value)
1445    {
1446        boolean required = value.equals("true");
1447
1448        int lastdotx = key.lastIndexOf('.');
1449
1450        String JavaDoc elementName = key.substring(9, lastdotx);
1451        String JavaDoc attributeName = key.substring(lastdotx + 1);
1452
1453        ElementParseInfo epi = (ElementParseInfo) _elementParseInfo.get(elementName);
1454
1455        if (epi == null)
1456        {
1457            epi = new ElementParseInfo();
1458            _elementParseInfo.put(elementName, epi);
1459        }
1460
1461        epi.addAttribute(attributeName, required);
1462    }
1463
1464    private Rule instantiateRule(String JavaDoc ruleClassName)
1465    {
1466        try
1467        {
1468            Class JavaDoc ruleClass = _resolver.findClass(ruleClassName);
1469
1470            return (Rule) ruleClass.newInstance();
1471        }
1472        catch (Exception JavaDoc ex)
1473        {
1474            throw new ApplicationRuntimeException(ParseMessages.badRuleClass(
1475                    ruleClassName,
1476                    getLocation(),
1477                    ex), getLocation(), ex);
1478        }
1479    }
1480
1481    /** @since 1.1 */
1482    public void initialize(Resource resource, ClassResolver resolver)
1483    {
1484        initializeParser(resource, STATE_START);
1485
1486        _resolver = resolver;
1487    }
1488
1489    /** @since 1.1 */
1490    public ModuleDescriptor getModuleDescriptor()
1491    {
1492        return _moduleDescriptor;
1493    }
1494
1495    /** @since 1.1 */
1496    public void reset()
1497    {
1498        super.resetParser();
1499
1500        _moduleDescriptor = null;
1501        _attributes.clear();
1502        _resolver = null;
1503    }
1504}
Popular Tags