View Javadoc

1   /*
2    * Copyright (c) 2005, The K-Wf Grid Consortium
3    * Fraunhofer Institute for Computer Architecture and Software Technology
4    * See http://www.kwfgrid.eu and http://www.first.fraunhofer.de for more details.
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  	// configure Protocol
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 }