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