View Javadoc

1   /*
2    * Copyright (c) 2004 UNINETT FAS
3    *
4    * This program is free software; you can redistribute it and/or modify it
5    * under the terms of the GNU General Public License as published by the Free
6    * Software Foundation; either version 2 of the License, or (at your option)
7    * any later version.
8    *
9    * This program is distributed in the hope that it will be useful, but WITHOUT
10   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11   * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12   * more details.
13   *
14   * You should have received a copy of the GNU General Public License along with
15   * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
16   * Place - Suite 330, Boston, MA 02111-1307, USA.
17   *
18   */
19  
20  package no.feide.moria.directory;
21  
22  import java.io.File;
23  import java.io.IOException;
24  import java.util.Properties;
25  import org.jdom.Attribute;
26  import org.jdom.Element;
27  import org.jdom.JDOMException;
28  import org.jdom.input.SAXBuilder;
29  
30  /***
31   * Configuration handler for the Directory Manager. Parses the configuration
32   * file.
33   */
34  public class DirectoryManagerConfiguration {
35  
36      /*** The location of the index file. */
37      private String indexFilename;
38  
39      /*** The index update frequency, in milliseconds. */
40      private long indexUpdateFrequency;
41  
42      /*** Internal representation of the backend class. */
43      private Class backendFactoryClass;
44  
45      /*** Internal representation of the backend configuration file structure. */
46      private Element backendConfiguration = null;
47  
48      /***
49       * The required configuration file property, for external reference.
50       * Currently contains the value
51       * <code>no.feide.moria.directory.configuration</code>.
52       */
53      public static final String CONFIGURATION_PROPERTY = "no.feide.moria.directory.configuration";
54  
55  
56      /***
57       * Constructor. Creates a new configuration object and reads the Directory
58       * Manager configuration file. <br>
59       * <br>
60       * Note that the actual parsing of the configuration file is done by
61       * <code>parseIndexConfig(Element)</code> and
62       * <code>parseBackendConfig(Element)</code>.
63       * @param config
64       *            The Directory Manager configuration passed on from
65       *            <code>DirectoryManager.setConfig(Properties)</code>. Must
66       *            include the property given by
67       *            <code>DirectoryManagerConfiguration.CONFIGURATION_PROPERTY</code>.
68       * @throws NullPointerException
69       *             If <code>config</code> is <code>null</code>.
70       * @throws DirectoryManagerConfigurationException
71       *             If the property given by
72       *             <code>DirectoryManagerConfiguration.CONFIGURATION_PROPERTY</code>
73       *             is not set or is an empty string. Also thrown if unable to
74       *             read from or parse the configuration file.
75       * @see DirectoryManager#setConfig(Properties)
76       * @see #CONFIGURATION_PROPERTY
77       * @see #parseBackendConfig(Element)
78       * @see #parseIndexConfig(Element)
79       */
80      public DirectoryManagerConfiguration(final Properties config) {
81  
82          // Sanity check.
83          if (config == null)
84              throw new NullPointerException("Configuration properties cannot be NULL");
85  
86          // Preparing to read configuration from file.
87          final String configFile = (String) config.get(CONFIGURATION_PROPERTY);
88          if (configFile == null || configFile.equals(""))
89              throw new DirectoryManagerConfigurationException("Property " + DirectoryManagerConfiguration.CONFIGURATION_PROPERTY + " not set)");
90  
91          // Read index (not the index files themselves, mind you) and backend
92          // configuration.
93          Element rootElement = null;
94          try {
95              rootElement = (new SAXBuilder()).build(new File(configFile)).getRootElement();
96          } catch (IOException e) {
97              throw new DirectoryManagerConfigurationException("Unable to read from configuration file \"" + configFile + '\"', e);
98          } catch (JDOMException e) {
99              throw new DirectoryManagerConfigurationException("Unable to parse configuration file \"" + configFile + '\"', e);
100         }
101         parseIndexConfig(rootElement);
102         backendConfiguration = parseBackendConfig(rootElement);
103 
104     }
105 
106 
107     /***
108      * Gets the backend configuration element.
109      * @return A copy of the backend configuration element, as per
110      *         <code>Element.clone()</code>.
111      * @see Element#clone()
112      */
113     public final Element getBackendElement() {
114 
115         return (Element) backendConfiguration.clone();
116 
117     }
118 
119 
120     /***
121      * Parses the subsection of the configuration file related to the index and
122      * updates the configuration. <br>
123      * <br>
124      * If more than one <code>Index</code> element is found, only the first is
125      * considered.
126      * @param rootElement
127      *            The root configuration element. Cannot be <code>null</code>.
128      * @throws NullPointerException
129      *             If <code>rootElement</code> is <code>null</code>.
130      * @throws DirectoryManagerConfigurationException
131      *             If index file (attribute <code>file</code> in element
132      *             <code>Index</code>) is not set, or if index update
133      *             frequency (attribute <code>update</code> in element
134      *             <code>Index</code>) is not set or is less than zero.
135      */
136     private void parseIndexConfig(final Element rootElement) {
137 
138         // Sanity check.
139         if (rootElement == null)
140             throw new NullPointerException("Root element cannot be NULL");
141 
142         // Get the index element, with sanity checks.
143         final Element indexElement = rootElement.getChild("Index");
144 
145         // Get index filename, with sanity checks.
146         Attribute a = indexElement.getAttribute("file");
147         if ((a == null) || (a.getValue() == null) || (a.getValue().equals("")))
148             throw new DirectoryManagerConfigurationException("Index file not set in configuration file");
149         indexFilename = a.getValue();
150 
151         // Get index update frequency, with sanity checks.
152         a = indexElement.getAttribute("update");
153         if ((a == null) || (a.getValue() == null) || (a.getValue().equals("")))
154             throw new DirectoryManagerConfigurationException("Index update frequency not set in configuration file");
155         indexUpdateFrequency = 1000 * Integer.parseInt(a.getValue());
156         if (indexUpdateFrequency <= 0)
157             throw new DirectoryManagerConfigurationException("Index update frequency must be greater than zero");
158 
159     }
160 
161 
162     /***
163      * Gets the serialized index file name.
164      * @return The index file name.
165      */
166     public final String getIndexFilename() {
167 
168         return indexFilename;
169 
170     }
171 
172 
173     /***
174      * Gets the index update frequency.
175      * @return The index update frequency, in milliseconds.
176      */
177     public final long getIndexUpdateFrequency() {
178 
179         return indexUpdateFrequency;
180 
181     }
182 
183 
184     /***
185      * Parses the subsection of the configuration file common to all backend
186      * implementations and updates the configuration. <br>
187      * <br>
188      * This method will only consider the attribute <code>class</code> in the
189      * <code>Backend</code> element; further parsing of the element is left to
190      * the backend implementation. If more than one <code>Backend</code>
191      * element is found, only the first is considered.
192      * @param rootElement
193      *            The root configuration element. Cannot be <code>null</code>.
194      * @return The backend configuration element, as per
195      *         <code>Element.clone()</code>.
196      * @throws NullPointerException
197      *             If <code>rootElement</code> is <code>null</code>.
198      * @throws DirectoryManagerConfigurationException
199      *             If backend factory class (attribute <code>class</code> in
200      *             element <code>Backend</code>) is not set, or if the given
201      *             backend factory class cannot be resolved.
202      * @see Element#clone()
203      * @see no.feide.moria.directory.backend.DirectoryManagerBackendFactory#setConfig(Element)
204      */
205     private Element parseBackendConfig(final Element rootElement) {
206 
207         // Sanity check.
208         if (rootElement == null)
209             throw new NullPointerException("Root element cannot be NULL");
210 
211         // Get the backend element, with sanity checks.
212         final Element backendElement = rootElement.getChild("Backend");
213 
214         // Get backend class, with sanity checks.
215         final Attribute a = backendElement.getAttribute("class");
216         if ((a == null) || (a.getValue() == null) || (a.getValue().equals("")))
217             throw new DirectoryManagerConfigurationException("Backend class not set in configuration file");
218         try {
219             backendFactoryClass = Class.forName(a.getValue());
220         } catch (ClassNotFoundException e) {
221             throw new DirectoryManagerConfigurationException("Backend factory class " + a.getValue() + " not found", e);
222         }
223 
224         return (Element) backendElement.clone();
225 
226     }
227 
228 
229     /***
230      * Gets the backend factory class implementation.
231      * @return The backend factory class.
232      */
233     public final Class getBackendFactoryClass() {
234 
235         return backendFactoryClass;
236 
237     }
238 
239 }