View Javadoc
1   /*
2    * Licensed to The Apereo Foundation under one or more contributor license
3    * agreements. See the NOTICE file distributed with this work for additional
4    * information regarding copyright ownership.
5    *
6    *
7    * The Apereo Foundation licenses this file to you under the Educational
8    * Community License, Version 2.0 (the "License"); you may not use this file
9    * except in compliance with the License. You may obtain a copy of the License
10   * at:
11   *
12   *   http://opensource.org/licenses/ecl2.txt
13   *
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
16   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
17   * License for the specific language governing permissions and limitations under
18   * the License.
19   *
20   */
21  
22  package org.opencastproject.index.service.catalog.adapter;
23  
24  import static java.lang.String.format;
25  import static org.apache.commons.lang3.StringUtils.isBlank;
26  
27  import org.opencastproject.util.ConfigurationException;
28  import org.opencastproject.util.XmlNamespaceContext;
29  
30  import java.util.Dictionary;
31  import java.util.Enumeration;
32  import java.util.HashMap;
33  import java.util.Map;
34  
35  /**
36   * This class parses a catalog UI adapter configuration and provides convenience access methods.
37   */
38  public final class CatalogUIAdapterConfiguration {
39  
40    /* Configuration keys */
41    public static final String KEY_XML_ROOT_ELEMENT_NAME = "xml.rootElement.name";
42    public static final String KEY_XML_ROOT_ELEMENT_NS_URI = "xml.rootElement.namespace.URI";
43    public static final String XML_BINDING_KEY_PREFIX = "xml.namespaceBinding.";
44    public static final String XML_BINDING_URI_SUFFIX = ".URI";
45    public static final String XML_BINDING_PREFIX_SUFFIX = ".prefix";
46  
47    /** The raw configuration properties */
48    private final Dictionary<String, ?> configProperties;
49  
50    /** The xml namespace binding context */
51    private XmlNamespaceContext xmlNSContext;
52  
53    /**
54     * Load configuration from a dictionary.
55     *
56     * @param properties
57     *          The configuration properties
58     * @return The parsed configuration as {@link CatalogUIAdapterConfiguration} instance
59     * @throws ConfigurationException
60     *           If the configuration has any errors
61     */
62    public static CatalogUIAdapterConfiguration loadFromDictionary(Dictionary<String, ?> properties)
63            throws ConfigurationException {
64      return new CatalogUIAdapterConfiguration(properties);
65    }
66  
67    private CatalogUIAdapterConfiguration(Dictionary<String, ?> properties) throws ConfigurationException {
68      this.configProperties = properties;
69      loadXmlNSContext();
70      validate();
71    }
72  
73    /**
74     * Validates the configuration and throws a {@link ConfigurationException} if there is any error.
75     *
76     * @throws ConfigurationException
77     *           if the configuration is not valid
78     */
79    private void validate() throws ConfigurationException {
80      if (configProperties.get(KEY_XML_ROOT_ELEMENT_NAME) == null) {
81        throw new ConfigurationException(format(
82            "Value for configuration key '%s' is missing", KEY_XML_ROOT_ELEMENT_NAME));
83      }
84  
85      if (configProperties.get(KEY_XML_ROOT_ELEMENT_NS_URI) == null) {
86        throw new ConfigurationException(format(
87            "Value for configuration key '%s' is missing", KEY_XML_ROOT_ELEMENT_NS_URI));
88      }
89  
90      if (xmlNSContext.getPrefix(getCatalogXmlRootNamespace()) == null) {
91        throw new ConfigurationException(format(
92            "Binding for XML namespace URI '%s' is missing", getCatalogXmlRootNamespace()));
93      }
94    }
95  
96    /**
97     * Load the XML namespace bindings from the configuration and build the XML namespace context.
98     */
99    private void loadXmlNSContext() {
100     final Enumeration<String> keys = configProperties.keys();
101     final Map<String, String> prefixToUri = new HashMap<String, String>();
102     while (keys.hasMoreElements()) {
103       final String key = keys.nextElement();
104       if (key.startsWith(XML_BINDING_KEY_PREFIX)) {
105         // First, we need to get the name of the binding
106         final String nsBindingName = getXmlBindingNameFromConfigKey(key);
107         // Once we have the name, we're able to retrieve the URI as well as the prefix
108         final String nsUri = (String) configProperties
109                 .get(XML_BINDING_KEY_PREFIX + nsBindingName + XML_BINDING_URI_SUFFIX);
110         final String nsPrefix = (String) configProperties
111                 .get(XML_BINDING_KEY_PREFIX + nsBindingName + XML_BINDING_PREFIX_SUFFIX);
112         // Check if URI and the prefix have valid values
113         if (isBlank(nsUri)) {
114           throw new ConfigurationException(format("No URI for namespace binding '%s' found", nsBindingName));
115         }
116         if (nsPrefix == null) {
117           throw new ConfigurationException(format("No prefix for namespace binding '%s' found", nsBindingName));
118         }
119         // Add prefix & URI to the intermediate map
120         prefixToUri.put(nsPrefix, nsUri);
121       }
122     }
123 
124     xmlNSContext = new XmlNamespaceContext(prefixToUri);
125   }
126 
127   /**
128    * Get the name of an XML namespace binding by one of its configuration keys.
129    *
130    * @param key
131    *          the key name
132    * @return the XML namespace binding name
133    */
134   private static String getXmlBindingNameFromConfigKey(final String key) {
135     if (isBlank(key) || !key.startsWith(XML_BINDING_KEY_PREFIX)) {
136       throw new IllegalArgumentException(format("The given key '%s' is not part of a XML binding definition", key));
137     }
138     final String keyWithoutPrefix = key.substring(XML_BINDING_KEY_PREFIX.length());
139     return keyWithoutPrefix.substring(0, keyWithoutPrefix.indexOf("."));
140   }
141 
142   /**
143    * Return the value of the configuration property {@link CatalogUIAdapterConfiguration#KEY_XML_ROOT_ELEMENT_NAME}
144    */
145   public String getCatalogXmlRootElementName() {
146     return (String) configProperties.get(KEY_XML_ROOT_ELEMENT_NAME);
147   }
148 
149   /**
150    * Return the value of the configuration property {@link CatalogUIAdapterConfiguration#KEY_XML_ROOT_ELEMENT_NS_URI}
151    */
152   public String getCatalogXmlRootNamespace() {
153     return (String) configProperties.get(KEY_XML_ROOT_ELEMENT_NS_URI);
154   }
155 
156   /**
157    * Returns the XML namespace context that could be built out of the configuration.
158    */
159   public XmlNamespaceContext getXmlNamespaceContext() {
160     return xmlNSContext;
161   }
162 
163 }