1
2
3
4
5
6 package net.kwfgrid.gwui;
7
8 import net.kwfgrid.gwui.workflow.SwingClientDelegateExt;
9 import net.kwfgrid.gworkflowdl.structure.*;
10 import net.kwfgrid.gworkflowdl.protocol.client.*;
11 import net.kwfgrid.gworkflowdl.protocol.*;
12 import net.kwfgrid.gworkflowdl.protocol.service.IStructureService;
13 import net.kwfgrid.gworkflowdl.protocol.xupdate.*;
14 import net.kwfgrid.gworkflowdl.structure.DefaultCreator;
15 import net.kwfgrid.gworkflowdl.structure.Creator;
16 import net.kwfgrid.gworkflowdl.structure.Factory;
17 import net.kwfgrid.jxupdate.jaxen.jbind.BindingFactory;
18 import net.kwfgrid.jxupdate.xupdate.XUpdateHandler;
19 import net.kwfgrid.jxupdate.xupdate.jbind.JXUpdateHandler;
20 import net.kwfgrid.gwes.restfulclient.RestfulStructureGWES;
21
22 import org.apache.log4j.Logger;
23
24 import org.glassbox.executor.Executor;
25 import org.glassbox.SwingThread;
26
27 import java.util.*;
28 import javax.swing.JDialog;
29 import java.rmi.RemoteException;
30 import java.net.URL;
31
32 /***
33 This implementation of WorkflowInstanceManager handles a single ClientWorkflow instance.
34 The workflow is updated regularly (see <code>POLL_TIME</code>) from the server.
35 The class is also responsible for configuring the GWorkflowDL protocol and factory.
36 */
37 public class SingleClientWorkflowInstanceManager implements WorkflowInstanceManager {
38 /*** Poll interval for workflow updating in ms. */
39 public static final int POLL_TIME = 200;
40 /*** Number of retries when update failed. */
41 public static final int RETRIES = 5;
42
43 private static final Logger logger = Logger.getLogger(SingleClientWorkflowInstanceManager.class);
44
45 static {
46 logger.info("Initializing GWorkflowDL protocol ...");
47
48
49 IStructureService service = null;
50 try {
51 service = GWUI.getInstance().getIStructureService();
52 } catch (Exception e) {
53 logger.error("exception:\n" + e, e);
54 }
55 IMethodCallStrategy defaults = new DefaultMethodCallStrategyExt();
56 IMethodCallStrategy protocol = new SwingClientDelegateExt(service);
57 BindingFactory bfact = JBindFactoryProvider.getBindingFactory();
58 XUpdateHandler guihandler = new JXUpdateHandler(bfact);
59 IModificationHandler handler = new XUModificationHandler(guihandler, bfact);
60 IMethodCallEncoder encoder = new XUMethodCallEncoder();
61 Protocol.setDefaultMethodCallStrategy(defaults);
62 Protocol.setProtocolMethodCallStrategy(protocol);
63 Protocol.setModificationHandler(handler);
64 Protocol.setMethodCallEncoder(encoder);
65
66 Creator creator = new ClientCreator(new DefaultCreator());
67 Factory.setCreator(creator);
68
69 logger.info("Initializing GWorkflowDL protocol READY.");
70
71 logger.info("Applying workaround for URL StreamHandlerFactory ...");
72
73 URL.setURLStreamHandlerFactory( null );
74 System.setProperty( "java.protocol.handler.pkgs", "sun.net.www.protocol" );
75
76 logger.info("Applying workaround for URL StreamHandlerFactory READY.");
77 }
78
79 protected class Updater extends Thread {
80 private boolean _cancel;
81 private ClientWorkflow _client;
82 private int _retry;
83 private Throwable _exception;
84 private WorkflowGroup _group;
85 private String _exceptiontitle;
86
87 public Updater(WorkflowGroup group, ClientWorkflow client) {
88 super("ClientUpdater");
89 _client = client;
90 _cancel = false;
91 _retry = RETRIES;
92 _exception = null;
93 _exceptiontitle = null;
94 _group = group;
95 }
96
97 public synchronized void cancel() {
98 logger.debug("cancel()");
99
100 _cancel = true;
101 notifyAll();
102
103 logger.debug("cancel() exited.");
104 }
105
106 public void run() {
107 try {
108 synchronized (this) {
109 while (!_cancel && _retry > 0 && !Thread.currentThread().isInterrupted()) {
110 try {
111 logger.debug("Updating client.");
112
113 _client.update();
114
115 logger.debug("Updating client ready.");
116
117 _retry = RETRIES;
118 _exception = null;
119 } catch (RemoteException x) {
120 logger.error("Could not update client.", x);
121 _exception = x;
122 _exceptiontitle = "Server connection failed.";
123 _retry--;
124 }
125 wait(POLL_TIME);
126 }
127 }
128 } catch (InterruptedException xx) {
129 logger.warn("Interrupted.");
130 } catch (Exception x) {
131 logger.error("Could not update client.", x);
132 _exception = x;
133 _exceptiontitle = "Could not update workflow.";
134 }
135
136 logger.debug("About to exit run()");
137
138 if (!_cancel && _exception != null) {
139 JDialog e = SwingFactory2.createErrorDialog("Error", _exceptiontitle, _exception);
140 e.show();
141 }
142
143 logger.debug("run() exited.");
144 }
145 }
146
147 private ClientWorkflow _client;
148 private Updater _updater;
149
150 public SingleClientWorkflowInstanceManager() {
151 _client = null;
152 _updater = null;
153 }
154
155 public synchronized void setWorkflowID(final WorkflowGroup group, String newworkflowid) {
156 logger.debug("setWorkflowID("+group+", "+newworkflowid+")");
157
158 Workflow oldworkflow = (Workflow)group.getProperty(WorkflowGroup.ACTIVE_WORKFLOW_DOCUMENT_KEY);
159 String oldworkflowid = oldworkflow==null?null:oldworkflow.getID();
160 if (newworkflowid == null && _client != null) {
161 interruptClient();
162 SwingThread.invokeAndWaitSilently(new Runnable() {
163 public void run() {
164 group.setProperty(WorkflowGroup.ACTIVE_WORKFLOW_DOCUMENT_KEY, null);
165 }
166 });
167 } else if (newworkflowid != null && !newworkflowid.equals(oldworkflowid)) {
168 interruptClient();
169 createNewClient(group, newworkflowid);
170 SwingThread.invokeAndWaitSilently(new Runnable() {
171 public void run() {
172 group.setProperty(WorkflowGroup.ACTIVE_WORKFLOW_DOCUMENT_KEY, _client);
173 }
174 });
175 }
176
177 logger.debug("setWorkflowID() exited.");
178 }
179
180 public synchronized void interruptClient() {
181 logger.debug("interruptClient()");
182
183 if (_updater != null) {
184 try {
185 _updater.interrupt();
186 } catch (Exception x) {
187 logger.debug("Got exception when interrupting client, ignored.", x);
188 }
189 _updater = null;
190 }
191 _client = null;
192
193 logger.debug("interruptClient() exited.");
194 }
195
196 private void createNewClient(WorkflowGroup group, String workflowid) {
197 logger.debug("Creating new client with ID: "+workflowid);
198
199 _client = (ClientWorkflow)Factory.newWorkflow(workflowid);
200 try {
201 _client.update();
202 } catch (RemoteException rx) {
203 logger.error("Could not update client.", rx);
204 }
205 createUpdater(group, _client);
206
207 logger.debug("Client created.");
208 }
209
210 private void createUpdater(WorkflowGroup group, ClientWorkflow workflow) {
211 _updater = new Updater(group, workflow);
212 _updater.start();
213 }
214 }