KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jivesoftware > admin > AdminConsole


1 /**
2  * $RCSfile: AdminConsole.java,v $
3  * $Revision: 1.19 $
4  * $Date: 2005/03/25 01:36:32 $
5  *
6  * Copyright (C) 2004 Jive Software. All rights reserved.
7  *
8  * This software is published under the terms of the GNU Public License (GPL),
9  * a copy of which is included in this distribution.
10  */

11
12 package org.jivesoftware.admin;
13
14 import org.jivesoftware.util.ClassUtils;
15 import org.jivesoftware.util.Log;
16 import org.jivesoftware.messenger.XMPPServer;
17 import org.dom4j.Document;
18 import org.dom4j.Element;
19 import org.dom4j.DocumentFactory;
20 import org.dom4j.io.SAXReader;
21
22 import java.util.*;
23 import java.io.InputStream JavaDoc;
24 import java.net.URL JavaDoc;
25
26 /**
27  * A model for admin tab and sidebar info. This class loads in xml definitions of the
28  * data and produces an in-memory model.<p>
29  *
30  * This class loads its data from the <tt>admin-sidebar.xml</tt> file which is assumed
31  * to be in the main application jar file. In addition, it will load files from
32  * <tt>META-INF/admin-sidebar.xml</tt> if they're found. This allows developers to
33  * extend the functionality of the admin console to provide more options. See the main
34  * <tt>admin-sidebar.xml</tt> file for documentation of its format.
35  */

