1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 package uk.ac.rdg.resc.jstyx.gridservice.client;
30
31 import javax.swing.tree.DefaultMutableTreeNode;
32 import java.util.Vector;
33
34 import org.apache.log4j.Logger;
35
36 import uk.ac.rdg.resc.jstyx.client.CStyxFileChangeListener;
37 import uk.ac.rdg.resc.jstyx.client.CStyxFile;
38 import uk.ac.rdg.resc.jstyx.StyxUtils;
39 import uk.ac.rdg.resc.jstyx.StyxException;
40
41
42
43 import org.apache.mina.common.ByteBuffer;
44 import uk.ac.rdg.resc.jstyx.types.DirEntry;
45 import uk.ac.rdg.resc.jstyx.messages.TwriteMessage;
46 import uk.ac.rdg.resc.jstyx.messages.TreadMessage;
47
48 /***
49 * Node in the model that represents a CStyxFile. This allows the file to
50 * be represented with a different name in the GUI.
51 *
52 * @todo How much of this functionality can be shared with the SGSClient or
53 * SGSInstanceClient?
54 *
55 * @todo Would it be better to create subclasses of this for the different node
56 * types?
57 *
58 * @author Jon Blower
59 * $Revision: 569 $
60 * $Date: 2006-01-05 16:06:35 +0000 (Thu, 05 Jan 2006) $
61 * $Log$
62 * Revision 1.16 2006/01/05 16:06:34 jonblower
63 * SGS clients now deal with possibility that client could be created on a different server
64 *
65 * Revision 1.15 2005/12/07 17:49:05 jonblower
66 * Added getInstanceClient() method to CStyxFileNode
67 *
68 * Revision 1.14 2005/12/07 08:51:48 jonblower
69 * Added getSGSClient() method
70 *
71 * Revision 1.13 2005/09/14 07:26:46 jonblower
72 * Added error() method (from SGSChangeListener interface)
73 *
74 * Revision 1.12 2005/09/11 19:29:51 jonblower
75 * Changed call to getInstances() to getInstancesAsync()
76 *
77 * Revision 1.11 2005/08/12 08:08:39 jonblower
78 * Developments to support web interface
79 *
80 * Revision 1.10 2005/07/29 11:19:29 jonblower
81 * Implemented automatic update of SGS instances in SGS Explorer (and logging)
82 *
83 * Revision 1.6 2005/06/20 17:20:48 jonblower
84 * Added download() and downloadAsync() to CStyxFile
85 *
86 * Revision 1.5 2005/05/25 16:58:41 jonblower
87 * Added fileCreated()
88 *
89 * Revision 1.3 2005/05/18 17:13:51 jonblower
90 * Created SGSInstanceGUI
91 *
92 * Revision 1.2 2005/05/18 08:03:24 jonblower
93 * Implemented creation of new service instances
94 *
95 * Revision 1.1 2005/05/17 18:20:50 jonblower
96 * Separated CStyxFileNode from SGSExplorerTreeModel
97 *
98 */
99 class CStyxFileNode extends DefaultMutableTreeNode implements CStyxFileChangeListener,
100 SGSChangeListener
101 {
102
103 private static final Logger log = Logger.getLogger(CStyxFileNode.class);
104
105 public static final int ROOT = 0;
106 public static final int SERVER = 1;
107 public static final int SERVICE = 2;
108 public static final int INSTANCE = 3;
109
110 private CStyxFile file;
111 private CStyxFile instances;
112 private String name;
113 private SGSExplorerTreeModel dataModel;
114
115 private SGSClient sgsClient;
116 private SGSInstanceClient instanceClient;
117
118 public CStyxFileNode(SGSExplorerTreeModel dataModel, CStyxFile file, String name)
119 {
120 this.dataModel = dataModel;
121 this.file = file;
122 this.file.addChangeListener(this);
123 this.name = name;
124 }
125
126 public CStyxFileNode(SGSExplorerTreeModel dataModel, CStyxFile file)
127 {
128 this(dataModel, file, file.getName());
129 }
130
131 /***
132 * @return the CStyxFile that this node represents
133 */
134 public CStyxFile getFile()
135 {
136 return this.file;
137 }
138
139 /***
140 * @return the String that will be used to identify this node in the
141 * SGSExplorer
142 */
143 public String toString()
144 {
145 return this.name;
146 }
147
148 /***
149 * @return the SGSClient object associated with this node. Only relevant
150 * for SERVICE nodes (will return null otherwise)
151 */
152 public SGSClient getSGSClient()
153 {
154 return this.sgsClient;
155 }
156
157 /***
158 * @return the type of this node (ROOT, SERVER, SERVICE or INSTANCE) as an
159 * integer, corresponding to the constants defined in this class
160 */
161 public int getType()
162 {
163
164
165 return this.getPath().length - 1;
166 }
167
168 /***
169 * All nodes can have children except those representing service
170 * instances
171 */
172 public boolean getAllowsChildren()
173 {
174 return (this.getType() != INSTANCE);
175 }
176
177 /***
178 * Sends a message to get all the children of this node. When the reply
179 * arrives, the childrenFound method of this class will be called. Does
180 * nothing if the children have already been found.
181 */
182 public void findChildren()
183 {
184 if (this.children == null)
185 {
186 if (this.getType() == SERVICE)
187 {
188
189
190
191 this.sgsClient.getInstancesAsync();
192 }
193 else
194 {
195
196
197 this.file.getChildrenAsync();
198 }
199 }
200 }
201
202 /***
203 * Called when the children have been found. Adds them to this node's
204 * Vector of children
205 */
206 public void childrenFound(CStyxFile file, CStyxFile[] files)
207 {
208
209 this.removeAllChildren();
210 synchronized (this)
211 {
212 for (int i = 0; i < files.length; i++)
213 {
214 this.add(new CStyxFileNode(this.dataModel, files[i]));
215 }
216 }
217 this.dataModel.nodeStructureChanged(this);
218 }
219
220 /***
221 * Intercepts calls to add a child to this structure, creating SGSclient
222 * objects if the new child represents a SGS
223 */
224 private void add(CStyxFileNode newChild)
225 {
226 super.add(newChild);
227 if (newChild.getType() == SERVICE)
228 {
229
230 newChild.sgsClient = new SGSClient(newChild.getFile());
231 newChild.sgsClient.addChangeListener(newChild);
232 }
233 }
234
235 /***
236 * Sends a message to create a new instance (reads the clone file). This
237 * method will only be called if this node represents a Service.
238 */
239 public void createNewInstance()
240 {
241 if (this.getType() == SERVICE)
242 {
243
244
245
246 }
247 else
248 {
249 log.error("Can't create new instance from this type of node");
250 }
251 }
252
253 /***
254 * Gets an SGSInstanceClient for this node.
255 * @throws IllegalStateException if this node does not represent a service
256 * instance
257 * @throws StyxException if there was an error creating the client
258 */
259 public SGSInstanceClient getInstanceClient() throws StyxException
260 {
261 if (this.instanceClient == null)
262 {
263 if (this.getType() != INSTANCE)
264 {
265 throw new IllegalStateException("Can only call getInstanceClient "
266 + "on a service instance");
267 }
268
269 CStyxFileNode parent = (CStyxFileNode)this.getParent();
270 this.instanceClient = new SGSInstanceClient(parent.getSGSClient(), this.file);
271 }
272 return this.instanceClient;
273 }
274
275 /***
276 * Required by SGSChangeListener interface: called when this is a Service
277 * and we have a new list of instances
278 */
279 public void gotInstances(CStyxFile[] newInstances)
280 {
281 if (this.children == null)
282 {
283
284 this.childrenFound(null, newInstances);
285 }
286 else
287 {
288
289
290 synchronized (this.children)
291 {
292 log.debug("Got " + newInstances.length + " instances");
293
294
295
296
297 Vector newChildren = new Vector();
298
299 try
300 {
301 for (int i = 0; i < newInstances.length; i++)
302 {
303 log.debug("Examining new instance " + newInstances[i].getName());
304 boolean instanceFound = false;
305
306 for (int j = 0; j < this.children.size(); j++)
307 {
308 log.debug("Instance " + j + " is a "
309 + this.children.get(j).getClass());
310 CStyxFileNode existingInstanceNode =
311 (CStyxFileNode)this.children.get(j);
312 CStyxFile existingInstanceFile =
313 existingInstanceNode.getFile();
314 log.debug("Comparing new instance " +
315 newInstances[i].getName() + " with existing instance "
316 + existingInstanceFile.getName());
317
318
319
320
321 if (newInstances[i].isSameFile(existingInstanceFile))
322 {
323 log.debug("They are the same file");
324 newChildren.add(existingInstanceNode);
325 instanceFound = true;
326 break;
327 }
328 else
329 {
330 log.debug("They are not the same file");
331 }
332 }
333 if (!instanceFound)
334 {
335 log.debug("Adding new instance " + newInstances[i].getName()
336 + " to the list of children");
337 CStyxFileNode newNode = new CStyxFileNode(this.dataModel, newInstances[i]);
338 newNode.setParent(this);
339 newChildren.add(newNode);
340 }
341 }
342 this.children = newChildren;
343 this.dataModel.nodeStructureChanged(this);
344 }
345 catch (Exception e)
346 {
347
348
349
350 e.printStackTrace();
351 }
352 }
353 }
354 }
355
356 /***
357 * Overrides method in SGSChangeListener: this is called when an error occurs
358 * creating a new instance of the service or reading the instances
359 */
360 public void error(String message)
361 {
362 log.error("Error creating or getting instances: " + message);
363 }
364
365 /***
366 * Overrides method in CStyxFileChangeListener
367 */
368 public void error(CStyxFile file, String message)
369 {
370 log.error("Error with " + file.getName() + ": " + message);
371 }
372
373
374 public void dataArrived(CStyxFile theFile, TreadMessage tReadMsg, ByteBuffer data) {}
375 public void fileOpen(CStyxFile file, int mode){}
376 public void fileCreated(CStyxFile file, int mode){}
377 public void dataWritten(CStyxFile file, TwriteMessage tWriteMsg){}
378 public void statChanged(CStyxFile file, DirEntry newDirEntry){}
379 public void uploadComplete(CStyxFile targetFile){}
380 public void downloadComplete(CStyxFile sourceFile){}
381 }