001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 package org.apache.commons.configuration; 018 019 import java.lang.reflect.Method; 020 import java.util.Collection; 021 import java.util.HashMap; 022 import java.util.Iterator; 023 import java.util.Map; 024 025 import org.apache.commons.lang.SystemUtils; 026 import org.apache.tools.ant.taskdefs.Execute; 027 028 /** 029 * <p> 030 * A Configuration implementation that reads the platform specific environment 031 * variables. On pre java5 JRE it uses Ant Execute task to read the environment. 032 * (in this case ant must be present in classpath). On java >= 5 JRE it uses 033 * <code>java.lang.System#getenv()</code> and ant is not required. 034 * </p> 035 * <p> 036 * This configuration implementation is read-only. It allows read access to the 037 * defined OS environment variables, but their values cannot be changed. 038 * </p> 039 * <p> 040 * Usage of this class is easy: After an instance has been created the get 041 * methods provided by the <code>Configuration</code> interface can be used 042 * for querying environment variables, e.g.: 043 * 044 * <pre> 045 * Configuration envConfig = new EnvironmentConfiguration(); 046 * System.out.println("JAVA_HOME=" + envConfig.getString("JAVA_HOME"); 047 * </pre> 048 * 049 * </p> 050 * 051 * @author <a href="mailto:nicolas.deloof@gmail.com">Nicolas De Loof</a> 052 * @see org.apache.tools.ant.taskdefs.Execute#getProcEnvironment() 053 * @since 1.5 054 */ 055 public class EnvironmentConfiguration extends AbstractConfiguration 056 { 057 /** Constant for the name of the getenv() method. */ 058 private static final String METHOD_NAME = "getenv"; 059 060 /** Constant for the Java version 1.5. */ 061 private static final int VERSION_1_5 = 150; 062 063 /** Stores the environment properties. */ 064 private Map environment; 065 066 /** 067 * Constructor. 068 */ 069 public EnvironmentConfiguration() 070 { 071 if (SystemUtils.isJavaVersionAtLeast(VERSION_1_5)) 072 { 073 extractProperties15(); 074 } 075 else 076 { 077 extractProperties14(); 078 } 079 } 080 081 /** 082 * Adds a property to this configuration. Because this configuration is 083 * read-only, this operation is not allowed and will cause an exception. 084 * 085 * @param key the key of the property to be added 086 * @param value the property value 087 */ 088 protected void addPropertyDirect(String key, Object value) 089 { 090 throw new UnsupportedOperationException("Configuration is read-only!"); 091 } 092 093 /** 094 * {@inheritDoc} 095 * 096 * @see org.apache.commons.configuration.AbstractConfiguration#containsKey(java.lang.String) 097 */ 098 public boolean containsKey(String key) 099 { 100 return environment.containsKey(key); 101 } 102 103 /** 104 * {@inheritDoc} 105 * 106 * @see org.apache.commons.configuration.AbstractConfiguration#getKeys() 107 */ 108 public Iterator getKeys() 109 { 110 return environment.keySet().iterator(); 111 } 112 113 /** 114 * {@inheritDoc} 115 * 116 * @see org.apache.commons.configuration.AbstractConfiguration#getProperty(java.lang.String) 117 */ 118 public Object getProperty(String key) 119 { 120 return environment.get(key); 121 } 122 123 /** 124 * {@inheritDoc} 125 * 126 * @see org.apache.commons.configuration.AbstractConfiguration#isEmpty() 127 */ 128 public boolean isEmpty() 129 { 130 return environment.isEmpty(); 131 } 132 133 /** 134 * Removes a property from this configuration. Because this configuration is 135 * read-only, this operation is not allowed and will cause an exception. 136 * 137 * @param key the key of the property to be removed 138 */ 139 public void clearProperty(String key) 140 { 141 throw new UnsupportedOperationException("Configuration is read-only!"); 142 } 143 144 /** 145 * Removes all properties from this configuration. Because this 146 * configuration is read-only, this operation is not allowed and will cause 147 * an exception. 148 */ 149 public void clear() 150 { 151 throw new UnsupportedOperationException("Configuration is read-only!"); 152 } 153 154 /** 155 * Extracts environment properties on a JRE < 1.5. This implementation 156 * uses ant for this purpose. 157 */ 158 void extractProperties14() 159 { 160 extractPropertiesFromCollection(Execute.getProcEnvironment()); 161 } 162 163 /** 164 * An internally used method for processing a collection with environment 165 * entries. The collection must contain strings like 166 * <code>property=value</code>. Such a collection is returned by ant. 167 * 168 * @param env the collection with the properties 169 */ 170 void extractPropertiesFromCollection(Collection env) 171 { 172 environment = new HashMap(); 173 for (Iterator it = env.iterator(); it.hasNext();) 174 { 175 String entry = (String) it.next(); 176 int pos = entry.indexOf('='); 177 if (pos == -1) 178 { 179 getLogger().warn("Ignoring: " + entry); 180 } 181 else 182 { 183 environment.put(entry.substring(0, pos), entry 184 .substring(pos + 1)); 185 } 186 } 187 } 188 189 /** 190 * Extracts environment properties on a JR >= 1.5. From this Java version 191 * on, there is an official way of doing this. However because the code 192 * should compile on lower Java versions, too, we have to invoke the method 193 * using reflection. 194 */ 195 void extractProperties15() 196 { 197 try 198 { 199 Method method = System.class.getMethod(METHOD_NAME, null); 200 environment = (Map) method.invoke(null, null); 201 } 202 catch (Exception ex) 203 { 204 // this should normally not happen on a JRE >= 1.5 205 throw new ConfigurationRuntimeException( 206 "Error when accessing environment properties", ex); 207 } 208 } 209 }