1
2
3
4
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 }