Clover coverage report - Code Coverage for hivemind release 1.0-rc-2
Coverage timestamp: Sat Sep 11 2004 09:09:48 EDT
file stats: LOC: 1,473   Methods: 64
NCLOC: 946   Classes: 2
30 day Evaluation Version distributed via the Maven Jar Repository. Clover is not free. You have 30 days to evaluate it. Please visit http://www.thecortex.net/clover to obtain a licensed version of Clover
 
 Source file Conditionals Statements Methods TOTAL
DescriptorParser.java 88.1% 95.8% 100% 94.8%
coverage coverage
 1   
 //  Copyright 2004 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;
 18   
 import java.io.IOException;
 19   
 import java.io.InputStream;
 20   
 import java.net.URL;
 21   
 import java.util.Enumeration;
 22   
 import java.util.HashMap;
 23   
 import java.util.Iterator;
 24   
 import java.util.Map;
 25   
 import java.util.Properties;
 26   
 
 27   
 import javax.xml.parsers.FactoryConfigurationError;
 28   
 import javax.xml.parsers.ParserConfigurationException;
 29   
 import javax.xml.parsers.SAXParser;
 30   
 import javax.xml.parsers.SAXParserFactory;
 31   
 
 32   
 import org.apache.commons.logging.Log;
 33   
 import org.apache.commons.logging.LogFactory;
 34   
 import org.apache.hivemind.ApplicationRuntimeException;
 35   
 import org.apache.hivemind.Attribute;
 36   
 import org.apache.hivemind.ClassResolver;
 37   
 import org.apache.hivemind.ErrorHandler;
 38   
 import org.apache.hivemind.Location;
 39   
 import org.apache.hivemind.Occurances;
 40   
 import org.apache.hivemind.Resource;
 41   
 import org.apache.hivemind.impl.AttributeImpl;
 42   
 import org.apache.hivemind.impl.ElementImpl;
 43   
 import org.apache.hivemind.impl.RegistryAssembly;
 44   
 import org.apache.hivemind.schema.ElementModel;
 45   
 import org.apache.hivemind.schema.Rule;
 46   
 import org.apache.hivemind.schema.Schema;
 47   
 import org.apache.hivemind.schema.impl.AttributeModelImpl;
 48   
 import org.apache.hivemind.schema.impl.ElementModelImpl;
 49   
 import org.apache.hivemind.schema.impl.SchemaImpl;
 50   
 import org.apache.hivemind.schema.rules.CreateObjectRule;
 51   
 import org.apache.hivemind.schema.rules.InvokeParentRule;
 52   
 import org.apache.hivemind.schema.rules.PushAttributeRule;
 53   
 import org.apache.hivemind.schema.rules.ReadAttributeRule;
 54   
 import org.apache.hivemind.schema.rules.ReadContentRule;
 55   
 import org.apache.hivemind.schema.rules.SetModuleRule;
 56   
 import org.apache.hivemind.schema.rules.SetParentRule;
 57   
 import org.apache.hivemind.schema.rules.SetPropertyRule;
 58   
 import org.apache.hivemind.util.PropertyUtils;
 59   
 import org.apache.oro.text.regex.MalformedPatternException;
 60   
 import org.apache.oro.text.regex.Pattern;
 61   
 import org.apache.oro.text.regex.Perl5Compiler;
 62   
 import org.apache.oro.text.regex.Perl5Matcher;
 63   
 import org.xml.sax.InputSource;
 64   
 import org.xml.sax.SAXException;
 65   
 
 66   
 /**
 67   
  * Used to parse HiveMind module deployment descriptors.
 68   
  * 
 69   
  * <p>
 70   
  * TODO: The parser ignores element content except inside
 71   
  * &lt;contribution&gt; and &lt;invoke-factory&gt; ... it probably should forbid
 72   
  * non-whitespace content.
 73   
  *
 74   
  * @author Howard Lewis Ship
 75   
  */
 76   
 public final class DescriptorParser extends AbstractParser
 77   
 {
 78   
     private static final String DEFAULT_SERVICE_MODEL = "singleton";
 79   
 
 80   
     private class SchemaRelinker implements Runnable
 81   
     {
 82   
         private Object _container;
 83   
         private String _propertyName;
 84   
         private Location _referenceLocation;
 85   
         private RegistryAssembly _registryAssembly;
 86   
         private String _schemaId;
 87   
 
 88  58
         SchemaRelinker(
 89   
             String schemaId,
 90   
             Object container,
 91   
             String propertyName,
 92   
             RegistryAssembly assembly,
 93   
             Location referenceLocation)
 94   
         {
 95  58
             _schemaId = schemaId;
 96  58
             _container = container;
 97  58
             _propertyName = propertyName;
 98  58
             _registryAssembly = assembly;
 99  58
             _referenceLocation = referenceLocation;
 100   
         }
 101   
 
 102  55
         public void run()
 103   
         {
 104  55
             Schema s = _registryAssembly.getSchema(_schemaId);
 105   
 
 106  55
             if (s == null)
 107  1
                 _errorHandler.error(
 108   
                     LOG,
 109   
                     ParseMessages.unableToResolveSchema(_schemaId),
 110   
                     _referenceLocation,
 111   
                     null);
 112   
 
 113  55
             try
 114   
             {
 115  55
                 PropertyUtils.write(_container, _propertyName, s);
 116   
             }
 117   
             catch (Exception ex)
 118   
             {
 119  0
                 _errorHandler.error(LOG, ex.getMessage(), _referenceLocation, ex);
 120   
             }
 121   
         }
 122   
     }
 123   
 
 124   
     private static final Log LOG = LogFactory.getLog(DescriptorParser.class);
 125   
 
 126   
     /**
 127   
      * States used while parsing the document.  Most states
 128   
      * correspond to a particular XML element in the document.
 129   
      * STATE_START is the initial state, before the &lt;module&gt;
 130   
      * element is reached.
 131   
      */
 132   
     private static final int STATE_START = 0;
 133   
     private static final int STATE_MODULE = 1;
 134   
     // private static final int STATE_DESCRIPTION = 2;
 135   
     private static final int STATE_CONFIGURATION_POINT = 3;
 136   
     private static final int STATE_CONTRIBUTION = 4;
 137   
     private static final int STATE_SERVICE_POINT = 5;
 138   
     private static final int STATE_CREATE_INSTANCE = 6;
 139   
     private static final int STATE_IMPLEMENTATION = 8;
 140   
 
 141   
     /**
 142   
      * Used for both &lt;schema&;gt; within a &lt;extension-point&gt;,
 143   
      * and for &lt;parameters-schema&gt; within a
 144   
      * &lt;service&gt;.
 145   
      */
 146   
     private static final int STATE_SCHEMA = 9;
 147   
     private static final int STATE_ELEMENT = 10;
 148   
     private static final int STATE_RULES = 11;
 149   
 
 150   
     /**
 151   
      * Used with &lt;invoke-factory&gt; and &lt;interceptor&gt; to
 152   
      * collect parameters that will be passed to the implementation or
 153   
      * interceptor factory service.
 154   
      */
 155   
     private static final int STATE_COLLECT_SERVICE_PARAMETERS = 12;
 156   
 
 157   
     /**
 158   
      * Used with the &lt;conversion&gt; element (an alternative to
 159   
      * using &lt;rules&gt;. Finds &lt;map&gt; elements.
 160   
      */
 161   
     private static final int STATE_CONVERSION = 13;
 162   
 
 163   
     /**
 164   
      * Represents building Element hierarchy as a light-wieght DOM.
 165   
      */
 166   
 
 167   
     private static final int STATE_LWDOM = 100;
 168   
 
 169   
     /**
 170   
      * Special state for elements that are not allowed to contain
 171   
      * any other elements.
 172   
      */
 173   
 
 174   
     private static final int STATE_NO_CONTENT = 300;
 175   
 
 176   
     private static final String SIMPLE_ID = "[a-zA-Z0-9_]+";
 177   
 
 178   
     /**
 179   
      * Format for configuration point ids, service point ids and schema ids.
 180   
      * Consists of an optional leading underscore, followed by alphanumerics
 181   
      * and underscores.  Normal naming convention is to use a single CamelCase word,
 182   
      * like a Java class name.
 183   
      */
 184   
     public static final String ID_PATTERN = "^" + SIMPLE_ID + "$";
 185   
 
 186   
     /**
 187   
      * Module ids are a sequence of simple ids seperated by periods.
 188   
      * In practice, they look like Java package names.
 189   
      */
 190   
     public static final String MODULE_ID_PATTERN = "^" + SIMPLE_ID + "(\\." + SIMPLE_ID + ")*$";
 191   
 
 192   
     public static final String VERSION_PATTERN = "[0-9]+(\\.[0-9]+){2}$";
 193   
 
 194   
     /**
 195   
      * 
 196   
      */
 197   
     /**
 198   
      * Temporary storage of the current {@link Attributes}.
 199   
      */
 200   
     private Map _attributes = new HashMap();
 201   
 
 202   
     /**
 203   
      * Built from DescriptorParser.properties.  Key is
 204   
      * element name, value is an instance of {@link ElementParseInfo}.
 205   
      */
 206   
 
 207   
     private Map _elementParseInfo = new HashMap();
 208   
     private ModuleDescriptor _moduleDescriptor;
 209   
     private SAXParser _parser;
 210   
 
 211   
     private ErrorHandler _errorHandler;
 212   
 
 213   
     /**
 214   
      * Used to resolve schema references during the parse.
 215   
      */
 216   
     private RegistryAssembly _registryAssembly;
 217   
 
 218   
     private ClassResolver _resolver;
 219   
 
 220   
     private Perl5Compiler _compiler;
 221   
     private Perl5Matcher _matcher;
 222   
     private Map _compiledPatterns;
 223   
 
 224   
     /**
 225   
      * Map of Rule keyed on class name, used with &lt;custom&gt; rules.
 226   
      */
 227   
     private final Map _ruleMap = new HashMap();
 228   
 
 229   
     private final Map OCCURS_MAP = new HashMap();
 230   
 
 231   
     {
 232  118
         OCCURS_MAP.put("0..1", Occurances.OPTIONAL);
 233  118
         OCCURS_MAP.put("1", Occurances.REQUIRED);
 234  118
         OCCURS_MAP.put("1..n", Occurances.ONE_PLUS);
 235  118
         OCCURS_MAP.put("0..n", Occurances.UNBOUNDED);
 236  118
         OCCURS_MAP.put("none", Occurances.NONE);
 237   
     }
 238   
 
 239  118
     public DescriptorParser(ErrorHandler errorHandler, RegistryAssembly assembly)
 240   
     {
 241  118
         _errorHandler = errorHandler;
 242  118
         _registryAssembly = assembly;
 243   
 
 244  118
         initializeFromPropertiesFile();
 245   
     }
 246   
 
 247  28922
     public void begin(String elementName, Map attributes)
 248   
     {
 249  28922
         _attributes = attributes;
 250   
 
 251  28922
         switch (getState())
 252   
         {
 253   
             case STATE_START :
 254   
 
 255  216
                 beginStart(elementName);
 256  216
                 break;
 257   
 
 258   
             case STATE_MODULE :
 259   
 
 260  3233
                 beginModule(elementName);
 261  3233
                 break;
 262   
 
 263   
             case STATE_CONFIGURATION_POINT :
 264   
 
 265  580
                 beginConfigurationPoint(elementName);
 266  580
                 break;
 267   
 
 268   
             case STATE_CONTRIBUTION :
 269   
 
 270  2240
                 beginContribution(elementName);
 271  2240
                 break;
 272   
 
 273   
             case STATE_LWDOM :
 274   
 
 275  829
                 beginLWDom(elementName);
 276  829
                 break;
 277   
 
 278   
             case STATE_SERVICE_POINT :
 279   
 
 280  1697
                 beginServicePoint(elementName);
 281  1697
                 break;
 282   
 
 283   
             case STATE_IMPLEMENTATION :
 284   
 
 285  14
                 beginImplementation(elementName);
 286  14
                 break;
 287   
 
 288   
             case STATE_SCHEMA :
 289   
 
 290  1045
                 beginSchema(elementName);
 291  1044
                 break;
 292   
 
 293   
             case STATE_ELEMENT :
 294   
 
 295  8502
                 beginElement(elementName);
 296  8501
                 break;
 297   
 
 298   
             case STATE_RULES :
 299   
 
 300  8960
                 beginRules(elementName);
 301  8959
                 break;
 302   
 
 303   
             case STATE_COLLECT_SERVICE_PARAMETERS :
 304   
 
 305  830
                 beginCollectServiceParameters(elementName);
 306  830
                 break;
 307   
 
 308   
             case STATE_CONVERSION :
 309   
 
 310  776
                 beginConversion(elementName);
 311  776
                 break;
 312   
 
 313   
             default :
 314   
 
 315  0
                 unexpectedElement(elementName);
 316  0
                 break;
 317   
         }
 318   
     }
 319   
 
 320   
     /**
 321   
      * Very similar to {@link #beginContribution(String)}, in that it creates an
 322   
      * {@link ElementImpl}, adds it as a parameter to the
 323   
      * {@link AbstractServiceInvocationDescriptor}, then enters STATE_LWDOM to fill in its
 324   
      * attributes and content.
 325   
      */
 326   
 
 327  830
     private void beginCollectServiceParameters(String elementName)
 328   
     {
 329  830
         ElementImpl element = buildLWDomElement(elementName);
 330   
 
 331  830
         AbstractServiceInvocationDescriptor sid =
 332   
             (AbstractServiceInvocationDescriptor) peekObject();
 333   
 
 334  830
         sid.addParameter(element);
 335   
 
 336  830
         push(elementName, element, STATE_LWDOM, false);
 337   
     }
 338   
 
 339   
     /**
 340   
      * Invoked when a new element starts within STATE_CONFIGURATION_POINT.
 341   
      */
 342  580
     private void beginConfigurationPoint(String elementName)
 343   
     {
 344  580
         if (elementName.equals("schema"))
 345   
         {
 346  580
             enterEmbeddedConfigurationPointSchema(elementName);
 347  580
             return;
 348   
         }
 349   
 
 350  0
         unexpectedElement(elementName);
 351   
     }
 352   
 
 353  2240
     private void beginContribution(String elementName)
 354   
     {
 355   
         // This is where things get tricky, the point where we outgrew Jakarta Digester.
 356   
 
 357  2240
         ElementImpl element = buildLWDomElement(elementName);
 358   
 
 359  2240
         ContributionDescriptor ed = (ContributionDescriptor) peekObject();
 360  2240
         ed.addElement(element);
 361   
 
 362  2240
         push(elementName, element, STATE_LWDOM, false);
 363   
     }
 364   
 
 365  776
     private void beginConversion(String elementName)
 366   
     {
 367  776
         if (elementName.equals("map"))
 368   
         {
 369  776
             ConversionDescriptor cd = (ConversionDescriptor) peekObject();
 370   
 
 371  776
             AttributeMappingDescriptor amd = new AttributeMappingDescriptor();
 372   
 
 373  776
             push(elementName, amd, STATE_NO_CONTENT);
 374   
 
 375  776
             checkAttributes();
 376   
 
 377  776
             amd.setAttributeName(getAttribute("attribute"));
 378  776
             amd.setPropertyName(getAttribute("property"));
 379   
 
 380  776
             cd.addAttributeMapping(amd);
 381   
 
 382  776
             return;
 383   
         }
 384   
 
 385  0
         unexpectedElement(elementName);
 386   
     }
 387   
 
 388  8502
     private void beginElement(String elementName)
 389   
     {
 390  8502
         if (elementName.equals("attribute"))
 391   
         {
 392  3780
             enterAttribute(elementName);
 393  3780
             return;
 394   
         }
 395   
 
 396  4722
         if (elementName.equals("conversion"))
 397   
         {
 398  488
             enterConversion(elementName);
 399  488
             return;
 400   
         }
 401   
 
 402  4234
         if (elementName.equals("rules"))
 403   
         {
 404  2393
             enterRules(elementName);
 405  2393
             return;
 406   
         }
 407   
 
 408   
         // <element> is recursive ... possible, but tricky, if using Digester.
 409   
 
 410  1841
         if (elementName.equals("element"))
 411   
         {
 412  1840
             ElementModelImpl elementModel = (ElementModelImpl) peekObject();
 413   
 
 414  1840
             elementModel.addElementModel(enterElement(elementName));
 415  1840
             return;
 416   
         }
 417   
 
 418  1
         unexpectedElement(elementName);
 419   
     }
 420   
 
 421  1614
     private void beginImplementation(String elementName)
 422   
     {
 423   
 
 424  1614
         if (elementName.equals("create-instance"))
 425   
         {
 426  726
             enterCreateInstance(elementName);
 427  726
             return;
 428   
         }
 429   
 
 430  888
         if (elementName.equals("invoke-factory"))
 431   
         {
 432  828
             enterInvokeFactory(elementName);
 433  828
             return;
 434   
         }
 435   
 
 436  60
         if (elementName.equals("interceptor"))
 437   
         {
 438  60
             enterInterceptor(elementName);
 439  60
             return;
 440   
         }
 441   
 
 442  0
         unexpectedElement(elementName);
 443   
     }
 444   
 
 445  829
     private void beginLWDom(String elementName)
 446   
     {
 447  829
         ElementImpl element = buildLWDomElement(elementName);
 448   
 
 449  829
         ElementImpl parent = (ElementImpl) peekObject();
 450  829
         parent.addElement(element);
 451   
 
 452  829
         push(elementName, element, STATE_LWDOM, false);
 453   
     }
 454   
 
 455   
     /**
 456   
      * Invoked when a new element occurs while in STATE_MODULE.
 457   
      */
 458  3233
     private void beginModule(String elementName)
 459   
     {
 460  3233
         if (elementName.equals("configuration-point"))
 461   
         {
 462  836
             enterConfigurationPoint(elementName);
 463   
 
 464  836
             return;
 465   
         }
 466   
 
 467  2397
         if (elementName.equals("contribution"))
 468   
         {
 469  556
             enterContribution(elementName);
 470  556
             return;
 471   
         }
 472   
 
 473  1841
         if (elementName.equals("service-point"))
 474   
         {
 475  1565
             enterServicePoint(elementName);
 476   
 
 477  1565
             return;
 478   
         }
 479   
 
 480  276
         if (elementName.equals("implementation"))
 481   
         {
 482  13
             enterImplementation(elementName);
 483   
 
 484  13
             return;
 485   
         }
 486   
 
 487  263
         if (elementName.equals("schema"))
 488   
         {
 489  261
             enterSchema(elementName);
 490  261
             return;
 491   
         }
 492   
 
 493  2
         if (elementName.equals("sub-module"))
 494   
         {
 495  2
             enterSubModule(elementName);
 496   
 
 497  2
             return;
 498   
         }
 499   
 
 500   
         // TODO: dependency
 501   
 
 502  0
         unexpectedElement(elementName);
 503   
     }
 504   
 
 505  8960
     private void beginRules(String elementName)
 506   
     {
 507   
 
 508  8960
         if (elementName.equals("create-object"))
 509   
         {
 510  2675
             enterCreateObject(elementName);
 511  2675
             return;
 512   
         }
 513   
 
 514  6285
         if (elementName.equals("invoke-parent"))
 515   
         {
 516  2866
             enterInvokeParent(elementName);
 517  2866
             return;
 518   
         }
 519   
 
 520  3419
         if (elementName.equals("read-attribute"))
 521   
         {
 522  2216
             enterReadAttribute(elementName);
 523  2216
             return;
 524   
         }
 525   
 
 526  1203
         if (elementName.equals("read-content"))
 527   
         {
 528  793
             enterReadContent(elementName);
 529  793
             return;
 530   
         }
 531   
 
 532  410
         if (elementName.equals("set-module"))
 533   
         {
 534  9
             enterSetModule(elementName);
 535  9
             return;
 536   
         }
 537   
 
 538  401
         if (elementName.equals("set-property"))
 539   
         {
 540  195
             enterSetProperty(elementName);
 541  195
             return;
 542   
         }
 543   
 
 544  206
         if (elementName.equals("push-attribute"))
 545   
         {
 546  193
             enterPushAttribute(elementName);
 547  193
             return;
 548   
         }
 549   
 
 550  13
         if (elementName.equals("set-parent"))
 551   
         {
 552  11
             enterSetParent(elementName);
 553  11
             return;
 554   
         }
 555   
 
 556  2
         if (elementName.equals("custom"))
 557   
         {
 558  2
             enterCustom(elementName);
 559   
 
 560  1
             return;
 561   
         }
 562   
 
 563  0
         unexpectedElement(elementName);
 564   
     }
 565   
 
 566  1045
     private void beginSchema(String elementName)
 567   
     {
 568  1045
         if (elementName.equals("element"))
 569   
         {
 570  1045
             SchemaImpl schema = (SchemaImpl) peekObject();
 571   
 
 572  1045
             schema.addElementModel(enterElement(elementName));
 573  1044
             return;
 574   
         }
 575   
 
 576  0
         unexpectedElement(elementName);
 577   
     }
 578   
 
 579  1697
     private void beginServicePoint(String elementName)
 580   
     {
 581  1697
         if (elementName.equals("parameters-schema"))
 582   
         {
 583  97
             enterParametersSchema(elementName);
 584  97
             return;
 585   
         }
 586   
 
 587   
         // <service-point> allows an super-set of <implementation>.
 588   
 
 589  1600
         beginImplementation(elementName);
 590   
     }
 591   
 
 592   
     /**
 593   
      * begin outermost element, expect "module".
 594   
      */
 595  216
     private void beginStart(String elementName)
 596   
     {
 597  216
         if (!elementName.equals("module"))
 598  0
             throw new ApplicationRuntimeException(
 599   
                 ParseMessages.notModule(elementName, getLocation()),
 600   
                 getLocation(),
 601   
                 null);
 602   
 
 603  216
         ModuleDescriptor md = new ModuleDescriptor();
 604   
 
 605  216
         md.setClassResolver(_resolver);
 606   
 
 607  216
         push(elementName, md, STATE_MODULE);
 608   
 
 609  216
         checkAttributes();
 610   
 
 611  216
         md.setModuleId(getValidatedAttribute("id", MODULE_ID_PATTERN, "module-id-format"));
 612  216
         md.setVersion(getValidatedAttribute("version", VERSION_PATTERN, "version-format"));
 613   
 
 614   
         // And, this is what we ultimately return from the parse.
 615   
 
 616  216
         _moduleDescriptor = md;
 617   
     }
 618   
 
 619  3899
     private ElementImpl buildLWDomElement(String elementName)
 620   
     {
 621  3899
         ElementImpl result = new ElementImpl();
 622  3899
         result.setElementName(elementName);
 623   
 
 624  3899
         Iterator i = _attributes.entrySet().iterator();
 625  3899
         while (i.hasNext())
 626   
         {
 627  6784
             Map.Entry entry = (Map.Entry) i.next();
 628   
 
 629  6784
             String name = (String) entry.getKey();
 630  6784
             String value = (String) entry.getValue();
 631   
 
 632  6784
             Attribute a = new AttributeImpl(name, value);
 633   
 
 634  6784
             result.addAttribute(a);
 635   
         }
 636   
 
 637  3899
         return result;
 638   
     }
 639   
 
 640  22049
     private void checkAttributes()
 641   
     {
 642  22049
         checkAttributes(peekElementName());
 643   
     }
 644   
 
 645   
     /**
 646   
      * Checks that only known attributes are specified.
 647   
      * Checks that all required attribute are specified.
 648   
      */
 649  22629
     private void checkAttributes(String elementName)
 650   
     {
 651  22629
         Iterator i = _attributes.keySet().iterator();
 652   
 
 653  22629
         ElementParseInfo epi = (ElementParseInfo) _elementParseInfo.get(elementName);
 654   
 
 655   
         // A few elements have no attributes at all.
 656   
 
 657  22629
         if (epi == null)
 658   
         {
 659  196
             epi = new ElementParseInfo();
 660  196
             _elementParseInfo.put(elementName, epi);
 661   
         }
 662   
 
 663   
         // First, check that each attribute is in the set of expected attributes.
 664   
 
 665  22629
         while (i.hasNext())
 666   
         {
 667  33826
             String name = (String) i.next();
 668   
 
 669  33826
             if (!epi.isKnown(name))
 670  1
                 _errorHandler.error(
 671   
                     LOG,
 672   
                     ParseMessages.unknownAttribute(name, getElementPath()),
 673   
                     getLocation(),
 674   
                     null);
 675   
         }
 676   
 
 677   
         // Now check that all required attributes have been specified.
 678   
 
 679  22629
         i = epi.getRequiredNames();
 680  22629
         while (i.hasNext())
 681   
         {
 682  26092
             String name = (String) i.next();
 683   
 
 684  26092
             if (!_attributes.containsKey(name))
 685  1
                 throw new ApplicationRuntimeException(
 686   
                     ParseMessages.requiredAttribute(name, getElementPath(), getLocation()));
 687   
         }
 688   
 
 689   
     }
 690   
 
 691  28910
     public void end(String elementName)
 692   
     {
 693  28910
         switch (getState())
 694   
         {
 695   
             case STATE_LWDOM :
 696   
 
 697  3899
                 endLWDom();
 698  3899
                 break;
 699   
 
 700   
             case STATE_CONVERSION :
 701   
 
 702  488
                 endConversion();
 703  488
                 break;
 704   
 
 705   
             default :
 706  24523
                 break;
 707   
         }
 708   
 
 709   
         // Pop the top item off the stack.
 710   
 
 711  28910
         pop();
 712   
     }
 713   
 
 714  488
     private void endConversion()
 715   
     {
 716  488
         ConversionDescriptor cd = (ConversionDescriptor) peekObject();
 717   
 
 718  488
         cd.addRulesForModel();
 719   
     }
 720   
 
 721  3899
     private void endLWDom()
 722   
     {
 723  3899
         ElementImpl element = (ElementImpl) peekObject();
 724  3899
         element.setContent(peekContent());
 725   
     }
 726   
 
 727  3780
     private void enterAttribute(String elementName)
 728   
     {
 729  3780
         ElementModelImpl elementModel = (ElementModelImpl) peekObject();
 730   
 
 731  3780
         AttributeModelImpl attributeModel = new AttributeModelImpl();
 732   
 
 733  3780
         push(elementName, attributeModel, STATE_NO_CONTENT);
 734   
 
 735  3780
         checkAttributes();
 736   
 
 737  3780
         attributeModel.setName(getAttribute("name"));
 738  3780
         attributeModel.setRequired(getBooleanAttribute("required", false));
 739  3780
         attributeModel.setUnique(getBooleanAttribute("unique", false));
 740  3780
         attributeModel.setTranslator(getAttribute("translator", "smart"));
 741   
 
 742  3780
         elementModel.addAttributeModel(attributeModel);
 743   
     }
 744   
 
 745  836
     private void enterConfigurationPoint(String elementName)
 746   
     {
 747  836
         ModuleDescriptor md = (ModuleDescriptor) peekObject();
 748   
 
 749  836
         ConfigurationPointDescriptor cpd = new ConfigurationPointDescriptor();
 750   
 
 751  836
         push(elementName, cpd, STATE_CONFIGURATION_POINT);
 752   
 
 753  836
         checkAttributes();
 754   
 
 755  836
         cpd.setId(getValidatedAttribute("id", ID_PATTERN, "id-format"));
 756   
 
 757  836
         Occurances count = (Occurances) getEnumAttribute("occurs", OCCURS_MAP);
 758   
 
 759  836
         if (count != null)
 760  23
             cpd.setCount(count);
 761   
 
 762  836
         Schema s = obtainSchema(getAttribute("schema-id"), cpd, "contributionsSchema");
 763   
 
 764  836
         cpd.setContributionsSchema(s);
 765   
 
 766  836
         md.addConfigurationPoint(cpd);
 767   
     }
 768   
 
 769  556
     private void enterContribution(String elementName)
 770   
     {
 771  556
         ModuleDescriptor md = (ModuleDescriptor) peekObject();
 772   
 
 773  556
         ContributionDescriptor cd = new ContributionDescriptor();
 774   
 
 775  556
         push(elementName, cd, STATE_CONTRIBUTION);
 776   
 
 777  556
         checkAttributes();
 778   
 
 779  556
         cd.setConfigurationId(getAttribute("configuration-id"));
 780   
 
 781  556
         md.addContribution(cd);
 782   
     }
 783   
 
 784  488
     private void enterConversion(String elementName)
 785   
     {
 786  488
         ElementModelImpl elementModel = (ElementModelImpl) peekObject();
 787   
 
 788  488
         ConversionDescriptor cd =
 789   
             new ConversionDescriptor(_errorHandler, elementModel, getLocation());
 790   
 
 791  488
         push(elementName, cd, STATE_CONVERSION);
 792   
 
 793  488
         checkAttributes();
 794   
 
 795  488
         cd.setClassName(getAttribute("class"));
 796   
 
 797  488
         String methodName = getAttribute("parent-method");
 798   
 
 799  488
         if (methodName != null)
 800  1
             cd.setParentMethodName(methodName);
 801   
 
 802   
     }
 803   
 
 804  726
     private void enterCreateInstance(String elementName)
 805   
     {
 806  726
         AbstractServiceDescriptor sd = (AbstractServiceDescriptor) peekObject();
 807  726
         CreateInstanceDescriptor cid = new CreateInstanceDescriptor();
 808   
 
 809  726
         push(elementName, cid, STATE_CREATE_INSTANCE);
 810   
 
 811  726
         checkAttributes();
 812   
 
 813  726
         cid.setInstanceClassName(getAttribute("class"));
 814   
 
 815  726
         String model = getAttribute("model", DEFAULT_SERVICE_MODEL);
 816   
 
 817  726
         cid.setServiceModel(model);
 818   
 
 819  726
         sd.setInstanceBuilder(cid);
 820   
 
 821   
     }
 822   
 
 823  2675
     private void enterCreateObject(String elementName)
 824   
     {
 825  2675
         ElementModelImpl elementModel = (ElementModelImpl) peekObject();
 826  2675
         CreateObjectRule rule = new CreateObjectRule();
 827  2675
         push(elementName, rule, STATE_NO_CONTENT);
 828   
 
 829  2675
         checkAttributes();
 830   
 
 831  2675
         rule.setClassName(getAttribute("class"));
 832   
 
 833  2675
         elementModel.addRule(rule);
 834   
     }
 835   
 
 836  2
     private void enterCustom(String elementName)
 837   
     {
 838  2
         ElementModelImpl elementModel = (ElementModelImpl) peekObject();
 839   
 
 840   
         // Don't know what it is going to be, yet.
 841   
 
 842  2
         push(elementName, null, STATE_NO_CONTENT);
 843   
 
 844  2
         checkAttributes();
 845   
 
 846  2
         String ruleClassName = getAttribute("class");
 847   
 
 848  2
         Rule rule = getCustomRule(ruleClassName);
 849   
 
 850  1
         elementModel.addRule(rule);
 851   
     }
 852   
 
 853   
     /**
 854   
      * Pushes STATE_ELEMENT onto the stack and creates and returns
 855   
      * the {@link ElementModelImpl} it creates.
 856   
      */
 857  2885
     private ElementModel enterElement(String elementName)
 858   
     {
 859  2885
         ElementModelImpl result = new ElementModelImpl();
 860   
 
 861  2885
         push(elementName, result, STATE_ELEMENT);
 862   
 
 863  2885
         checkAttributes();
 864   
 
 865  2884
         result.setElementName(getAttribute("name"));
 866  2884
         result.setContentTranslator(getAttribute("content-translator"));
 867   
 
 868  2884
         return result;
 869   
     }
 870   
 
 871  580
     private void enterEmbeddedConfigurationPointSchema(String elementName)
 872   
     {
 873  580
         ConfigurationPointDescriptor cpd = (ConfigurationPointDescriptor) peekObject();
 874   
 
 875  580
         SchemaImpl schema = new SchemaImpl();
 876   
 
 877  580
         push(elementName, schema, STATE_SCHEMA);
 878   
 
 879   
         // TODO: Check if already has cpd / already specified schema-id
 880   
 
 881  580
         cpd.setContributionsSchema(schema);
 882   
 
 883  580
         checkAttributes("schema{embedded}");
 884   
     }
 885   
 
 886  97
     private void enterParametersSchema(String elementName)
 887   
     {
 888  97
         ServicePointDescriptor spd = (ServicePointDescriptor) peekObject();
 889  97
         SchemaImpl schema = new SchemaImpl();
 890   
 
 891  97
         push(elementName, schema, STATE_SCHEMA);
 892   
 
 893  97
         spd.setParametersSchema(schema);
 894   
 
 895  97
         checkAttributes();
 896   
     }
 897   
 
 898  13
     private void enterImplementation(String elementName)
 899   
     {
 900  13
         ModuleDescriptor md = (ModuleDescriptor) peekObject();
 901   
 
 902  13
         ImplementationDescriptor id = new ImplementationDescriptor();
 903   
 
 904  13
         push(elementName, id, STATE_IMPLEMENTATION);
 905   
 
 906  13
         checkAttributes();
 907   
 
 908  13
         id.setServiceId(getAttribute("service-id"));
 909   
 
 910  13
         md.addImplementation(id);
 911   
     }
 912   
 
 913  60
     private void enterInterceptor(String elementName)
 914   
     {
 915  60
         AbstractServiceDescriptor sd = (AbstractServiceDescriptor) peekObject();
 916  60
         InterceptorDescriptor id = new InterceptorDescriptor();
 917   
 
 918  60
         push(elementName, id, STATE_COLLECT_SERVICE_PARAMETERS);
 919   
 
 920  60
         checkAttributes();
 921   
 
 922  60
         id.setFactoryServiceId(getAttribute("service-id"));
 923   
 
 924  60
         id.setBefore(getAttribute("before"));
 925  60
         id.setAfter(getAttribute("after"));
 926   
 
 927  60
         sd.addInterceptor(id);
 928   
 
 929   
     }
 930   
 
 931  828
     private void enterInvokeFactory(String elementName)
 932   
     {
 933  828
         AbstractServiceDescriptor sd = (AbstractServiceDescriptor) peekObject();
 934  828
         InvokeFactoryDescriptor ifd = new InvokeFactoryDescriptor();
 935   
 
 936  828
         push(elementName, ifd, STATE_COLLECT_SERVICE_PARAMETERS);
 937   
 
 938  828
         checkAttributes();
 939   
 
 940  828
         ifd.setFactoryServiceId(getAttribute("service-id", "hivemind.BuilderFactory"));
 941   
 
 942  828
         String model = getAttribute("model", DEFAULT_SERVICE_MODEL);
 943   
 
 944  828
         ifd.setServiceModel(model);
 945   
 
 946   
         // TODO: Check if instanceBuilder already set
 947   
 
 948  828
         sd.setInstanceBuilder(ifd);
 949   
 
 950   
     }
 951   
 
 952  2866
     private void enterInvokeParent(String elementName)
 953   
     {
 954  2866
         ElementModelImpl elementModel = (ElementModelImpl) peekObject();
 955  2866
         InvokeParentRule rule = new InvokeParentRule();
 956   
 
 957  2866
         push(elementName, rule, STATE_NO_CONTENT);
 958   
 
 959  2866
         checkAttributes();
 960   
 
 961  2866
         rule.setMethodName(getAttribute("method"));
 962   
 
 963  2866
         if (_attributes.containsKey("depth"))
 964  2304
             rule.setDepth(getIntAttribute("depth"));
 965   
 
 966  2866
         elementModel.addRule(rule);
 967   
     }
 968   
 
 969  2216
     private void enterReadAttribute(String elementName)
 970   
     {
 971  2216
         ElementModelImpl elementModel = (ElementModelImpl) peekObject();
 972  2216
         ReadAttributeRule rule = new ReadAttributeRule();
 973   
 
 974  2216
         push(elementName, rule, STATE_NO_CONTENT);
 975   
 
 976  2216
         checkAttributes();
 977   
 
 978  2216
         rule.setPropertyName(getAttribute("property"));
 979  2216
         rule.setAttributeName(getAttribute("attribute"));
 980  2216
         rule.setSkipIfNull(getBooleanAttribute("skip-if-null", true));
 981  2216
         rule.setTranslator(getAttribute("translator"));
 982   
 
 983  2216
         elementModel.addRule(rule);
 984   
     }
 985   
 
 986  793
     private void enterReadContent(String elementName)
 987   
     {
 988  793
         ElementModelImpl elementModel = (ElementModelImpl) peekObject();
 989  793
         ReadContentRule rule = new ReadContentRule();
 990   
 
 991  793
         push(elementName, rule, STATE_NO_CONTENT);
 992   
 
 993  793
         checkAttributes();
 994   
 
 995  793
         rule.setPropertyName(getAttribute("property"));
 996   
 
 997  793
         elementModel.addRule(rule);
 998   
     }
 999   
 
 1000  2393
     private void enterRules(String elementName)
 1001   
     {
 1002  2393
         ElementModelImpl elementModel = (ElementModelImpl) peekObject();
 1003   
 
 1004  2393
         push(elementName, elementModel, STATE_RULES);
 1005   
 
 1006   
     }
 1007   
 
 1008  261
     private void enterSchema(String elementName)
 1009   
     {
 1010  261
         SchemaImpl schema = new SchemaImpl();
 1011   
 
 1012  261
         push(elementName, schema, STATE_SCHEMA);
 1013   
 
 1014  261
         checkAttributes();
 1015   
 
 1016  261
         String id = getValidatedAttribute("id", ID_PATTERN, "id-format");
 1017   
 
 1018   
         // TODO: check for duplicate name!
 1019   
 
 1020  261
         _registryAssembly.addSchema(qualify(id), schema);
 1021   
     }
 1022   
 
 1023  1565
     private void enterServicePoint(String elementName)
 1024   
     {
 1025  1565
         ModuleDescriptor md = (ModuleDescriptor) peekObject();
 1026   
 
 1027  1565
         ServicePointDescriptor spd = new ServicePointDescriptor();
 1028   
 
 1029  1565
         push(elementName, spd, STATE_SERVICE_POINT);
 1030   
 
 1031  1565
         checkAttributes();
 1032   
 
 1033  1565
         spd.setId(getValidatedAttribute("id", ID_PATTERN, "id-format"));
 1034  1565
         spd.setInterfaceClassName(getAttribute("interface"));
 1035   
 
 1036  1565
         Schema s = obtainSchema(getAttribute("parameters-schema-id"), spd, "parametersSchema");
 1037   
 
 1038  1565
         spd.setParametersSchema(s);
 1039   
 
 1040  1565
         Occurances count = (Occurances) getEnumAttribute("parameters-occurs", OCCURS_MAP);
 1041   
 
 1042  1565
         if (count != null)
 1043  0
             spd.setParametersCount(count);
 1044   
 
 1045  1565
         md.addServicePoint(spd);
 1046   
     }
 1047   
 
 1048  9
     private void enterSetModule(String elementName)
 1049   
     {
 1050  9
         ElementModelImpl elementModel = (ElementModelImpl) peekObject();
 1051  9
         SetModuleRule rule = new SetModuleRule();
 1052   
 
 1053  9
         push(elementName, rule, STATE_NO_CONTENT);
 1054   
 
 1055  9
         checkAttributes();
 1056   
 
 1057  9
         rule.setPropertyName(getAttribute("property"));
 1058   
 
 1059  9
         elementModel.addRule(rule);
 1060   
     }
 1061   
 
 1062  11
     private void enterSetParent(String elementName)
 1063   
     {
 1064  11
         ElementModelImpl elementModel = (ElementModelImpl) peekObject();
 1065  11
         SetParentRule rule = new SetParentRule();
 1066   
 
 1067  11
         push(elementName, rule, STATE_NO_CONTENT);
 1068   
 
 1069  11
         checkAttributes();
 1070   
 
 1071  11
         rule.setPropertyName(getAttribute("property"));
 1072   
 
 1073  11
         elementModel.addRule(rule);
 1074   
     }
 1075   
 
 1076  195
     private void enterSetProperty(String elementName)
 1077   
     {
 1078  195
         ElementModelImpl elementModel = (ElementModelImpl) peekObject();
 1079   
 
 1080  195
         SetPropertyRule rule = new SetPropertyRule();
 1081   
 
 1082  195
         push(elementName, rule, STATE_NO_CONTENT);
 1083   
 
 1084  195
         checkAttributes();
 1085   
 
 1086  195
         rule.setPropertyName(getAttribute("property"));
 1087  195
         rule.setValue(getAttribute("value"));
 1088   
 
 1089  195
         elementModel.addRule(rule);
 1090   
     }
 1091   
 
 1092  193
     private void enterPushAttribute(String elementName)
 1093   
     {
 1094  193
         ElementModelImpl elementModel = (ElementModelImpl) peekObject();
 1095   
 
 1096  193
         PushAttributeRule rule = new PushAttributeRule();
 1097   
 
 1098  193
         push(elementName, rule, STATE_NO_CONTENT);
 1099   
 
 1100  193
         checkAttributes();
 1101   
 
 1102  193
         rule.setAttributeName(getAttribute("attribute"));
 1103   
 
 1104  193
         elementModel.addRule(rule);
 1105   
     }
 1106   
 
 1107  2
     private void enterSubModule(String elementName)
 1108   
     {
 1109  2
         push(elementName, null, STATE_NO_CONTENT);
 1110   
 
 1111  2
         checkAttributes();
 1112   
 
 1113  2
         String path = getAttribute("descriptor");
 1114   
 
 1115  2
         Resource subModuleDescriptor = getResource().getRelativeResource(path);
 1116   
 
 1117  2
         if (subModuleDescriptor.getResourceURL() == null)
 1118   
         {
 1119  1
             _errorHandler.error(
 1120   
                 LOG,
 1121   
                 ParseMessages.subModuleDoesNotExist(subModuleDescriptor),
 1122   
                 getLocation(),
 1123   
                 null);
 1124  1
             return;
 1125   
         }
 1126   
 
 1127  1
         _registryAssembly.enqueueModuleParse(subModuleDescriptor, _resolver);
 1128   
     }
 1129   
 
 1130  48681
     private String getAttribute(String name)
 1131   
     {
 1132  48681
         return (String) _attributes.get(name);
 1133   
     }
 1134   
 
 1135  6162
     private String getAttribute(String name, String defaultValue)
 1136   
     {
 1137  6162
         String result = (String) _attributes.get(name);
 1138   
 
 1139  6162
         if (result == null)
 1140  4381
             result = defaultValue;
 1141   
 
 1142  6162
         return result;
 1143   
     }
 1144   
 
 1145  3094
     private String getValidatedAttribute(String name, String pattern, String formatKey)
 1146   
     {
 1147  3094
         String result = getAttribute(name);
 1148   
 
 1149  3094
         if (!validateFormat(result, pattern))
 1150  3
             _errorHandler.error(
 1151   
                 LOG,
 1152   
                 ParseMessages.invalidAttributeFormat(name, result, getElementPath(), formatKey),
 1153   
                 getLocation(),
 1154   
                 null);
 1155   
 
 1156  3094
         return result;
 1157   
     }
 1158   
 
 1159  3094
     private boolean validateFormat(String input, String pattern)
 1160   
     {
 1161  3094
         if (_compiler == null)
 1162   
         {
 1163  118
             _compiler = new Perl5Compiler();
 1164  118
             _matcher = new Perl5Matcher();
 1165  118
             _compiledPatterns = new HashMap();
 1166   
         }
 1167   
 
 1168  3094
         Pattern compiled = (Pattern) _compiledPatterns.get(pattern);
 1169  3094
         if (compiled == null)
 1170   
         {
 1171   
 
 1172  351
             try
 1173   
             {
 1174  351
                 compiled = _compiler.compile(pattern);
 1175   
             }
 1176   
             catch (MalformedPatternException ex)
 1177   
             {
 1178  0
                 throw new ApplicationRuntimeException(ex);
 1179   
             }
 1180   
 
 1181  351
             _compiledPatterns.put(pattern, compiled);
 1182   
         }
 1183   
 
 1184  3094
         return _matcher.matches(input, compiled);
 1185   
     }
 1186   
 
 1187  9776
     private boolean getBooleanAttribute(String name, boolean defaultValue)
 1188   
     {
 1189  9776
         String value = getAttribute(name);
 1190   
 
 1191  9776
         if (value == null)
 1192  7203
             return defaultValue;
 1193   
 
 1194  2573
         if (value.equals("true"))
 1195  2184
             return true;
 1196   
 
 1197  389
         if (value.equals("false"))
 1198  389
             return false;
 1199   
 
 1200  0
         _errorHandler.error(
 1201   
             LOG,
 1202   
             ParseMessages.booleanAttribute(value, name, getElementPath()),
 1203   
             getLocation(),
 1204   
             null);
 1205   
 
 1206  0
         return defaultValue;
 1207   
     }
 1208   
 
 1209  2
     private Rule getCustomRule(String ruleClassName)
 1210   
     {
 1211  2
         Rule result = (Rule) _ruleMap.get(ruleClassName);
 1212   
 
 1213  2
         if (result == null)
 1214   
         {
 1215  2
             result = instantiateRule(ruleClassName);
 1216   
 
 1217  1
             _ruleMap.put(ruleClassName, result);
 1218   
         }
 1219   
 
 1220  1
         return result;
 1221   
     }
 1222   
 
 1223  2401
     private Object getEnumAttribute(String name, Map translations)
 1224   
     {
 1225  2401
         String value = getAttribute(name);
 1226   
 
 1227  2401
         if (value == null)
 1228  2378
             return null;
 1229   
 
 1230  23
         Object result = translations.get(value);
 1231   
 
 1232  23
         if (result == null)
 1233  0
             _errorHandler.error(
 1234   
                 LOG,
 1235   
                 ParseMessages.invalidAttributeValue(value, name, getElementPath()),
 1236   
                 getLocation(),
 1237   
                 null);
 1238   
 
 1239  23
         return result;
 1240   
     }
 1241   
 
 1242  2304
     private int getIntAttribute(String name)
 1243   
     {
 1244  2304
         String value = getAttribute(name);
 1245   
 
 1246  2304
         try
 1247   
         {
 1248  2304
             return Integer.parseInt(value);
 1249   
         }
 1250   
         catch (NumberFormatException ex)
 1251   
         {
 1252  0
             _errorHandler.error(
 1253   
                 LOG,
 1254   
                 ParseMessages.invalidNumericValue(value, name, getElementPath()),
 1255   
                 getLocation(),
 1256   
                 ex);
 1257   
 
 1258  0
             return 0;
 1259   
         }
 1260   
     }
 1261   
 
 1262  216
     private SAXParser getSAXParser()
 1263   
         throws ParserConfigurationException, SAXException, FactoryConfigurationError
 1264   
     {
 1265  216
         if (_parser == null)
 1266  118
             _parser = SAXParserFactory.newInstance().newSAXParser();
 1267   
 
 1268  216
         return _parser;
 1269   
     }
 1270   
 
 1271  118
     private void initializeFromProperties(Properties p)
 1272   
     {
 1273  118
         Enumeration e = p.propertyNames();
 1274   
 
 1275  118
         while (e.hasMoreElements())
 1276   
         {
 1277  5192
             String key = (String) e.nextElement();
 1278  5192
             String value = p.getProperty(key);
 1279   
 
 1280  5192
             initializeFromProperty(key, value);
 1281   
         }
 1282   
     }
 1283   
 
 1284   
     /**
 1285   
      * Invoked from the constructor to read the properties file that defines
 1286   
      * certain aspects of the operation of the parser.
 1287   
      */
 1288  118
     private void initializeFromPropertiesFile()
 1289   
     {
 1290  118
         Properties p = new Properties();
 1291   
 
 1292  118
         try
 1293   
         {
 1294   
 
 1295  118
             InputStream propertiesIn =
 1296   
                 getClass().getResourceAsStream("DescriptorParser.properties");
 1297  118
             InputStream bufferedIn = new BufferedInputStream(propertiesIn);
 1298   
 
 1299  118
             p.load(bufferedIn);
 1300   
 
 1301  118
             bufferedIn.close();
 1302   
         }
 1303   
         catch (IOException ex)
 1304   
         {
 1305  0
             _errorHandler.error(LOG, ParseMessages.unableToInitialize(ex), null, ex);
 1306   
         }
 1307   
 
 1308  118
         initializeFromProperties(p);
 1309   
     }
 1310   
 
 1311  5192
     private void initializeFromProperty(String key, String value)
 1312   
     {
 1313  5192
         if (key.startsWith("required."))
 1314   
         {
 1315  5192
             initializeRequired(key, value);
 1316  5192
             return;
 1317   
         }
 1318   
 
 1319   
     }
 1320   
 
 1321  5192
     private void initializeRequired(String key, String value)
 1322   
     {
 1323  5192
         boolean required = value.equals("true");
 1324   
 
 1325  5192
         int lastdotx = key.lastIndexOf('.');
 1326   
 
 1327  5192
         String elementName = key.substring(9, lastdotx);
 1328  5192
         String attributeName = key.substring(lastdotx + 1);
 1329   
 
 1330  5192
         ElementParseInfo epi = (ElementParseInfo) _elementParseInfo.get(elementName);
 1331   
 
 1332  5192
         if (epi == null)
 1333   
         {
 1334  2714
             epi = new ElementParseInfo();
 1335  2714
             _elementParseInfo.put(elementName, epi);
 1336   
         }
 1337   
 
 1338  5192
         epi.addAttribute(attributeName, required);
 1339   
     }
 1340   
 
 1341  2
     private Rule instantiateRule(String ruleClassName)
 1342   
     {
 1343  2
         try
 1344   
         {
 1345  2
             Class ruleClass = _resolver.findClass(ruleClassName);
 1346   
 
 1347  1
             return (Rule) ruleClass.newInstance();
 1348   
         }
 1349   
         catch (Exception ex)
 1350   
         {
 1351  1
             throw new ApplicationRuntimeException(
 1352   
                 ParseMessages.badRuleClass(ruleClassName, getLocation(), ex),
 1353   
                 getLocation(),
 1354   
                 ex);
 1355   
         }
 1356   
     }
 1357   
 
 1358   
     /**
 1359   
      * Obtains a {@link Schema} based on a local or fully qualifed schema id. If the schema
 1360   
      * has not yet been defined, then a {@link RegistryAssembly#addPostProcessor(Runnable) post processor}
 1361   
      * is created to set the schema (within the containing descriptor object) once all modules
 1362   
      * have been parsed.
 1363   
      * 
 1364   
      * @param schemaId local or fully qualified id, or null
 1365   
      * @param container the object ({@link ConfigurationPointDescriptor} or {@link ServicePointDescriptor})
 1366   
      * that will contain the schema
 1367   
      * @param propertyName property of the container to update once the schema is known
 1368   
      * @return the Schema (if known), or null (if the schema will be located later)
 1369   
      * 
 1370   
      */
 1371  2401
     private Schema obtainSchema(String schemaId, Object container, String propertyName)
 1372   
     {
 1373  2401
         if (schemaId == null)
 1374  2043
             return null;
 1375   
 
 1376  358
         String fullId = qualify(schemaId);
 1377  358
         Schema reffed = _registryAssembly.getSchema(fullId);
 1378   
 
 1379  358
         if (reffed != null)
 1380  300
             return reffed;
 1381   
 
 1382   
         // Not found! We don't know what order modules are parsed in,
 1383   
         // so this is not necessarily an error (it could even be a forward
 1384   
         // reference within the same module). In any case, set up to relink
 1385   
         // to the resolved Schema object after all modules are parsed.    
 1386   
 
 1387  58
         Runnable r =
 1388   
             new SchemaRelinker(fullId, container, propertyName, _registryAssembly, getLocation());
 1389   
 
 1390  58
         _registryAssembly.addPostProcessor(r);
 1391   
 
 1392  58
         return null;
 1393   
     }
 1394   
 
 1395   
     /**
 1396   
      * Enters a new state, pushing an object onto the stack. If the object
 1397   
      * implements {@link ILocationHolder} then its location property
 1398   
      * is set to the current location.
 1399   
      */
 1400  216
     public ModuleDescriptor parse(Resource resource, ClassResolver resolver)
 1401   
     {
 1402  216
         try
 1403   
         {
 1404  216
             if (LOG.isDebugEnabled())
 1405  20
                 LOG.debug("Parsing " + resource);
 1406   
 
 1407  216
             initializeParser(resource, STATE_START);
 1408   
 
 1409  216
             _resolver = resolver;
 1410   
 
 1411  216
             parseXML(resource);
 1412   
 
 1413  213
             if (LOG.isDebugEnabled())
 1414  20
                 LOG.debug("Result: " + _moduleDescriptor);
 1415   
 
 1416  213
             return _moduleDescriptor;
 1417   
         }
 1418   
         catch (Exception ex)
 1419   
         {
 1420  3
             throw new ApplicationRuntimeException(
 1421   
                 ParseMessages.errorReadingDescriptor(resource, ex),
 1422   
                 resource,
 1423   
                 getLocation(),
 1424   
                 ex);
 1425   
         }
 1426   
         finally
 1427   
         {
 1428  216
             resetParser();
 1429   
 
 1430  216
             _moduleDescriptor = null;
 1431  216
             _attributes.clear();
 1432  216
             _resolver = null;
 1433   
         }
 1434   
     }
 1435   
 
 1436   
     /**
 1437   
      * Parses a document in the original format: unvalidated XML (with
 1438   
      * no document type).
 1439   
      */
 1440  216
     private void parseXML(Resource resource) throws Exception
 1441   
     {
 1442  216
         URL url = resource.getResourceURL();
 1443   
 
 1444  216
         if (url == null)
 1445  0
             throw new ApplicationRuntimeException(
 1446   
                 ParseMessages.missingResource(resource),
 1447   
                 resource,
 1448   
                 null,
 1449   
                 null);
 1450   
 
 1451  216
         InputSource source = new InputSource(url.toExternalForm());
 1452   
 
 1453  216
         try
 1454   
         {
 1455  216
             getSAXParser().parse(source, this);
 1456   
         }
 1457   
         catch (Exception ex)
 1458   
         {
 1459  3
             _parser = null;
 1460   
 
 1461  3
             throw ex;
 1462   
         }
 1463   
     }
 1464   
 
 1465  619
     private String qualify(String id)
 1466   
     {
 1467  619
         if (id.indexOf('.') >= 0)
 1468  0
             return id;
 1469   
 
 1470  619
         return _moduleDescriptor.getModuleId() + "." + id;
 1471   
     }
 1472   
 }
 1473