KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > oddjob > framework > RunnableWrapper


1 /*
2  * Copyright (c) 2005, Rob Gordon.
3  */

4 package org.oddjob.framework;
5
6 import java.io.IOException JavaDoc;
7 import java.io.ObjectInputStream JavaDoc;
8 import java.io.ObjectOutputStream JavaDoc;
9 import java.io.Serializable JavaDoc;
10 import java.lang.reflect.InvocationHandler JavaDoc;
11 import java.lang.reflect.Method JavaDoc;
12 import java.lang.reflect.Proxy JavaDoc;
13 import java.util.Arrays JavaDoc;
14 import java.util.HashMap JavaDoc;
15 import java.util.HashSet JavaDoc;
16 import java.util.Map JavaDoc;
17 import java.util.Set JavaDoc;
18
19 import org.apache.commons.beanutils.DynaBean;
20 import org.apache.log4j.MDC;
21 import org.oddjob.Iconic;
22 import org.oddjob.Resetable;
23 import org.oddjob.Stateful;
24 import org.oddjob.Stoppable;
25 import org.oddjob.images.IconHelper;
26 import org.oddjob.logging.Log4jArchiver;
27 import org.oddjob.logging.LogEnabled;
28 import org.oddjob.state.JobStateHandler;
29
30 /**
31  * Wraps a Runnable object and adds state to it.
32  * <p>
33  * This is a helper class for parent jobs which depend on their
34  * child being Stateful - this pretends an un Stateful Runnable
35  * is Statful thus allowing the parent to accept plain Runnables
36  * as children.
37  *
38  * @author Rob Gordon.
39  */

