View Javadoc

1   package org.apache.jcs.config;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.util.Properties;
23  
24  import org.apache.commons.logging.Log;
25  import org.apache.commons.logging.LogFactory;
26  
27  /***
28   * This class is based on the log4j class
29   * org.apache.log4j.helpers.OptionConverter that was made by Ceki
30   * Gülcü Simon Kitching; Avy Sharell (sharell@online.fr) Anders
31   * Kristensen Matthieu Verbert (mve@zurich.ibm.com) A convenience class to
32   * convert property values to specific types.
33   *
34   */
35  public class OptionConverter
36  {
37      private final static Log log = LogFactory.getLog( OptionConverter.class );
38  
39      static String DELIM_START = "${";
40  
41      static char DELIM_STOP = '}';
42  
43      static int DELIM_START_LEN = 2;
44  
45      static int DELIM_STOP_LEN = 1;
46  
47      static StringBuffer sbuf = new StringBuffer();
48  
49      /*** No instances please. */
50      private OptionConverter()
51      {
52          super();
53      }
54  
55      /***
56       * Combines two arrays.
57       *
58       * @param l
59       * @param r
60       * @return String[]
61       */
62      public static String[] concatanateArrays( String[] l, String[] r )
63      {
64          int len = l.length + r.length;
65          String[] a = new String[len];
66  
67          System.arraycopy( l, 0, a, 0, l.length );
68          System.arraycopy( r, 0, a, l.length, r.length );
69  
70          return a;
71      }
72  
73      /***
74       * Escapes special cahracters/
75       *
76       * @param s
77       * @return  String
78       */
79      public static String convertSpecialChars( String s )
80      {
81          char c;
82          int len = s.length();
83          StringBuffer sbuf = new StringBuffer( len );
84  
85          int i = 0;
86          while ( i < len )
87          {
88              c = s.charAt( i++ );
89              if ( c == '//' )
90              {
91                  c = s.charAt( i++ );
92                  if ( c == 'n' )
93                  {
94                      c = '\n';
95                  }
96                  else if ( c == 'r' )
97                  {
98                      c = '\r';
99                  }
100                 else if ( c == 't' )
101                 {
102                     c = '\t';
103                 }
104                 else if ( c == 'f' )
105                 {
106                     c = '\f';
107                 }
108                 else if ( c == '\b' )
109                 {
110                     c = '\b';
111                 }
112                 else if ( c == '\"' )
113                 {
114                     c = '\"';
115                 }
116                 else if ( c == '\'' )
117                 {
118                     c = '\'';
119                 }
120                 else if ( c == '//' )
121                 {
122                     c = '//';
123                 }
124             }
125             sbuf.append( c );
126         }
127         return sbuf.toString();
128     }
129 
130     /***
131      * Very similar to <code>System.getProperty</code> except that the {@link
132      * SecurityException} is hidden.
133      *
134      * @param key
135      *            The key to search for.
136      * @param def
137      *            The default value to return.
138      * @return the string value of the system property, or the default value if
139      *         there is no property with that key.
140      * @since 1.1
141      */
142 
143     public static String getSystemProperty( String key, String def )
144     {
145         try
146         {
147             return System.getProperty( key, def );
148         }
149         catch ( Throwable e )
150         {
151             // MS-Java throws com.ms.security.SecurityExceptionEx
152             log.debug( "Was not allowed to read system property \"" + key + "\"." );
153             return def;
154         }
155     }
156 
157     /***
158      * Creates an object for the className value of the key.
159      *
160      * @param props
161      * @param key
162      * @param superClass
163      * @param defaultValue
164      * @return Object that was created
165      */
166     public static Object instantiateByKey( Properties props, String key, Class superClass, Object defaultValue )
167     {
168 
169         // Get the value of the property in string form
170         String className = findAndSubst( key, props );
171         if ( className == null )
172         {
173             if ( log.isTraceEnabled() )
174             {
175                 log.info( "Could not find value for key " + key );
176             }
177             return defaultValue;
178         }
179         // Trim className to avoid trailing spaces that cause problems.
180         return OptionConverter.instantiateByClassName( className.trim(), superClass, defaultValue );
181     }
182 
183     /***
184      * If <code>value</code> is "true", then <code>true</code> is returned.
185      * If <code>value</code> is "false", then <code>true</code> is returned.
186      * Otherwise, <code>default</code> is returned.
187      * <p>
188      *
189      * Case of value is unimportant.
190      * @param value
191      * @param dEfault
192      * @return  Object
193      */
194 
195     public static boolean toBoolean( String value, boolean dEfault )
196     {
197         if ( value == null )
198         {
199             return dEfault;
200         }
201         String trimmedVal = value.trim();
202         if ( "true".equalsIgnoreCase( trimmedVal ) )
203         {
204             return true;
205         }
206         if ( "false".equalsIgnoreCase( trimmedVal ) )
207         {
208             return false;
209         }
210         return dEfault;
211     }
212 
213     /*** Description of the Method
214      * @param value
215      * @param dEfault
216      * @return
217      */
218     public static int toInt( String value, int dEfault )
219     {
220         if ( value != null )
221         {
222             String s = value.trim();
223             try
224             {
225                 return Integer.valueOf( s ).intValue();
226             }
227             catch ( NumberFormatException e )
228             {
229                 log.error( "[" + s + "] is not in proper int form." );
230                 e.printStackTrace();
231             }
232         }
233         return dEfault;
234     }
235 
236     /***
237      * @param value
238      * @param dEfault
239      * @return
240      */
241     public static long toFileSize( String value, long dEfault )
242     {
243         if ( value == null )
244         {
245             return dEfault;
246         }
247 
248         String s = value.trim().toUpperCase();
249         long multiplier = 1;
250         int index;
251 
252         if ( ( index = s.indexOf( "KB" ) ) != -1 )
253         {
254             multiplier = 1024;
255             s = s.substring( 0, index );
256         }
257         else if ( ( index = s.indexOf( "MB" ) ) != -1 )
258         {
259             multiplier = 1024 * 1024;
260             s = s.substring( 0, index );
261         }
262         else if ( ( index = s.indexOf( "GB" ) ) != -1 )
263         {
264             multiplier = 1024 * 1024 * 1024;
265             s = s.substring( 0, index );
266         }
267         if ( s != null )
268         {
269             try
270             {
271                 return Long.valueOf( s ).longValue() * multiplier;
272             }
273             catch ( NumberFormatException e )
274             {
275                 log.error( "[" + s + "] is not in proper int form" );
276                 log.error( "[" + value + "] not in expected format", e );
277             }
278         }
279         return dEfault;
280     }
281 
282     /***
283      * Find the value corresponding to <code>key</code> in <code>props</code>.
284      * Then perform variable substitution on the found value.
285      * @param key
286      * @param props
287      * @return
288      */
289 
290     public static String findAndSubst( String key, Properties props )
291     {
292         String value = props.getProperty( key );
293         if ( value == null )
294         {
295             return null;
296         }
297 
298         try
299         {
300             return substVars( value, props );
301         }
302         catch ( IllegalArgumentException e )
303         {
304             log.error( "Bad option value [" + value + "]", e );
305             return value;
306         }
307     }
308 
309     /***
310      * Instantiate an object given a class name. Check that the
311      * <code>className</code> is a subclass of <code>superClass</code>. If
312      * that test fails or the object could not be instantiated, then
313      * <code>defaultValue</code> is returned.
314      *
315      * @param className
316      *            The fully qualified class name of the object to instantiate.
317      * @param superClass
318      *            The class to which the new object should belong.
319      * @param defaultValue
320      *            The object to return in case of non-fulfillment
321      * @return
322      */
323 
324     public static Object instantiateByClassName( String className, Class superClass, Object defaultValue )
325     {
326         if ( className != null )
327         {
328             try
329             {
330                 Class classObj = Class.forName( className );
331                 if ( !superClass.isAssignableFrom( classObj ) )
332                 {
333                     log.error( "A \"" + className + "\" object is not assignable to a \"" + superClass.getName()
334                         + "\" variable." );
335                     return defaultValue;
336                 }
337                 return classObj.newInstance();
338             }
339             catch ( Exception e )
340             {
341                 log.error( "Could not instantiate class [" + className + "]", e );
342             }
343         }
344         return defaultValue;
345     }
346 
347     /***
348      * Perform variable substitution in string <code>val</code> from the
349      * values of keys found in the system propeties.
350      * <p>
351      *
352      * The variable substitution delimeters are <b>${ </b> and <b>} </b>.
353      * <p>
354      *
355      * For example, if the System properties contains "key=value", then the call
356      *
357      * <pre>
358      * String s = OptionConverter.substituteVars( &quot;Value of key is ${key}.&quot; );
359      * </pre>
360      *
361      * will set the variable <code>s</code> to "Value of key is value.".
362      * <p>
363      *
364      * If no value could be found for the specified key, then the
365      * <code>props</code> parameter is searched, if the value could not be
366      * found there, then substitution defaults to the empty string.
367      * <p>
368      *
369      * For example, if system propeties contains no value for the key
370      * "inexistentKey", then the call
371      *
372      * <pre>
373      * String s = OptionConverter.subsVars( &quot;Value of inexistentKey is [${inexistentKey}]&quot; );
374      * </pre>
375      *
376      * will set <code>s</code> to "Value of inexistentKey is []"
377      * <p>
378      *
379      * An {@link java.lang.IllegalArgumentException}is thrown if
380      * <code>val</code> contains a start delimeter "${" which is not balanced
381      * by a stop delimeter "}".
382      * </p>
383      * <p>
384      *
385      * <b>Author </b> Avy Sharell </a>
386      * </p>
387      *
388      * @param val
389      *            The string on which variable substitution is performed.
390      * @param props
391      * @return String
392      * @throws IllegalArgumentException
393      *             if <code>val</code> is malformed.
394      */
395 
396     public static String substVars( String val, Properties props )
397         throws IllegalArgumentException
398     {
399         sbuf.setLength( 0 );
400 
401         int i = 0;
402         int j;
403         int k;
404 
405         while ( true )
406         {
407             j = val.indexOf( DELIM_START, i );
408             if ( j == -1 )
409             {
410                 if ( i == 0 )
411                 {
412                     return val;
413                 }
414                 sbuf.append( val.substring( i, val.length() ) );
415                 return sbuf.toString();
416             }
417             sbuf.append( val.substring( i, j ) );
418             k = val.indexOf( DELIM_STOP, j );
419             if ( k == -1 )
420             {
421                 throw new IllegalArgumentException( '"' + val + "\" has no closing brace. Opening brace at position "
422                     + j + '.' );
423             }
424             j += DELIM_START_LEN;
425             String key = val.substring( j, k );
426             // first try in System properties
427             String replacement = getSystemProperty( key, null );
428             // then try props parameter
429             if ( replacement == null && props != null )
430             {
431                 replacement = props.getProperty( key );
432             }
433 
434             if ( replacement != null )
435             {
436                 sbuf.append( replacement );
437             }
438             i = k + DELIM_STOP_LEN;
439         }
440     }
441 
442 }
443 // end class