View Javadoc

1   /*
2    *
3    * <cvs:source>$Source: /devel/astrogrid/filestore/server/src/java/org/astrogrid/filestore/server/FileStoreImpl.java,v $</cvs:source>
4    * <cvs:author>$Author: clq2 $</cvs:author>
5    * <cvs:date>$Date: 2005/01/28 10:44:03 $</cvs:date>
6    * <cvs:version>$Revision: 1.12 $</cvs:version>
7    * <cvs:log>
8    *   $Log: FileStoreImpl.java,v $
9    *   Revision 1.12  2005/01/28 10:44:03  clq2
10   *   dave_dev_200501141257 (filemanager)
11   *
12   *   Revision 1.11.6.1  2005/01/17 17:19:21  dave
13   *   Fixed bug in FileManagerImpl test (missing '/' in repository path on Unix) ...
14   *   Changed tabs to spaces ..
15   *
16   *   Revision 1.11  2004/12/16 17:25:49  jdt
17   *   merge from dave-dev-200410061224-200412161312
18   *
19   *   Revision 1.9.14.7  2004/12/08 17:54:55  dave
20   *   Added update to FileManager client and server side ...
21   *
22   *   Revision 1.9.14.6  2004/11/09 17:41:36  dave
23   *   Added file:// URL handling to allow server URLs to be tested.
24   *   Added importInit and exportInit to server implementation.
25   *   Moved remaining tests out of extended test abd removed it.
26   *
27   *   Revision 1.9.14.5  2004/10/27 10:56:30  dave
28   *   Changed inport init to save the details, and simplified tests for debug
29   *
30   *   Revision 1.9.14.4  2004/10/26 16:11:31  dave
31   *   Fixed debug ..
32   *
33   *   Revision 1.9.14.3  2004/10/26 15:07:12  dave
34   *   Added initial code for import init ...
35   *
36   *   Revision 1.9.14.2  2004/10/26 11:13:11  dave
37   *   Changed transfer properties 'source' to 'location', makes more sense for PUT transfers.
38   *
39   *   Revision 1.9.14.1  2004/10/19 14:56:16  dave
40   *   Refactored config and resolver to enable multiple instances of mock implementation.
41   *   Required to implement handling of multiple FileStore(s) in FileManager.
42   *
43   *   Revision 1.9  2004/09/17 06:57:10  dave
44   *   Added commons logging to FileStore.
45   *   Updated logging properties in Community.
46   *   Fixed bug in AGINAB deployment.
47   *   Removed MySpace tests with hard coded grendel address.
48   *
49   *   Revision 1.8.20.1  2004/09/17 01:08:36  dave
50   *   Updated debug to use commons logging API ....
51   *
52   *   Revision 1.8  2004/08/27 22:43:15  dave
53   *   Updated filestore and myspace to report file size correctly.
54   *
55   *   Revision 1.7.12.1  2004/08/26 19:06:50  dave
56   *   Modified filestore to return file size in properties.
57   *
58   *   Revision 1.7  2004/08/18 19:00:01  dave
59   *   Myspace manager modified to use remote filestore.
60   *   Tested before checkin - integration tests at 91%.
61   *
62   *   Revision 1.6  2004/08/18 10:03:19  gtr
63   *   BZ486. I added an early version of the getSecureUrl operation. This implementation doesn't yet work.
64   *
65   *   Revision 1.5.10.2  2004/08/06 22:25:06  dave
66   *   Refactored bits and broke a few tests ...
67   *
68   *   Revision 1.5.10.1  2004/08/04 06:35:02  dave
69   *   Added initial stubs for servlet ....
70   *
71   *   Revision 1.5  2004/07/23 09:11:16  dave
72   *   Merged development branch, dave-dev-200407221513, into HEAD
73   *
74   *   Revision 1.4.6.1  2004/07/23 02:10:58  dave
75   *   Added IvornFactory and IvornParser
76   *
77   *   Revision 1.4  2004/07/21 18:11:55  dave
78   *   Merged development branch, dave-dev-200407201059, into HEAD
79   *
80   *   Revision 1.3.2.1  2004/07/21 16:28:16  dave
81   *   Added content properties and tests
82   *
83   *   Revision 1.3  2004/07/19 23:42:07  dave
84   *   Merged development branch, dave-dev-200407151443, into HEAD
85   *
86   *   Revision 1.2.4.1  2004/07/19 19:40:28  dave
87   *   Debugged and worked around Axis Exception handling
88   *
89   *   Revision 1.2  2004/07/14 13:50:29  dave
90   *   Merged development branch, dave-dev-200406301228, into HEAD
91   *
92   *   Revision 1.1.2.3  2004/07/14 10:34:08  dave
93   *   Reafctored server to use array of properties
94   *
95   *   Revision 1.1.2.2  2004/07/12 14:39:03  dave
96   *   Added server repository classes
97   *
98   *   Revision 1.1.2.1  2004/07/08 07:31:30  dave
99   *   Added container impl and tests
100  *
101  * </cvs:log>
102  *
103  */
104 package org.astrogrid.filestore.server ;
105 
106 import org.apache.commons.logging.Log ;
107 import org.apache.commons.logging.LogFactory ;
108 
109 import java.net.URL ;
110 import java.net.MalformedURLException ;
111 
112 import java.io.IOException ;
113 
114 import java.util.Map ;
115 import java.util.HashMap ;
116 
117 import java.rmi.RemoteException  ;
118 import org.apache.axis.AxisFault ;
119 
120 import org.astrogrid.filestore.common.FileStore ;
121 import org.astrogrid.filestore.common.file.FileProperty ;
122 import org.astrogrid.filestore.common.file.FileProperties ;
123 import org.astrogrid.filestore.common.file.FileIdentifier ;
124 import org.astrogrid.filestore.common.transfer.TransferProperties ;
125 import org.astrogrid.filestore.common.exception.FileStoreException ;
126 import org.astrogrid.filestore.common.exception.FileStoreNotFoundException ;
127 import org.astrogrid.filestore.common.exception.FileStoreIdentifierException ;
128 import org.astrogrid.filestore.common.exception.FileStoreServiceException ;
129 import org.astrogrid.filestore.common.exception.FileStoreTransferException ;
130 
131 import org.astrogrid.filestore.server.repository.Repository ;
132 import org.astrogrid.filestore.server.repository.RepositoryImpl ;
133 import org.astrogrid.filestore.server.repository.RepositoryContainer ;
134 
135 import org.astrogrid.filestore.server.streamer.StreamTicket;
136 import org.astrogrid.filestore.server.streamer.StreamTicketList;
137 
138 import org.astrogrid.filestore.common.FileStoreConfig ;
139 import org.astrogrid.filestore.server.FileStoreConfigImpl ;
140 
141 /***
142  * The main server implementation of the store service.
143  *
144  */
145 public class FileStoreImpl
146     implements FileStore
147     {
148     /***
149      * Our debug logger.
150      *
151      */
152     private static Log log = LogFactory.getLog(FileStoreImpl.class);
153 
154     /***
155      * Public constructor.
156      *
157      */
158     public FileStoreImpl()
159         {
160         this(
161             new FileStoreConfigImpl()
162             ) ;
163         }
164 
165     /***
166      * Public constructor.
167      * @param config The local repository configuration.
168      *
169      */
170     public FileStoreImpl(FileStoreConfig config)
171         {
172         this(
173             config,
174             new RepositoryImpl(
175                 config
176                 )
177             ) ;
178         }
179 
180     /***
181      * Public constructor.
182      * @param config The local repository configuration.
183      * @param repository A local file repository.
184      *
185      */
186     public FileStoreImpl(FileStoreConfig config, Repository repository)
187         {
188         this.config = config ;
189         this.repository = repository ;
190         }
191 
192     /***
193      * Reference to our configuration.
194      *
195      */
196     private FileStoreConfig config ;
197 
198     /***
199      * Reference to our repository.
200      *
201      */
202     private Repository repository ;
203 
204     /***
205      * Get the service identifier.
206      * @return The ivo identifier for this service.
207      * @throws FileStoreServiceException if unable handle the request.
208      *
209      */
210     public String identifier()
211         throws FileStoreServiceException
212         {
213         return config.getServiceIvorn().toString() ;
214         }
215 
216     /***
217      * Import (store) a string of data.
218      * @param properties An array of FileProperties describing the imported data.
219      * @param data The string of data to store.
220      * @return An array of FileProperties describing the imported data.
221      * @throws FileStoreException if the data string is null.
222      * @throws FileStoreServiceException if unable handle the request.
223      *
224      */
225     public FileProperty[] importString(FileProperty[] properties, String data)
226         throws FileStoreServiceException, FileStoreException
227         {
228         log.debug("") ;
229         log.debug("----\"----") ;
230         log.debug("FileStoreImpl.importString()") ;
231         //
232         // Check for null data.
233         if (null == data)
234             {
235             throw new FileStoreException(
236                 "Null data"
237                 ) ;
238             }
239         //
240         // Convert to bytes and import that.
241         return this.importBytes(
242             properties,
243             data.getBytes()
244             ) ;
245         }
246 
247     /***
248      * Import (store) a byte array of data.
249      * @param properties An array of FileProperties describing the imported data.
250      * @param data The byte array of data to store.
251      * @return An array of FileProperties describing the imported data.
252      * @throws FileStoreException if the data string is null.
253      * @throws FileStoreServiceException if unable handle the request.
254      *
255      */
256     public FileProperty[] importBytes(FileProperty[] properties, byte[] data)
257         throws FileStoreServiceException, FileStoreException
258         {
259         log.debug("") ;
260         log.debug("----\"----") ;
261         log.debug("FileStoreImpl.importBytes()") ;
262         //
263         // Check for null data.
264         if (null == data)
265             {
266             throw new FileStoreException(
267                 "Null data"
268                 ) ;
269             }
270         //
271         // Create a new container.
272         RepositoryContainer container = repository.create(
273             new FileProperties(
274                 properties
275                 )
276             ) ;
277         //
278         // Import our data into the container.
279         container.importBytes(
280             data
281             ) ;
282         //
283         // Return the container properties.
284         return container.properties().toArray() ;
285         }
286 
287     /***
288      * Append a string to existing file.
289      * @param ident The internal identifier of the target.
290      * @param data The string to append.
291      * @return An array of FileProperties describing the imported data.
292      * @throws FileStoreIdentifierException if the identifier is null or not valid.
293      * @throws FileStoreNotFoundException if unable to locate the file.
294      * @throws FileStoreException if the string is null.
295      * @throws FileStoreServiceException if unable handle the request.
296      *
297      */
298     public FileProperty[] appendString(String ident, String data)
299         throws FileStoreServiceException, FileStoreIdentifierException, FileStoreNotFoundException, FileStoreException
300         {
301         log.debug("") ;
302         log.debug("----\"----") ;
303         log.debug("FileStoreImpl.appendString()") ;
304         //
305         // Check for null ident.
306         if (null == ident)
307             {
308             throw new FileStoreIdentifierException(
309                 FileStoreIdentifierException.NULL_IDENT_MESSAGE
310                 ) ;
311             }
312         //
313         // Check for null data.
314         if (null == data)
315             {
316             throw new FileStoreException(
317                 "Null data"
318                 ) ;
319             }
320         //
321         // Convert to bytes and append that.
322         return this.appendBytes(
323             ident,
324             data.getBytes()
325             ) ;
326         }
327 
328     /***
329      * Append an array of bytes to existing data.
330      * @param ident The internal identifier of the target.
331      * @param data The bytes to append.
332      * @return An array of FileProperties describing the imported data.
333      * @throws FileStoreIdentifierException if the identifier is null or not valid.
334      * @throws FileStoreNotFoundException if unable to locate the file.
335      * @throws FileStoreException if the array is null.
336      * @throws FileStoreServiceException if unable handle the request.
337      *
338      */
339     public FileProperty[] appendBytes(String ident, byte[] data)
340         throws FileStoreServiceException, FileStoreIdentifierException, FileStoreNotFoundException, FileStoreException
341         {
342         log.debug("") ;
343         log.debug("----\"----") ;
344         log.debug("FileStoreImpl.appendBytes()") ;
345         //
346         // Check for null ident.
347         if (null == ident)
348             {
349             throw new FileStoreIdentifierException(
350                 FileStoreIdentifierException.NULL_IDENT_MESSAGE
351                 ) ;
352             }
353         //
354         // Check for null data.
355         if (null == data)
356             {
357             throw new FileStoreException(
358                 "Null data"
359                 ) ;
360             }
361         //
362         // Locate the container.
363         RepositoryContainer container = repository.load(ident) ;
364         //
365         // Append the data to our container.
366         container.appendBytes(
367             data
368             ) ;
369         //
370         // Return the container properties.
371         return container.properties().toArray() ;
372         }
373 
374     /***
375      * Export (read) the contents of a file as a string.
376      * @param ident The internal identifier of the target file.
377      * @return The contents of a data object as a string.
378      * @throws FileStoreIdentifierException if the identifier is null or not valid.
379      * @throws FileStoreNotFoundException if unable to locate the file.
380      * @throws FileStoreServiceException if unable handle the request.
381      *
382      */
383     public String exportString(String ident)
384         throws FileStoreServiceException, FileStoreIdentifierException, FileStoreNotFoundException
385         {
386         log.debug("") ;
387         log.debug("----\"----") ;
388         log.debug("FileStoreImpl.exportString()") ;
389         return new String(
390             this.exportBytes(
391                 ident
392                 )
393             ) ;
394         }
395 
396     /***
397      * Export (read) the contents of a file as an array of bytes.
398      * @param ident The internal identifier of the target file.
399      * @return The contents of a data object as a string.
400      * @throws FileStoreIdentifierException if the identifier is null or not valid.
401      * @throws FileStoreNotFoundException if unable to locate the file.
402      * @throws FileStoreServiceException if unable handle the request.
403      *
404      */
405     public byte[] exportBytes(String ident)
406         throws FileStoreServiceException, FileStoreIdentifierException, FileStoreNotFoundException
407         {
408         log.debug("") ;
409         log.debug("----\"----") ;
410         log.debug("FileStoreImpl.exportBytes()") ;
411         //
412         // Check for null ident.
413         if (null == ident)
414             {
415             throw new FileStoreIdentifierException(
416                 FileStoreIdentifierException.NULL_IDENT_MESSAGE
417                 ) ;
418             }
419         return repository.load(ident).exportBytes() ;
420         }
421 
422     /***
423      * Create a local duplicate (copy) of a file.
424      * @param ident The internal identifier of the target file.
425      * @param properties An optional array of FileProperties describing the copy.
426      * @return An array of FileProperties describing the copied data.
427      * @throws FileStoreTransferException if unable to transfer the data.
428      * @throws FileStoreIdentifierException if the identifier is null or not valid.
429      * @throws FileStoreNotFoundException if unable to locate the file.
430      * @throws FileStoreServiceException if unable handle the request.
431      *
432      */
433     public FileProperty[] duplicate(String ident, FileProperty[] properties)
434         throws FileStoreServiceException, FileStoreIdentifierException, FileStoreNotFoundException, FileStoreTransferException
435         {
436         //
437         // Check for null ident.
438         if (null == ident)
439             {
440             throw new FileStoreIdentifierException(
441                 FileStoreIdentifierException.NULL_IDENT_MESSAGE
442                 ) ;
443             }
444         return repository.duplicate(ident).properties().toArray() ;
445         }
446 
447     /***
448      * Delete a file.
449      * @param ident The internal identifier of the target file.
450      * @return An array of FileProperties describing the deleted data.
451      * @throws FileStoreIdentifierException if the identifier is null or not valid.
452      * @throws FileStoreNotFoundException if unable to locate the file.
453      * @throws FileStoreServiceException if unable handle the request.
454      * @throws RemoteException If the WebService call fails.
455      *
456      */
457     public FileProperty[] delete(String ident)
458         throws FileStoreServiceException, FileStoreIdentifierException, FileStoreNotFoundException
459         {
460         //
461         // Locate the container.
462         RepositoryContainer container = repository.load(ident) ;
463         //
464         // Try to delete the container.
465         container.delete() ;
466         //
467         // Return the original properties.
468         return container.properties().toArray() ;
469         }
470 
471     /***
472      * Get the local meta data information for a file.
473      * @param ident The internal identifier of the target file.
474      * @return An array of FileProperties describing the data.
475      * @throws FileStoreIdentifierException if the identifier is null or not valid.
476      * @throws FileStoreNotFoundException if unable to locate the file.
477      * @throws FileStoreServiceException if unable handle the request.
478      *
479      */
480     public FileProperty[] properties(String ident)
481         throws FileStoreServiceException, FileStoreIdentifierException, FileStoreNotFoundException
482         {
483         //
484         // Locate the container.
485         RepositoryContainer container = repository.load(
486             ident
487             );
488         //
489         // Update and save the properties.
490         container.update() ;
491         //
492         // Return the updated properties.
493         return container.properties().toArray() ;
494         }
495 
496     /***
497      * Prepare to receive a data object from a remote source.
498      * @param transfer A TransferProperties describing the transfer.
499      * @return A new TransferProperties describing the transfer.
500      * @throws FileStoreTransferException if there is an error in the transfer properties.
501      *
502      */
503     public TransferProperties importInit(TransferProperties transfer)
504         throws FileStoreServiceException, FileStoreTransferException
505         {
506         log.debug("") ;
507         log.debug("----\"----") ;
508         log.debug("FileStoreImpl.importInit()") ;
509         //
510         // Check for null transfer properties.
511         if (null == transfer)
512             {
513             throw new FileStoreTransferException(
514                 "Null transfer properties"
515                 ) ;
516             }
517         //
518         // Create a new container.
519         RepositoryContainer container = repository.create(
520             new FileProperties(
521                 transfer.getFileProperties()
522                 )
523             ) ;
524         //
525         // Set the transfer import URL.
526         transfer.setLocation(
527             config.getResourceUrl(
528                 container.ident().toString()
529                 ).toString()
530             ) ;
531         log.debug("  URL : " + transfer.getLocation()) ;
532         //
533         // Update and save the container.
534         container.update() ;
535         //
536         // Add the updated file properties.
537         transfer.setFileProperties(
538             container.properties().toArray()
539             ) ;
540         //
541         // Return the transfer properties.
542         return transfer ;
543         }
544 
545     /***
546      * Import a data object from a remote source.
547      * @param transfer A TransferProperties describing the transfer.
548      * @return A new TransferProperties describing the transfer.
549      * @throws FileStoreServiceException if there is an error in the service.
550      * @throws FileStoreTransferException if there is an error in the transfer.
551      *
552      */
553     public TransferProperties importData(TransferProperties transfer)
554         throws FileStoreServiceException, FileStoreTransferException
555         {
556         log.debug("") ;
557         log.debug("----\"----") ;
558         log.debug("FileStoreImpl.importData()") ;
559         //
560         // Check for null transfer properties.
561         if (null == transfer)
562             {
563             throw new FileStoreTransferException(
564                 "Null transfer properties"
565                 ) ;
566             }
567         //
568         // Check for null URL.
569         if (null == transfer.getLocation())
570             {
571             throw new FileStoreTransferException(
572                 "Null transfer source"
573                 ) ;
574             }
575         //
576         // Create a new container.
577         RepositoryContainer container = repository.create(
578             new FileProperties(
579                 transfer.getFileProperties()
580                 )
581             ) ;
582         //
583         // Transfer the data into our container.
584         try {
585             container.importData(
586                 new URL(
587                     transfer.getLocation()
588                     )
589                 ) ;
590             }
591         catch (MalformedURLException ouch)
592             {
593             throw new FileStoreTransferException(
594                 ouch
595                 ) ;
596             }
597         //
598         // Add the updated file properties.
599         transfer.setFileProperties(
600             container.properties().toArray()
601             ) ;
602         //
603         // Return the transfer properties.
604         return transfer ;
605         }
606 
607     /***
608      * Prepare to send a data object to a remote destination.
609      * Essentially, this returns a vaild URL to access data in the TransferProperties location.
610      * @param transfer A TransferProperties describing the transfer.
611      * @throws FileStoreTransferException if the transfer properties are null.
612      * @throws FileStoreNotFoundException If unable to locate the target object.
613      * @throws FileStoreServiceException if unable handle the request.
614      * @return A new TransferProperties describing the transfer.
615      *
616      */
617     public TransferProperties exportInit(TransferProperties transfer)
618         throws FileStoreTransferException, FileStoreServiceException, FileStoreNotFoundException
619         {
620         log.debug("") ;
621         log.debug("----\"----") ;
622         log.debug("FileStoreImpl.importInit()") ;
623         //
624         // Check for null transfer properties.
625         if (null == transfer)
626             {
627             throw new FileStoreTransferException(
628                 "Null transfer properties"
629                 ) ;
630             }
631         //
632         // Get the transfer file properties.
633         FileProperties properties = new FileProperties(
634             transfer.getFileProperties()
635             ) ;
636         //
637         // Get the file identifier.
638         String ident = null ;
639         try {
640             ident = properties.getStoreResourceIdent();
641             }
642         catch (FileStoreIdentifierException ouch)
643             {
644             throw new FileStoreNotFoundException(
645                 "Unable to parse resource identifier"
646                 ) ;
647             }
648         //
649         // If we have a valid identifier.
650         if (null != ident)
651             {
652             //
653             // Try to locate the container.
654             try {
655                 RepositoryContainer container = repository.load(ident) ;
656 //
657 // Update the transfer properties.
658 //
659                 //
660                 // Set the transfer import URL.
661                 transfer.setLocation(
662                     config.getResourceUrl(
663                         container.ident().toString()
664                         ).toString()
665                     ) ;
666                 log.debug("  URL : " + transfer.getLocation()) ;
667                 return transfer ;
668                 }
669             catch (FileStoreIdentifierException ouch)
670                 {
671                 throw new FileStoreNotFoundException(
672                     "Unable to load resource properties"
673                     ) ;
674                 }
675             }
676         //
677         // If we don't have a valid identifier.
678         else {
679             throw new FileStoreNotFoundException(
680                 "Null target file identifier"
681                 );
682             }
683         }
684 
685     /***
686      * Export a data object to a remote destination.
687      * @param transfer A TransferProperties describing the transfer.
688      * @return A new TransferProperties describing the transfer.
689      *
690      */
691     public TransferProperties exportData(TransferProperties transfer)
692         {
693         return transfer ;
694         }
695 
696     /***
697      * Throw a FileStoreIdentifierException, useful for debugging the transfer of Exceptions via SOAP.
698      * @throws FileStoreIdentifierException as requested.
699      *
700      */
701     public void throwIdentifierException()
702         throws FileStoreIdentifierException
703         {
704         throw new FileStoreIdentifierException(
705             "TEST FAULT",
706             "TEST IDENT"
707             ) ;
708         }
709 
710     /***
711     * Issues a stream ticket (see {@link org.astrogrid.filestore.server.streamer})
712     * for a data item and returns a URL from which that item may be streamed.
713     * The URL embeds the name of the ticket, which is not predictable and may
714     * only be streamed once. Hence, the streaming is reasonably secure.
715     * This operation is intended to make data items available to web browsers
716     * without making them public.
717     *
718     * @param ident The filestore identifier for the data item to be streamed.
719     * @return the URL from which the data may be streamed.
720     * @throws FileStoreIdentifierException if the identifier is null or not valid.
721     * @throws FileStoreNotFoundException if unable to locate the file.
722     * @throws FileStoreServiceException if unable handle the request.
723     * @throws RemoteException If the WebService call fails.
724     */
725     public String getSecureUrl(String ident)
726         throws FileStoreServiceException,
727              FileStoreIdentifierException,
728              FileStoreNotFoundException,
729              RemoteException {
730         String streamUrl = null;
731 
732         // Locate the container for the data item.
733         // This throws  FileStoreIdentifierException if the id
734         // is null or otherwise invalid.
735         RepositoryContainer container = repository.load(ident);
736 
737         // Issue the stream ticket, thus authorizing the streaming of the data.
738         // The target property of the ticket is set to the data-item id; i.e. the
739         // ticketing mechanism has to work with the repository mechanism to
740         // find the data.
741         StreamTicket ticket = new StreamTicket();
742         ticket.setTarget(ident);
743         // @TODO Set the MIME type of the data.
744         StreamTicketList list = new StreamTicketList();
745         list.add(ticket);
746         streamUrl = ticket.getName();
747 
748         return streamUrl;
749         }
750 
751     }
752