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 }