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 }