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}