1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32 package org.osjava.sj.loader;
33
34
35 import java.io.File;
36 import java.io.FileInputStream;
37 import java.io.IOException;
38 import java.util.HashMap;
39 import java.util.Hashtable;
40 import java.util.Iterator;
41 import java.util.Map;
42 import java.util.Properties;
43
44 import javax.naming.Context;
45 import javax.naming.NamingException;
46
47 import org.osjava.sj.loader.convert.ConvertRegistry;
48 import org.osjava.sj.loader.convert.Converter;
49
50 import org.osjava.sj.loader.util.AbstractProperties;
51 import org.osjava.sj.loader.util.CustomProperties;
52 import org.osjava.sj.loader.util.IniProperties;
53 import org.osjava.sj.loader.util.Utils;
54 import org.osjava.sj.loader.util.XmlProperties;
55
56 /***
57 * Loads a .properties file into a JNDI server.
58 */
59 public class JndiLoader {
60
61
62 public static final String SIMPLE_DELIMITER = "org.osjava.sj.delimiter";
63
64
65 public static final String SIMPLE_SHARED = "org.osjava.sj.shared";
66
67
68 public static final String SIMPLE_COLON_REPLACE = "org.osjava.sj.colon.replace";
69
70 private static ConvertRegistry convertRegistry = new ConvertRegistry();
71
72 private Hashtable table = new Hashtable();
73
74 public JndiLoader() {
75 this.table.put(SIMPLE_DELIMITER, "/");
76 }
77
78 public JndiLoader(Hashtable env) {
79 if(!env.containsKey(SIMPLE_DELIMITER)) {
80 throw new IllegalArgumentException("The property "+SIMPLE_DELIMITER+" is mandatory. ");
81 }
82
83
84 this.table.put(SIMPLE_DELIMITER, env.get(SIMPLE_DELIMITER));
85
86 if(env.containsKey(SIMPLE_COLON_REPLACE)) {
87 this.table.put(SIMPLE_COLON_REPLACE, env.get(SIMPLE_COLON_REPLACE));
88 }
89
90 }
91
92 public void putParameter(String key, String value) {
93 table.put(key, value);
94 }
95
96 public String getParameter(String key) {
97 return (String) table.get(key);
98 }
99
100 /***
101 * Loads all .properties files in a directory into a context
102 */
103 public void loadDirectory(File directory, Context ctxt) throws NamingException, IOException {
104 loadDirectory(directory, ctxt, null, "");
105 }
106 public void loadDirectory(File directory, Context ctxt, Context parentCtxt, String ctxtName) throws NamingException, IOException {
107
108
109 if( !directory.isDirectory() ) {
110 throw new IllegalArgumentException("java.io.File parameter must be a directory. ["+directory+"]");
111 }
112
113 File[] files = directory.listFiles();
114 if(files == null) {
115
116 return;
117 }
118
119 for(int i=0; i<files.length; i++) {
120 File file = files[i];
121 String name = file.getName();
122
123 String colonReplace = (String) this.table.get(SIMPLE_COLON_REPLACE);
124 if(colonReplace != null) {
125 if(name.indexOf(colonReplace) != -1) {
126 name = Utils.replace( name, colonReplace, ":" );
127 }
128 }
129
130
131
132 if( file.isDirectory() ) {
133
134 if(name.equals(".svn") || name.equals("CVS")) {
135 continue;
136 }
137
138
139 Context tmpCtxt = ctxt.createSubcontext( name );
140 loadDirectory(file, tmpCtxt, ctxt, name);
141 } else {
142
143 String[] extensions = new String[] { ".properties", ".ini", ".xml" };
144 for(int j=0; j<extensions.length; j++) {
145 String extension = extensions[j];
146 if( file.getName().endsWith(extension) ) {
147
148 Context tmpCtxt = ctxt;
149 if(!file.getName().equals("default"+extension)) {
150 name = name.substring(0, name.length() - extension.length());
151
152 tmpCtxt = ctxt.createSubcontext( name );
153 parentCtxt = ctxt;
154 ctxtName = name;
155 }
156 load( loadFile(file), tmpCtxt, parentCtxt, ctxtName );
157 }
158 }
159 }
160 }
161
162 }
163
164 private Properties loadFile(File file) throws IOException {
165
166 AbstractProperties p = null;
167
168 if(file.getName().endsWith(".xml")) {
169 p = new XmlProperties();
170 } else
171 if(file.getName().endsWith(".ini")) {
172 p = new IniProperties();
173 } else {
174 p = new CustomProperties();
175 }
176
177 p.setDelimiter( (String) this.table.get(SIMPLE_DELIMITER) );
178
179 FileInputStream fin = null;
180 try {
181 fin = new FileInputStream(file);
182 p.load(fin);
183 return p;
184 } finally {
185 if(fin != null) fin.close();
186 }
187 }
188
189
190 /***
191 * Loads a properties object into a context.
192 */
193 public void load(Properties properties, Context ctxt) throws NamingException {
194 load(properties, ctxt, null, "");
195 }
196 public void load(Properties properties, Context ctxt, Context parentCtxt, String ctxtName) throws NamingException {
197
198
199 String delimiter = (String) this.table.get(SIMPLE_DELIMITER);
200 String typePostfix = delimiter + "type";
201
202
203
204
205
206
207
208 Map typeMap = new HashMap();
209 Iterator iterator = properties.keySet().iterator();
210 while(iterator.hasNext()) {
211 String key = (String) iterator.next();
212
213 if(key.equals("type") || key.endsWith( typePostfix )) {
214 Properties tmp = new Properties();
215 tmp.put( "type", properties.get(key) );
216 if( key.equals( "type" ) ) {
217 typeMap.put( "", tmp );
218 } else {
219 typeMap.put( key.substring(0, key.length() - typePostfix.length()), tmp );
220 }
221 }
222
223 }
224
225
226
227
228
229
230
231
232
233 iterator = properties.keySet().iterator();
234 while(iterator.hasNext()) {
235 String key = (String) iterator.next();
236 Object value = properties.get(key);
237
238 if(key.equals("type") || key.endsWith( typePostfix )) {
239 continue;
240 }
241
242 if(typeMap.containsKey(key)) {
243
244 ( (Properties) typeMap.get(key) ).put("", value);
245 continue;
246 }
247
248 if(key.indexOf(delimiter) != -1) {
249 String pathText = removeLastElement( key, delimiter );
250 String nodeText = getLastElement( key, delimiter );
251
252
253 if(typeMap.containsKey(pathText)) {
254
255 ( (Properties) typeMap.get(pathText) ).put(nodeText, value);
256 continue;
257 }
258 } else
259 if(typeMap.containsKey("")) {
260
261 ( (Properties) typeMap.get("") ).put(key, value);
262 continue;
263 }
264
265
266 jndiPut( ctxt, key, properties.get(key) );
267 }
268
269 Iterator typeIterator = typeMap.keySet().iterator();
270 while(typeIterator.hasNext()) {
271 String typeKey = (String) typeIterator.next();
272 Properties typeProperties = (Properties) typeMap.get(typeKey);
273
274 Object value = convert(typeProperties);
275
276 if(typeKey.equals("")) {
277 jndiPut( parentCtxt, ctxtName, value );
278 } else {
279 jndiPut( ctxt, typeKey, value );
280 }
281 }
282
283 }
284
285 private void jndiPut(Context ctxt, String key, Object value) throws NamingException {
286
287
288
289
290
291
292 String[] path = Utils.split( key, (String) this.table.get(SIMPLE_DELIMITER) );
293
294
295 int lastIndex = path.length - 1;
296
297
298 Context tmpCtxt = ctxt;
299
300 for(int i=0; i < lastIndex; i++) {
301 Object obj = tmpCtxt.lookup(path[i]);
302 if(obj == null) {
303
304 tmpCtxt = tmpCtxt.createSubcontext(path[i]);
305 } else
306 if(obj instanceof Context) {
307
308 tmpCtxt = (Context) obj;
309 } else {
310 throw new RuntimeException("Illegal node/branch clash. At branch value '"+path[i]+"' an Object was found: " +obj);
311 }
312 }
313
314 Object obj = tmpCtxt.lookup(path[lastIndex]);
315 if(obj instanceof Context) {
316 tmpCtxt.destroySubcontext(path[lastIndex]);
317 obj = null;
318 }
319 if(obj == null) {
320
321 tmpCtxt.bind( path[lastIndex], value );
322 } else {
323
324 tmpCtxt.rebind( path[lastIndex], value );
325 }
326 }
327
328 private static Object convert(Properties properties) {
329 String type = properties.getProperty("type");
330
331
332 String converterClassName = properties.getProperty("converter");
333 if(converterClassName != null) {
334 try {
335 Class converterClass = Class.forName( converterClassName );
336 Converter converter = (Converter) converterClass.newInstance();
337 return converter.convert(properties, type);
338 } catch(ClassNotFoundException cnfe) {
339 throw new RuntimeException("Unable to find class: "+converterClassName, cnfe);
340 } catch(IllegalAccessException ie) {
341 throw new RuntimeException("Unable to access class: "+type, ie);
342 } catch(InstantiationException ie) {
343 throw new RuntimeException("Unable to create Converter " + type + " via empty constructor. ", ie);
344 }
345 }
346
347
348
349 Converter converter = convertRegistry.getConverter(type);
350 if(converter != null) {
351 return converter.convert(properties, type);
352 }
353
354 return properties.get("");
355
356 }
357
358
359 private static String getLastElement( String str, String delimiter ) {
360 int idx = str.lastIndexOf(delimiter);
361 return str.substring(idx + 1);
362 }
363 private static String removeLastElement( String str, String delimiter ) {
364 int idx = str.lastIndexOf(delimiter);
365 return str.substring(0, idx);
366 }
367
368 }