KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sslexplorer > language > LanguagePackManager


1 /*
2  * SSL-Explorer
3  *
4  * Copyright (C) 2003-2006 3SP LTD. All Rights Reserved
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2 of
9  * the License, or (at your option) any later version.
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public
16  * License along with this program; if not, write to the Free Software
17  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */

19             
20 package com.sslexplorer.language;
21
22 import java.io.File JavaDoc;
23 import java.io.FileInputStream JavaDoc;
24 import java.io.IOException JavaDoc;
25 import java.io.InputStream JavaDoc;
26 import java.net.URL JavaDoc;
27 import java.util.ArrayList JavaDoc;
28 import java.util.Collections JavaDoc;
29 import java.util.HashMap JavaDoc;
30 import java.util.Hashtable JavaDoc;
31 import java.util.Iterator JavaDoc;
32 import java.util.List JavaDoc;
33 import java.util.Map JavaDoc;
34 import java.util.zip.ZipEntry JavaDoc;
35 import java.util.zip.ZipInputStream JavaDoc;
36
37 import org.apache.commons.logging.Log;
38 import org.apache.commons.logging.LogFactory;
39
40 import com.sslexplorer.boot.ContextHolder;
41 import com.sslexplorer.boot.Util;
42
43 /**
44  * Singleton responsible for managing registered <i>Language Packs</i> and
45  * translation categories.
46  * <p>
47  * Internally, two lists of categories are maintained, one from resources called
48  * <i>ApplicationResources.properties</i> automatically detected via the class
49  * path and two from those registered via
50  * {@link #registerCategory(LanguageCategory)}.
51  *
52  * @author Brett Smith <a HREF="mailto: brett@3sp.com">&lt;brett@3sp.com&gt;</a>
53  * @see LanguagePackDefinition
54  * @see LanguageCategory
55  */

