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.gworkflowdl.protocol.client;
7   
8   import net.kwfgrid.gworkflowdl.protocol.IncompatibleVersionsException;
9   import net.kwfgrid.gworkflowdl.protocol.IllegalModificationException;
10  import net.kwfgrid.gworkflowdl.protocol.IMethodCallEncoder;
11  import net.kwfgrid.gworkflowdl.protocol.AbstractMethodCallStrategyExt;
12  import net.kwfgrid.gworkflowdl.protocol.Protocol;
13  import net.kwfgrid.gworkflowdl.protocol.service.IStructureService;
14  import net.kwfgrid.gworkflowdl.protocol.calls.MethodCallException;
15  import net.kwfgrid.gworkflowdl.protocol.calls.IMethodCall;
16  import net.kwfgrid.gworkflowdl.protocol.structure.IStructureTask;
17  import net.kwfgrid.gworkflowdl.protocol.structure.ProtocolWorkflow;
18  import net.kwfgrid.gworkflowdl.structure.WorkflowFormatException;
19  import net.kwfgrid.gworkflowdl.structure.CapacityException;
20  
21  import java.rmi.RemoteException;
22  import java.io.IOException;
23  import java.util.List;
24  
25  import org.apache.log4j.Logger;
26  
27  /***
28     Extended default implementation of <code>IClientDelegate</code>.
29     This implementation calls the methods of <code>IStructureListenerExt</code> and
30     executes additional tasks added to the queue <code>IRootObject.getTaskQueue()</code>
31     during structure event dispatching.
32   */
33  public class DefaultClientDelegateExt extends AbstractMethodCallStrategyExt implements IClientDelegate {
34      private IStructureService _servicestub;
35      private String _userID;
36  
37      private static final Logger logger = Logger.getLogger(DefaultClientDelegate.class);
38  
39      /***
40         Constructor.
41       @param servicestub The service stub to contact the server.
42        * @param userID
43       */
44      public DefaultClientDelegateExt(IStructureService servicestub, String userID) {
45  	    _servicestub = servicestub;
46          _userID = userID;
47      }
48  
49      public Object execute(IMethodCall call) throws MethodCallException, IllegalModificationException, IncompatibleVersionsException {
50  	IClientRootObject structure = (IClientRootObject)call.getTarget();
51  	IMethodCallEncoder encoder = Protocol.getMethodCallEncoder();
52  	String enc = null;
53  	Object ret = null;	
54  	IStructureTask tasks[] = null;
55  
56  	synchronized(structure.getStructureLock()) {	    
57  	    try {
58  		enc = encoder.encode(call);
59  	    } catch (IOException x) {
60  		IllegalModificationException ix = new IllegalModificationException("Could not encode method call.");
61  		ix.initCause(x);
62  		throw ix;
63  	    }
64  	    try {
65  		commit(structure, enc);
66  	    } catch (RemoteException x) {
67  		IllegalModificationException ix = new IllegalModificationException("Could not commit changes. Exception on server-side.");
68  		ix.initCause(x);
69  		throw ix;		
70  	    }
71  	    
72  	    fireBeginModifications(structure);
73  	    
74  	    try {
75  		ret = call.execute();
76  	    } catch (Exception x) {
77  		fireException(structure, x);
78  		throw new MethodCallException("Could not invoke method call. Structure invalid and needs to be checked out again.", x);
79  	    }
80  	    
81  	    fireEndModifications(structure);
82  
83  	    List queue = structure.getTaskQueue();
84  	    tasks = (IStructureTask[])queue.toArray(new IStructureTask[queue.size()]);
85  	    queue.clear();
86  	}
87  
88  	try {
89  	    for (int i=0; i<tasks.length; i++) {
90  		tasks[i].run();
91  	    }
92  	} catch (IncompatibleVersionsException x) {
93  	    IncompatibleVersionsException ix = new IncompatibleVersionsException("Nested IncompatibleVersionsException.", x);
94  	    throw ix;
95  	} catch (IllegalModificationException x) {
96  	    IllegalModificationException ix = new IllegalModificationException("Nested IllegalModificationException.", x);
97  	    throw ix;
98  	} catch (Exception x) {
99  	    throw new MethodCallException("Could not execute inner method call.", x);
100 	}
101 
102 	return ret;
103     }
104 
105     public void commit(IClientRootObject structure, String modification) throws IllegalModificationException, IncompatibleVersionsException, RemoteException {
106        synchronized (structure.getStructureLock()) {
107            int newversion = _servicestub.commitModification(structure.getID(), structure.getVersionNumber(), modification, _userID);
108 	   structure.setVersionNumber(newversion);
109        }
110     }
111     
112     public void update(IClientRootObject structure) throws IllegalModificationException, RemoteException {
113 	boolean exception = true;
114 	IStructureTask tasks[] = null;
115 		
116 	try {
117 	    synchronized (structure.getStructureLock()) {
118 		/// VERSION, COMMAND, CONTENT
119 		String[][] updates = _servicestub.getModificationsForUpdate(structure.getID(), structure.getVersionNumber(), _userID);
120 
121 		if (updates.length > 0) {
122 
123 		    fireBeginModifications(structure);
124 		    
125 		    for (int i=0; i<updates.length; i++) {
126 			String version = updates[i][0];
127 			String command = updates[i][1];
128 			String content = updates[i][2];
129 			handleUpdate(structure, updates[i][1], updates[i][2]);
130 			structure.setVersionNumber(Integer.parseInt(updates[i][0]));
131 		    }
132 
133 		    fireEndModifications(structure);
134 
135 		    List queue = structure.getTaskQueue();
136 		    tasks = (IStructureTask[])queue.toArray(new IStructureTask[queue.size()]);
137 		    queue.clear();
138 		}
139 
140 		exception = false;
141 	    }   
142 	} catch (NumberFormatException x) {
143 	    throw new IllegalModificationException("Could not parse version number as int.", x);
144 	} finally {
145 	    if (exception) fireException(structure, new Exception("Unknown exception during client update. See log output for details"));
146 	}
147 
148 	try {
149 	    for (int i=0; tasks!=null && i<tasks.length; i++) {
150 		tasks[i].run();
151 	    }
152 	} catch (IncompatibleVersionsException x) {
153 	    IllegalModificationException ix = new IllegalModificationException("Nested IncompatibleVersionsException.", x);
154 	    throw ix;
155 	} catch (IllegalModificationException x) {
156 	    IllegalModificationException ix = new IllegalModificationException("Nested IllegalModificationException.", x);
157 	    throw ix;
158 	} catch (Exception x) {
159 	    IllegalModificationException ix = new IllegalModificationException("Nested Exception during inner method call.", x);
160 	    throw ix;
161 	}
162     }
163 
164     private void handleUpdate(IClientRootObject structure, String command, String content) throws IllegalModificationException {
165 	if (Protocol.IDENTIFIER_FULLUPDATE.equals(command)) {
166 	    try {
167 		((ProtocolWorkflow)structure).__fromXML(content);
168 	    } catch (WorkflowFormatException x) {
169 		throw new IllegalModificationException("Could not parse workflow description.", x);
170 	    } catch (CapacityException x) {
171 		throw new IllegalModificationException("Could not parse workflow description.", x);
172 	    }
173 	} else if (Protocol.IDENTIFIER_MODIFICATION.equals(command))  {
174 	    Protocol.getModificationHandler().handleModification(structure, content);
175 	} else {
176 	    throw new IllegalModificationException("Unknown update command: "+command);
177 	}	
178     }
179 }