View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.chain.config;
18  
19  import org.apache.commons.chain.Catalog;
20  import org.apache.commons.chain.CatalogFactory;
21  import org.apache.commons.chain.Context;
22  import org.apache.commons.digester.Rule;
23  import org.xml.sax.Attributes;
24  
25  /**
26   * Digester rule that will cause the top-most element on the Digester
27   * stack (if it is a {@link Catalog} to be registered with the
28   * {@link CatalogFactory} instance for our application. If the attribute
29   * specified to our constructor has a value, that will be used as the name
30   * under which to register this {@link Catalog}. Otherwise, this will
31   * become the default {@link Catalog} for this application.
32   *
33   * @author Craig R. McClanahan
34   * @version $Revision$ $Date$
35   */
36  class ConfigCatalogRule extends Rule {
37  
38      // ----------------------------------------------------- Instance Variables
39  
40      /**
41       * The fully qualified class name of a {@link Catalog} class to use for
42       * instantiating new instances.
43       */
44      private final String catalogClass;
45  
46      /**
47       * The name of the attribute under which we can retrieve the name
48       * this catalog should be registered with (if any).
49       */
50      private final String nameAttribute;
51  
52      // ----------------------------------------------------------- Constructors
53  
54      /**
55       * Construct a new instance of this rule that looks for an attribute
56       * with the specified name.
57       *
58       * @param nameAttribute Name of the attribute containing the name under
59       *        which this command should be registered
60       * @param catalogClass Name of the implementation class for newly
61       *        created {@link Catalog} instances
62       */
63      ConfigCatalogRule(String nameAttribute, String catalogClass) {
64          this.nameAttribute = nameAttribute;
65          this.catalogClass = catalogClass;
66      }
67  
68      // --------------------------------------------------------- Public Methods
69  
70      /**
71       * Retrieve or create a {@link Catalog} with the name specified by
72       * the {@code nameAttribute} attribute, or the default {@link Catalog}
73       * if there is no such attribute defined. Push it onto the top of the
74       * stack.
75       *
76       * @param namespace the namespace URI of the matching element, or an
77       *        empty string if the parser is not namespace aware or the
78       *        element has no namespace
79       * @param name the local name if the parser is namespace aware, or
80       *        just the element name otherwise
81       * @param attributes The attribute list of this element
82       */
83      @Override
84      public void begin(String namespace, String name, Attributes attributes)
85          throws Exception {
86  
87          // Retrieve any current Catalog with the specified name
88          Catalog<Context> catalog;
89          CatalogFactory<Context> factory = CatalogFactory.getInstance();
90          String nameValue = attributes.getValue(nameAttribute);
91          if (nameValue == null) {
92              catalog = factory.getCatalog();
93          } else {
94              catalog = factory.getCatalog(nameValue);
95          }
96  
97          // Create and register a new Catalog instance if necessary
98          if (catalog == null) {
99              Class<?> clazz = digester.getClassLoader().loadClass(catalogClass);
100 
101             /* Convert catalog pulled from digester to default generic signature
102              * with the assumption that the Catalog returned from digester will
103              * comply with the historic chain contract. */
104             @SuppressWarnings("unchecked")
105             Catalog<Context> digesterCatalog = (Catalog<Context>) clazz.getDeclaredConstructor().newInstance();
106 
107             catalog = digesterCatalog;
108             if (nameValue == null) {
109                 factory.setCatalog(catalog);
110             } else {
111                 factory.addCatalog(nameValue, catalog);
112             }
113         }
114 
115         // Push this Catalog onto the top of the stack
116         digester.push(catalog);
117     }
118 }