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(
82                format("Value for configuration key '%s' is missing", KEY_XML_ROOT_ELEMENT_NAME));
83  
84      if (configProperties.get(KEY_XML_ROOT_ELEMENT_NS_URI) == null)
85        throw new ConfigurationException(
86                format("Value for configuration key '%s' is missing", KEY_XML_ROOT_ELEMENT_NS_URI));
87  
88      if (xmlNSContext.getPrefix(getCatalogXmlRootNamespace()) == null)
89        throw new ConfigurationException(
90                format("Binding for XML namespace URI '%s' is missing", getCatalogXmlRootNamespace()));
91    }
92  
93    /**
94     * Load the XML namespace bindings from the configuration and build the XML namespace context.
95     */
96    private void loadXmlNSContext() {
97      final Enumeration<String> keys = configProperties.keys();
98      final Map<String, String> prefixToUri = new HashMap<String, String>();
99      while (keys.hasMoreElements()) {
100       final String key = keys.nextElement();
101       if (key.startsWith(XML_BINDING_KEY_PREFIX)) {
102         // First, we need to get the name of the binding
103         final String nsBindingName = getXmlBindingNameFromConfigKey(key);
104         // Once we have the name, we're able to retrieve the URI as well as the prefix
105         final String nsUri = (String) configProperties
106                 .get(XML_BINDING_KEY_PREFIX + nsBindingName + XML_BINDING_URI_SUFFIX);
107         final String nsPrefix = (String) configProperties
108                 .get(XML_BINDING_KEY_PREFIX + nsBindingName + XML_BINDING_PREFIX_SUFFIX);
109         // Check if URI and the prefix have valid values
110         if (isBlank(nsUri))
111           throw new ConfigurationException(format("No URI for namespace binding '%s' found", nsBindingName));
112         if (nsPrefix == null)
113           throw new ConfigurationException(format("No prefix for namespace binding '%s' found", nsBindingName));
114         // Add prefix & URI to the intermediate map
115         prefixToUri.put(nsPrefix, nsUri);
116       }
117     }
118 
119     xmlNSContext = new XmlNamespaceContext(prefixToUri);
120   }
121 
122   /**
123    * Get the name of an XML namespace binding by one of its configuration keys.
124    *
125    * @param key
126    *          the key name
127    * @return the XML namespace binding name
128    */
129   private static String getXmlBindingNameFromConfigKey(final String key) {
130     if (isBlank(key) || !key.startsWith(XML_BINDING_KEY_PREFIX))
131       throw new IllegalArgumentException(format("The given key '%s' is not part of a XML binding definition", key));
132     final String keyWithoutPrefix = key.substring(XML_BINDING_KEY_PREFIX.length());
133     return keyWithoutPrefix.substring(0, keyWithoutPrefix.indexOf("."));
134   }
135 
136   /**
137    * Return the value of the configuration property {@link CatalogUIAdapterConfiguration#KEY_XML_ROOT_ELEMENT_NAME}
138    */
139   public String getCatalogXmlRootElementName() {
140     return (String) configProperties.get(KEY_XML_ROOT_ELEMENT_NAME);
141   }
142 
143   /**
144    * Return the value of the configuration property {@link CatalogUIAdapterConfiguration#KEY_XML_ROOT_ELEMENT_NS_URI}
145    */
146   public String getCatalogXmlRootNamespace() {
147     return (String) configProperties.get(KEY_XML_ROOT_ELEMENT_NS_URI);
148   }
149 
150   /**
151    * Returns the XML namespace context that could be built out of the configuration.
152    */
153   public XmlNamespaceContext getXmlNamespaceContext() {
154     return xmlNSContext;
155   }
156 
157 }