1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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
83 if (config == null)
84 throw new NullPointerException("Configuration properties cannot be NULL");
85
86
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
92
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
139 if (rootElement == null)
140 throw new NullPointerException("Root element cannot be NULL");
141
142
143 final Element indexElement = rootElement.getChild("Index");
144
145
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
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
208 if (rootElement == null)
209 throw new NullPointerException("Root element cannot be NULL");
210
211
212 final Element backendElement = rootElement.getChild("Backend");
213
214
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 }