KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > dspace > app > itemimport > ItemImport


1 /*
2  * ItemImport.java
3  *
4  * Version: $Revision: 1.27 $
5  *
6  * Date: $Date: 2005/11/16 21:40:51 $
7  *
8  * Copyright (c) 2002-2005, Hewlett-Packard Company and Massachusetts
9  * Institute of Technology. All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions are
13  * met:
14  *
15  * - Redistributions of source code must retain the above copyright
16  * notice, this list of conditions and the following disclaimer.
17  *
18  * - Redistributions in binary form must reproduce the above copyright
19  * notice, this list of conditions and the following disclaimer in the
20  * documentation and/or other materials provided with the distribution.
21  *
22  * - Neither the name of the Hewlett-Packard Company nor the name of the
23  * Massachusetts Institute of Technology nor the names of their
24  * contributors may be used to endorse or promote products derived from
25  * this software without specific prior written permission.
26  *
27  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
30  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
31  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
32  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
33  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
34  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
35  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
36  * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
37  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
38  * DAMAGE.
39  */

40 package org.dspace.app.itemimport;
41
42 import java.io.BufferedInputStream JavaDoc;
43 import java.io.BufferedReader JavaDoc;
44 import java.io.File JavaDoc;
45 import java.io.FileInputStream JavaDoc;
46 import java.io.FileReader JavaDoc;
47 import java.io.FileWriter JavaDoc;
48 import java.io.FilenameFilter JavaDoc;
49 import java.io.IOException JavaDoc;
50 import java.io.PrintWriter JavaDoc;
51 import java.sql.SQLException JavaDoc;
52 import java.util.ArrayList JavaDoc;
53 import java.util.HashMap JavaDoc;
54 import java.util.Iterator JavaDoc;
55 import java.util.Map JavaDoc;
56 import java.util.StringTokenizer JavaDoc;
57
58 import javax.xml.parsers.DocumentBuilder JavaDoc;
59 import javax.xml.parsers.DocumentBuilderFactory JavaDoc;
60 import javax.xml.parsers.ParserConfigurationException JavaDoc;
61 import javax.xml.transform.TransformerException JavaDoc;
62
63 import org.apache.commons.cli.CommandLine;
64 import org.apache.commons.cli.CommandLineParser;
65 import org.apache.commons.cli.HelpFormatter;
66 import org.apache.commons.cli.Options;
67 import org.apache.commons.cli.PosixParser;
68 import org.apache.xpath.XPathAPI;
69 import org.dspace.authorize.AuthorizeException;
70 import org.dspace.content.Bitstream;
71 import org.dspace.content.BitstreamFormat;
72 import org.dspace.content.Bundle;
73 import org.dspace.content.Collection;
74 import org.dspace.content.FormatIdentifier;
75 import org.dspace.content.InstallItem;
76 import org.dspace.content.Item;
77 import org.dspace.content.MetadataSchema;
78 import org.dspace.content.WorkspaceItem;
79 import org.dspace.core.ConfigurationManager;
80 import org.dspace.core.Constants;
81 import org.dspace.core.Context;
82 import org.dspace.eperson.EPerson;
83 import org.dspace.handle.HandleManager;
84 import org.dspace.workflow.WorkflowManager;
85 import org.w3c.dom.Document JavaDoc;
86 import org.w3c.dom.NamedNodeMap JavaDoc;
87 import org.w3c.dom.Node JavaDoc;
88 import org.w3c.dom.NodeList JavaDoc;
89 import org.xml.sax.SAXException JavaDoc;
90
91 /**
92  * Import items into DSpace. The conventional use is upload files by copying
93  * them. DSpace writes the item's bitstreams into its assetstore. Metadata is
94  * also loaded to the DSpace database.
95  * <P>
96  * A second use assumes the bitstream files already exist in a storage
97  * resource accessible to DSpace. In this case the bitstreams are 'registered'.
98  * That is, the metadata is loaded to the DSpace database and DSpace is given
99  * the location of the file which is subsumed into DSpace.
100  * <P>
101  * The distinction is controlled by the format of lines in the 'contents' file.
102  * See comments in processContentsFile() below.
103  * <P>
104  * Modified by David Little, UCSD Libraries 12/21/04 to
105  * allow the registration of files (bitstreams) into DSpace.
106  */

