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.monitoring.configuration;
018
019 import org.apache.commons.monitoring.MonitoringException;
020 import org.apache.commons.monitoring.util.ClassLoaders;
021
022 import java.io.File;
023 import java.io.FileInputStream;
024 import java.io.FileNotFoundException;
025 import java.io.InputStream;
026 import java.lang.annotation.ElementType;
027 import java.lang.annotation.Retention;
028 import java.lang.annotation.RetentionPolicy;
029 import java.lang.annotation.Target;
030 import java.lang.reflect.Method;
031 import java.util.ArrayList;
032 import java.util.Collection;
033 import java.util.Properties;
034 import java.util.logging.Level;
035 import java.util.logging.Logger;
036
037 public final class Configuration {
038 private static final Logger LOGGER = Logger.getLogger(Configuration.class.getName());
039
040 private static final Collection<ToDestroy> INSTANCES = new ArrayList<ToDestroy>();
041
042 public static final String COMMONS_MONITORING_PREFIX = "org.apache.commons.monitoring.";
043 private static final String DEFAULT_CONFIGURATION_FILE = "commons-monitoring.properties";
044
045 private static Thread shutdownHook = null;
046
047 private static final Properties PROPERTIES = new Properties(System.getProperties());
048 static {
049 try {
050 final InputStream is = findConfiguration();
051 if (is != null) {
052 PROPERTIES.load(is);
053 }
054 } catch (final Exception e) {
055 LOGGER.log(Level.SEVERE, e.getMessage(), e);
056 }
057 }
058 private static InputStream findConfiguration() throws FileNotFoundException {
059 final String filename = System.getProperty(COMMONS_MONITORING_PREFIX + "configuration", DEFAULT_CONFIGURATION_FILE);
060 if (new File(filename).exists()) {
061 return new FileInputStream(filename);
062 }
063
064 return ClassLoaders.current().getResourceAsStream(filename);
065 }
066
067 public static synchronized <T> T newInstance(final Class<T> clazz) {
068 try {
069 String config = PROPERTIES.getProperty(clazz.getName());
070 if (config == null) {
071 config = clazz.getPackage().getName() + ".Default" + clazz.getSimpleName();
072 }
073
074 Class<?> loadedClass;
075 try {
076 loadedClass = ClassLoaders.current().loadClass(config);
077 } catch (final Throwable throwable) { // NoClassDefFoundError or Exception
078 loadedClass = clazz;
079 }
080
081 final Object instance = loadedClass.newInstance();
082 for (final Method m : loadedClass.getMethods()) {
083 if (m.getAnnotation(Created.class) != null) {
084 m.invoke(instance);
085 } else if (m.getAnnotation(Destroying.class) != null) {
086 if (shutdownHook == null == is(COMMONS_MONITORING_PREFIX + "shutdown.hook", true)) {
087 shutdownHook = new Thread() {
088 @Override
089 public void run() {
090 shutdown();
091 }
092 };
093 Runtime.getRuntime().addShutdownHook(shutdownHook);
094 }
095 INSTANCES.add(new ToDestroy(m, instance));
096 }
097 }
098
099 return clazz.cast(instance);
100 } catch (final Exception e) {
101 throw new MonitoringException(e);
102 }
103 }
104
105 public static boolean is(final String key, final boolean defaultValue) {
106 return Boolean.parseBoolean(getProperty(key, Boolean.toString(defaultValue)));
107 }
108
109 public static int getInteger(final String key, final int defaultValue) {
110 return Integer.parseInt(getProperty(key, Integer.toString(defaultValue)));
111 }
112
113 public static String getProperty(final String key, final String defaultValue) {
114 return PROPERTIES.getProperty(key, defaultValue);
115 }
116
117 public static void shutdown() {
118 for (final ToDestroy c : INSTANCES) {
119 c.destroy();
120 }
121 INSTANCES.clear();
122 }
123
124 private Configuration() {
125 // no-op
126 }
127
128 @Retention(RetentionPolicy.RUNTIME)
129 @Target(ElementType.METHOD)
130 public static @interface Created {
131 }
132
133 @Retention(RetentionPolicy.RUNTIME)
134 @Target(ElementType.METHOD)
135 public static @interface Destroying {
136 }
137
138 private static class ToDestroy {
139 private final Method method;
140 private final Object target;
141
142 public ToDestroy(final Method m, final Object instance) {
143 this.method = m;
144 this.target = instance;
145 }
146
147 public void destroy() {
148 try {
149 method.invoke(target);
150 } catch (final Exception e) {
151 // no-op
152 }
153 }
154 }
155 }