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.server;
7   
8   import net.kwfgrid.gworkflowdl.protocol.IncompatibleVersionsException;
9   import net.kwfgrid.gworkflowdl.protocol.IllegalModificationException;
10  import net.kwfgrid.gworkflowdl.protocol.IModificationHandler;
11  import net.kwfgrid.gworkflowdl.protocol.IMethodCallEncoder;
12  import net.kwfgrid.gworkflowdl.protocol.AbstractMethodCallStrategyExt;
13  import net.kwfgrid.gworkflowdl.protocol.Protocol;
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.structure.JdomString;
18  import net.kwfgrid.gworkflowdl.structure.Workflow;
19  
20  import java.io.IOException;
21  import java.util.List;
22  
23  import org.apache.log4j.Logger;
24  
25  /***
26     Extended default implementation of <code>IServerDelegate</code> for a <code>Workflow</code> structure.
27     This implementation calls the methods of <code>IStructureListenerExt</code> and
28     executes additional tasks added to the queue <code>IRootObject.getTaskQueue()</code>
29     during structure event dispatching.
30   */
31  public class DefaultServerDelegateExt extends AbstractMethodCallStrategyExt implements IServerDelegate {
32      private static final Logger logger = Logger.getLogger(DefaultServerDelegateExt.class);
33  
34      public Object execute(IMethodCall call) throws MethodCallException, IllegalModificationException {
35  	IServerRootObject structure = (IServerRootObject)call.getTarget();
36  	IMethodCallEncoder encoder = Protocol.getMethodCallEncoder();
37  	Object ret = null;
38  	String enc = null;
39  	int newversion = -1;
40  	IStructureTask tasks[] = null;
41  
42  	synchronized(structure.getStructureLock()) {
43  	    boolean cupdate = structure.getClientUpdateOccured();
44  	    if (cupdate) {
45  		try {
46  		    enc = encoder.encode(call);
47  		} catch (IOException x) {
48  		    throw new IllegalModificationException("Could not encode method call.", x);
49  		}
50  	    }
51  	    
52  	    fireBeginModifications(structure);
53  	    
54  	    try {		
55  		ret = call.execute();
56  	    } catch (Exception x) {
57  		fireException(structure, x);
58  		throw new MethodCallException("Could not execute method call.", x);
59  	    }
60  	    
61  	    fireEndModifications(structure);
62  	    
63  	    newversion = structure.incrementVersionNumber();
64  	    
65  	    if (cupdate) {
66  		structure.getModificationBuffer().write(newversion, enc);
67  	    } else {
68  		structure.getModificationBuffer().setInitialVersion(newversion);
69  	    }
70  	    
71  	    structure.setXMLValid(false);
72  
73  	    List queue = structure.getTaskQueue();
74  	    tasks = (IStructureTask[])queue.toArray(new IStructureTask[queue.size()]);
75  	    queue.clear();
76  	}
77  
78  	try {
79  	    for (int i=0; i<tasks.length; i++) {
80  		tasks[i].run();
81  	    }
82  	} catch (IllegalModificationException x) {
83  	    IllegalModificationException ix = new IllegalModificationException("Nested IllegalModificationException.", x);
84  	    throw ix;
85  	} catch (Exception x) {
86  	    throw new MethodCallException("Could not execute inner method call.", x);
87  	}
88  
89  	return ret;
90      }
91  
92      public String[][] getModificationsForUpdate(IServerRootObject structure, int clientversion) {
93  	synchronized (structure.getStructureLock()) {
94  	    structure.setClientUpdateOccured();
95  	    ModificationBuffer buffer = structure.getModificationBuffer();
96  	    if (clientversion < buffer.firstHandleableVersion()) {
97  		return new String[][] { { ""+structure.getVersionNumber(), Protocol.IDENTIFIER_FULLUPDATE, structure.getXML() } };
98  	    } else {
99  		return buffer.read(clientversion);
100 	    }
101 	}
102     }
103 
104     public int commitModification(IServerRootObject structure, int clientversion, String modification) throws IncompatibleVersionsException, IllegalModificationException {
105 	boolean exception = true;
106 	int newversion = -1;
107 	IStructureTask[] tasks = null;
108 
109 	try {
110 	    synchronized(structure.getStructureLock()) {
111 		if (structure.getVersionNumber() != clientversion)
112 		    throw new IncompatibleVersionsException("The client's version is incompatible for commit ("+clientversion+" != "+structure.getVersionNumber()+").");
113 		
114 		fireBeginModifications(structure);
115 		
116 		Protocol.getModificationHandler().handleModification(structure, modification);	       
117 		
118 		exception = false;
119 		
120 		fireEndModifications(structure);
121 
122 		newversion = structure.incrementVersionNumber();
123 		
124 		if (structure.getClientUpdateOccured()) {
125 		    structure.getModificationBuffer().write(newversion, modification);
126 		} else {
127 		    structure.getModificationBuffer().setInitialVersion(newversion);
128 		}
129 		
130 		structure.setXMLValid(false);
131 
132 		List queue = structure.getTaskQueue();
133 		tasks = (IStructureTask[])queue.toArray(new IStructureTask[queue.size()]);
134 		queue.clear();
135 		
136 	    }	
137 	} finally {
138 	    if (exception) fireException(structure, new Exception("Unknown exception during commit. See log output for details."));
139 	}
140 
141 	try {
142 	    for (int i=0; i<tasks.length; i++) {
143 		tasks[i].run();
144 	    }
145 	} catch (Exception x) {
146 	    logger.error("Exception during inner method call after client commit for structure: "+structure.getID(), x);
147 	}
148 	
149 	return newversion;		
150     }
151 
152     public String getXML(IServerRootObject structure, String currentxml) {
153 	synchronized(structure.getStructureLock()) {
154 	    if (!structure.isXMLValid()) {
155 		try {
156 		    currentxml = JdomString.workflow2string((Workflow)structure);
157 		    structure.setXML(currentxml);
158 		    structure.setXMLValid(true);
159 		} catch (IOException x) {
160 		    logger.error("FATAL: Could not write XML description of workflow.", x);
161 		    currentxml = "<workflow/>";
162 		}
163 	    }	    
164 	    return currentxml;
165 	}
166     }
167 }