56 public class LanguagePackManager {
57
58     final static Log log = LogFactory.getLog(LanguagePackManager.class);
59
60     // Private instance variables
61
private Map JavaDoc<String JavaDoc, LanguagePackDefinition> languagePackDefinitions;
62     private List JavaDoc<LanguageCategory> detectedCategories;
63     private Hashtable JavaDoc<String JavaDoc, LanguageCategory> detectedHaCategories;
64     private List JavaDoc<LanguageCategory> categories;
65     private Hashtable JavaDoc<String JavaDoc, LanguageCategory> haCategories;
66     private URL JavaDoc[] classpath;
67
68     // Private statics
69
private static LanguagePackManager instance;
70
71     /**
72      * Although this call is used as a singleton, it has this package
73      * protected constructor for junit tests.
74      */

75     public LanguagePackManager() {
76         super();
77         languagePackDefinitions = new HashMap JavaDoc<String JavaDoc, LanguagePackDefinition>();
78         categories = new ArrayList JavaDoc<LanguageCategory>();
79         haCategories = new Hashtable JavaDoc<String JavaDoc, LanguageCategory>();
80     }
81
82     /**
83      * Register a new category. This will always be available regardless of
84      * whether or not it is found on the classpath. This can be used by plugins
85      * to add categories for resource files that do not use the SSL-Explorer
86      * wide <i>ApplicationResources.properties</i> resource name (e.g.
87      * resources for audit reports).
88      *
89      * @param category category
90      */

91     public void registerCategory(LanguageCategory category) {
92         categories.add(category);
93         haCategories.put(category.getId(), category);
94     }
95
96     /**
97      * Add a new language pack definition
98      *
99      * @param def language pack definition
100      */

101     public void addLanguagePackDefinition(LanguagePackDefinition def) {
102         log.info("Adding new language pack '" + def.getName() + "'");
103         if (def.getExtensionDescriptor() != null) {
104             log.info("Pack requires host version " + def.getExtensionDescriptor().getApplicationBundle().getRequiredHostVersion());
105         }
106         languagePackDefinitions.put(def.getName(), def);
107     }
108
109     /**
110      * Remove a language pack definition
111      *
112      * @param def language pack definition
113      */

114     public void removeLanguagePack(LanguagePackDefinition def) {
115         log.info("Removing language pack '" + def.getName() + "'");
116         languagePackDefinitions.remove(def.getName());
117     }
118
119     /**
120      * Get an instance of the language manager.
121      *
122      * @return language manager
123      */

124     public static LanguagePackManager getInstance() {
125         if (instance == null) {
126             instance = new LanguagePackManager();
127         }
128         return instance;
129     }
130
131     /**
132      * Get an iteration of all available {@link LanguagePackDefinition} objects
133      * registered.
134      *
135      * @return registered language pack definitions
136      */

137     public Iterator JavaDoc packDefinitions() {
138         return languagePackDefinitions.values().iterator();
139     }
140
141     /**
142      * Get an iteration of all available {@link Language} objects
143      *
144      * @return languagePackDefinitions
145      */

146     public Iterator JavaDoc languages() {
147         List JavaDoc<Language> l = new ArrayList JavaDoc<Language>();
148         for (Iterator JavaDoc i = languagePackDefinitions.values().iterator(); i.hasNext();) {
149             LanguagePackDefinition def = (LanguagePackDefinition) i.next();
150             for (Iterator JavaDoc j = def.languages(); j.hasNext();) {
151                 Language lang = (Language) j.next();
152                 if (!l.contains(lang)) {
153                     l.add(lang);
154                 }
155             }
156         }
157         Collections.sort(l);
158         return l.iterator();
159     }
160
161     /**
162      * Get all internationalisation categories. This includes all categories
163      * registered using {@link #registerCategory(LanguageCategory)} and all
164      * those found by looking for ApplicationResources.properties files in the
165      * classpath.
166      * <p>
167      * This method returns a list of objects of type {@link LanguageCategory}.
168      * <p>
169      * The first call to this method may take some time as all JARS and class
170      * directories will be scanned.
171      *
172      * @return language category object
173      * @throws IOException
174      */

175     public List JavaDoc<LanguageCategory> getCategories() throws IOException JavaDoc {
176         checkCategories();
177         List JavaDoc<LanguageCategory> l = new ArrayList JavaDoc<LanguageCategory>();
178         l.addAll(detectedCategories);
179         l.addAll(categories);
180         return l;
181     }
182
183     synchronized void checkCategories() throws IOException JavaDoc {
184         boolean classpathChanged = false;
185         if (classpath != null) {
186             URL JavaDoc[] newClasspath = ContextHolder.getContext().getContextLoaderClassPath();
187             if (classpathDiffer(classpath, newClasspath)) {
188                 classpath = newClasspath;
189                 classpathChanged = true;
190             }
191         } else {
192             classpath = ContextHolder.getContext().getContextLoaderClassPath();
193         }
194         if (detectedCategories == null || classpathChanged) {
195             log.info("Scanning classpath for default message resources");
196             detectedCategories = new ArrayList JavaDoc<LanguageCategory>();
197             detectedHaCategories = new Hashtable JavaDoc<String JavaDoc, LanguageCategory>();
198             for (int i = 0; i < classpath.length; i++) {
199                 log.debug("Scanning " + classpath[i]);
200                 if (classpath[i].getProtocol().equals("file")) {
201                     if (classpath[i].getPath().endsWith(".jar")) {
202                         addFileJarCategory(classpath[i]);
203                     } else {
204                         addFileDirectoryCategory(classpath[i]);
205                     }
206                 }
207             }
208         }
209     }
210
211     boolean classpathDiffer(URL JavaDoc[] classpath, URL JavaDoc[] newClasspath) {
212         if (classpath.length != newClasspath.length) {
213             return true;
214         }
215         for (int i = 0; i < classpath.length; i++) {
216             if (!classpath[i].equals(newClasspath[i])) {
217                 return true;
218             }
219         }
220         return false;
221     }
222
223     /**
224      * Get all internationalisation categories. This includes all categories
225      * registered using {@link #registerCategory(LanguageCategory)} and all
226      * those found by looking for ApplicationResources.properties files in the
227      * classpath.
228      * <p>
229      * This method returns a Hashtable of objects of type
230      * {@link LanguageCategory}.
231      * <p>
232      * The first call to this method may take some time as all JARS and class
233      * directories will be scanned.
234      *
235      * @return language category object
236      * @throws IOException
237      */

238     public Hashtable JavaDoc getHaCategories() throws IOException JavaDoc {
239         checkCategories();
240         Hashtable JavaDoc<String JavaDoc, LanguageCategory> all = new Hashtable JavaDoc<String JavaDoc, LanguageCategory>();
241         all.putAll(detectedHaCategories);
242         all.putAll(haCategories);
243         return all;
244     }
245     
246     void addFileDirectoryCategory(URL JavaDoc url) throws IOException JavaDoc {
247         File JavaDoc p = new File JavaDoc(url.getPath());
248         List JavaDoc<File JavaDoc> files = new ArrayList JavaDoc<File JavaDoc>();
249         findFile(p, "ApplicationResources.properties", files);
250         for (Iterator JavaDoc it = files.iterator(); it.hasNext();) {
251             File JavaDoc f = (File JavaDoc) it.next();
252             String JavaDoc path = f.getAbsolutePath().substring(p.getAbsolutePath().length() + 1).replace("\\", "/");
253             InputStream JavaDoc in = null;
254             try {
255                 String JavaDoc name = path;
256                 String JavaDoc resourceBundleId = path;
257                 int idx = name.lastIndexOf('/');
258                 if (idx != -1) {
259                     resourceBundleId = name.substring(0, idx).replace('/', '.');
260                     name = name.substring(idx + 1);
261                 }
262                 in = new FileInputStream JavaDoc(f);
263                 LanguageCategory category = new LanguageCategory(in, url, path, resourceBundleId);
264                 if (!detectedHaCategories.containsKey(category.getId())) {
265                     detectedCategories.add(category);
266                     detectedHaCategories.put(category.getId(), category);
267                 }
268             }
269             finally {
270                 Util.closeStream(in);
271             }
272         }
273         
274     }
275     
276     void addFileJarCategory(URL JavaDoc url) throws IOException JavaDoc {
277
278         InputStream JavaDoc in = null;
279         try {
280             File JavaDoc f = new File JavaDoc(url.getPath());
281             if (!f.exists()) {
282                 return;
283             }
284             in = new FileInputStream JavaDoc(url.getPath());
285             ZipInputStream JavaDoc zin = new ZipInputStream JavaDoc(in);
286             while (true) {
287                 ZipEntry JavaDoc entry = zin.getNextEntry();
288                 if (entry == null) {
289                     break;
290                 }
291                 String JavaDoc path = entry.getName();
292                 String JavaDoc name = path;
293                 String JavaDoc resourceBundleId = path;
294                 int idx = name.lastIndexOf('/');
295                 if (idx != -1) {
296                     resourceBundleId = name.substring(0, idx).replace('/', '.');
297                     ;
298                     name = name.substring(idx + 1);
299                 }
300                 if (name.equals("ApplicationResources.properties")) {
301                     LanguageCategory category = new LanguageCategory(zin, url, path, resourceBundleId);
302                     if (!detectedHaCategories.containsKey(category.getId())) {
303                         detectedCategories.add(category);
304                         detectedHaCategories.put(category.getId(), category);
305                     }
306                 }
307             }
308         } finally {
309             Util.closeStream(in);
310         }
311         
312     }
313
314     /**
315      * Get a language pack given its name (e.g. sslexplorer-language-fr).
316      * <code>null</code> will be returned if no such language pack exists.
317      *
318      * @param name name
319      * @return language pack
320      */

321     public LanguagePackDefinition getLanguagePack(String JavaDoc name) {
322         return (LanguagePackDefinition)languagePackDefinitions.get(name);
323     }
324
325     void findFile(File JavaDoc dir, String JavaDoc name, List JavaDoc<File JavaDoc> files) {
326         File JavaDoc[] l = dir.listFiles();
327         for (int i = 0; l != null && i < l.length; i++) {
328             if (l[i].isDirectory()) {
329                 findFile(l[i], name, files);
330             } else if (l[i].isFile() && l[i].getName().equals(name)) {
331                 files.add(l[i]);
332             }
333         }
334     }
335 }
336
Popular Tags