KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > log4j > helpers > OptionConverter


1 /*
2  * Copyright 1999-2005 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.apache.log4j.helpers;
18
19 import java.util.Properties JavaDoc;
20 import java.net.URL JavaDoc;
21 import org.apache.log4j.Level;
22 import org.apache.log4j.spi.Configurator;
23 import org.apache.log4j.spi.LoggerRepository;
24 import org.apache.log4j.PropertyConfigurator;
25
26 // Contributors: Avy Sharell (sharell@online.fr)
27
// Matthieu Verbert (mve@zurich.ibm.com)
28
// Colin Sampaleanu
29

30 /**
31    A convenience class to convert property values to specific types.
32
33    @author Ceki Gülcü
34    @author Simon Kitching;
35    @author Anders Kristensen
36 */

37 public class OptionConverter {
38
39   static String JavaDoc DELIM_START = "${";
40   static char DELIM_STOP = '}';
41   static int DELIM_START_LEN = 2;
42   static int DELIM_STOP_LEN = 1;
43
44   /** OptionConverter is a static class. */
45   private OptionConverter() {}
46
47   public
48   static
49   String JavaDoc[] concatanateArrays(String JavaDoc[] l, String JavaDoc[] r) {
50     int len = l.length + r.length;
51     String JavaDoc[] a = new String JavaDoc[len];
52
53     System.arraycopy(l, 0, a, 0, l.length);
54     System.arraycopy(r, 0, a, l.length, r.length);
55
56     return a;
57   }
58
59   public
60   static
61   String JavaDoc convertSpecialChars(String JavaDoc s) {
62     char c;
63     int len = s.length();
64     StringBuffer JavaDoc sbuf = new StringBuffer JavaDoc(len);
65
66     int i = 0;
67     while(i < len) {
68       c = s.charAt(i++);
69       if (c == '\\') {
70     c = s.charAt(i++);
71     if(c == 'n') c = '\n';
72     else if(c == 'r') c = '\r';
73     else if(c == 't') c = '\t';
74     else if(c == 'f') c = '\f';
75     else if(c == '\b') c = '\b';
76     else if(c == '\"') c = '\"';
77     else if(c == '\'') c = '\'';
78     else if(c == '\\') c = '\\';
79       }
80       sbuf.append(c);
81     }
82     return sbuf.toString();
83   }
84
85
86   /**
87      Very similar to <code>System.getProperty</code> except
88      that the {@link SecurityException} is hidden.
89
90      @param key The key to search for.
91      @param def The default value to return.
92      @return the string value of the system property, or the default
93      value if there is no property with that key.
94
95      @since 1.1 */

96   public
97   static
98   String JavaDoc getSystemProperty(String JavaDoc key, String JavaDoc def) {
99     try {
100       return System.getProperty(key, def);
101     } catch(Throwable JavaDoc e) { // MS-Java throws com.ms.security.SecurityExceptionEx
102
LogLog.debug("Was not allowed to read system property \""+key+"\".");
103       return def;
104     }
105   }
106
107
108   public
109   static
110   Object JavaDoc instantiateByKey(Properties JavaDoc props, String JavaDoc key, Class JavaDoc superClass,
111                 Object JavaDoc defaultValue) {
112
113     // Get the value of the property in string form
114
String JavaDoc className = findAndSubst(key, props);
115     if(className == null) {
116       LogLog.error("Could not find value for key " + key);
117       return defaultValue;
118     }
119     // Trim className to avoid trailing spaces that cause problems.
120
return OptionConverter.instantiateByClassName(className.trim(), superClass,
121                           defaultValue);
122   }
123
124   /**
125      If <code>value</code> is "true", then <code>true</code> is
126      returned. If <code>value</code> is "false", then
127      <code>true</code> is returned. Otherwise, <code>default</code> is
128      returned.
129
130      <p>Case of value is unimportant. */

131   public
132   static
133   boolean toBoolean(String JavaDoc value, boolean dEfault) {
134     if(value == null)
135       return dEfault;
136     String JavaDoc trimmedVal = value.trim();
137     if("true".equalsIgnoreCase(trimmedVal))
138       return true;
139     if("false".equalsIgnoreCase(trimmedVal))
140       return false;
141     return dEfault;
142   }
143
144   public
145   static
146   int toInt(String JavaDoc value, int dEfault) {
147     if(value != null) {
148       String JavaDoc s = value.trim();
149       try {
150     return Integer.valueOf(s).intValue();
151       }
152       catch (NumberFormatException JavaDoc e) {
153      LogLog.error("[" + s + "] is not in proper int form.");
154     e.printStackTrace();
155       }
156     }
157     return dEfault;
158   }
159
160   /**
161      Converts a standard or custom priority level to a Level
162      object. <p> If <code>value</code> is of form
163      "level#classname", then the specified class' toLevel method
164      is called to process the specified level string; if no '#'
165      character is present, then the default {@link org.apache.log4j.Level}
166      class is used to process the level value.
167
168      <p>As a special case, if the <code>value</code> parameter is
169      equal to the string "NULL", then the value <code>null</code> will
170      be returned.
171
172      <p> If any error occurs while converting the value to a level,
173      the <code>defaultValue</code> parameter, which may be
174      <code>null</code>, is returned.
175
176      <p> Case of <code>value</code> is insignificant for the level level, but is
177      significant for the class name part, if present.
178
179      @since 1.1 */

180   public
181   static
182   Level toLevel(String JavaDoc value, Level defaultValue) {
183     if(value == null)
184       return defaultValue;
185
186     int hashIndex = value.indexOf('#');
187     if (hashIndex == -1) {
188       if("NULL".equalsIgnoreCase(value)) {
189     return null;
190       } else {
191     // no class name specified : use standard Level class
192
return(Level) Level.toLevel(value, defaultValue);
193       }
194     }
195
196     Level result = defaultValue;
197
198     String JavaDoc clazz = value.substring(hashIndex+1);
199     String JavaDoc levelName = value.substring(0, hashIndex);
200
201     // This is degenerate case but you never know.
202
if("NULL".equalsIgnoreCase(levelName)) {
203     return null;
204     }
205
206     LogLog.debug("toLevel" + ":class=[" + clazz + "]"
207          + ":pri=[" + levelName + "]");
208
209     try {
210       Class JavaDoc customLevel = Loader.loadClass(clazz);
211
212       // get a ref to the specified class' static method
213
// toLevel(String, org.apache.log4j.Level)
214
Class JavaDoc[] paramTypes = new Class JavaDoc[] { String JavaDoc.class,
215                      org.apache.log4j.Level.class
216                                        };
217       java.lang.reflect.Method JavaDoc toLevelMethod =
218                       customLevel.getMethod("toLevel", paramTypes);
219
220       // now call the toLevel method, passing level string + default
221
Object JavaDoc[] params = new Object JavaDoc[] {levelName, defaultValue};
222       Object JavaDoc o = toLevelMethod.invoke(null, params);
223
224       result = (Level) o;
225     } catch(ClassNotFoundException JavaDoc e) {
226       LogLog.warn("custom level class [" + clazz + "] not found.");
227     } catch(NoSuchMethodException JavaDoc e) {
228       LogLog.warn("custom level class [" + clazz + "]"
229         + " does not have a constructor which takes one string parameter", e);
230     } catch(java.lang.reflect.InvocationTargetException JavaDoc e) {
231       LogLog.warn("custom level class [" + clazz + "]"
232            + " could not be instantiated", e);
233     } catch(ClassCastException JavaDoc e) {
234       LogLog.warn("class [" + clazz
235         + "] is not a subclass of org.apache.log4j.Level", e);
236     } catch(IllegalAccessException JavaDoc e) {
237       LogLog.warn("class ["+clazz+
238            "] cannot be instantiated due to access restrictions", e);
239     } catch(Exception JavaDoc e) {
240       LogLog.warn("class ["+clazz+"], level ["+levelName+
241            "] conversion failed.", e);
242     }
243     return result;
244    }
245
246   public
247   static
248   long toFileSize(String JavaDoc value, long dEfault) {
249     if(value == null)
250       return dEfault;
251
252     String JavaDoc s = value.trim().toUpperCase();
253     long multiplier = 1;
254     int index;
255
256     if((index = s.indexOf("KB")) != -1) {
257       multiplier = 1024;
258       s = s.substring(0, index);
259     }
260     else if((index = s.indexOf("MB")) != -1) {
261       multiplier = 1024*1024;
262       s = s.substring(0, index);
263     }
264     else if((index = s.indexOf("GB")) != -1) {
265       multiplier = 1024*1024*1024;
266       s = s.substring(0, index);
267     }
268     if(s != null) {
269       try {
270     return Long.valueOf(s).longValue() * multiplier;
271       }
272       catch (NumberFormatException JavaDoc e) {
273     LogLog.error("[" + s + "] is not in proper int form.");
274     LogLog.error("[" + value + "] not in expected format.", e);
275       }
276     }
277     return dEfault;
278   }
279
280   /**
281      Find the value corresponding to <code>key</code> in
282      <code>props</code>. Then perform variable substitution on the
283      found value.
284
285  */

286   public
287   static
288   String JavaDoc findAndSubst(String JavaDoc key, Properties JavaDoc props) {
289     String JavaDoc value = props.getProperty(key);
290     if(value == null)
291       return null;
292
293     try {
294       return substVars(value, props);
295     } catch(IllegalArgumentException JavaDoc e) {
296       LogLog.error("Bad option value ["+value+"].", e);
297       return value;
298     }
299   }
300
301   /**
302      Instantiate an object given a class name. Check that the
303      <code>className</code> is a subclass of
304      <code>superClass</code>. If that test fails or the object could
305      not be instantiated, then <code>defaultValue</code> is returned.
306
307      @param className The fully qualified class name of the object to instantiate.
308      @param superClass The class to which the new object should belong.
309      @param defaultValue The object to return in case of non-fulfillment
310    */

311   public
312   static
313   Object JavaDoc instantiateByClassName(String JavaDoc className, Class JavaDoc superClass,
314                 Object JavaDoc defaultValue) {
315     if(className != null) {
316       try {
317     Class JavaDoc classObj = Loader.loadClass(className);
318     if(!superClass.isAssignableFrom(classObj)) {
319       LogLog.error("A \""+className+"\" object is not assignable to a \""+
320                superClass.getName() + "\" variable.");
321       LogLog.error("The class \""+ superClass.getName()+"\" was loaded by ");
322       LogLog.error("["+superClass.getClassLoader()+"] whereas object of type ");
323       LogLog.error("\"" +classObj.getName()+"\" was loaded by ["
324                +classObj.getClassLoader()+"].");
325       return defaultValue;
326     }
327     return classObj.newInstance();
328       } catch (Exception JavaDoc e) {
329     LogLog.error("Could not instantiate class [" + className + "].", e);
330       }
331     }
332     return defaultValue;
333   }
334
335
336   /**
337      Perform variable substitution in string <code>val</code> from the
338      values of keys found in the system propeties.
339
340      <p>The variable substitution delimeters are <b>${</b> and <b>}</b>.
341
342      <p>For example, if the System properties contains "key=value", then
343      the call
344      <pre>
345      String s = OptionConverter.substituteVars("Value of key is ${key}.");
346      </pre>
347
348      will set the variable <code>s</code> to "Value of key is value.".
349
350      <p>If no value could be found for the specified key, then the
351      <code>props</code> parameter is searched, if the value could not
352      be found there, then substitution defaults to the empty string.
353
354      <p>For example, if system propeties contains no value for the key
355      "inexistentKey", then the call
356
357      <pre>
358      String s = OptionConverter.subsVars("Value of inexistentKey is [${inexistentKey}]");
359      </pre>
360      will set <code>s</code> to "Value of inexistentKey is []"
361
362      <p>An {@link java.lang.IllegalArgumentException} is thrown if
363      <code>val</code> contains a start delimeter "${" which is not
364      balanced by a stop delimeter "}". </p>
365
366      <p><b>Author</b> Avy Sharell</a></p>
367
368      @param val The string on which variable substitution is performed.
369      @throws IllegalArgumentException if <code>val</code> is malformed.
370
371   */

372   public static
373   String JavaDoc substVars(String JavaDoc val, Properties JavaDoc props) throws
374                         IllegalArgumentException JavaDoc {
375
376     StringBuffer JavaDoc sbuf = new StringBuffer JavaDoc();
377
378     int i = 0;
379     int j, k;
380
381     while(true) {
382       j=val.indexOf(DELIM_START, i);
383       if(j == -1) {
384     // no more variables
385
if(i==0) { // this is a simple string
386
return val;
387     } else { // add the tail string which contails no variables and return the result.
388
sbuf.append(val.substring(i, val.length()));
389       return sbuf.toString();
390     }
391       } else {
392     sbuf.append(val.substring(i, j));
393     k = val.indexOf(DELIM_STOP, j);
394     if(k == -1) {
395       throw new IllegalArgumentException JavaDoc('"'+val+
396               "\" has no closing brace. Opening brace at position " + j
397                          + '.');
398     } else {
399       j += DELIM_START_LEN;
400       String JavaDoc key = val.substring(j, k);
401       // first try in System properties
402
String JavaDoc replacement = getSystemProperty(key, null);
403       // then try props parameter
404
if(replacement == null && props != null) {
405         replacement = props.getProperty(key);
406       }
407
408       if(replacement != null) {
409         // Do variable substitution on the replacement string
410
// such that we can solve "Hello ${x2}" as "Hello p1"
411
// the where the properties are
412
// x1=p1
413
// x2=${x1}
414
String JavaDoc recursiveReplacement = substVars(replacement, props);
415         sbuf.append(recursiveReplacement);
416       }
417       i = k + DELIM_STOP_LEN;
418     }
419       }
420     }
421   }
422
423
424   /**
425      Configure log4j given a URL.
426
427      <p>The url must point to a file or resource which will be interpreted by
428      a new instance of a log4j configurator.
429
430      <p>All configurations steps are taken on the
431      <code>hierarchy</code> passed as a parameter.
432
433      <p>
434      @param url The location of the configuration file or resource.
435      @param clazz The classname, of the log4j configurator which will parse
436      the file or resource at <code>url</code>. This must be a subclass of
437      {@link Configurator}, or null. If this value is null then a default
438      configurator of {@link PropertyConfigurator} is used, unless the
439      filename pointed to by <code>url</code> ends in '.xml', in which case
440      {@link org.apache.log4j.xml.DOMConfigurator} is used.
441      @param hierarchy The {@link org.apache.log4j.Hierarchy} to act on.
442
443      @since 1.1.4 */

444
445   static
446   public
447   void selectAndConfigure(URL JavaDoc url, String JavaDoc clazz, LoggerRepository hierarchy) {
448    Configurator configurator = null;
449    String JavaDoc filename = url.getFile();
450
451    if(clazz == null && filename != null && filename.endsWith(".xml")) {
452      clazz = "org.apache.log4j.xml.DOMConfigurator";
453    }
454
455    if(clazz != null) {
456      LogLog.debug("Preferred configurator class: " + clazz);
457      configurator = (Configurator) instantiateByClassName(clazz,
458                               Configurator.class,
459                               null);
460      if(configurator == null) {
461       LogLog.error("Could not instantiate configurator ["+clazz+"].");
462       return;
463      }
464    } else {
465      configurator = new PropertyConfigurator();
466    }
467
468    configurator.doConfigure(url, hierarchy);
469   }
470 }
471
Popular Tags