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 }