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