001 /*
002 * $Id: Environment.java,v 1.26 2014/04/21 16:04:52 oboehm Exp $
003 *
004 * Copyright (c) 2010 by Oliver Boehm
005 *
006 * Licensed under the Apache License, Version 2.0 (the "License");
007 * you may not use this file except in compliance with the License.
008 * You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express orimplied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 *
018 * (c)reated 01.02.2010 by oliver (ob@oasd.de)
019 */
020
021 package patterntesting.runtime.util;
022
023 import java.io.*;
024 import java.net.*;
025 import java.util.Map.Entry;
026 import java.util.*;
027 import java.util.jar.*;
028
029 import org.slf4j.*;
030
031 import patterntesting.runtime.io.FileHelper;
032 import patterntesting.runtime.monitor.ClasspathMonitor;
033
034 /**
035 * This class provides some utilities for the access to the environment
036 * (e.g. the system properties).
037 * <br/>
038 * TODO: Use common.lang.SystemUtils for OS_NAME or other system properties
039 *
040 * @author oliver
041 * @since 1.0 (01.02.2010)
042 */
043 public final class Environment {
044
045 private static final Logger log = LoggerFactory.getLogger(Environment.class);
046
047 /** operating system (e.g. "Mac OS X"). */
048 public static final String OS_NAME = System.getProperty("os.name", "unknown");
049 /** architecture (e.g. "x86_64"). */
050 public static final String OS_ARCH = System.getProperty("os.arch", "unknown");
051 /** os version (e.g. "10.6.2"). */
052 public static final String OS_VERSION = System.getProperty("os.version", "unknown");
053 /** JDK version (e.g. "1.6.0_17"). */
054 public static final String JAVA_VERSION = System.getProperty("java.version");
055 /** Java vendor (e.g. "Apple Inc."). */
056 public static final String JAVA_VENDOR = System.getProperty("java.vendor");
057 /** User (e.g. "oliver") */
058 public static final String USER_NAME = System.getProperty("user.name");
059 /** System property to disable multithreading. */
060 public static final String DISABLE_THREADS = "patterntesting.disableThreads";
061 /** System property to enable integration tests */
062 public static final String INTEGRATION_TEST = "patterntesting.integrationTest";
063 /** System property for annotation RunTestsParallel. */
064 public static final String RUN_TESTS_PARALLEL = "patterntesting.runTestsParallel";
065 /** System property for annotation SmokeTest. */
066 public static final String RUN_SMOKE_TESTS = "patterntesting.runSmokeTests";
067 /** True if property for integration test is set. */
068 public static final boolean integrationTestEnabled = Environment
069 .isPropertyEnabled(Environment.INTEGRATION_TEST);
070 /** True if SmokeTest property is set. */
071 public static final boolean smokeTestEnabled = Environment
072 .isPropertyEnabled(Environment.RUN_SMOKE_TESTS);
073
074 /** to avoid instantiation of this (static) utility class. */
075 private Environment() {}
076
077 /**
078 * The name of an environment is derived from the classloader.
079 * I.e. on a Tomcat server the name is "org.apache.catalina".
080 *
081 * @return e.g. "com.google.apphosting" for Google App Enginge
082 */
083 public static String getName() {
084 String name = getClassLoader().getClass().getName();
085 String[] packages = name.split("\\.|\\$", 4);
086 return packages[0] + "." + packages[1] + "." + packages[2];
087 }
088
089 /**
090 * @{link "http://www.odi.ch/prog/design/newbies.php#23"}
091 * @return a valid classloader
092 */
093 public static ClassLoader getClassLoader() {
094 ClassLoader cloader = Thread.currentThread().getContextClassLoader();
095 if (cloader == null) {
096 cloader = Environment.class.getClassLoader();
097 log.warn("no ContextClassLoader found - using " + cloader);
098 }
099 return cloader;
100 }
101
102 /**
103 * Looks if one of the given properties matches a system property.
104 * If one system property is found and this system property is not
105 * "false" true is returned.
106 *
107 * @param props the properties to be checked
108 * @return true if one of the given properties exist (and are not "false")
109 */
110 public static boolean matchesOneOf(final String[] props) {
111 for (int i = 0; i < props.length; i++) {
112 if (props[i].contains("*") || props[i].contains("?")) {
113 log.warn("Wildcard in property \"" + props[i] + "\" is not supported!");
114 }
115 String prop = System.getProperty(props[i]);
116 if ((prop != null) && !"false".equalsIgnoreCase(prop)) {
117 return true;
118 }
119 }
120 return false;
121 }
122
123 /**
124 * Returns true if the given property is set as System property and the
125 * value of it is not false.
126 *
127 * @param key e.g. "patterntesting.runTestsParallel"
128 * @return true if property is set
129 */
130 public static boolean isPropertyEnabled(final String key) {
131 String prop = System.getProperty(key, "false");
132 return !prop.equalsIgnoreCase("false");
133 }
134
135 /**
136 * Loads the properties from the classpath and provides them as system
137 * properties.
138 *
139 * @param resource the name of the classpath resource
140 * @return the loaded properties
141 * @throws IOException if properties can't be loaded
142 * @see #loadProperties(InputStream)
143 */
144 public static Properties loadProperties(final String resource)
145 throws IOException {
146 ClassLoader cloader = getClassLoader();
147 InputStream istream = cloader.getResourceAsStream(resource);
148 if ((istream == null) && resource.startsWith("/")) {
149 istream = cloader.getResourceAsStream(resource.substring(1));
150 }
151 if (istream == null) {
152 log.debug("using Environment.class to get " + resource + "...");
153 istream = Environment.class.getResourceAsStream(resource);
154 }
155 Properties props = loadProperties(istream);
156 istream.close();
157 return props;
158 }
159
160 /**
161 * Loads the properties from the given InputStream and provides them as
162 * system properties.
163 * </br>
164 * Note: Setting it as system property is not guaranteed to run in a
165 * cluster or cloud. E.g. on Google's App Engine this seems not to work.
166 *
167 * @param istream from here the properties are loaded
168 * @return the loaded properties
169 * @throws IOException if properties can't be loaded
170 */
171 public static Properties loadProperties(final InputStream istream)
172 throws IOException {
173 Properties props = new Properties();
174 props.load(istream);
175 Properties systemProps = System.getProperties();
176 for (Entry<Object, Object>entry : props.entrySet()) {
177 systemProps.setProperty((String) entry.getKey(), (String) entry
178 .getValue());
179 }
180 if (log.isDebugEnabled()) {
181 log.debug(props.size() + " properties loaded from " + istream);
182 }
183 return props;
184 }
185
186 /**
187 * In some JEE environment like Google's App Engine (GAE) it is not allowed
188 * to use multi threading. But you can also disable multi threading by
189 * setting the system property {@link #DISABLE_THREADS}.
190 *
191 * @return normally true
192 */
193 public static boolean areThreadsAllowed() {
194 if (isGoogleAppEngine() || isPropertyEnabled(DISABLE_THREADS)) {
195 return false;
196 }
197 return true;
198 }
199
200 /**
201 * If we are in a Google App Engine (GAE) environment we will return true
202 * here.
203 *
204 * @return true if application runs on GAE
205 */
206 public static boolean isGoogleAppEngine() {
207 return System.getProperty("com.google.appengine.runtime.version") != null;
208 }
209
210 /**
211 * If we are inside a Weblogic Server (WLS) we will return true here.
212 * We look only for the system property "weblogic.Name" here.
213 * Another possibility (not realized) would be to look at the classloader.
214 *
215 * @return true inside Weblogic Server
216 */
217 public static boolean isWeblogicServer() {
218 return System.getProperty("weblogic.Name") != null;
219 }
220
221 /**
222 * Normally you'll find the local Maven repository at ~/.m2/repository.
223 * But on cloudbees it is the local .repository directory. So we try to
224 * find out here which one we should use.
225 *
226 * @return the root dir of the local Maven repository
227 * @throws IOException Signals that an I/O exception has occurred.
228 */
229 public static File getLocalMavenRepositoryDir() throws IOException {
230 File[] repoDirs = { new File(FileHelper.getHomeDir(), ".m2/repository"),
231 new File(".repository").getAbsoluteFile(),
232 new File("../.repository").getAbsoluteFile() };
233 for (int i = 0; i < repoDirs.length; i++) {
234 if (repoDirs[i].exists() && repoDirs[i].isDirectory()) {
235 return repoDirs[i];
236 }
237 }
238 throw new IOException("local maven repository not found in " + Converter.toString(repoDirs));
239 }
240
241 /**
242 * It is only tested for Jamon 2.4 and 2.7 so we look for it
243 *
244 * @return true if Jamon 2.4 or 2.7 (or greater) was found
245 */
246 public static boolean isJamonAvailable() {
247 String resource = "/com/jamonapi/MonitorFactory.class";
248 try {
249 URL classURL = Environment.class.getResource(resource);
250 URI jarURI = ClasspathHelper.getParent(classURL.toURI(), resource);
251 JarFile jarfile = ClasspathMonitor.whichResourceJar(jarURI);
252 Manifest manifest = jarfile.getManifest();
253 Attributes attributes = manifest.getMainAttributes();
254 String version = attributes.getValue("version");
255 if (version.equalsIgnoreCase("JAMon 2.4") || (version.compareTo("JAMon 2.7") >= 0)) {
256 log.info("{} available for profiling.", version);
257 return true;
258 } else {
259 log.info(version
260 + " not supported (only JAMon 2.4 and 2.7 or higher), using simple profiling.");
261 }
262 } catch (RuntimeException e) {
263 // if JAMon is not in classpath we come with a NPE to here
264 log.debug("JAMon not available, using simple profiling");
265 } catch (IOException ioe) {
266 log.info("Manifest for JAMon not found, using simple profiling", ioe);
267 } catch (URISyntaxException use) {
268 log.info(resource + " not available as URI, using simple profiling", use);
269 }
270 return false;
271 }
272
273 }
274