36 public class AdminConsole {
37
38     private static Element coreModel;
39     private static Map<String JavaDoc,Element> overrideModels;
40     private static Element generatedModel;
41
42     static {
43         init();
44     }
45
46     private static void init() {
47         overrideModels = new LinkedHashMap<String JavaDoc,Element>();
48         load();
49     }
50
51     /** Not instantiatable */
52     private AdminConsole() {
53     }
54
55     /**
56      * Adds XML stream to the tabs/sidebar model.
57      *
58      * @param name the name.
59      * @param in the XML input stream.
60      * @throws Exception if an error occurs when parsing the XML or adding it to the model.
61      */

62     public static void addModel(String JavaDoc name, InputStream JavaDoc in) throws Exception JavaDoc {
63         SAXReader saxReader = new SAXReader();
64         Document doc = saxReader.read(in);
65         addModel(name, (Element)doc.selectSingleNode("/adminconsole"));
66     }
67
68     /**
69      * Adds an &lt;adminconsole&gt; Element to the tabs/sidebar model.
70      *
71      * @param name the name.
72      * @param element the Element
73      * @throws Exception if an error occurs.
74      */

75     public static void addModel(String JavaDoc name, Element element) throws Exception JavaDoc {
76         overrideModels.put(name, element);
77         rebuildModel();
78     }
79
80     /**
81      * Removes an &lt;adminconsole&gt; Element from the tabs/sidebar model.
82      *
83      * @param name the name.
84      */

85     public static void removeModel(String JavaDoc name) {
86         overrideModels.remove(name);
87         rebuildModel();
88     }
89
90     /**
91      * Returns the name of the application.
92      */

93     public static String JavaDoc getAppName() {
94         Element appName = (Element)generatedModel.selectSingleNode("//adminconsole/global/appname");
95         if (appName != null) {
96             return appName.getText();
97         }
98         else {
99             return null;
100         }
101     }
102
103     /**
104      * Returns the URL of the main logo image for the admin console.
105      *
106      * @return the logo image.
107      */

108     public static String JavaDoc getLogoImage() {
109         Element globalLogoImage = (Element)generatedModel.selectSingleNode(
110                 "//adminconsole/global/logo-image");
111         if (globalLogoImage != null) {
112             return globalLogoImage.getText();
113         }
114         else {
115             return null;
116         }
117     }
118
119     /**
120      * Returns the URL of the login image for the admin console.
121      *
122      * @return the login image.
123      */

124     public static String JavaDoc getLoginLogoImage() {
125         Element globalLoginLogoImage = (Element)generatedModel.selectSingleNode(
126                 "//adminconsole/global/login-image");
127         if (globalLoginLogoImage != null) {
128             return globalLoginLogoImage.getText();
129         }
130         else {
131             return null;
132         }
133     }
134
135     /**
136      * Returns the version string displayed in the admin console.
137      *
138      * @return the version string.
139      */

140     public static String JavaDoc getVersionString() {
141         Element globalVersion = (Element)generatedModel.selectSingleNode(
142                 "//adminconsole/global/version");
143         if (globalVersion != null) {
144             return globalVersion.getText();
145         }
146         else {
147             // Default to the Jive Messenger version if none has been provided via XML.
148
XMPPServer xmppServer = XMPPServer.getInstance();
149             return xmppServer.getServerInfo().getVersion().getVersionString();
150         }
151     }
152
153     /**
154      * Returns the model. The model should be considered read-only.
155      *
156      * @return the model.
157      */

158     public static Element getModel() {
159         return generatedModel;
160     }
161
162     /**
163      * Convenience method to select an element from the model by its ID. If an
164      * element with a matching ID is not found, <tt>null</tt> will be returned.
165      *
166      * @param id the ID.
167      * @return the element.
168      */

169     public static Element getElemnetByID(String JavaDoc id) {
170         return (Element)generatedModel.selectSingleNode("//*[@id='" + id + "']");
171     }
172
173     private static void load() {
174         // Load the core model as the admin-sidebar.xml file from the classpath.
175
InputStream JavaDoc in = ClassUtils.getResourceAsStream("/admin-sidebar.xml");
176         if (in == null) {
177             Log.error("Failed to load admin-sidebar.xml file from Jive Messenger classes - admin "
178                     + "console will not work correctly.");
179             return;
180         }
181         try {
182             SAXReader saxReader = new SAXReader();
183             Document doc = saxReader.read(in);
184             coreModel = (Element)doc.selectSingleNode("/adminconsole");
185         }
186         catch (Exception JavaDoc e) {
187             Log.error("Failure when parsing main admin-sidebar.xml file", e);
188         }
189         try {
190             in.close();
191         }
192         catch (Exception JavaDoc ignored) {}
193
194         // Load other admin-sidebar.xml files from the classpath
195
ClassLoader JavaDoc[] classLoaders = getClassLoaders();
196         for (int i=0; i<classLoaders.length; i++) {
197             URL JavaDoc url = null;
198             try {
199                 if (classLoaders[i] != null) {
200                     Enumeration e = classLoaders[i].getResources("/META-INF/admin-sidebar.xml");
201                     while (e.hasMoreElements()) {
202                         url = (URL JavaDoc)e.nextElement();
203                         try {
204                             in = url.openStream();
205                             addModel("admin", in);
206                         }
207                         finally {
208                             try { if (in != null) { in.close(); } }
209                             catch (Exception JavaDoc ignored) {}
210                         }
211                     }
212                 }
213             }
214             catch (Exception JavaDoc e) {
215                 String JavaDoc msg = "Failed to load admin-sidebar.xml";
216                 if (url != null) {
217                     msg += " from resource: " + url.toString();
218                 }
219                 Log.warn(msg, e);
220             }
221         }
222         rebuildModel();
223     }
224
225     /**
226      * Rebuilds the generated model.
227      */

228     private static void rebuildModel() {
229         Document doc = DocumentFactory.getInstance().createDocument();
230         generatedModel = coreModel.createCopy();
231         doc.add(generatedModel);
232
233         // Add in all overrides.
234
for (Element element : overrideModels.values()) {
235             // See if global settings are overriden.
236
Element appName = (Element)element.selectSingleNode("//adminconsole/global/appname");
237             if (appName != null) {
238                 Element existingAppName = (Element)generatedModel.selectSingleNode(
239                         "//adminconsole/global/appname");
240                 existingAppName.setText(appName.getText());
241             }
242             Element appLogoImage = (Element)element.selectSingleNode("//adminconsole/global/logo-image");
243             if (appLogoImage != null) {
244                 Element existingLogoImage = (Element)generatedModel.selectSingleNode(
245                         "//adminconsole/global/logo-image");
246                 existingLogoImage.setText(appLogoImage.getText());
247             }
248             Element appLoginImage = (Element)element.selectSingleNode("//adminconsole/global/login-image");
249             if (appLoginImage != null) {
250                 Element existingLoginImage = (Element)generatedModel.selectSingleNode(
251                         "//adminconsole/global/login-image");
252                 existingLoginImage.setText(appLoginImage.getText());
253             }
254             Element appVersion = (Element)element.selectSingleNode("//adminconsole/global/version");
255             if (appVersion != null) {
256                 Element existingVersion = (Element)generatedModel.selectSingleNode(
257                         "//adminconsole/global/version");
258                 if (existingVersion != null) {
259                     existingVersion.setText(appVersion.getText());
260                 }
261                 else {
262                     ((Element)generatedModel.selectSingleNode(
263                             "//adminconsole/global")).add(appVersion.createCopy());
264                 }
265             }
266             // Tabs
267
for (Iterator i=element.selectNodes("//tab").iterator(); i.hasNext(); ) {
268                 Element tab = (Element)i.next();
269                 String JavaDoc id = tab.attributeValue("id");
270                 Element existingTab = getElemnetByID(id);
271                 // Simple case, there is no existing tab with the same id.
272
if (existingTab == null) {
273                     // Make sure that the URL on the tab is set. If not, default to the
274
// url of the first item.
275
if (tab.attributeValue("url") == null) {
276                         Element firstItem = (Element)tab.selectSingleNode(
277                                 "//item[@url]");
278                         if (firstItem != null) {
279                             tab.addAttribute("url", firstItem.attributeValue("url"));
280                         }
281                     }
282                     generatedModel.add(tab.createCopy());
283                 }
284                 // More complex case -- a tab with the same id already exists.
285
// In this case, we have to overrite only the difference between
286
// the two elements.
287
else {
288                     overrideTab(existingTab, tab);
289                 }
290             }
291         }
292     }
293
294     private static void overrideTab(Element tab, Element overrideTab) {
295         // Override name, url, description.
296
if (overrideTab.attributeValue("name") != null) {
297             tab.addAttribute("name", overrideTab.attributeValue("name"));
298         }
299         if (overrideTab.attributeValue("url") != null) {
300             tab.addAttribute("url", overrideTab.attributeValue("url"));
301         }
302         if (overrideTab.attributeValue("description") != null) {
303             tab.addAttribute("description", overrideTab.attributeValue("description"));
304         }
305         // Override sidebar items.
306
for (Iterator i=overrideTab.elementIterator(); i.hasNext(); ) {
307             Element sidebar = (Element)i.next();
308             String JavaDoc id = sidebar.attributeValue("id");
309             Element existingSidebar = getElemnetByID(id);
310             // Simple case, there is no existing sidebar with the same id.
311
if (existingSidebar == null) {
312                 tab.add(sidebar.createCopy());
313             }
314             // More complex case -- a sidebar with the same id already exists.
315
// In this case, we have to overrite only the difference between
316
// the two elements.
317
else {
318                 overrideSidebar(existingSidebar, sidebar);
319             }
320         }
321     }
322
323     private static void overrideSidebar(Element sidebar, Element overrideSidebar) {
324         // Override name.
325
if (overrideSidebar.attributeValue("name") != null) {
326             sidebar.addAttribute("name", overrideSidebar.attributeValue("name"));
327         }
328         // Override entries.
329
for (Iterator i=overrideSidebar.elementIterator(); i.hasNext(); ) {
330             Element entry = (Element)i.next();
331             String JavaDoc id = entry.attributeValue("id");
332             Element existingEntry = getElemnetByID(id);
333             // Simple case, there is no existing sidebar with the same id.
334
if (existingEntry == null) {
335                 sidebar.add(entry.createCopy());
336             }
337             // More complex case -- an entry with the same id already exists.
338
// In this case, we have to overrite only the difference between
339
// the two elements.
340
else {
341                 overrideEntry(existingEntry, entry);
342             }
343         }
344     }
345
346     private static void overrideEntry(Element entry, Element overrideEntry) {
347         // Override name.
348
if (overrideEntry.attributeValue("name") != null) {
349             entry.addAttribute("name", overrideEntry.attributeValue("name"));
350         }
351         if (overrideEntry.attributeValue("url") != null) {
352             entry.addAttribute("url", overrideEntry.attributeValue("url"));
353         }
354         if (overrideEntry.attributeValue("description") != null) {
355             entry.addAttribute("description", overrideEntry.attributeValue("description"));
356         }
357         // Override any sidebars contained in the entry.
358
for (Iterator i=overrideEntry.elementIterator(); i.hasNext(); ) {
359             Element sidebar = (Element)i.next();
360             String JavaDoc id = sidebar.attributeValue("id");
361             Element existingSidebar = getElemnetByID(id);
362             // Simple case, there is no existing sidebar with the same id.
363
if (existingSidebar == null) {
364                 entry.add(sidebar.createCopy());
365             }
366             // More complex case -- a sidebar with the same id already exists.
367
// In this case, we have to overrite only the difference between
368
// the two elements.
369
else {
370                 overrideSidebar(existingSidebar, sidebar);
371             }
372         }
373     }
374
375     /**
376      * Returns an array of class loaders to load resources from.
377      */

378     private static ClassLoader JavaDoc[] getClassLoaders() {
379         ClassLoader JavaDoc[] classLoaders = new ClassLoader JavaDoc[3];
380         classLoaders[0] = AdminConsole.class.getClass().getClassLoader();
381         classLoaders[1] = Thread.currentThread().getContextClassLoader();
382         classLoaders[2] = ClassLoader.getSystemClassLoader();
383         return classLoaders;
384     }
385 }
Popular Tags