/Users/lyon/j4p/src/classUtils/pack/util/EnvironmentVariables.java

1    package classUtils.pack.util; 
2     
3    import java.io.BufferedReader; 
4    import java.io.IOException; 
5    import java.io.InputStream; 
6    import java.io.StringReader; 
7    import java.io.StringWriter; 
8    import java.text.CharacterIterator; 
9    import java.text.StringCharacterIterator; 
10   import java.util.ArrayList; 
11   import java.util.HashMap; 
12   import java.util.HashSet; 
13   import java.util.Iterator; 
14   import java.util.List; 
15   import java.util.Map; 
16   import java.util.Properties; 
17   import java.util.Set; 
18    
19   /** 
20    * An helper class to handle environment variables when they're present on 
21    * the underlying operating system. 
22    * So far, the only supported operating system is Windows 2000 - but the 
23    * underlying mechanism (based on running  a 'set' command on the system 
24    * shell) is easly usable for different o/s. 
25    * <p> 
26    * In order to add support for one OS, add the identification string and 
27    * the associated shell command in the private <b>getGenerator()</b> method, 
28    * and check that the parsing code in setBasedGenerator.getEnvironment() is 
29    * correct for parsing the result. 
30    * <p> 
31    * A typical usage consists in just invoking 
32    * <pre> 
33    *   EnvironmentVariables.getInstance().{@link #toSystemProperties() toSystemProperties()}; 
34    * </pre> 
35    * <p> 
36    * and then browse the system properties for <tt>env.</tt> entries. 
37    *  
38    * @author cris 
39    */ 
40   public class EnvironmentVariables { 
41        
42       /** 
43        * A class implementing this interface is able to retrieve environment 
44        * information in some way. 
45        *  
46        * @author cris 
47        */ 
48       public static interface Generator { 
49            
50           /** 
51            * Return an array of a 2-columns array of Strings containing variable 
52            * names and values 
53            * @return String 
54            */ 
55           public String[][] getEnvironment(); 
56            
57       } 
58        
59       /** 
60        * Classes implementing this interface can transform environment 
61        * names in a "canonical" form 
62        *  
63        * @author cris 
64        */ 
65       public static interface NameTransformer { 
66            
67           public String transform(String name); 
68       } 
69        
70    
71       /** 
72        * A {@link Generator Generator} based on running 'set' and parsing the  
73        * result 
74        *  
75        * @author cris 
76        */ 
77       private class SetBasedGenerator implements Generator { 
78            
79           private String cmd; 
80            
81           public SetBasedGenerator(String cmd) { 
82               this.cmd=cmd; 
83           } 
84            
85           /** 
86            * @see classUtils.pack.util.EnvironmentVariables.Generator#getEnvironment() 
87            */ 
88           public String[][] getEnvironment() { 
89               try { 
90                   Process p = Runtime.getRuntime().exec(cmd); 
91                   try { 
92                       InputStream is = p.getInputStream(); 
93                       StringWriter sw = new StringWriter(); 
94                       int c; 
95                       while ((c=is.read())!=-1) sw.write(c); 
96                       is.close(); 
97                        
98                       BufferedReader br = new BufferedReader(new StringReader(sw.toString())); 
99                       String line; 
100                      List l = new ArrayList(); 
101                      while((line=br.readLine())!=null) { 
102                          int i=line.indexOf("="); 
103                          if (i==-1) continue; 
104                          String [] envEntry = new String[2]; 
105                          envEntry[0]=line.substring(0, i); 
106                          if (line.length()==i+1) continue; 
107                          envEntry[1]=line.substring(i+1); 
108                          l.add(envEntry); 
109                      } 
110                      String[][] result=new String[l.size()][2]; 
111                      l.toArray(result); 
112                      return result; 
113                       
114                  } catch (IOException e) { 
115                      e.printStackTrace(); 
116                      throw new RuntimeException("Problem obtaining the result of the 'set' command"); 
117                  } 
118              } catch (IOException e) { 
119                  e.printStackTrace(); 
120                  throw new RuntimeException("Impossible to run the 'set' command"); 
121              } 
122          } 
123      } 
124       
125      /** 
126       * A {@link EnvironmentVariables.NameTransformer NameTransformer} which doesn't make any trasformation 
127       *  
128       * @author cris 
129       */ 
130      private static class IdenticalNameTransformer implements NameTransformer { 
131           
132          private static IdenticalNameTransformer instance = new IdenticalNameTransformer(); 
133   
134          private IdenticalNameTransformer() { } 
135           
136          public static IdenticalNameTransformer getInstance() { return instance; } 
137           
138          /** 
139           * @see classUtils.pack.util.EnvironmentVariables.NameTransformer#transform(java.lang.String) 
140           */ 
141          public String transform(String name) { 
142              return name; 
143          } 
144      } 
145       
146      /** 
147       * A {@link EnvironmentVariables.NameTransformer NameTransformer} which produces names in the style 
148       * of typical java property names. In detail: 
149       * <ul> 
150       * <li>Each property is prefixed with a given prefix (default <tt>env.</tt>) 
151       * <li>Character case is lowered 
152       * <li>Underscores are substituted with dots 
153       * <li>If the original variable name contains both lowercase and uppercase letters, 
154       *     every nonconsecutive uppercase letter is considered the start of a word, 
155       *     and words are divided by dots. 
156       * </ul> 
157       * <p> 
158       * For example, <tt>JAVA_HOME</tt> will become <tt>env.java.home</tt>, 
159       * <tt>CommSpec</tt> will become <tt>comm.spec</tt> and 
160       * <tt>My_StrangeVariableName</tt> will become my.strange.variable.name 
161       *  
162       * @version 1.1 
163       * @author cris 
164       */ 
165      public class SimpleNameTransformer implements NameTransformer { 
166   
167          private Map cachedNames = new HashMap();         
168          private String prefix; 
169           
170          public SimpleNameTransformer(String prefix) { 
171              this.prefix=prefix; 
172          } 
173           
174          public SimpleNameTransformer() { 
175              this("env"); 
176          } 
177           
178          public String transform(String name) { 
179              if (name.toUpperCase().equals(name)) { 
180                  return transformAllUpperCase(name); 
181              } else { 
182                  // Preprocess the name 
183                  CharacterIterator iter = new StringCharacterIterator(name); 
184                  StringBuffer sb = new StringBuffer(prefix); 
185                  boolean lastWasUpperCase=false; 
186                  for(char c = iter.first(); c != CharacterIterator.DONE; c = iter.next()) { 
187                      if (Character.isUpperCase(c)) { 
188                          if (! lastWasUpperCase) { 
189                              sb.append("_"); 
190                              lastWasUpperCase=true; 
191                          } else { 
192                              lastWasUpperCase=false; 
193                          } 
194                          sb.append(c); 
195                      } 
196                  } 
197                  return transformAllUpperCase(sb.toString()); 
198              } 
199          } 
200           
201          /** 
202           * @see classUtils.pack.util.EnvironmentVariables.NameTransformer#transform(java.lang.String) 
203           */ 
204          public String transformAllUpperCase(String name) { 
205              String result; 
206               
207              if ((result=(String)cachedNames.get(name)) != null)      
208                  return result; 
209               
210              CharacterIterator iter = new StringCharacterIterator(name); 
211              StringBuffer sb = new StringBuffer(prefix); 
212              if (prefix.length()>0) sb.append("."); 
213              for(char c = iter.first(); c != CharacterIterator.DONE; c = iter.next()) { 
214                  if (c=='_') { 
215                      if (sb.length()>0) sb.append("."); 
216                  } else sb.append(Character.toLowerCase(c)); 
217              } 
218               
219              result=sb.toString(); 
220              cachedNames.put(name, result); 
221               
222              return result; 
223          } 
224      } 
225       
226      private static EnvironmentVariables instance; 
227      private Map env = new HashMap(); 
228      private SimpleNameTransformer simpleNameTransformer; 
229   
230   
231      /** 
232       * Constructor for EnvironmentVariables. 
233       */ 
234      public EnvironmentVariables() { 
235          String [][] env=getGenerator().getEnvironment(); 
236          for(int i=0;i<env.length;i++) { 
237              this.env.put(env[i][0], env[i][1]); 
238          } 
239          this.simpleNameTransformer=new SimpleNameTransformer(); 
240      } 
241       
242      /** 
243       * Return the name of the given variable, after applying the 
244       * given {@link NameTransformer name transformation} 
245       *  
246       * @param name the name of the required environment entry 
247       * @param t the transformation to apply 
248       * @return the value of the variable with the transformed name, 
249       *          or <b>null</b> if such a name is undefined 
250       */ 
251      protected String getEnv(String name, NameTransformer t) { 
252          return (String)env.get(t.transform(name)); 
253      } 
254       
255      /** 
256       * Return the value of the environemnt variable of the given 
257       * name 
258       * @param name the environemnt variable name 
259       * @return the environemnt variable value 
260       */ 
261      public String getEnv(String name) { 
262          return getEnv(name, IdenticalNameTransformer.getInstance()); 
263      } 
264       
265      /** 
266       * Return the value of a property whose name is a transformation 
267       * of an environment variable name according to a {@link SimpleNameTransformer 
268       * SimpleNameTransformer} 
269       * @param name 
270       * @return String 
271       */ 
272      public String getEnvProperty(String name) { 
273          return getEnv(name, simpleNameTransformer); 
274      } 
275       
276      /** 
277       * Return the set of environment variables names 
278       * @return the set of environment variables names 
279       */ 
280      public Set envNames() { return new HashSet(env.keySet()); } 
281       
282      /** 
283       * Return the set of property names derived by the environment variables, 
284       * as obtained by {@link #getEnvProperty(java.lang.String) getEnvProperty()} 
285       *  
286       * @return the set of property names derived by the environment variables 
287       */ 
288      public Set envPropertyNames() {  
289          Set s = new HashSet(); 
290          for(Iterator i=env.keySet().iterator();i.hasNext();) { 
291              s.add(simpleNameTransformer.transform((String)i.next())); 
292          } 
293          return s; 
294      } 
295       
296      /** 
297       * Return a Properties object with the environment properties, whose 
298       * names are names derived by the environment variables, 
299       * as obtained by {@link #getEnvProperty(java.lang.String) getEnvProperty()} 
300       *  
301       * @return Properties 
302       */ 
303      public Properties getAsProperties() { 
304          return getAsProperties(new Properties()); 
305      } 
306           
307      private Properties getAsProperties(Properties p) { 
308           
309          for(Iterator i=env.keySet().iterator();i.hasNext();) { 
310              String name=(String)i.next(); 
311              p.put(simpleNameTransformer.transform(name), env.get(name)); 
312          } 
313          return p; 
314      } 
315       
316      /** 
317       * Add properties obtained by {@link #getEnvProperty(java.lang.String)  
318       * getEnvProperty()} to the system properties. 
319       */ 
320      public void toSystemProperties() { 
321          getAsProperties(System.getProperties()); 
322      } 
323       
324      /** 
325       * Return the single instance of this class 
326       * @return EnvironmentVariables 
327       */ 
328      public static EnvironmentVariables getInstance() {  
329          if (instance==null) instance=new EnvironmentVariables(); 
330          return instance;  
331      } 
332   
333      /** 
334       * This method checks the operating system name to know  
335       * and produces a suitable EnvironmentListGenerator for the  
336       * platform, or throws an UnsupportedOperationException 
337       *  
338       * @throws UnsupportedOperationException 
339       */ 
340      private Generator getGenerator() throws UnsupportedOperationException { 
341          String osName = System.getProperties().getProperty("os.name"); 
342           
343          if (osName.startsWith("Windows")) 
344              return new SetBasedGenerator("cmd /c set"); 
345          // Else, we can't 
346          throw new UnsupportedOperationException(""); 
347      } 
348   
349  } 
350