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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94 package org.astrogrid.filemanager.client.delegate ;
95
96 import org.apache.commons.logging.Log ;
97 import org.apache.commons.logging.LogFactory ;
98
99 import java.net.URL ;
100
101 import java.util.Date ;
102 import java.util.List ;
103 import java.util.Iterator ;
104
105 import java.io.IOException ;
106 import java.io.InputStream ;
107 import java.io.OutputStream ;
108
109 import org.astrogrid.store.Ivorn ;
110
111 import org.astrogrid.filestore.common.file.FileProperty;
112 import org.astrogrid.filestore.common.FileStoreInputStream;
113 import org.astrogrid.filestore.common.FileStoreOutputStream;
114 import org.astrogrid.filestore.common.transfer.TransferUtil;
115 import org.astrogrid.filestore.common.transfer.TransferProperties;
116 import org.astrogrid.filestore.common.exception.FileStoreIdentifierException ;
117
118 import org.astrogrid.filemanager.common.FileManagerProperties;
119 import org.astrogrid.filemanager.common.exception.NodeNotFoundException ;
120 import org.astrogrid.filemanager.common.exception.DuplicateNodeException;
121 import org.astrogrid.filemanager.common.exception.FileManagerIdentifierException;
122 import org.astrogrid.filemanager.common.exception.FileManagerServiceException;
123 import org.astrogrid.filemanager.common.exception.FileManagerPropertiesException;
124
125 import org.astrogrid.filemanager.client.FileManagerNode;
126
127 /***
128 * Client implementation of the FileManagerNode interface.
129 *
130 */
131 public class FileManagerDelegateNode
132 implements FileManagerNode
133 {
134
135 /***
136 * Our debug logger.
137 *
138 */
139 protected static Log log = LogFactory.getLog(FileManagerDelegateNode.class);
140
141 /***
142 * A reference to the FileManagerDelegate that created this node.
143 *
144 */
145 private FileManagerCoreDelegate delegate ;
146
147 /***
148 * Protected constructor from an array of file properties.
149 * @param delegate A reference to the FileManagerDelegate that created this node.
150 * @param properties An array of properties for the node.
151 *
152 */
153 protected FileManagerDelegateNode(FileManagerCoreDelegate delegate, FileProperty[] properties)
154 {
155 this(
156 delegate,
157 new FileManagerProperties(
158 properties
159 )
160 );
161 }
162
163 /***
164 * Protected constructor from a FileManagerProperties map.
165 * @param delegate A reference to the FileManagerDelegate that created this node.
166 * @param properties An array of properties for the node.
167 *
168 */
169 protected FileManagerDelegateNode(FileManagerCoreDelegate delegate, FileManagerProperties properties)
170 {
171 if (null == delegate)
172 {
173 throw new IllegalArgumentException(
174 "Null delegate"
175 );
176 }
177 if (null == properties)
178 {
179 throw new IllegalArgumentException(
180 "Null properties"
181 );
182 }
183 this.delegate = delegate ;
184 this.properties = properties ;
185 }
186
187 /***
188 * Our node properties.
189 *
190 */
191 private FileManagerProperties properties ;
192
193 /***
194 * Get the node ivorn.
195 * @return The ivorn identifier for this node.
196 * @throws FileManagerIdentifierException If the ivorn is invalid.
197 *
198 */
199 public Ivorn ivorn()
200 throws FileManagerIdentifierException
201 {
202 return properties.getManagerResourceIvorn();
203 }
204
205 /***
206 * Get the node name.
207 * @return The name for this node.
208 *
209 */
210 public String name()
211 {
212 return properties.getManagerResourceName();
213 }
214
215 /***
216 * Get the content size for a data node.
217 * @return The size of the stored data for a data node, or -1 for a container node.
218 *
219 */
220 public long size()
221 {
222 return properties.getContentSize();
223 }
224
225
226 /***
227 * Get the data file create date.
228 * @return The file create date, if the node has stored data, or null if the node does not contains any data.
229 *
230 */
231 public Date getFileCreateDate()
232 {
233 return properties.getFileCreateDate();
234 }
235
236 /***
237 * Get the data file modified date.
238 * @return The file modified date, if the node has stored data, or null if the node does not contains any data.
239 *
240 */
241 public Date getFileModifyDate()
242 {
243 return properties.getFileModifyDate();
244 }
245
246 /***
247 * Get the node create date.
248 * @return The node create date.
249 *
250 */
251 public Date getNodeCreateDate()
252 {
253 return properties.getNodeCreateDate();
254 }
255
256 /***
257 * Get the node modified date.
258 * @return The node modified date.
259 *
260 */
261 public Date getNodeModifyDate()
262 {
263 return properties.getNodeModifyDate();
264 }
265
266 /***
267 * Get the create date.
268 * @return The create date.
269 *
270 */
271 public Date getCreateDate()
272 {
273 return getNodeCreateDate();
274 }
275
276 /***
277 * Get the modified date.
278 * This returns whichever is the most recent modified date, for the node or the file.
279 * @return The modified date.
280 *
281 */
282 public Date getModifyDate()
283 {
284 Date node = getNodeModifyDate();
285 Date file = getFileModifyDate();
286 if (null != file)
287 {
288 if (file.after(node))
289 {
290 return file ;
291 }
292 else {
293 return node ;
294 }
295 }
296 else {
297 return node ;
298 }
299 }
300
301 /***
302 * Get the node (FileStore) location of the node data.
303 * This returns the (FileStore) location where the data is actually stored.
304 * @return The Ivorn for the (FileStore) location where the data is currently stored, or null if the node does not contain any data.
305 * @throws UnsupportedOperationException If the node represents a container (although future extensions may allow this).
306 * @throws FileManagerIdentifierException If the location Ivorn is not valid.
307 *
308 */
309 public Ivorn location()
310 throws UnsupportedOperationException, FileManagerIdentifierException
311 {
312 return properties.getManagerLocationIvorn();
313 }
314
315 /***
316 * Get the parent node.
317 * @return The parent node, or null for a root node.
318 * @throws NodeNotFoundException If the node is not in the database.
319 * @throws FileManagerServiceException If a problem occurs when handling the request.
320 * @todo Check for an existing node in the local cache.
321 *
322 */
323 public FileManagerNode parent()
324 throws NodeNotFoundException, FileManagerServiceException
325 {
326 try {
327 return delegate.getNode(
328 properties.getManagerParentIvorn()
329 );
330 }
331 catch(FileManagerIdentifierException ouch)
332 {
333 throw new FileManagerServiceException(
334 ouch.getMessage()
335 );
336 }
337 }
338
339 /***
340 * Check if this represents a file.
341 * @return true if this represents a file.
342 *
343 */
344 public boolean isFile()
345 {
346 return FileManagerProperties.DATA_NODE_TYPE.equals(
347 properties.getManagerResourceType()
348 ) ;
349 }
350
351 /***
352 * Check if this represents a container.
353 * @return true if this represents a container.
354 *
355 */
356 public boolean isContainer()
357 {
358 return FileManagerProperties.CONTAINER_NODE_TYPE.equals(
359 properties.getManagerResourceType()
360 ) ;
361 }
362
363 /***
364 * Delete this node.
365 * @throws NodeNotFoundException If the node is not in the database.
366 * @throws FileManagerServiceException If a problem occurs when handling the request.
367 *
368 */
369 public void delete()
370 throws NodeNotFoundException, FileManagerServiceException
371 {
372 }
373
374 /***
375 * Add a new child node.
376 * @param name The node name.
377 * @return A new node for the container.
378 * @throws UnsupportedOperationException If this node represents a file.
379 * @throws DuplicateNodeException If a node with the same name already exists.
380 * @throws NodeNotFoundException If the current node is no longer in the database.
381 * @throws FileManagerServiceException If a problem occurs when handling the request.
382 *
383 */
384 public FileManagerNode addNode(String name)
385 throws
386 UnsupportedOperationException,
387 NodeNotFoundException,
388 DuplicateNodeException,
389 FileManagerServiceException
390 {
391 return this.add(
392 name,
393 FileManagerProperties.CONTAINER_NODE_TYPE
394 );
395 }
396
397 /***
398 * Add a new file node.
399 * @param name The node name.
400 * @return A new node for the file.
401 * @throws UnsupportedOperationException If this node represents a file.
402 * @throws DuplicateNodeException If a node with the same name already exists.
403 * @throws NodeNotFoundException If the current node is no longer in the database.
404 * @throws FileManagerServiceException If a problem occurs when handling the request.
405 *
406 */
407 public FileManagerNode addFile(String name)
408 throws
409 UnsupportedOperationException,
410 NodeNotFoundException,
411 DuplicateNodeException ,
412 FileManagerServiceException
413 {
414 return this.add(
415 name,
416 FileManagerProperties.DATA_NODE_TYPE
417 );
418 }
419
420 /***
421 * Add a new child node.
422 * @param name The node name.
423 * @param type The node type (either DATA_NODE_TYPE or CONTAINER_NODE_TYPE).
424 * @return A new node for the container.
425 * @throws UnsupportedOperationException If this node represents a file.
426 * @throws DuplicateNodeException If a node with the same name already exists.
427 * @throws NodeNotFoundException If the current node is no longer in the database.
428 * @throws FileManagerServiceException If a problem occurs when handling the request.
429 * @see FileManagerProperties.DATA_NODE_TYPE
430 * @see FileManagerProperties.CONTAINER_NODE_TYPE
431 *
432 */
433 protected FileManagerNode add(String name, String type)
434 throws UnsupportedOperationException, NodeNotFoundException, DuplicateNodeException , FileManagerServiceException
435 {
436 if (null == name)
437 {
438 throw new IllegalArgumentException(
439 "Null node name"
440 );
441 }
442 if (null == type)
443 {
444 throw new IllegalArgumentException(
445 "Null node type"
446 );
447 }
448 if (!this.isContainer())
449 {
450 throw new UnsupportedOperationException(
451 "Node is not a container."
452 );
453 }
454 try {
455 return delegate.add(
456 this,
457 name,
458 type
459 ) ;
460 }
461 catch (FileManagerIdentifierException ouch)
462 {
463 throw new FileManagerServiceException(
464 "Invalid parent node identifier"
465 );
466 }
467 }
468
469 /***
470 * Get a child node by path.
471 * @param path The path to the child node.
472 * @return A reference to the child node.
473 * @throws UnsupportedOperationException If this node represents a file.
474 * @throws NodeNotFoundException If the node is not in the database.
475 * @throws FileManagerServiceException If a problem occurs when handling the request.
476 *
477 */
478 public FileManagerNode child(String path)
479 throws UnsupportedOperationException, NodeNotFoundException, FileManagerServiceException
480 {
481 if (null == path)
482 {
483 throw new IllegalArgumentException(
484 "Null path"
485 );
486 }
487 if (!this.isContainer())
488 {
489 throw new UnsupportedOperationException(
490 "Node is not a container."
491 );
492 }
493 try {
494 return delegate.getChild(
495 this,
496 path
497 ) ;
498 }
499 catch (FileManagerIdentifierException ouch)
500 {
501 throw new FileManagerServiceException(
502 "Invalid parent node identifier"
503 );
504 }
505 }
506
507 /***
508 * Open a java OutputStream to send (import) data into the node.
509 * @return An OutputStream connected directly to the node store.
510 * @throws IOException If a problem occurs openning the stream.
511 * @throws UnsupportedOperationException If the node represents a container.
512 * @throws NodeNotFoundException If the node is not in the database.
513 * @throws FileManagerServiceException If a problem occurs when handling the request.
514 *
515 */
516 public OutputStream importStream()
517 throws
518 IOException,
519 UnsupportedOperationException,
520 NodeNotFoundException,
521 FileManagerServiceException
522 {
523 if (!this.isFile())
524 {
525 throw new UnsupportedOperationException(
526 "Node is not a file."
527 );
528 }
529
530
531 try {
532 TransferProperties transfer =
533 delegate.importInit(
534 this.properties
535 ) ;
536
537
538 if (null != transfer.getLocation())
539 {
540
541
542 FileStoreOutputStream stream = new FileStoreOutputStream(
543 transfer.getLocation()
544 )
545 {
546 public void close()
547 throws IOException
548 {
549 super.close();
550 try {
551 refresh();
552 }
553 catch (Exception ouch)
554 {
555 log.warn("Exception in refresh() following IOStream close()");
556 }
557 }
558 } ;
559 stream.open() ;
560 return stream ;
561 }
562
563
564 else {
565 throw new FileManagerServiceException(
566 "Unable to get transfer location (URL)"
567 );
568 }
569 }
570 catch (FileManagerPropertiesException ouch)
571 {
572 throw new FileManagerServiceException(
573 "Unable to get transfer location (URL)",
574 ouch
575 );
576 }
577 }
578
579 /***
580 * Open a java InputStream to read (export) data from the node.
581 * @return An InputStream connected directly to the node store.
582 * @throws IOException If a problem occurs openning the stream.
583 * @throws UnsupportedOperationException If the node represents a container.
584 * @throws NodeNotFoundException If the node is not in the database.
585 * @throws FileManagerServiceException If a problem occurs when handling the request.
586 *
587 */
588 public InputStream exportStream()
589 throws
590 IOException,
591 UnsupportedOperationException,
592 NodeNotFoundException,
593 FileManagerServiceException
594 {
595
596
597 FileStoreInputStream stream = new FileStoreInputStream(
598 exportURL()
599 ) ;
600 stream.open() ;
601 return stream ;
602 }
603
604 /***
605 * Get a URL to access the node data from.
606 * @return A URL which connects directly to the node store.
607 * @throws UnsupportedOperationException If the node represents a container.
608 * @throws NodeNotFoundException If the node is not in the database.
609 * @throws FileManagerServiceException If a problem occurs when handling the request.
610 *
611 */
612 public URL exportURL()
613 throws
614 UnsupportedOperationException,
615 NodeNotFoundException,
616 FileManagerServiceException
617 {
618 if (!this.isFile())
619 {
620 throw new UnsupportedOperationException(
621 "Not a data node."
622 );
623 }
624
625
626 try {
627 TransferProperties transfer =
628 delegate.exportInit(
629 this.properties
630 ) ;
631
632
633 if (null != transfer.getLocation())
634 {
635 try {
636 return new URL(
637 transfer.getLocation()
638 );
639 }
640 catch (Exception ouch)
641 {
642 throw new FileManagerServiceException(
643 "Unable to get transfer location (URL)",
644 ouch
645 );
646 }
647 }
648
649
650 else {
651 throw new FileManagerServiceException(
652 "Unable to get transfer location (URL)"
653 );
654 }
655 }
656 catch (FileManagerPropertiesException ouch)
657 {
658 throw new FileManagerServiceException(
659 "Unable to get transfer location (URL)",
660 ouch
661 );
662 }
663 }
664
665 /***
666 * Import data from a URL.
667 * @throws UnsupportedOperationException If the node represents a container.
668 * @throws NodeNotFoundException If the node is not in the database.
669 * @throws FileManagerServiceException If a problem occurs when handling the request.
670 *
671 */
672 public void importData(URL url)
673 throws UnsupportedOperationException, NodeNotFoundException, FileManagerServiceException
674 {
675 throw new UnsupportedOperationException(
676 "Not implemented yet ..."
677 );
678 }
679
680
681 /***
682 * Create a copy of this node.
683 * If the node already has stored data, then this will create a copy of the data.
684 * @return A reference to the new node.
685 * @param name The name of the new Node.
686 * @param node The new parent Node in the metadata tree (null to create the new node in the same location in the tree).
687 * @param store The Ivorn of the FileStore for new Node (null to store the copy at the same location).
688 * @throws DuplicateNodeException If a node with the same name already exists in the metadata tree.
689 * @throws NodeNotFoundException If the current node is no longer in the database.
690 * @throws NodeNotFoundException If the new parent node is no longer in the database.
691 * @throws FileManagerServiceException If a problem occurs when handling the request.
692 *
693 */
694 public FileManagerNode copy(String name, FileManagerNode parent, Ivorn location)
695 throws DuplicateNodeException, NodeNotFoundException, FileManagerServiceException
696 {
697 FileManagerProperties request = new FileManagerProperties();
698 try {
699 request.setManagerResourceIvorn(
700 this.ivorn()
701 );
702 }
703 catch (FileManagerIdentifierException ouch)
704 {
705 throw new FileManagerServiceException(
706 "Unable to parse node ivorn"
707 );
708 }
709 if (null != name)
710 {
711 request.setManagerResourceName(
712 name
713 );
714 }
715 if (null != parent)
716 {
717 try {
718 request.setManagerParentIvorn(
719 parent.ivorn()
720 );
721 }
722 catch (FileManagerIdentifierException ouch)
723 {
724 throw new FileManagerServiceException(
725 "Unable to parse parent node ivorn"
726 );
727 }
728 }
729 if (null != location)
730 {
731 request.setManagerLocationIvorn(
732 location
733 );
734 }
735 try {
736 return delegate.copy(
737 request
738 );
739 }
740 catch (FileManagerPropertiesException ouch)
741 {
742 throw new FileManagerServiceException(
743 "Error in client code, invalid request properties"
744 );
745 }
746 }
747
748 /***
749 * Move this node to a new location.
750 * If the node already has stored data, then this may involve transfering the data to a new location.
751 * @param name The name of the new Node.
752 * @param node The new parent Node in the metadata tree (null to leave the node in the same location in the tree).
753 * @param store The Ivorn of the FileStore location (null to leave the data at the same location).
754 * @throws DuplicateNodeException If a node with the same name already exists in the metadata tree.
755 * @throws NodeNotFoundException If the current node is no longer in the database.
756 * @throws NodeNotFoundException If the new parent node is no longer in the database.
757 * @throws FileManagerServiceException If a problem occurs when handling the request.
758 *
759 */
760 public void move(String name, FileManagerNode parent, Ivorn location)
761 throws DuplicateNodeException, NodeNotFoundException, FileManagerServiceException
762 {
763 FileManagerProperties request = new FileManagerProperties();
764 try {
765 request.setManagerResourceIvorn(
766 this.ivorn()
767 );
768 }
769 catch (FileManagerIdentifierException ouch)
770 {
771 throw new FileManagerServiceException(
772 "Unable to parse node ivorn"
773 );
774 }
775 if (null != name)
776 {
777 request.setManagerResourceName(
778 name
779 );
780 }
781 if (null != parent)
782 {
783 try {
784 request.setManagerParentIvorn(
785 parent.ivorn()
786 );
787 }
788 catch (FileManagerIdentifierException ouch)
789 {
790 throw new FileManagerServiceException(
791 "Unable to parse parent node ivorn"
792 );
793 }
794 }
795 if (null != location)
796 {
797 request.setManagerLocationIvorn(
798 location
799 );
800 }
801 try {
802 this.properties = new FileManagerProperties(
803 delegate.move(
804 request
805 )
806 );
807 }
808 catch (FileManagerPropertiesException ouch)
809 {
810 throw new FileManagerServiceException(
811 "Error in client code, invalid request properties"
812 );
813 }
814 }
815
816 /***
817 * Refresh the node properties.
818 * If the node has stored data, this will trigger a call to the FileStore to refresh the data properties.
819 * Clients should call this method after a data import has completed to update the node properties.
820 * @throws NodeNotFoundException If the node no longer exists in the server database.
821 * @throws FileManagerServiceException If a problem occurs when handling the request.
822 * @todo Also needs to update list of children ?
823 *
824 */
825 public void refresh()
826 throws NodeNotFoundException, FileManagerServiceException
827 {
828 log.debug("");
829 log.debug("FileManagerDelegateNode.refresh()");
830 try {
831 this.properties = new FileManagerProperties(
832 delegate.refresh(
833 this
834 )
835 );
836 }
837 catch (FileManagerIdentifierException ouch)
838 {
839 throw new FileManagerServiceException(
840 "Error in client code, invalid node identifier"
841 );
842 }
843 }
844
845 /***
846 * Inner class to provide an iterator on child nodes.
847 *
848 */
849 protected class NodeIteratorImpl
850 implements FileManagerNode.NodeIterator
851 {
852 /***
853 * Our internal iterator of the ivorn list.
854 *
855 */
856 private Iterator iter ;
857
858 /***
859 * Create an iterator for a list of nodes.
860 *
861 */
862 public NodeIteratorImpl(List list)
863 {
864 log.debug("");
865 log.debug("NodeIteratorImpl.NodeIteratorImpl()");
866 this.iter = list.iterator() ;
867 }
868
869 /***
870 * Check if the there are more nodes in the iteration.
871 *
872 */
873 public boolean hasNext()
874 {
875 return this.iter.hasNext();
876 }
877
878 /***
879 * Get the next node in the iteration.
880 * @throws NodeNotFoundException If the node is no longer in the server database (this can happen if another client deletes the node after this iterator was created).
881 * @throws FileManagerServiceException If a problem occurs when handling the request.
882 *
883 */
884 public FileManagerNode next()
885 throws NodeNotFoundException, FileManagerServiceException
886 {
887 log.debug("");
888 log.debug("NodeIteratorImpl.next()");
889 try {
890 return delegate.getNode(
891 (Ivorn) this.iter.next()
892 );
893 }
894 catch (FileManagerIdentifierException ouch)
895 {
896 throw new FileManagerServiceException(
897 "Unable to parse node ivorn",
898 ouch
899 );
900 }
901 }
902 }
903
904 /***
905 * Get an iterator for the child nodes of this node.
906 * @throws NodeNotFoundException If this node is no longer in the server database.
907 * @throws FileManagerServiceException If a problem occurs when handling the request.
908 * @throws UnsupportedOperationException If the node does not represent a container.
909 *
910 */
911 public FileManagerNode.NodeIterator iterator()
912 throws NodeNotFoundException, FileManagerServiceException
913 {
914 log.debug("");
915 log.debug("FileManagerDelegateNode.iterator()");
916 try {
917 return new NodeIteratorImpl(
918 delegate.getChildren(
919 this.ivorn()
920 )
921 );
922 }
923 catch (FileManagerIdentifierException ouch)
924 {
925 throw new FileManagerServiceException(
926 "Error in client code, invalid node identifier"
927 );
928 }
929 }
930 }