107 public class ItemImport
108 {
109     static boolean useWorkflow = false;
110
111     static boolean isTest = false;
112
113     static boolean isResume = false;
114
115     static PrintWriter JavaDoc mapOut = null;
116
117     // File listing filter to look for metadata files
118
static FilenameFilter JavaDoc metadataFileFilter = new FilenameFilter JavaDoc()
119     {
120         public boolean accept(File JavaDoc dir, String JavaDoc n)
121         {
122             return n.startsWith("metadata_");
123         }
124     };
125
126     // File listing filter to check for folders
127
static FilenameFilter JavaDoc directoryFilter = new FilenameFilter JavaDoc()
128     {
129         public boolean accept(File JavaDoc dir, String JavaDoc n)
130         {
131             File JavaDoc item = new File JavaDoc(dir.getAbsolutePath() + File.separatorChar + n);
132             return item.isDirectory();
133         }
134     };
135
136
137     public static void main(String JavaDoc[] argv) throws Exception JavaDoc
138     {
139         // create an options object and populate it
140
CommandLineParser parser = new PosixParser();
141
142         Options options = new Options();
143
144         options.addOption("a", "add", false, "add items to DSpace");
145         options.addOption("r", "replace", false, "replace items in mapfile");
146         options.addOption("d", "delete", false,
147                 "delete items listed in mapfile");
148         options.addOption("s", "source", true, "source of items (directory)");
149         options.addOption("c", "collection", true,
150                 "destination collection(s) Handle or database ID");
151         options.addOption("m", "mapfile", true, "mapfile items in mapfile");
152         options.addOption("e", "eperson", true,
153                 "email of eperson doing importing");
154         options.addOption("w", "workflow", false,
155                 "send submission through collection's workflow");
156         options.addOption("t", "test", false,
157                 "test run - do not actually import items");
158         options.addOption("R", "resume", false,
159                 "resume a failed import (add only)");
160
161         options.addOption("h", "help", false, "help");
162
163         CommandLine line = parser.parse(options, argv);
164
165         String JavaDoc command = null; // add replace remove, etc
166
String JavaDoc sourcedir = null;
167         String JavaDoc mapfile = null;
168         String JavaDoc eperson = null; // db ID or email
169
String JavaDoc[] collections = null; // db ID or handles
170

171         if (line.hasOption('h'))
172         {
173             HelpFormatter myhelp = new HelpFormatter();
174             myhelp.printHelp("ItemImport\n", options);
175             System.out
176                     .println("\nadding items: ItemImport -a -e eperson -c collection -s sourcedir -m mapfile");
177             System.out
178                     .println("replacing items: ItemImport -r -e eperson -c collection -s sourcedir -m mapfile");
179             System.out
180                     .println("deleting items: ItemImport -d -e eperson -m mapfile");
181             System.out
182                     .println("If multiple collections are specified, the first collection will be the one that owns the item.");
183
184             System.exit(0);
185         }
186
187         if (line.hasOption('a'))
188         {
189             command = "add";
190         }
191
192         if (line.hasOption('r'))
193         {
194             command = "replace";
195         }
196
197         if (line.hasOption('d'))
198         {
199             command = "delete";
200         }
201
202         if (line.hasOption('w'))
203         {
204             useWorkflow = true;
205         }
206
207         if (line.hasOption('t'))
208         {
209             isTest = true;
210             System.out.println("**Test Run** - not actually importing items.");
211         }
212
213         if (line.hasOption('s')) // source
214
{
215             sourcedir = line.getOptionValue('s');
216         }
217
218         if (line.hasOption('m')) // mapfile
219
{
220             mapfile = line.getOptionValue('m');
221         }
222
223         if (line.hasOption('e')) // eperson
224
{
225             eperson = line.getOptionValue('e');
226         }
227
228         if (line.hasOption('c')) // collections
229
{
230             collections = line.getOptionValues('c');
231         }
232
233         if (line.hasOption('R'))
234         {
235             isResume = true;
236             System.out
237                     .println("**Resume import** - attempting to import items not already imported");
238         }
239
240         // now validate
241
// must have a command set
242
if (command == null)
243         {
244             System.out
245                     .println("Error - must run with either add, replace, or remove (run with -h flag for details)");
246             System.exit(1);
247         }
248         else if (command.equals("add") || command.equals("replace"))
249         {
250             if (sourcedir == null)
251             {
252                 System.out
253                         .println("Error - a source directory containing items must be set");
254                 System.out.println(" (run with -h flag for details)");
255                 System.exit(1);
256             }
257
258             if (mapfile == null)
259             {
260                 System.out
261                         .println("Error - a map file to hold importing results must be specified");
262                 System.out.println(" (run with -h flag for details)");
263                 System.exit(1);
264             }
265
266             if (eperson == null)
267             {
268                 System.out
269                         .println("Error - an eperson to do the importing must be specified");
270                 System.out.println(" (run with -h flag for details)");
271                 System.exit(1);
272             }
273
274             if (collections == null)
275             {
276                 System.out
277                         .println("Error - at least one destination collection must be specified");
278                 System.out.println(" (run with -h flag for details)");
279                 System.exit(1);
280             }
281         }
282         else if (command.equals("delete"))
283         {
284             if (eperson == null)
285             {
286                 System.out
287                         .println("Error - an eperson to do the importing must be specified");
288                 System.exit(1);
289             }
290
291             if (mapfile == null)
292             {
293                 System.out.println("Error - a map file must be specified");
294                 System.exit(1);
295             }
296         }
297
298         // can only resume for adds
299
if (isResume && !command.equals("add"))
300         {
301             System.out
302                     .println("Error - resume option only works with --add command");
303             System.exit(1);
304         }
305
306         // do checks around mapfile - if mapfile exists and 'add' is selected,
307
// resume must be chosen
308
File JavaDoc myFile = new File JavaDoc(mapfile);
309
310         if (myFile.exists() && command.equals("add") && !isResume)
311         {
312             System.out.println("Error - the mapfile " + mapfile
313                     + " already exists.");
314             System.out
315                     .println("Either delete it or use --resume if attempting to resume an aborted import.");
316             System.exit(1);
317         }
318
319         ItemImport myloader = new ItemImport();
320
321         // create a context
322
Context c = new Context();
323
324         // find the EPerson, assign to context
325
EPerson myEPerson = null;
326
327         if (eperson.indexOf('@') != -1)
328         {
329             // @ sign, must be an email
330
myEPerson = EPerson.findByEmail(c, eperson);
331         }
332         else
333         {
334             myEPerson = EPerson.find(c, Integer.parseInt(eperson));
335         }
336
337         if (myEPerson == null)
338         {
339             System.out.println("Error, eperson cannot be found: " + eperson);
340             System.exit(1);
341         }
342
343         c.setCurrentUser(myEPerson);
344
345         // find collections
346
Collection[] mycollections = null;
347
348         // don't need to validate collections set if command is "delete"
349
if (!command.equals("delete"))
350         {
351             System.out.println("Destination collections:");
352
353             mycollections = new Collection[collections.length];
354
355             // validate each collection arg to see if it's a real collection
356
for (int i = 0; i < collections.length; i++)
357             {
358                 // is the ID a handle?
359
if (collections[i].indexOf('/') != -1)
360                 {
361                     // string has a / so it must be a handle - try and resolve
362
// it
363
mycollections[i] = (Collection) HandleManager
364                             .resolveToObject(c, collections[i]);
365
366                     // resolved, now make sure it's a collection
367
if ((mycollections[i] == null)
368                             || (mycollections[i].getType() != Constants.COLLECTION))
369                     {
370                         mycollections[i] = null;
371                     }
372                 }
373                 // not a handle, try and treat it as an integer collection
374
// database ID
375
else if (collections[i] != null)
376                 {
377                     mycollections[i] = Collection.find(c, Integer
378                             .parseInt(collections[i]));
379                 }
380
381                 // was the collection valid?
382
if (mycollections[i] == null)
383                 {
384                     throw new IllegalArgumentException JavaDoc("Cannot resolve "
385                             + collections[i] + " to collection");
386                 }
387
388                 // print progress info
389
String JavaDoc owningPrefix = "";
390
391                 if (i == 0)
392                 {
393                     owningPrefix = "Owning ";
394                 }
395
396                 System.out.println(owningPrefix + " Collection: "
397                         + mycollections[i].getMetadata("name"));
398             }
399         } // end of validating collections
400

401         try
402         {
403             c.setIgnoreAuthorization(true);
404
405             if (command.equals("add"))
406             {
407                 myloader.addItems(c, mycollections, sourcedir, mapfile);
408             }
409             else if (command.equals("replace"))
410             {
411                 myloader.replaceItems(c, mycollections, sourcedir, mapfile);
412             }
413             else if (command.equals("delete"))
414             {
415                 myloader.deleteItems(c, mapfile);
416             }
417
418             // complete all transactions
419
c.complete();
420         }
421         catch (Exception JavaDoc e)
422         {
423             // abort all operations
424
if (mapOut != null)
425             {
426                 mapOut.close();
427             }
428
429             mapOut = null;
430
431             c.abort();
432             e.printStackTrace();
433             System.out.println(e);
434         }
435
436         if (mapOut != null)
437         {
438             mapOut.close();
439         }
440
441         if (isTest)
442         {
443             System.out.println("***End of Test Run***");
444         }
445     }
446
447     private void addItems(Context c, Collection[] mycollections,
448             String JavaDoc sourceDir, String JavaDoc mapFile) throws Exception JavaDoc
449     {
450         Map JavaDoc skipItems = new HashMap JavaDoc(); // set of items to skip if in 'resume'
451
// mode
452

453         System.out.println("Adding items from directory: " + sourceDir);
454         System.out.println("Generating mapfile: " + mapFile);
455
456         // create the mapfile
457
File JavaDoc outFile = null;
458
459         if (!isTest)
460         {
461             // get the directory names of items to skip (will be in keys of
462
// hash)
463
if (isResume)
464             {
465                 skipItems = readMapFile(mapFile);
466             }
467
468             // sneaky isResume == true means open file in append mode
469
outFile = new File JavaDoc(mapFile);
470             mapOut = new PrintWriter JavaDoc(new FileWriter JavaDoc(outFile, isResume));
471
472             if (mapOut == null)
473             {
474                 throw new Exception JavaDoc("can't open mapfile: " + mapFile);
475             }
476         }
477
478         // open and process the source directory
479
File JavaDoc d = new java.io.File JavaDoc(sourceDir);
480
481         if (d == null)
482         {
483             System.out.println("Error, cannot open source directory "
484                     + sourceDir);
485             System.exit(1);
486         }
487
488         String JavaDoc[] dircontents = d.list(directoryFilter);
489
490         for (int i = 0; i < dircontents.length; i++)
491         {
492             if (skipItems.containsKey(dircontents[i]))
493             {
494                 System.out.println("Skipping import of " + dircontents[i]);
495             }
496             else
497             {
498                 addItem(c, mycollections, sourceDir, dircontents[i], mapOut);
499                 System.out.println(i + " " + dircontents[i]);
500             }
501         }
502     }
503
504     private void replaceItems(Context c, Collection[] mycollections,
505             String JavaDoc sourceDir, String JavaDoc mapFile) throws Exception JavaDoc
506     {
507         // verify the source directory
508
File JavaDoc d = new java.io.File JavaDoc(sourceDir);
509
510         if (d == null)
511         {
512             System.out.println("Error, cannot open source directory "
513                     + sourceDir);
514             System.exit(1);
515         }
516
517         // read in HashMap first, to get list of handles & source dirs
518
Map JavaDoc myhash = readMapFile(mapFile);
519
520         // for each handle, re-import the item, discard the new handle
521
// and re-assign the old handle
522
Iterator JavaDoc i = myhash.keySet().iterator();
523         ArrayList JavaDoc itemsToDelete = new ArrayList JavaDoc();
524
525         while (i.hasNext())
526         {
527             // get the old handle
528
String JavaDoc newItemName = (String JavaDoc) i.next();
529             String JavaDoc oldHandle = (String JavaDoc) myhash.get(newItemName);
530
531             Item oldItem = null;
532             Item newItem = null;
533
534             if (oldHandle.indexOf('/') != -1)
535             {
536                 System.out.println("\tReplacing: " + oldHandle);
537
538                 // add new item, locate old one
539
oldItem = (Item) HandleManager.resolveToObject(c, oldHandle);
540             }
541             else
542             {
543                 oldItem = Item.find(c, Integer.parseInt(oldHandle));
544             }
545             
546             /* Rather than exposing public item methods to change handles --
547              * two handles can't exist at the same time due to key constraints
548              * so would require temp handle being stored, old being copied to new and
549              * new being copied to old, all a bit messy -- a handle file is written to
550              * the import directory containing the old handle, the existing item is
551              * deleted and then the import runs as though it were loading an item which
552              * had already been assigned a handle (so a new handle is not even assigned).
553              * As a commit does not occur until after a successful add, it is safe to
554              * do a delete as any error results in an aborted transaction without harming
555              * the original item */

556             File JavaDoc handleFile = new File JavaDoc(sourceDir + File.separatorChar + newItemName + File.separatorChar + "handle");
557             PrintWriter JavaDoc handleOut = new PrintWriter JavaDoc(new FileWriter JavaDoc(handleFile, true));
558
559             if (handleOut == null)
560             {
561                 throw new Exception JavaDoc("can't open handle file: " + handleFile.getCanonicalPath());
562             }
563             
564             handleOut.println(oldHandle);
565             handleOut.close();
566             
567             deleteItem(c, oldItem);
568             
569             newItem = addItem(c, mycollections, sourceDir, newItemName, null);
570         }
571     }
572
573     private void deleteItems(Context c, String JavaDoc mapFile) throws Exception JavaDoc
574     {
575         System.out.println("Deleting items listed in mapfile: " + mapFile);
576
577         // read in the mapfile
578
Map JavaDoc myhash = readMapFile(mapFile);
579
580         // now delete everything that appeared in the mapFile
581
Iterator JavaDoc i = myhash.keySet().iterator();
582
583         while (i.hasNext())
584         {
585             String JavaDoc itemID = (String JavaDoc) myhash.get(i.next());
586
587             if (itemID.indexOf('/') != -1)
588             {
589                 String JavaDoc myhandle = itemID;
590                 System.out.println("Deleting item " + myhandle);
591                 deleteItem(c, myhandle);
592             }
593             else
594             {
595                 // it's an ID
596
Item myitem = Item.find(c, Integer.parseInt(itemID));
597                 System.out.println("Deleting item " + itemID);
598                 deleteItem(c, myitem);
599             }
600         }
601     }
602
603     /**
604      * item? try and add it to the archive c mycollection path itemname handle -
605      * non-null means we have a pre-defined handle already mapOut - mapfile
606      * we're writing
607      */

608     private Item addItem(Context c, Collection[] mycollections, String JavaDoc path,
609             String JavaDoc itemname, PrintWriter JavaDoc mapOut) throws Exception JavaDoc
610     {
611         String JavaDoc mapOutput = null;
612
613         System.out.println("Adding item from directory " + itemname);
614
615         // create workspace item
616
Item myitem = null;
617         WorkspaceItem wi = null;
618
619         if (!isTest)
620         {
621             wi = WorkspaceItem.create(c, mycollections[0], false);
622             myitem = wi.getItem();
623         }
624
625         // now fill out dublin core for item
626
loadMetadata(c, myitem, path + File.separatorChar + itemname
627                 + File.separatorChar);
628
629         // and the bitstreams from the contents file
630
// process contents file, add bistreams and bundles
631
processContentsFile(c, myitem, path + File.separatorChar + itemname,
632                 "contents");
633
634         if (useWorkflow)
635         {
636             // don't process handle file
637
// start up a workflow
638
if (!isTest)
639             {
640                 WorkflowManager.startWithoutNotify(c, wi);
641
642                 // send ID to the mapfile
643
mapOutput = itemname + " " + myitem.getID();
644             }
645         }
646         else
647         {
648             // only process handle file if not using workflow system
649
String JavaDoc myhandle = processHandleFile(c, myitem, path
650                     + File.separatorChar + itemname, "handle");
651
652             // put item in system
653
if (!isTest)
654             {
655                 InstallItem.installItem(c, wi, myhandle);
656
657                 // find the handle, and output to map file
658
myhandle = HandleManager.findHandle(c, myitem);
659
660                 mapOutput = itemname + " " + myhandle;
661             }
662         }
663
664         // now add to multiple collections if requested
665
if (mycollections.length > 1)
666         {
667             for (int i = 1; i < mycollections.length; i++)
668             {
669                 if (!isTest)
670                 {
671                     mycollections[i].addItem(myitem);
672                 }
673             }
674         }
675
676         // made it this far, everything is fine, commit transaction
677
if (mapOut != null)
678         {
679             mapOut.println(mapOutput);
680         }
681
682         c.commit();
683
684         return myitem;
685     }
686
687     // remove, given the actual item
688
private void deleteItem(Context c, Item myitem) throws Exception JavaDoc
689     {
690         if (!isTest)
691         {
692             Collection[] collections = myitem.getCollections();
693
694             // Remove item from all the collections it's in
695
for (int i = 0; i < collections.length; i++)
696             {
697                 collections[i].removeItem(myitem);
698             }
699         }
700     }
701
702     // remove, given a handle
703
private void deleteItem(Context c, String JavaDoc myhandle) throws Exception JavaDoc
704     {
705         // bit of a hack - to remove an item, you must remove it
706
// from all collections it's a part of, then it will be removed
707
Item myitem = (Item) HandleManager.resolveToObject(c, myhandle);
708
709         if (myitem == null)
710         {
711             System.out.println("Error - cannot locate item - already deleted?");
712         }
713         else
714         {
715             deleteItem(c, myitem);
716         }
717     }
718
719     ////////////////////////////////////
720
// utility methods
721
////////////////////////////////////
722
// read in the map file and generate a hashmap of (file,handle) pairs
723
private Map JavaDoc readMapFile(String JavaDoc filename) throws Exception JavaDoc
724     {
725         Map JavaDoc myhash = new HashMap JavaDoc();
726
727         BufferedReader JavaDoc is = null;
728         try
729         {
730             is = new BufferedReader JavaDoc(new FileReader JavaDoc(filename));
731
732             String JavaDoc line;
733
734             while ((line = is.readLine()) != null)
735             {
736                 String JavaDoc myfile;
737                 String JavaDoc myhandle;
738
739                 // a line should be archive filename<whitespace>handle
740
StringTokenizer JavaDoc st = new StringTokenizer JavaDoc(line);
741
742                 if (st.hasMoreTokens())
743                 {
744                     myfile = st.nextToken();
745                 }
746                 else
747                 {
748                     throw new Exception JavaDoc("Bad mapfile line:\n" + line);
749                 }
750
751                 if (st.hasMoreTokens())
752                 {
753                     myhandle = st.nextToken();
754                 }
755                 else
756                 {
757                     throw new Exception JavaDoc("Bad mapfile line:\n" + line);
758                 }
759
760                 myhash.put(myfile, myhandle);
761             }
762         }
763         finally
764         {
765             if (is != null)
766             {
767                 is.close();
768             }
769         }
770
771         return myhash;
772     }
773
774     // Load all metadata schemas into the item.
775
private void loadMetadata(Context c, Item myitem, String JavaDoc path)
776             throws SQLException JavaDoc, IOException JavaDoc, ParserConfigurationException JavaDoc,
777             SAXException JavaDoc, TransformerException JavaDoc
778     {
779         // Load the dublin core metadata
780
loadDublinCore(c, myitem, path + "dublin_core.xml");
781
782         // Load any additional metadata schemas
783
File JavaDoc folder = new File JavaDoc(path);
784         File JavaDoc file[] = folder.listFiles(metadataFileFilter);
785         for (int i = 0; i < file.length; i++)
786         {
787             loadDublinCore(c, myitem, file[i].getAbsolutePath());
788         }
789     }
790
791     private void loadDublinCore(Context c, Item myitem, String JavaDoc filename)
792             throws SQLException JavaDoc, IOException JavaDoc, ParserConfigurationException JavaDoc,
793             SAXException JavaDoc, TransformerException JavaDoc //, AuthorizeException
794
{
795         Document JavaDoc document = loadXML(filename);
796
797         // Get the schema, for backward compatibility we will default to the
798
// dublin core schema if the schema name is not available in the import
799
// file
800
String JavaDoc schema;
801         NodeList JavaDoc metadata = XPathAPI.selectNodeList(document, "/dublin_core");
802         Node JavaDoc schemaAttr = metadata.item(0).getAttributes().getNamedItem(
803                 "schema");
804         if (schemaAttr == null)
805         {
806             schema = MetadataSchema.DC_SCHEMA;
807         }
808         else
809         {
810             schema = schemaAttr.getNodeValue();
811         }
812          
813         // Get the nodes corresponding to formats
814
NodeList JavaDoc dcNodes = XPathAPI.selectNodeList(document,
815                 "/dublin_core/dcvalue");
816
817         System.out.println("\tLoading dublin core from " + filename);
818
819         // Add each one as a new format to the registry
820
for (int i = 0; i < dcNodes.getLength(); i++)
821         {
822             Node JavaDoc n = dcNodes.item(i);
823             addDCValue(myitem, schema, n);
824         }
825     }
826
827     private void addDCValue(Item i, String JavaDoc schema, Node JavaDoc n) throws TransformerException JavaDoc
828     {
829         String JavaDoc value = getStringValue(n); //n.getNodeValue();
830
// compensate for empty value getting read as "null", which won't display
831
if (value == null)
832             value = "";
833         // //getElementData(n, "element");
834
String JavaDoc element = getAttributeValue(n, "element");
835         String JavaDoc qualifier = getAttributeValue(n, "qualifier"); //NodeValue();
836
// //getElementData(n,
837
// "qualifier");
838
String JavaDoc language = getAttributeValue(n, "language");
839
840         System.out.println("\tSchema: " + schema + " Element: " + element + " Qualifier: " + qualifier
841                 + " Value: " + value);
842
843         if (qualifier.equals("none") || "".equals(qualifier))
844         {
845             qualifier = null;
846         }
847
848         // if language isn't set, use the system's default value
849
if (language.equals(""))
850         {
851             language = ConfigurationManager.getProperty("default.language");
852         }
853
854         // a goofy default, but there it is
855
if (language == null)
856         {
857             language = "en";
858         }
859
860         if (!isTest)
861         {
862             i.addMetadata(schema, element, qualifier, language, value);
863         }
864     }
865
866     /**
867      * Return the String value of a Node
868      */

869     public String JavaDoc getStringValue(Node JavaDoc node)
870     {
871         String JavaDoc value = node.getNodeValue();
872
873         if (node.hasChildNodes())
874         {
875             Node JavaDoc first = node.getFirstChild();
876
877             if (first.getNodeType() == Node.TEXT_NODE)
878             {
879                 return first.getNodeValue();
880             }
881         }
882
883         return value;
884     }
885
886     /**
887      * Read in the handle file or return null if empty or doesn't exist
888      */

889     private String JavaDoc processHandleFile(Context c, Item i, String JavaDoc path,
890             String JavaDoc filename)
891     {
892         String JavaDoc filePath = path + File.separatorChar + filename;
893         String JavaDoc line = "";
894         String JavaDoc result = null;
895
896         System.out.println("Processing handle file: " + filename);
897         BufferedReader JavaDoc is = null;
898         try
899         {
900             is = new BufferedReader JavaDoc(new FileReader JavaDoc(filePath));
901
902             // result gets contents of file, or null
903
result = is.readLine();
904
905             System.out.println("read handle: '" + result + "'");
906
907         }
908         catch (Exception JavaDoc e)
909         {
910             // probably no handle file, just return null
911
System.out
912                     .println("It appears there is no handle file -- generating one");
913         }
914         finally
915         {
916             if (is != null)
917             {
918                 try
919                 {
920                     is.close();
921                 }
922                 catch (IOException JavaDoc e1)
923                 {
924                     System.err
925                             .println("Non-critical problem releasing resources.");
926                 }
927             }
928         }
929
930         return result;
931     }
932
933     /**
934      * Given a contents file and an item, stuffing it with bitstreams from the
935      * contents file
936      */

937     private void processContentsFile(Context c, Item i, String JavaDoc path,
938             String JavaDoc filename) throws SQLException JavaDoc, IOException JavaDoc,
939             AuthorizeException
940     {
941         String JavaDoc contentspath = path + File.separatorChar + filename;
942         String JavaDoc line = "";
943
944         System.out.println("\tProcessing contents file: " + contentspath);
945
946         BufferedReader JavaDoc is = null;
947         try
948         {
949             is = new BufferedReader JavaDoc(new FileReader JavaDoc(contentspath));
950
951             while ((line = is.readLine()) != null)
952             {
953                 if ("".equals(line.trim()))
954                 {
955                     continue;
956                 }
957
958                 // 1) registered into dspace (leading -r)
959
// 2) imported conventionally into dspace (no -r)
960
if (line.trim().startsWith("-r "))
961                 {
962                     // line should be one of these two:
963
// -r -s n -f filepath
964
// -r -s n -f filepath\tbundle:bundlename
965
// where
966
// n is the assetstore number
967
// filepath is the path of the file to be registered
968
// bundlename is an optional bundle name
969
String JavaDoc sRegistrationLine = line.trim();
970                     int iAssetstore = -1;
971                     String JavaDoc sFilePath = null;
972                     String JavaDoc sBundle = null;
973                     StringTokenizer JavaDoc tokenizer =
974                             new StringTokenizer JavaDoc(sRegistrationLine);
975                     while (tokenizer.hasMoreTokens())
976                     {
977                         String JavaDoc sToken = tokenizer.nextToken();
978                         if (sToken.equals("-r"))
979                         {
980                             continue;
981                         }
982                         else if (sToken.equals("-s") && tokenizer.hasMoreTokens())
983                         {
984                             try
985                             {
986                                 iAssetstore =
987                                     Integer.parseInt(tokenizer.nextToken());
988                             }
989                             catch (NumberFormatException JavaDoc e)
990                             {
991                                 // ignore - iAssetstore remains -1
992
}
993                         }
994                         else if (sToken.equals("-f") && tokenizer.hasMoreTokens())
995                         {
996                             sFilePath = tokenizer.nextToken();
997
998                         }
999                         else if (sToken.startsWith("bundle:"))
1000                        {
1001                            sBundle = sToken.substring(7);
1002                        }
1003                        else
1004                        {
1005                            // unrecognized token - should be no problem
1006
}
1007                    } // while
1008
if (iAssetstore == -1 || sFilePath == null)
1009                    {
1010                        System.out.println("\tERROR: invalid contents file line");
1011                        System.out.println("\t\tSkipping line: "
1012                                + sRegistrationLine);
1013                        continue;
1014                    }
1015                    registerBitstream(c, i, iAssetstore, sFilePath, sBundle);
1016                    System.out.println("\tRegistering Bitstream: " + sFilePath
1017                            + "\tAssetstore: " + iAssetstore
1018                            + "\tBundle: " + sBundle);
1019                    continue; // process next line in contents file
1020
}
1021
1022                // look for a bundle name
1023
String JavaDoc bundleMarker = "\tbundle:";
1024
1025                int markerIndex = line.indexOf(bundleMarker);
1026
1027                if (markerIndex == -1)
1028                {
1029                    // no bundle found
1030
processContentFileEntry(c, i, path, line, null);
1031                    System.out.println("\tBitstream: " + line);
1032                }
1033                else
1034                {
1035                    // found bundle
1036
String JavaDoc bundleName = line.substring(markerIndex
1037                            + bundleMarker.length());
1038                    String JavaDoc bitstreamName = line.substring(0, markerIndex);
1039                    bitstreamName = bitstreamName.trim();
1040                    
1041                    processContentFileEntry(c, i, path, bitstreamName,
1042                            bundleName);
1043                    System.out.println("\tBitstream: " + bitstreamName
1044                            + "\tBundle: " + bundleName);
1045                }
1046            }
1047        }
1048        finally
1049        {
1050            if (is != null)
1051            {
1052                is.close();
1053            }
1054        }
1055    }
1056
1057    // each entry represents a bitstream....
1058
public void processContentFileEntry(Context c, Item i, String JavaDoc path,
1059            String JavaDoc fileName, String JavaDoc bundleName) throws SQLException JavaDoc,
1060            IOException JavaDoc, AuthorizeException
1061    {
1062        String JavaDoc fullpath = path + File.separatorChar + fileName;
1063
1064        // get an input stream
1065
BufferedInputStream JavaDoc bis = new BufferedInputStream JavaDoc(new FileInputStream JavaDoc(
1066                fullpath));
1067
1068        Bitstream bs = null;
1069        String JavaDoc newBundleName = bundleName;
1070
1071        if (bundleName == null)
1072        {
1073            // is it license.txt?
1074
if (fileName.equals("license.txt"))
1075            {
1076                newBundleName = "LICENSE";
1077            }
1078            else
1079            {
1080                // call it ORIGINAL
1081
newBundleName = "ORIGINAL";
1082            }
1083        }
1084
1085        if (!isTest)
1086        {
1087            // find the bundle
1088
Bundle[] bundles = i.getBundles(newBundleName);
1089            Bundle targetBundle = null;
1090
1091            if (bundles.length < 1)
1092            {
1093                // not found, create a new one
1094
targetBundle = i.createBundle(newBundleName);
1095            }
1096            else
1097            {
1098                // put bitstreams into first bundle
1099
targetBundle = bundles[0];
1100            }
1101
1102            // now add the bitstream
1103
bs = targetBundle.createBitstream(bis);
1104
1105            bs.setName(fileName);
1106
1107            // Identify the format
1108
// FIXME - guessing format guesses license.txt incorrectly as a text
1109
// file format!
1110
BitstreamFormat bf = FormatIdentifier.guessFormat(c, bs);
1111            bs.setFormat(bf);
1112
1113            bs.update();
1114        }
1115    }
1116
1117    /**
1118     * Register the bitstream file into DSpace
1119     *
1120     * @param c
1121     * @param i
1122     * @param assetstore
1123     * @param bitstreamPath the full filepath expressed in the contents file
1124     * @param bundleName
1125     * @throws SQLException
1126     * @throws IOException
1127     * @throws AuthorizeException
1128     */

1129    public void registerBitstream(Context c, Item i, int assetstore,
1130            String JavaDoc bitstreamPath, String JavaDoc bundleName )
1131            throws SQLException JavaDoc, IOException JavaDoc, AuthorizeException
1132    {
1133        // TODO validate assetstore number
1134
// TODO make sure the bitstream is there
1135

1136        Bitstream bs = null;
1137        String JavaDoc newBundleName = bundleName;
1138        
1139        if (bundleName == null)
1140        {
1141            // is it license.txt?
1142
if (bitstreamPath.endsWith("license.txt"))
1143            {
1144                newBundleName = "LICENSE";
1145            }
1146            else
1147            {
1148                // call it ORIGINAL
1149
newBundleName = "ORIGINAL";
1150            }
1151        }
1152
1153        if(!isTest)
1154        {
1155            // find the bundle
1156
Bundle[] bundles = i.getBundles(newBundleName);
1157            Bundle targetBundle = null;
1158                
1159            if( bundles.length < 1 )
1160            {
1161                // not found, create a new one
1162
targetBundle = i.createBundle(newBundleName);
1163            }
1164            else
1165            {
1166                // put bitstreams into first bundle
1167
targetBundle = bundles[0];
1168            }
1169    
1170            // now add the bitstream
1171
bs = targetBundle.registerBitstream(assetstore, bitstreamPath);
1172    
1173            // set the name to just the filename
1174
int iLastSlash = bitstreamPath.lastIndexOf('/');
1175            bs.setName(bitstreamPath.substring(iLastSlash + 1));
1176    
1177            // Identify the format
1178
// FIXME - guessing format guesses license.txt incorrectly as a text file format!
1179
BitstreamFormat bf = FormatIdentifier.guessFormat(c, bs);
1180            bs.setFormat(bf);
1181    
1182            bs.update();
1183        }
1184    }
1185
1186    // XML utility methods
1187
public String JavaDoc getAttributeValue(Node JavaDoc n, String JavaDoc myattributename)
1188    {
1189        String JavaDoc myvalue = "";
1190
1191        NamedNodeMap JavaDoc nm = n.getAttributes();
1192
1193        for (int i = 0; i < nm.getLength(); i++)
1194        {
1195            Node JavaDoc node = nm.item(i);
1196            String JavaDoc name = node.getNodeName();
1197            String JavaDoc value = node.getNodeValue();
1198
1199            if (myattributename.equals(name))
1200            {
1201                return value;
1202            }
1203        }
1204
1205        return myvalue;
1206    }
1207
1208    // XML utility methods stolen from administer.
1209

1210    /**
1211     * Get the CDATA of a particular element. For example, if the XML document
1212     * contains:
1213     * <P>
1214     * <code>
1215     * &lt;foo&gt;&lt;mimetype&gt;application/pdf&lt;/mimetype&gt;&lt;/foo&gt;
1216     * </code>
1217     * passing this the <code>foo</code> node and <code>mimetype</code> will
1218     * return <code>application/pdf</code>.
1219     * </P>
1220     * Why this isn't a core part of the XML API I do not know...
1221     *
1222     * @param parentElement
1223     * the element, whose child element you want the CDATA from
1224     * @param childName
1225     * the name of the element you want the CDATA from
1226     *
1227     * @return the CDATA as a <code>String</code>
1228     */

1229    private String JavaDoc getElementData(Node JavaDoc parentElement, String JavaDoc childName)
1230            throws TransformerException JavaDoc
1231    {
1232        // Grab the child node
1233
Node JavaDoc childNode = XPathAPI.selectSingleNode(parentElement, childName);
1234
1235        if (childNode == null)
1236        {
1237            // No child node, so no values
1238
return null;
1239        }
1240
1241        // Get the #text
1242
Node JavaDoc dataNode = childNode.getFirstChild();
1243
1244        if (dataNode == null)
1245        {
1246            return null;
1247        }
1248
1249        // Get the data
1250
String JavaDoc value = dataNode.getNodeValue().trim();
1251
1252        return value;
1253    }
1254
1255    /**
1256     * Load in the XML from file.
1257     *
1258     * @param filename
1259     * the filename to load from
1260     *
1261     * @return the DOM representation of the XML file
1262     */

1263    private static Document JavaDoc loadXML(String JavaDoc filename) throws IOException JavaDoc,
1264            ParserConfigurationException JavaDoc, SAXException JavaDoc
1265    {
1266        DocumentBuilder JavaDoc builder = DocumentBuilderFactory.newInstance()
1267                .newDocumentBuilder();
1268
1269        return builder.parse(new File JavaDoc(filename));
1270    }
1271}
1272
Popular Tags