View Javadoc

1   /*
2    * Copyright 2001-2004 The Apache Software Foundation.
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  package org.jdiagnose.runtime;
17  
18  import java.util.ArrayList;
19  import java.util.Iterator;
20  import java.util.List;
21  import java.util.Stack;
22  
23  import org.jdiagnose.DiagnosticContainer;
24  import org.jdiagnose.MessageFactory;
25  import org.jdiagnose.ResultInfo;
26  import org.jdiagnose.concurrent.QueuedExecutor;
27  import org.jdiagnose.message.ExceptionMessageFactory;
28  
29  /***
30   * The DiagnosticRunner is responsible for running a diagnostic and all
31   * of it's children. It has been design to support synchronous and
32   * asynchronous running. Usage is usually:
33   *
34   * <code>
35   * SucceedingDiagnostic diagnostic = new SucceedingDiagnostic();
36   * DiagnosticRunner runner = new DiagnosticRunner(diagnostic);
37   * runner.run();
38   * if(runnner.getResult().getState() == ResultState.FAILURE) {
39   *   log.warn("Diagnostics failed");
40   * }
41   * </code>
42   *
43   * TODO jamie there is an issue with diagnostic results and concurrency
44   * TODO jamie consider attaching the listeners to the inner class
45   * TODO jamie consider creating new diagnostic results per run
46   */
47  public class DefaultDiagnosticRunner implements DiagnosticRunner {
48  
49      private DiagnosticContainerResult containerResult;
50      private Object runLock = new Object();
51      private boolean running = false;
52      private QueuedExecutor executor = new QueuedExecutor();
53      private ArrayList runListeners = new ArrayList();
54      private ArrayList resultListeners = new ArrayList();
55      private MessageFactory messageFactory = ExceptionMessageFactory.DEFAULT_EXCEPTION_MESSAGE_FACTORY;
56  
57      public DefaultDiagnosticRunner(DiagnosticContainer container) {
58          this.containerResult = new DefaultDiagnosticContainerResult(messageFactory, container);
59      }
60      
61      private ResultInfo[] convert(Stack stack) {
62          return (ResultInfo[]) stack.toArray(new ResultInfo[stack.size()]);
63      }
64      
65      protected void runDiagnosticContainerResult(Stack stack, DiagnosticContainerResult container) {
66          try {
67          stack.push(container);
68          fireDiagnosticResultStarted(new ResultEvent(this, container, convert(stack)));
69          for (Iterator containerIterator = container.getContainerResults().iterator(); containerIterator.hasNext();) {
70              DiagnosticContainerResult childContainerResult = (DiagnosticContainerResult) containerIterator.next();
71              runDiagnosticContainerResult(stack, childContainerResult);
72          }
73          for (Iterator resultIterator = container.getResults().iterator(); resultIterator.hasNext();) {
74              DiagnosticResult result = (DiagnosticResult) resultIterator.next();
75              try {
76                  stack.push(result);
77                  fireDiagnosticResultStarted(new ResultEvent(this, result, convert(stack)));
78                  result.diagnose();
79              } finally {
80                  fireDiagnosticResultFinished(new ResultEvent(this, result, convert(stack)));
81                  stack.pop();
82              }
83          }
84          fireDiagnosticResultFinished(new ResultEvent(this, container, convert(stack)));
85          } finally {
86              stack.pop();
87          }
88      }
89      
90      protected void realRun() {
91          try {
92              fireDiagnosticRunStarted(new RunEvent(this, this));
93  
94              runDiagnosticContainerResult(new Stack(), containerResult);
95              
96          } finally {
97              fireDiagnosticRunFinished(new RunEvent(this, this));
98          }
99      }
100 
101     public DiagnosticContainerResult run() {
102         synchronized (runLock) {
103             if (!running) {
104                 try {
105                     running = true;
106                     realRun();
107                 } finally {
108                     running = false;
109                 }
110             }
111             return containerResult;
112         }
113     }
114 
115     public DiagnosticContainerResult runAsynchronously() throws InterruptedException {
116         synchronized (runLock) {
117             if(!running) {
118                     running = true;
119                     executor.execute(new Runnable() {
120                         public void run() {
121                             try {
122                                 DefaultDiagnosticRunner.this.realRun();
123                             } finally {
124                                 running = false;
125                             }
126                         }
127                     });
128             }
129             return containerResult;
130         }
131     }
132 
133     protected void fireDiagnosticRunStarted(RunEvent event) {
134         List clonedListeners = (ArrayList) runListeners.clone();
135         for (Iterator iterator = clonedListeners.iterator(); iterator.hasNext();) {
136             RunListener listener = (RunListener) iterator.next();
137             listener.runStarted(event);
138         }
139     }
140 
141     protected void fireDiagnosticRunFinished(RunEvent event) {
142         List clonedListeners = (ArrayList) runListeners.clone();
143         for (Iterator iterator = clonedListeners.iterator(); iterator.hasNext();) {
144             RunListener listener = (RunListener) iterator.next();
145             listener.runFinished(event);
146         }
147     }
148 
149     protected void fireDiagnosticResultStarted(ResultEvent event) {
150         List clonedListeners = (ArrayList) resultListeners.clone();
151         for (Iterator iterator = clonedListeners.iterator(); iterator.hasNext();) {
152             ResultListener listener = (ResultListener) iterator.next();
153             listener.diagnosticStarted(event);
154         }
155     }
156 
157     protected void fireDiagnosticResultFinished(ResultEvent event) {
158         List clonedListeners = (ArrayList) resultListeners.clone();
159         for (Iterator iterator = clonedListeners.iterator(); iterator.hasNext();) {
160             ResultListener listener = (ResultListener) iterator.next();
161             listener.diagnosticFinished(event);
162         }
163     }
164     
165     public void addRunListener(RunListener runListener) {
166         this.runListeners.add(runListener);
167     }
168     
169     public void removeRunListener(RunListener runListener) {
170         this.runListeners.remove(runListener);
171     }
172 
173     public void addResultListener(ResultListener resultListener) {
174         this.resultListeners.add(resultListener);
175     }
176     
177     public void removeResultListener(ResultListener resultListener) {
178         this.resultListeners.remove(resultListener);
179     }
180     
181     public boolean isRunning() {
182         return running;
183     }
184     
185     public DiagnosticContainerResult getContainerResult() {
186         return containerResult;
187     }
188 
189     /* (non-Javadoc)
190      * @see org.jdiagnose.runtime.DiagnosticRunner#setRunListeners(java.util.List)
191      */
192     public void setRunListeners(List runListeners) {
193         this.runListeners.clear();
194         this.runListeners.addAll(runListeners);
195     }
196 
197     /* (non-Javadoc)
198      * @see org.jdiagnose.runtime.DiagnosticRunner#setResultListeners(java.util.List)
199      */
200     public void setResultListeners(List resultListeners) {
201         this.resultListeners.clear();
202         this.resultListeners.addAll(resultListeners);
203     }
204 }