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}