View Javadoc

1   /**
2    * Logback: the reliable, generic, fast and flexible logging framework.
3    * Copyright (C) 1999-2011, QOS.ch. All rights reserved.
4    *
5    * This program and the accompanying materials are dual-licensed under
6    * either the terms of the Eclipse Public License v1.0 as published by
7    * the Eclipse Foundation
8    *
9    *   or (per the licensee's choosing)
10   *
11   * under the terms of the GNU Lesser General Public License version 2.1
12   * as published by the Free Software Foundation.
13   */
14  package ch.qos.logback.core.util;
15  
16  import java.util.Properties;
17  
18  import ch.qos.logback.core.Context;
19  import ch.qos.logback.core.CoreConstants;
20  import ch.qos.logback.core.spi.ContextAware;
21  import ch.qos.logback.core.spi.PropertyContainer;
22  
23  /**
24   * @author Ceki Gulcu
25   */
26  public class OptionHelper {
27  
28    public static Object instantiateByClassName(String className,
29        Class superClass, Context context) throws IncompatibleClassException,
30        DynamicClassLoadingException {
31      ClassLoader classLoader = Loader.getClassLoaderOfObject(context);
32      return instantiateByClassName(className, superClass, classLoader);
33    }
34  
35    @SuppressWarnings("unchecked")
36    public static Object instantiateByClassName(String className,
37        Class superClass, ClassLoader classLoader)
38        throws IncompatibleClassException, DynamicClassLoadingException {
39  
40      if (className == null) {
41        throw new NullPointerException();
42      }
43  
44      try {
45        Class classObj = null;
46        classObj = classLoader.loadClass(className);
47        if (!superClass.isAssignableFrom(classObj)) {
48          throw new IncompatibleClassException(superClass, classObj);
49        }
50        return classObj.newInstance();
51      } catch (IncompatibleClassException ice) {
52        throw ice;
53      } catch (Throwable t) {
54        throw new DynamicClassLoadingException("Failed to instantiate type "
55            + className, t);
56      }
57    }
58  
59    /**
60     * Find the value corresponding to <code>key</code> in <code>props</code>.
61     * Then perform variable substitution on the found value.
62     * 
63     */
64    // public static String findAndSubst(String key, Properties props) {
65    // String value = props.getProperty(key);
66    //
67    // if (value == null) {
68    // return null;
69    // }
70    //
71    // try {
72    // return substVars(value, props);
73    // } catch (IllegalArgumentException e) {
74    // return value;
75    // }
76    // }
77    final static String DELIM_START = "${";
78    final static char DELIM_STOP = '}';
79    final static int DELIM_START_LEN = 2;
80    final static int DELIM_STOP_LEN = 1;
81    final static String _IS_UNDEFINED = "_IS_UNDEFINED";
82  
83    /**
84     * @see  #substVars(String, PropertyContainer, PropertyContainer)
85     */
86     public static String substVars(String val, PropertyContainer pc1) {
87       return substVars(val, pc1, null);
88     }
89  
90    /**
91     * See  http://logback.qos.ch/manual/configuration.html#variableSubstitution
92     */
93    public static String substVars(String val, PropertyContainer pc1, PropertyContainer pc2) {
94  
95      StringBuffer sbuf = new StringBuffer();
96  
97      int i = 0;
98      int j;
99      int k;
100 
101     while (true) {
102       j = val.indexOf(DELIM_START, i);
103 
104       if (j == -1) {
105         // no more variables
106         if (i == 0) { // this is a simple string
107 
108           return val;
109         } else { // add the tail string which contains no variables and return
110           // the result.
111           sbuf.append(val.substring(i, val.length()));
112 
113           return sbuf.toString();
114         }
115       } else {
116         sbuf.append(val.substring(i, j));
117         k = val.indexOf(DELIM_STOP, j);
118 
119         if (k == -1) {
120           throw new IllegalArgumentException('"' + val
121               + "\" has no closing brace. Opening brace at position " + j + '.');
122         } else {
123           j += DELIM_START_LEN;
124 
125           String rawKey = val.substring(j, k);
126 
127           // Massage the key to extract a default replacement if there is one
128           String[] extracted = extractDefaultReplacement(rawKey);
129           String key = extracted[0];
130           String defaultReplacement = extracted[1]; // can be null
131 
132           String replacement = propertyLookup(key, pc1, pc2);
133 
134           // if replacement is still null, use the defaultReplacement which
135           // can be null as well
136           if (replacement == null) {
137             replacement = defaultReplacement;
138           }
139 
140           if (replacement != null) {
141             // Do variable substitution on the replacement string
142             // such that we can solve "Hello ${x2}" as "Hello p1"
143             // where the properties are
144             // x1=p1
145             // x2=${x1}
146             String recursiveReplacement = substVars(replacement, pc1, pc2);
147             sbuf.append(recursiveReplacement);
148           } else {
149             // if we could not find a replacement, then signal the error
150             sbuf.append(key + "_IS_UNDEFINED");
151           }
152 
153           i = k + DELIM_STOP_LEN;
154         }
155       }
156     }
157   }
158 
159   public static String propertyLookup(String key, PropertyContainer pc1,
160                                PropertyContainer pc2) {
161     String value = null;
162     // first try the props passed as parameter
163     value = pc1.getProperty(key);
164 
165     // then try  the pc2
166     if (value == null && pc2 != null) {
167       value = pc2.getProperty(key);
168     }
169     // then try in System properties
170     if (value == null) {
171       value = getSystemProperty(key, null);
172     }
173     if (value == null) {
174       value = getEnv(key);
175     }
176     return value;
177   }
178 
179   /**
180    * Very similar to <code>System.getProperty</code> except that the
181    * {@link SecurityException} is absorbed.
182    * 
183    * @param key
184    *                The key to search for.
185    * @param def
186    *                The default value to return.
187    * @return the string value of the system property, or the default value if
188    *         there is no property with that key.
189    */
190   public static String getSystemProperty(String key, String def) {
191     try {
192       return System.getProperty(key, def);
193     } catch (SecurityException e) {
194       return def;
195     }
196   }
197 
198   /**
199    * Lookup a key from the environment.
200    * @param key
201    * @return value corresponding to key from the OS environment
202    */
203   public static String getEnv(String key) {
204     try {
205       return System.getenv(key);
206     } catch (SecurityException e) {
207       return null;
208     }
209   }
210 
211 
212   /**
213    * Very similar to <code>System.getProperty</code> except that the
214    * {@link SecurityException} is absorbed.
215    * 
216    * @param key
217    *                The key to search for.
218    * 
219    * @return the string value of the system property.
220    */
221   public static String getSystemProperty(String key) {
222     try {
223       return System.getProperty(key);
224     } catch (SecurityException e) {
225       return null;
226     }
227   }
228 
229   public static void setSystemProperties(ContextAware contextAware, Properties props) {
230     for(Object o: props.keySet()) {
231       String key = (String) o;
232       String value = props.getProperty(key);
233       setSystemProperty(contextAware, key, value);
234     }
235   }
236 
237   public static void setSystemProperty(ContextAware contextAware, String key, String value) {
238     try {
239       System.setProperty(key, value);
240     } catch (SecurityException e) {
241       contextAware.addError("Failed to set system property ["+key+"]", e);
242     }
243   }
244 
245   /**
246    * Very similar to {@link System#getProperties()} except that the
247    * {@link SecurityException} is absorbed.
248    * 
249    * @return the system properties
250    */
251   public static Properties getSystemProperties() {
252     try {
253       return System.getProperties();
254     } catch (SecurityException e) {
255       return new Properties();
256     }
257   }
258 
259   static public String[] extractDefaultReplacement(String key) {
260     String[] result = new String[2];
261     result[0] = key;
262     int d = key.indexOf(":-");
263     if (d != -1) {
264       result[0] = key.substring(0, d);
265       result[1] = key.substring(d + 2);
266     }
267     return result;
268   }
269 
270   /**
271    * If <code>value</code> is "true", then <code>true</code> is returned. If
272    * <code>value</code> is "false", then <code>true</code> is returned.
273    * Otherwise, <code>default</code> is returned.
274    * 
275    * <p> Case of value is unimportant.
276    */
277   public static boolean toBoolean(String value, boolean dEfault) {
278     if (value == null) {
279       return dEfault;
280     }
281 
282     String trimmedVal = value.trim();
283 
284     if ("true".equalsIgnoreCase(trimmedVal)) {
285       return true;
286     }
287 
288     if ("false".equalsIgnoreCase(trimmedVal)) {
289       return false;
290     }
291 
292     return dEfault;
293   }
294 
295   public static boolean isEmpty(String str) {
296     return ((str == null) || CoreConstants.EMPTY_STRING.equals(str));
297   }
298 
299 
300 }