40 public class RunnableWrapper extends BaseWrapper
41 implements InvocationHandler JavaDoc, Serializable JavaDoc {
42     private static final long serialVersionUID = 20051231;
43     
44     private Runnable JavaDoc wrapped;
45     private transient DynaBean dynaBean;
46     
47     private volatile transient Thread JavaDoc thread;
48     
49     private transient Map JavaDoc methods;
50     
51     private Object JavaDoc proxy;
52     
53     protected RunnableWrapper() { }
54     
55     private RunnableWrapper(Runnable JavaDoc wrapped) {
56        setWrapped(wrapped);
57     }
58     
59     public static Runnable JavaDoc wrapperFor(Runnable JavaDoc wrapped) {
60         RunnableWrapper wrapper = new RunnableWrapper(wrapped);
61         Set JavaDoc interfaces = new HashSet JavaDoc();
62         interfaces.addAll(Arrays.asList(interfacesFor(wrapped)));
63         interfaces.add(Stateful.class);
64         interfaces.add(Resetable.class);
65         interfaces.add(DynaBean.class);
66         interfaces.add(Stoppable.class);
67         interfaces.add(Iconic.class);
68         interfaces.add(LogEnabled.class);
69         interfaces.add(ContextAware.class);
70         interfaces.add(Initializable.class);
71         interfaces.add(Destroyable.class);
72         if (!(wrapped instanceof Serializable JavaDoc)) {
73             interfaces.add(Transient.class);
74         }
75         wrapper.proxy =
76             Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
77                 (Class JavaDoc[]) interfaces.toArray(new Class JavaDoc[0]),
78                 wrapper);
79         
80         wrapper.stateHandler = new JobStateHandler(wrapper.proxy);
81         wrapper.iconHelper = new IconHelper(wrapper.proxy);
82         
83         return (Runnable JavaDoc) wrapper.proxy;
84     }
85     
86     public Object JavaDoc invoke(Object JavaDoc proxy, Method JavaDoc method, Object JavaDoc[] args) throws Throwable JavaDoc {
87         Object JavaDoc destination = methods.get(method);
88         if (destination == null) {
89             // hashCode etc
90
destination = this;
91         }
92         return method.invoke(destination, args);
93     }
94     
95     protected Object JavaDoc getWrapped() {
96         return wrapped;
97     }
98
99     protected DynaBean getDynaBean() {
100         return dynaBean;
101     }
102
103     protected Object JavaDoc getProxy() {
104         return proxy;
105     }
106
107     
108     protected void setWrapped(Runnable JavaDoc wrapped) {
109         this.wrapped = wrapped;
110         this.dynaBean = new WrapDynaBean(wrapped);
111         this.methods = new HashMap JavaDoc();
112         
113         Class JavaDoc[] interfaces = interfacesFor(wrapped);
114         for (int i = 0; i < interfaces.length; ++i) {
115             addMethods(interfaces[i], wrapped);
116         }
117         addMethods(Stateful.class, this);
118         addMethods(Resetable.class, this);
119         addMethods(DynaBean.class, this);
120         addMethods(Stoppable.class, this);
121         addMethods(Iconic.class, this);
122         addMethods(Runnable JavaDoc.class, this);
123         addMethods(LogEnabled.class, this);
124         addMethods(ContextAware.class, this);
125         addMethods(Initializable.class, this);
126         addMethods(Destroyable.class, this);
127     }
128     
129     private void addMethods(Class JavaDoc from, Object JavaDoc destination) {
130         Method JavaDoc[] ms = from.getDeclaredMethods();
131         for (int i = 0; i < ms.length; ++i) {
132             methods.put(ms[i], destination);
133         }
134     }
135     
136     public void run() {
137         lock.accquire("Job executing.");
138         String JavaDoc oldMDC = (String JavaDoc)MDC.get(Log4jArchiver.MDC);
139         try {
140             MDC.put(Log4jArchiver.MDC, getLogger());
141             if (!stateHandler.requestJobStateExecuting()) {
142                 logger().debug("Can't execute job [" + this + "] because state is ["
143                         + stateHandler.getJobState() + "]");
144                 return;
145             }
146             iconHelper.changeIcon(IconHelper.EXECUTING);
147
148             // runtime configuration.
149
if (!configure()) {
150                 return;
151             }
152             logger().info("Executing job [" + wrapped + "]");
153             
154             thread = Thread.currentThread();
155             wrapped.run();
156
157             logger().info("Finished Job [" + wrapped + "]");
158             int result = getResult();
159             if (result == 0) {
160                 setJobStateComplete();
161             } else {
162                 setJobStateNotComplete();
163             }
164         } catch (Throwable JavaDoc t) {
165             logger().warn("Job Exception in [" + wrapped + "]", t);
166             setJobStateException(t);
167         }
168         finally {
169             thread = null;
170             if (oldMDC != null) {
171                 MDC.put(Log4jArchiver.MDC, oldMDC);
172             }
173             else {
174                 MDC.remove(Log4jArchiver.MDC);
175             }
176             lock.release();
177         }
178     }
179     
180     
181     public void onStop() {
182         if (wrapped instanceof Stoppable) {
183             ((Stoppable) wrapped).stop();
184         } else if (thread != null){
185             thread.interrupt();
186         }
187     }
188     
189     /**
190      * Custom serialsation.
191      */

192     private void writeObject(ObjectOutputStream JavaDoc s)
193     throws IOException JavaDoc {
194         if (destroyed) {
195             throw new IllegalStateException JavaDoc("[" + this + "] destroyed");
196         }
197         s.defaultWriteObject();
198         s.writeObject((Serializable JavaDoc) getWrapped());
199         s.writeObject(stateHandler);
200         s.writeObject(iconHelper);
201     }
202
203     /**
204      * Custom serialisation.
205      */

206     private void readObject(ObjectInputStream JavaDoc s)
207     throws IOException JavaDoc, ClassNotFoundException JavaDoc {
208         s.defaultReadObject();
209         Runnable JavaDoc wrapped = (Runnable JavaDoc) s.readObject();
210         setWrapped(wrapped);
211         stateHandler = (JobStateHandler) s.readObject();
212         stateHandler.setSource(proxy);
213         iconHelper = (IconHelper) s.readObject();
214         iconHelper.setSource(proxy);
215     }
216     
217 }
218
Popular Tags