001package org.javasimon; 002 003import org.javasimon.callback.Callback; 004import org.javasimon.callback.CompositeCallback; 005import org.javasimon.utils.SystemDebugCallback; 006 007import java.io.FileNotFoundException; 008import java.io.FileReader; 009import java.io.InputStream; 010import java.io.InputStreamReader; 011import java.util.Collection; 012 013/** 014 * SimonManager is static utility class providing so called "default {@link org.javasimon.Manager}. 015 * It is possible to create separate Manager, but it cannot be accessed via this convenient 016 * utility-like class. This option may be useful in Java EE environment when it's required to 017 * separate Simon trees across different applications. For majority of Java SE applications this 018 * class is recommended. 019 * <p/> 020 * SimonManager also provides configuration initialization via properties. To initialize configuration 021 * with the configuration file following option can be added to JVM executable: 022 * <pre>-Djavasimon.config.file=some-path/simon.config.xml</pre> 023 * To configure the SimonManager via resource that can be found on classpath: 024 * <pre>-Djavasimon.config.resource=org/javasimon/example/wannabe-config.xml</pre> 025 * 026 * @author <a href="mailto:virgo47@gmail.com">Richard "Virgo" Richter</a> 027 */ 028public final class SimonManager { 029 030 /** Property name for the Simon configuration file is "javasimon.config.file". */ 031 public static final String PROPERTY_CONFIG_FILE_NAME = "javasimon.config.file"; 032 033 /** Property name for the Simon configuration resource is "javasimon.config.resource". */ 034 public static final String PROPERTY_CONFIG_RESOURCE_NAME = "javasimon.config.resource"; 035 036 private static Manager manager = new SwitchingManager(); 037 038 /* Calls {@link #init()}. */ 039 static { 040 init(); 041 } 042 043 /** 044 * Initializes the configuration facility for the default Simon Manager. Fetches exception 045 * if configuration resource or file is not found. This method does NOT clear the manager 046 * itself, only the configuration is reloaded. Method also preserves Callback setup. 047 */ 048 static void init() { 049 Callback temporaryDebugCallback = new SystemDebugCallback(); 050 manager.callback().addCallback(temporaryDebugCallback); // just for reporting warnings, will be removed 051 try { 052 manager.configuration().clear(); 053 String fileName = System.getProperty(PROPERTY_CONFIG_FILE_NAME); 054 if (fileName != null) { 055 try (FileReader fileReader = new FileReader(fileName)) { 056 manager.configuration().readConfig(fileReader); 057 } 058 } 059 String resourceName = System.getProperty(PROPERTY_CONFIG_RESOURCE_NAME); 060 if (resourceName != null) { 061 InputStream is = SimonManager.class.getClassLoader().getResourceAsStream(resourceName); 062 if (is == null) { 063 throw new FileNotFoundException(resourceName); 064 } 065 manager.configuration().readConfig(new InputStreamReader(is)); 066 } 067 } catch (Exception e) { 068 manager.callback().onManagerWarning("SimonManager initialization error", e); 069 } 070 manager.callback().removeCallback(temporaryDebugCallback); 071 } 072 073 private SimonManager() { 074 throw new AssertionError(); 075 } 076 077 /** 078 * Returns Simon by its name if it exists. 079 * 080 * @param name name of the Simon 081 * @return Simon object 082 */ 083 public static Simon getSimon(String name) { 084 return manager.getSimon(name); 085 } 086 087 /** 088 * Destroys Simon or replaces it with UnknownSimon if it's necessary to preserve the hierarchy. 089 * 090 * @param name name of the Simon 091 */ 092 public static void destroySimon(String name) { 093 manager.destroySimon(name); 094 } 095 096 /** 097 * Returns existing Counter or creates new if necessary. "Anonymous" Counter can 098 * be obtained if null name is specified - then it is not added to the Simon hierarchy. 099 * 100 * @param name name of the Counter 101 * @return counter object 102 */ 103 public static Counter getCounter(String name) { 104 return manager.getCounter(name); 105 } 106 107 /** 108 * Returns existing Stopwatch or creates new if necessary. "Anonymous" Stopwatch can 109 * be obtained if null name is specified - then it is not added to the Simon hierarchy. 110 * 111 * @param name name of the Stopwatch 112 * @return stopwatch object 113 */ 114 public static Stopwatch getStopwatch(String name) { 115 return manager.getStopwatch(name); 116 } 117 118 /** Enables the Simon Manager. Enabled manager provides real Simons. */ 119 public static void enable() { 120 manager.enable(); 121 } 122 123 /** Disables the Simon Manager. Disabled manager provides null Simons that actually do nothing. */ 124 public static void disable() { 125 manager.disable(); 126 } 127 128 /** 129 * Returns true if the Simon Manager is enabled. 130 * 131 * @return true if the Simon Manager is enabled 132 */ 133 public static boolean isEnabled() { 134 return manager.isEnabled(); 135 } 136 137 /** 138 * Returns root Simon. Type of the Simon is unknown at the start but it can be replaced 139 * by the real Simon later. Specific get method with root Simon name constant can be used 140 * in that case. 141 * 142 * @return root Simon 143 */ 144 public static Simon getRootSimon() { 145 return manager.getRootSimon(); 146 } 147 148 /** 149 * Returns unmodifiable collection containing names of all existing Simons. 150 * 151 * @return collection of all Simon names 152 * @since 3.1 153 */ 154 public static Collection<String> getSimonNames() { 155 return manager.getSimonNames(); 156 } 157 158 /** 159 * Returns collection containing all existing Simons accepted by specified {@link SimonFilter}. 160 * If {@code null} pattern is provided all Simons are returned in an unmodifiable Collection. 161 * Otherwise new collection with matching Simons is returned. 162 * 163 * @param simonFilter filter accepting the Simons to result collection 164 * @return collection of all Simons which pass the filter 165 * @see SimonPattern to find out more about possible patterns 166 * @since 3.1 167 */ 168 public static Collection<Simon> getSimons(SimonFilter simonFilter) { 169 return manager.getSimons(simonFilter); 170 } 171 172 /** 173 * Clears the SimonManager (ignored if manager is disabled). All Simons are lost, 174 * but configuration is preserved. 175 */ 176 public static void clear() { 177 manager.clear(); 178 } 179 180 /** 181 * Accesses Simon callback. 182 * 183 * @return Simon callback 184 */ 185 public static CompositeCallback callback() { 186 return manager.callback(); 187 } 188 189 /** 190 * Accesses configuration of this manager. 191 * 192 * @return configuration of this manager 193 */ 194 public static ManagerConfiguration configuration() { 195 return manager.configuration(); 196 } 197 198 /** 199 * Accesses default Simon Manager which is the switching manager. 200 * 201 * @return default Simon Manager 202 */ 203 public static Manager manager() { 204 return manager; 205 } 206 207 /** 208 * Method propagates message to manager's {@link org.javasimon.callback.Callback}. This allows user to report any 209 * message if they implement {@link org.javasimon.callback.Callback#onManagerMessage(String)}. 210 * 211 * @param message message text 212 */ 213 public static void message(String message) { 214 manager.message(message); 215 } 216 217 /** 218 * Method propagates warning to manager's {@link org.javasimon.callback.Callback}. This allows user to report any 219 * warning and/or exception if they implement {@link org.javasimon.callback.Callback#onManagerWarning(String, Exception)}. 220 * 221 * @param warning arbitrary warning message 222 * @param cause exception causing this warning 223 */ 224 public static void warning(String warning, Exception cause) { 225 manager.warning(warning, cause); 226 } 227}