1 4 package org.oddjob.framework; 5 6 import java.io.IOException ; 7 import java.io.ObjectInputStream ; 8 import java.io.ObjectOutputStream ; 9 import java.io.Serializable ; 10 import java.lang.reflect.InvocationHandler ; 11 import java.lang.reflect.Method ; 12 import java.lang.reflect.Proxy ; 13 import java.util.Arrays ; 14 import java.util.HashMap ; 15 import java.util.HashSet ; 16 import java.util.Map ; 17 import java.util.Set ; 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 40 public class RunnableWrapper extends BaseWrapper 41 implements InvocationHandler , Serializable { 42 private static final long serialVersionUID = 20051231; 43 44 private Runnable wrapped; 45 private transient DynaBean dynaBean; 46 47 private volatile transient Thread thread; 48 49 private transient Map methods; 50 51 private Object proxy; 52 53 protected RunnableWrapper() { } 54 55 private RunnableWrapper(Runnable wrapped) { 56 setWrapped(wrapped); 57 } 58 59 public static Runnable wrapperFor(Runnable wrapped) { 60 RunnableWrapper wrapper = new RunnableWrapper(wrapped); 61 Set interfaces = new HashSet (); 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 )) { 73 interfaces.add(Transient.class); 74 } 75 wrapper.proxy = 76 Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), 77 (Class []) interfaces.toArray(new Class [0]), 78 wrapper); 79 80 wrapper.stateHandler = new JobStateHandler(wrapper.proxy); 81 wrapper.iconHelper = new IconHelper(wrapper.proxy); 82 83 return (Runnable ) wrapper.proxy; 84 } 85 86 public Object invoke(Object proxy, Method method, Object [] args) throws Throwable { 87 Object destination = methods.get(method); 88 if (destination == null) { 89 destination = this; 91 } 92 return method.invoke(destination, args); 93 } 94 95 protected Object getWrapped() { 96 return wrapped; 97 } 98 99 protected DynaBean getDynaBean() { 100 return dynaBean; 101 } 102 103 protected Object getProxy() { 104 return proxy; 105 } 106 107 108 protected void setWrapped(Runnable wrapped) { 109 this.wrapped = wrapped; 110 this.dynaBean = new WrapDynaBean(wrapped); 111 this.methods = new HashMap (); 112 113 Class [] 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 .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 from, Object destination) { 130 Method [] 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 oldMDC = (String )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 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 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 192 private void writeObject(ObjectOutputStream s) 193 throws IOException { 194 if (destroyed) { 195 throw new IllegalStateException ("[" + this + "] destroyed"); 196 } 197 s.defaultWriteObject(); 198 s.writeObject((Serializable ) getWrapped()); 199 s.writeObject(stateHandler); 200 s.writeObject(iconHelper); 201 } 202 203 206 private void readObject(ObjectInputStream s) 207 throws IOException , ClassNotFoundException { 208 s.defaultReadObject(); 209 Runnable wrapped = (Runnable ) 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 |