1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.caleigo.core;
20
21 import java.util.*;
22
23 import org.caleigo.core.exception.DataServiceException;
24 import org.caleigo.service.ServiceException;
25 import org.caleigo.toolkit.tunnel.*;
26
27
28 /***
29 *
30 * @author Mattias Hagstrand
31 * @version 1.00
32 *
33 *//*
34 *
35 * WHEN WHO WHY & WHAT
36 * -----------------------------------------------------------------------------
37 * 2002-08-01 Mattias Hagstrand Creation
38 */
39 public class TunneledDataService extends AbstractDataService implements org.caleigo.service.IProxyService
40 {
41
42 protected transient ITunnel mTunnel;
43
44
45 public TunneledDataService(Object serviceType,
46 Object serviceIdentity,
47 IDataSourceDescriptor dataSourceDescriptor,
48 ITunnel tunnel)
49 {
50 super(serviceType, serviceIdentity, dataSourceDescriptor);
51 mTunnel = tunnel;
52 }
53
54
55
56 /*** Returns <code>true</code> if this IProxyService can be reconnected to
57 * an IService.
58 */
59 public boolean isReconnectable()
60 {
61 return false;
62 }
63
64 /*** Tries to reconnect to the provided service. If the reconnection fails
65 * or if this IProxyService doesn't support reconnection an exception is
66 * thrown.
67 */
68 public void reconnect(ITunnel tunnel) throws ServiceException
69 {
70 throw new ServiceException("Operation not supported");
71 }
72
73 /*** Sets the ITunnel that should be used by this IProxyService.
74 */
75 public void setServiceTunnel(ITunnel tunnel)
76 {
77 mTunnel = tunnel;
78 }
79
80
81 public IDataTransaction newTransaction()
82 {
83 return new TunneledDataTransaction(getTimeout(),
84 getServiceInterfaceClass(),
85 getServiceType(),
86 getServiceIdentity(),
87 mTunnel);
88 }
89
90 public boolean ping()
91 {
92 try
93 {
94 mTunnel.ping();
95 return true;
96 }
97 catch (TunnelException e)
98 {
99 return false;
100 }
101 }
102
103
104 protected static class TunneledDataTransaction extends AbstractDataTransaction implements IMessageConsumer
105 {
106
107 protected Class mServiceInterfaceClass;
108 protected Object mServiceType;
109 protected Object mServiceIdentity;
110 protected transient ITunnel mTunnel;
111
112
113 public TunneledDataTransaction(int timeout,
114 Class serviceInterfaceClass,
115 Object serviceType,
116 Object serviceIdentity,
117 ITunnel tunnel)
118 {
119 super(timeout);
120
121 mServiceInterfaceClass = serviceInterfaceClass;
122 mServiceType = serviceType;
123 mServiceIdentity = serviceIdentity;
124 mTunnel = tunnel;
125
126 mTunnel.addMessageConsumer(this);
127 }
128
129
130
131 /*** Commit performs all the stored operations in the transaction.
132 * If any of the operations fail a rollback on all operations will be
133 * automatically performed and a TransactionFailedException will be thrown.
134 */
135 public void commit() throws DataServiceException
136 {
137 TunneledDataServiceReturnMessage returnMessage = null;
138 try
139 {
140 returnMessage = (TunneledDataServiceReturnMessage) mTunnel.ask(new TunneledDataServiceCommitMessage(mServiceInterfaceClass, mServiceType, mServiceIdentity, this));
141 }
142 catch (TunnelException e)
143 {
144 throw new DataServiceException(e.getMessage());
145 }
146
147 this.copyTransactionData(returnMessage.getOperations());
148 }
149
150 public void abortTransaction() throws DataServiceException
151 {
152 try
153 {
154 mTunnel.ask(new TunneledDataServiceAbortTransactionMessage(mServiceInterfaceClass, mServiceType, mServiceIdentity, this.getID()));
155 } catch (TunnelException e)
156 {
157 throw new DataServiceException(e.getMessage());
158 }
159 }
160
161
162
163 public boolean acceptsMessage(Object message)
164 {
165 return (message instanceof TunneledDataServiceProgressMessage);
166 }
167
168 public Object answerMessage(Object message)
169 {
170 return null;
171 }
172
173 public void consumeMessage(Object message)
174 {
175 if (mJob != null)
176 {
177 TunneledDataServiceProgressMessage progressMessage = (TunneledDataServiceProgressMessage) message;
178 mJob.fireProgressChangedEvent(progressMessage.mMaxProgress, progressMessage.mCurrentProgress);
179 }
180 }
181
182
183 protected void copyTransactionData(AbstractDataTransaction.DataOperation[] sourceDataOperations)
184 {
185 Enumeration targetDataOperations = this.getOperations();
186
187 for (int i = 0; i < sourceDataOperations.length && targetDataOperations.hasMoreElements(); i++)
188 {
189
190 DataOperation sourceOperation = sourceDataOperations[i];
191 DataOperation targetOperation = (DataOperation) targetDataOperations.nextElement();
192 switch(sourceOperation.getOperationType())
193 {
194 case DataOperation.LOAD:
195 case DataOperation.REFRESH:
196 this.copyEntity(sourceOperation.getEntity(), targetOperation.getEntity());
197 break;
198 case DataOperation.QUERY:
199 Iterator entities = sourceOperation.getEntitySelection().iterator();
200 while (entities.hasNext())
201 targetOperation.getEntitySelection().addEntity((IEntity) entities.next());
202 break;
203 case DataOperation.STORE:
204 case DataOperation.DELETE:
205 this.copyEntityStatusFlags(sourceOperation.getEntity(), targetOperation.getEntity());
206 break;
207 }
208 }
209 }
210
211 protected void copyEntity(IEntity sourceEntity, IEntity targetEntity)
212 {
213 targetEntity.copyData(sourceEntity);
214 this.copyEntityStatusFlags(sourceEntity, targetEntity);
215 }
216
217 protected void copyEntityStatusFlags(IEntity sourceEntity, IEntity targetEntity)
218 {
219 if (sourceEntity.isDirty())
220 targetEntity.setStatusFlag(IEntity.DIRTY);
221 else
222 targetEntity.clearStatusFlag(IEntity.DIRTY);
223 if (sourceEntity.isEmpty())
224 targetEntity.setStatusFlag(IEntity.EMPTY);
225 else
226 targetEntity.clearStatusFlag(IEntity.EMPTY);
227 if (sourceEntity.isPersistent())
228 targetEntity.setStatusFlag(IEntity.PERSISTENT);
229 else
230 targetEntity.clearStatusFlag(IEntity.PERSISTENT);
231 }
232 }
233
234 protected abstract static class TunneledDataServiceMessage implements java.io.Serializable
235 {
236
237 protected Class mServiceInterfaceClass;
238 protected Object mServiceType;
239 protected Object mServiceIdentity;
240
241
242 public TunneledDataServiceMessage(Class serviceInterfaceClass,
243 Object serviceType,
244 Object serviceIdentity)
245 {
246 mServiceInterfaceClass = serviceInterfaceClass;
247 mServiceType = serviceType;
248 mServiceIdentity = serviceIdentity;
249 }
250 }
251
252 protected static class TunneledDataServiceCommitMessage extends TunneledDataServiceMessage
253 {
254
255 protected TunneledDataTransaction mTransaction;
256
257
258 public TunneledDataServiceCommitMessage(Class serviceInterfaceClass,
259 Object serviceType,
260 Object serviceIdentity,
261 TunneledDataTransaction transaction)
262 {
263 super(serviceInterfaceClass, serviceType, serviceIdentity);
264 mTransaction = transaction;
265 }
266
267
268 public TunneledDataTransaction getTransaction()
269 {
270 return mTransaction;
271 }
272 }
273
274 protected static class TunneledDataServiceAbortTransactionMessage extends TunneledDataServiceMessage
275 {
276
277 private int mTransactionID;
278
279
280 public TunneledDataServiceAbortTransactionMessage(Class serviceInterfaceClass,
281 Object serviceType,
282 Object serviceIdentity,
283 int transactionID)
284 {
285 super(serviceInterfaceClass, serviceType, serviceIdentity);
286 mTransactionID = transactionID;
287 }
288
289
290 public int getTransactionID()
291 {
292 return mTransactionID;
293 }
294 }
295
296 protected static class TunneledDataServiceProgressMessage extends TunneledDataServiceMessage
297 {
298
299 protected int mMaxProgress;
300 protected int mCurrentProgress;
301
302
303 public TunneledDataServiceProgressMessage(Class serviceInterfaceClass,
304 Object serviceType,
305 Object serviceIdentity,
306 int maxProgress,
307 int currentProgress)
308 {
309 super(serviceInterfaceClass, serviceType, serviceIdentity);
310 mMaxProgress = maxProgress;
311 mCurrentProgress = currentProgress;
312 }
313 }
314
315 protected static class TunneledDataServiceReturnMessage implements java.io.Serializable
316 {
317
318 protected AbstractDataTransaction.DataOperation[] mOperations;
319 protected DataServiceException mException;
320
321
322 public TunneledDataServiceReturnMessage(AbstractDataTransaction.DataOperation[] operations)
323 {
324 mOperations = operations;
325 }
326
327 public TunneledDataServiceReturnMessage(DataServiceException exception)
328 {
329 mException = exception;
330 }
331
332
333 public AbstractDataTransaction.DataOperation[] getOperations()
334 throws DataServiceException
335 {
336 if (mException != null)
337 throw mException;
338
339 return mOperations;
340 }
341 }
342 }