View Javadoc

1   /*
2    Copyright 2006 Ernest Micklei @ PhilemonWorks.com
3   
4    Licensed under the Apache License, Version 2.0 (the "License");
5    you may not use this file except in compliance with the License.
6    You may obtain a copy of the License at
7   
8    http://www.apache.org/licenses/LICENSE-2.0
9   
10   Unless required by applicable law or agreed to in writing, software
11   distributed under the License is distributed on an "AS IS" BASIS,
12   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   See the License for the specific language governing permissions and
14   limitations under the License.
15   
16   */
17  package com.philemonworks.selfdiagnose;
18  
19  import java.io.InputStream;
20  import java.net.URL;
21  import java.util.ArrayList;
22  import java.util.Collections;
23  import java.util.List;
24  
25  import javax.xml.parsers.SAXParser;
26  import javax.xml.parsers.SAXParserFactory;
27  
28  import org.apache.log4j.Logger;
29  
30  import com.philemonworks.selfdiagnose.output.DiagnoseRun;
31  import com.philemonworks.selfdiagnose.output.DiagnoseRunReporter;
32  import com.philemonworks.selfdiagnose.output.XMLReporter;
33  
34  /**
35   * SelfDiagnose is the component that keeps a registration of DiagnosticTasks
36   * and can run them providing a simple report that is logged using Log4j.
37   * Registration is done:
38   * <ul>
39   * <li>programmatically by invoking the register() method passing a
40   * DiagnosticTask subclass instance</li>
41   * <li>declarative by providing a configuration file named
42   * <strong>selfdiagnose.xml</strong> that conforms to the
43   * <strong>selfdiagnose.xsd</strong></li>
44   * </ul>
45   * 
46   * @author Ernest M. Micklei
47   */
48  public abstract class SelfDiagnose {
49  	public static final String MDC_SELFDIAGNOSE_TASK_RESULT = "selfdiagnose-task-result";
50  
51  	/**
52  	 * The name of the resource that holds the specification of tasks.
53  	 */
54  	public final static String VERSION = "2.4-SNAPSHOT";
55  	public final static String COPYRIGHT = "(c) PhilemonWorks.com";
56  	public final static String CONFIG = "selfdiagnose.xml";
57  	private static URL CONFIG_URL = null; // will be initialized by configure(...)
58  	private final static Logger LOG = Logger.getLogger(SelfDiagnose.class);
59  
60  	private static List<DiagnosticTask> tasks = Collections.synchronizedList(new ArrayList<DiagnosticTask>());
61  	static {
62  		SelfDiagnose.configure(CONFIG);
63  	}
64  
65  	/**
66  	 * Return the filename that is used to configure SelfDiagnose
67  	 * @return
68  	 */
69  	public static String getConfigFilename(){
70  	    if (SelfDiagnose.CONFIG_URL == null) return "unknown";
71  	    String resourceName = SelfDiagnose.CONFIG_URL.getFile();
72  	    return resourceName.substring(resourceName.lastIndexOf('/')+1);
73  	}
74  	/**
75  	 * Try to configure SelfDiagnose using the XML configuration file with the
76  	 * given resource name.
77  	 * 
78  	 * @param resourceName : String
79  	 */
80  	public static void configure(String resourceName) {
81  		// If a configuration file can be founds then process it first.
82  		URL configURL = DiagnoseUtil.findResource(resourceName, false);
83  		if (configURL == null) {
84  			LOG
85  					.warn("No configuration found. SelfDiagnose will only run tasks that are registered by the application. "
86  							+ "If this was not intended then make sure that the configuration ["
87  							+ resourceName
88  							+ "] can be found on the classpath.");
89  			return;
90  		}
91  		SelfDiagnose.configure(configURL);
92  	}
93  	/**
94  	 * Read the configuration from the resource by URL.
95  	 * @param configURL : URL
96  	 */
97  	public static void configure(URL configURL) {
98  		if (configURL == null) {
99  			LOG.info("Unable to configure because URL is not given");
100 			return;
101 		}
102 		LOG.info("Initializing from configuration [" + configURL.getFile() + "]");
103 		tasks = Collections.synchronizedList(new ArrayList());
104 		CONFIG_URL = configURL;
105 		try {			
106 			configure(configURL.openStream());
107 		} catch (Exception e) {
108 			LOG.error("Aborted configuration of SelfDiagnose using [" + configURL.getFile() + "] because: " + e.toString());
109 		}
110 	}
111 	/**
112 	 * Read the configuration from an InputStream
113 	 * @param is
114 	 * @throws Exception
115 	 */
116 	public static void configure(InputStream is) throws Exception {
117 	    
118         SAXParser p = SAXParserFactory.newInstance().newSAXParser();
119         SelfDiagnoseHandler s = new SelfDiagnoseHandler();
120         p.parse(is, s);
121         is.close();	    
122 	}
123 
124 	/**
125 	 * Flush all registered tasks from the configuration and re-load the
126 	 * configuration.
127 	 */
128 	public static void reloadConfiguration() {
129 		LOG.info("Flushing registered diagnostic tasks by configuration");
130 		SelfDiagnose.configure(CONFIG_URL);
131 	}
132 
133 	/**
134 	 * Add the argument to the global list of Diagnostic tasks.
135 	 * 
136 	 * @param task
137 	 *            DiagnosticTask
138 	 * @return DiagnosticTask
139 	 */
140 	public static DiagnosticTask register(DiagnosticTask task) {
141 		return SelfDiagnose.register(task, DiagnoseUtil.detectRequestorClass().getName());
142 	}
143 
144 	/**
145 	 * Add the argument to the global list of Diagnostic tasks.
146 	 * 
147 	 * @param task
148 	 *            DiagnosticTask
149 	 * @param identifier
150 	 *            String
151 	 * @return DiagnosticTask
152 	 */
153 	public static DiagnosticTask register(DiagnosticTask task, String identifier) {
154 		task.setRequestor(identifier);
155 		tasks.add(task);
156 		return task;
157 	}
158 
159   public static DiagnoseRun runTasks() { return runTasks(new XMLReporter()); }	
160 
161   
162       /**
163        * Basic method to run all registered tasks.
164        * 
165        */
166       public static DiagnoseRun runTasks(DiagnoseRunReporter reporter) {
167           return SelfDiagnose.runTasks(tasks, reporter, new ExecutionContext());
168       }
169       /**
170        * Basic method to run all registered tasks.
171        * 
172        */
173       public static DiagnoseRun runTasks(DiagnoseRunReporter reporter, ExecutionContext ctx) {
174           return SelfDiagnose.runTasks(tasks, reporter, ctx);
175       }      
176 	/**
177 	 * Basic method to the tasks provided 
178 	 * 
179 	 */
180 	public static DiagnoseRun runTasks(List<DiagnosticTask> taskList, DiagnoseRunReporter reporter, ExecutionContext ctx) {
181 	    DiagnoseRun run = new DiagnoseRun();
182 		List<DiagnosticTaskResult> results = new ArrayList<DiagnosticTaskResult>(taskList.size());
183 		for (int i = 0; i < taskList.size(); i++) {
184 			DiagnosticTask each = (DiagnosticTask) taskList.get(i);
185 			DiagnosticTaskResult result = each.run(ctx);
186 			result.addToResults(results);
187 		}
188 		run.finished();
189 		run.results = results;
190 		reporter.report(run);
191 		return run;
192 	}
193 
194 	/**
195 	 * Run all registered DiagnosticTasks and report to the LOG. After running
196 	 * all tasks, some simple statistics are logged.
197 	 */
198 	public static void run() {
199 		SelfDiagnose.runTasks(new XMLReporter());
200 	}
201 	/**
202 	 * Flush all registered tasks
203 	 */
204 	public static void flush() {
205 		tasks = Collections.synchronizedList(new ArrayList<DiagnosticTask>());
206 	}
207 
208 	/**
209 	 * Return the modifiable collection of registered Diagnostic tasks. Use at
210 	 * your own risk.
211 	 */
212 	public static List<DiagnosticTask> getTasks() {
213 		return tasks;
214 	}
215 }