SerialDataStore.java
001 /*
002  *  SerialDataStore.java
003  *
004  *  Copyright (c) 1995-2010, The University of Sheffield. See the file
005  *  COPYRIGHT.txt in the software or at http://gate.ac.uk/gate/COPYRIGHT.txt
006  *
007  *  This file is part of GATE (see http://gate.ac.uk/), and is free
008  *  software, licenced under the GNU Library General Public License,
009  *  Version 2, June 1991 (in the distribution as file licence.html,
010  *  and also available at http://gate.ac.uk/gate/licence.html).
011  *
012  *  Hamish Cunningham, 19/Jan/2001
013  *
014  *  $Id: SerialDataStore.java 12722 2010-06-03 19:53:33Z thomas_heitz $
015  */
016 
017 package gate.persist;
018 
019 import java.io.*;
020 import java.net.MalformedURLException;
021 import java.net.URISyntaxException;
022 import java.net.URL;
023 import java.util.*;
024 import java.util.zip.GZIPInputStream;
025 import java.util.zip.GZIPOutputStream;
026 
027 import gate.*;
028 import gate.corpora.SerialCorpusImpl;
029 import gate.creole.ResourceData;
030 import gate.event.DatastoreEvent;
031 import gate.event.DatastoreListener;
032 import gate.security.*;
033 import gate.security.SecurityException;
034 import gate.util.*;
035 
036 /**
037  * A data store based on Java serialisation.
038  */
039 public class SerialDataStore
040 extends AbstractFeatureBearer implements DataStore {
041 
042   /** Debug flag */
043   private static final boolean DEBUG = false;
044 
045   /** The name of the datastore */
046   protected String name;
047 
048   /**
049    * Construction requires a file protocol URL
050    * pointing to the storage directory used for
051    * the serialised classes. <B>NOTE:</B> should not be called except by
052    * GATE code.
053    */
054   public SerialDataStore(String storageDirUrlthrows PersistenceException {
055     setStorageUrl(storageDirUrl);
056   // construction from URL
057 
058   /**
059    * Default construction. <B>NOTE:</B> should not be called except by
060    * GATE code.
061    */
062   public SerialDataStore() { };
063 
064   /**
065    * The directory used for the serialised classes.
066    */
067   protected File storageDir;
068 
069   /** Set method for storage URL */
070   public void setStorageDir(File storageDir) { this.storageDir = storageDir; }
071 
072   /** Get method for storage URL */
073   public File getStorageDir() { return storageDir; }
074 
075   /** Set the URL for the underlying storage mechanism. */
076   public void setStorageUrl(String urlStringthrows PersistenceException {
077     URL storageUrl = null;
078     try {
079      storageUrl  = new URL(urlString);
080     catch (java.net.MalformedURLException ex) {
081       throw new PersistenceException(
082         "The URL passed is not correct: " + urlString
083       );
084     }
085     if(! storageUrl.getProtocol().equalsIgnoreCase("file"))
086       throw new PersistenceException(
087         "A serial data store needs a file URL, not " + storageUrl
088       );
089     try {
090       this.storageDir = new File(storageUrl.toURI());
091     catch(URISyntaxException use){
092       this.storageDir = Files.fileFromURL(storageUrl);
093     }
094   // setStorageUrl
095 
096   /** Get the URL for the underlying storage mechanism. */
097   public String getStorageUrl() {
098     if(storageDir == nullreturn null;
099 
100     URL u = null;
101     try u = storageDir.toURI().toURL()catch(MalformedURLException e) {
102       // we can assume that this never happens as storageUrl should always
103       // be a valid file and therefore convertable to URL
104     }
105 
106     return u.toString();
107   // getStorageUrl()
108 
109   /** Create a new data store. This tries to create a directory in
110     * the local file system. If the directory already exists and is
111     * non-empty, or is
112     * a file, or cannot be created, PersistenceException is thrown.
113     */
114   public void create()
115   throws PersistenceException {
116     if(storageDir == null)
117       throw new PersistenceException("null storage directory: cannot create");
118 
119     if(! storageDir.exists()) { // if doesn't exist create it
120       
121       if(! storageDir.mkdir())
122         throw new
123           PersistenceException("cannot create directory " + storageDir);
124     else // must be empty
125       String[] existingFiles = filterIgnoredFileNames(storageDir.list());
126       if((existingFiles == null || existingFiles.length == 0) )
127         throw new PersistenceException(
128           "directory "+ storageDir +" is not empty: cannot use for data store"
129         );
130     }
131 
132     // dump the version file
133     try {
134       File versionFile = getVersionFile();
135       OutputStreamWriter osw = new OutputStreamWriter(
136         new FileOutputStream(versionFile)
137       );
138       osw.write(versionNumber + Strings.getNl());
139       osw.close();
140     catch(IOException e) {
141       throw new PersistenceException("couldn't write version file: " + e);
142     }
143   // create()
144 
145   /** The name of the version file */
146   protected static String versionFileName = "__GATE_SerialDataStore__";
147 
148   /** The protocol version of the currently open data store */
149   protected static String currentProtocolVersion = null;
150 
151   /** Get a File for the protocol version file. */
152   protected File getVersionFile() throws IOException {
153     return new File(storageDir, versionFileName);
154   // getVersionFile
155 
156   /**
157    * Version number for variations in the storage protocol.
158    * Protocol versions:
159    <UL>
160    <LI>
161    * 1.0: uncompressed. Originally had no version file - to read a 1.0
162    * SerialDataStore that has no version file add a version file containing
163    * the line "1.0".
164    <LI>
165    * 1.1: has a version file. Uses GZIP compression.
166    </UL>
167    * This variable stores the version of the current level of the
168    * protocol, NOT the level in use in the currently open data store.
169    */
170   protected String versionNumber = "1.1";
171 
172   /** List of valid protocol version numbers. */
173   protected String[] protocolVersionNumbers = {
174     "1.0",
175     "1.1"
176   }// protocolVersionNumbers
177 
178   /** Check a version number for validity. */
179   protected boolean isValidProtocolVersion(String versionNumber) {
180     if(versionNumber == null)
181       return false;
182 
183     for(int i = 0; i < protocolVersionNumbers.length; i++)
184       if(protocolVersionNumbers[i].equals(versionNumber))
185         return true;
186 
187     return false;
188   // isValidProtocolVersion
189 
190   /** Delete the data store.
191     */
192   public void delete() throws PersistenceException {
193     if(storageDir == null || ! Files.rmdir(storageDir))
194       throw new PersistenceException("couldn't delete " + storageDir);
195 
196     Gate.getDataStoreRegister().remove(this);
197   // delete()
198 
199   /** Delete a resource from the data store.
200     */
201   public void delete(String lrClassName, Object lrPersistenceId)
202   throws PersistenceException {
203 
204     // find the subdirectory for resources of this type
205     File resourceTypeDirectory = new File(storageDir, lrClassName);
206     if(
207       (! resourceTypeDirectory.exists()) ||
208       (! resourceTypeDirectory.isDirectory())
209     ) {
210       throw new PersistenceException("Can't find " + resourceTypeDirectory);
211     }
212 
213     // create a File to representing the resource storage file
214     File resourceFile = new File(resourceTypeDirectory, (String)lrPersistenceId);
215     if(! resourceFile.exists() || ! resourceFile.isFile())
216       throw new PersistenceException("Can't find file " + resourceFile);
217 
218     // delete the beast
219     if(! resourceFile.delete())
220       throw new PersistenceException("Can't delete file " + resourceFile);
221 
222     // if there are no more resources of this type, delete the dir too
223     if(filterIgnoredFileNames(resourceTypeDirectory.list()).length == 0)
224       if(! resourceTypeDirectory.delete())
225         throw new PersistenceException("Can't delete " + resourceTypeDirectory);
226 
227     //let the world know about it
228     fireResourceDeleted(
229       new DatastoreEvent(
230         this, DatastoreEvent.RESOURCE_DELETED, null, (StringlrPersistenceId
231       )
232     );
233   // delete(lr)
234 
235   /** Adopt a resource for persistence. */
236   public LanguageResource adopt(LanguageResource lr,SecurityInfo secInfo)
237   throws PersistenceException,gate.security.SecurityException {
238 
239     //ignore security info
240 
241     // check the LR's current DS
242     DataStore currentDS = lr.getDataStore();
243     if(currentDS == null) {  // an orphan - do the adoption
244       LanguageResource res = lr;
245 
246       if (lr instanceof Corpus) {
247         FeatureMap features1 = Factory.newFeatureMap();
248         features1.put("transientSource", lr);
249         try {
250           //here we create the persistent LR via Factory, so it's registered
251           //in GATE
252           res = (LanguageResource)
253             Factory.createResource("gate.corpora.SerialCorpusImpl", features1);
254           //Here the transient corpus is not deleted from the CRI, because
255           //this might not always be the desired behaviour
256           //since we chose that it is for the GUI, this functionality is
257           //now move to the 'Save to' action code in NameBearerHandle
258         catch (gate.creole.ResourceInstantiationException ex) {
259           throw new GateRuntimeException(ex.getMessage());
260         }
261 
262       }
263 
264       res.setDataStore(this);
265 
266       // let the world know
267       fireResourceAdopted(
268           new DatastoreEvent(this, DatastoreEvent.RESOURCE_ADOPTED, lr, null)
269       );
270       return res;
271     else if(currentDS.equals(this))         // adopted already here
272       return lr;
273     else {                      // someone else's child
274       throw new PersistenceException(
275         "Can't adopt a resource which is already in a different datastore"
276       );
277     }
278 
279 
280   // adopt(LR)
281 
282   /** Open a connection to the data store. */
283   public void open() throws PersistenceException {
284     if(storageDir == null)
285       throw new PersistenceException("Can't open: storage dir is null");
286 
287     // check storage directory is readable
288     if(! storageDir.canRead()) {
289       throw new PersistenceException("Can't read " + storageDir);
290     }
291 
292     // check storage directory is a valid serial datastore
293 // if we want to support old style:
294 // String versionInVersionFile = "1.0";
295 // (but this means it will open *any* directory)
296     try {
297       FileReader fis = new FileReader(getVersionFile());
298       BufferedReader isr = new BufferedReader(fis);
299       currentProtocolVersion = isr.readLine();
300       if(DEBUGOut.prln("opening SDS version " + currentProtocolVersion);
301       isr.close();
302     catch(IOException e) {
303       throw new PersistenceException(
304         "Invalid storage directory: " + e
305       );
306     }
307     if(! isValidProtocolVersion(currentProtocolVersion))
308       throw new PersistenceException(
309         "Invalid protocol version number: " + currentProtocolVersion
310       );
311 
312   // open()
313 
314   /** Close the data store. */
315   public void close() throws PersistenceException {
316     Gate.getDataStoreRegister().remove(this);
317   // close()
318 
319   /** Save: synchonise the in-memory image of the LR with the persistent
320     * image.
321     */
322   public void sync(LanguageResource lrthrows PersistenceException {
323 //    Out.prln("SDS: LR sync called. Saving " + lr.getClass().getName());
324 
325     // check that this LR is one of ours (i.e. has been adopted)
326     if(lr.getDataStore() == null || ! lr.getDataStore().equals(this))
327       throw new PersistenceException(
328         "LR " + lr.getName() " has not been adopted by this DataStore"
329       );
330 
331     // find the resource data for this LR
332     ResourceData lrData =
333       (ResourceDataGate.getCreoleRegister().get(lr.getClass().getName());
334 
335     // create a subdirectory for resources of this type if none exists
336     File resourceTypeDirectory = new File(storageDir, lrData.getClassName());
337     if(
338       (! resourceTypeDirectory.exists()) ||
339       (! resourceTypeDirectory.isDirectory())
340     ) {
341       // try to create the directory, throw an exception if it does not
342       // exist after this attempt.  It is possible for mkdir to fail and exists
343       // still to return true if another thread managed to sneak in and
344       // create the directory in the meantime
345       if(! resourceTypeDirectory.mkdir() && ! resourceTypeDirectory.exists())
346         throw new PersistenceException("Can't write " + resourceTypeDirectory);
347     }
348 
349     // create an indentifier for this resource
350     String lrName = null;
351     Object lrPersistenceId = null;
352     lrName = lr.getName();
353     lrPersistenceId = lr.getLRPersistenceId();
354 
355     if(lrName == null)
356       lrName = lrData.getName();
357     if(lrPersistenceId == null) {
358       lrPersistenceId = constructPersistenceId(lrName);
359       lr.setLRPersistenceId(lrPersistenceId);
360     }
361 
362     //we're saving a corpus. I need to save its documents first
363     if (lr instanceof Corpus) {
364       //check if the corpus is the one we support. CorpusImpl cannot be saved!
365       if ((lr instanceof SerialCorpusImpl))
366         throw new PersistenceException("Can't save a corpus which " +
367                                        "is not of type SerialCorpusImpl!");
368       SerialCorpusImpl corpus = (SerialCorpusImpllr;
369       //this is a list of the indexes of all newly-adopted documents
370       //which will be used by the SerialCorpusImpl to update the
371       //corresponding document IDs
372       for (int i = 0; i < corpus.size(); i++) {
373         //if the document is not in memory, there's little point in saving it
374         if ( (!corpus.isDocumentLoaded(i)) && corpus.isPersistentDocument(i))
375           continue;
376         if (DEBUG)
377           Out.prln("Saving document at position " + i);
378         if (DEBUG)
379           Out.prln("Document in memory " + corpus.isDocumentLoaded(i));
380         if (DEBUG)
381           Out.prln("is persistent? "+ corpus.isPersistentDocument(i));
382         if (DEBUG)
383           Out.prln("Document name at position" + corpus.getDocumentName(i));
384         Document doc = (Documentcorpus.get(i);
385         try {
386           //if the document is not already adopted, we need to do that first
387           if (doc.getLRPersistenceId() == null) {
388             if (DEBUGOut.prln("Document adopted" + doc.getName());
389             doc = (Documentthis.adopt(doc, null);
390             this.sync(doc);
391             if (DEBUGOut.prln("Document sync-ed");
392             corpus.setDocumentPersistentID(i, doc.getLRPersistenceId());
393           else{
394             //if it is adopted, just sync it
395             this.sync(doc);
396             if (DEBUGOut.prln("Document sync-ed");
397           }
398           // store the persistent ID. Needs to be done even if the document was
399           //already adopted, in case the doc was already persistent 
400           //when added to the corpus
401           corpus.setDocumentPersistentID(i, doc.getLRPersistenceId());
402           if (DEBUGOut.prln("new document ID " + doc.getLRPersistenceId());
403         catch (Exception ex) {
404           throw new PersistenceException("Error while saving corpus: "
405                                          + corpus
406                                          "because of an error storing document "
407                                          + ex.getMessage(), ex);
408         }
409       }//for loop through documents
410     }
411 
412     // create a File to store the resource in
413     File resourceFile = new File(resourceTypeDirectory, (StringlrPersistenceId);
414 
415     // dump the LR into the new File
416     try {
417       OutputStream os = new FileOutputStream(resourceFile);
418 
419       // after 1.1 the serialised files are compressed
420       if(! currentProtocolVersion.equals("1.0"))
421         os = new GZIPOutputStream(os);
422 
423       os=new BufferedOutputStream(os);
424       
425       ObjectOutputStream oos = new ObjectOutputStream(os);
426       oos.writeObject(lr);
427       oos.close();
428     catch(IOException e) {
429       throw new PersistenceException("Couldn't write to storage file: " + e);
430     }
431 
432     // let the world know about it
433     fireResourceWritten(
434       new DatastoreEvent(
435         this, DatastoreEvent.RESOURCE_WRITTEN, lr, (StringlrPersistenceId
436       )
437     );
438   // sync(LR)
439 
440   /** Create a persistent store Id from the name of a resource. */
441   protected String constructPersistenceId(String lrName) {
442     // change the persistence ID so that it can be used as a filename
443     lrName=lrName.replaceAll("[\\/:\\*\\?\"<>|]","_");
444     return lrName + "___" new Date().getTime() "___" + random();
445   // constructPersistenceId
446 
447   /** Get a resource from the persistent store.
448     <B>Don't use this method - use Factory.createResource with
449     * DataStore and DataStoreInstanceId parameters set instead.</B>
450     * (Sometimes I wish Java had "friend" declarations...)
451     */
452   public LanguageResource getLr(String lrClassName, Object lrPersistenceId)
453   throws PersistenceException,SecurityException {
454 
455     // find the subdirectory for resources of this type
456     File resourceTypeDirectory = new File(storageDir, lrClassName);
457     if(
458       (! resourceTypeDirectory.exists()) ||
459       (! resourceTypeDirectory.isDirectory())
460     ) {
461         throw new PersistenceException("Can't find " + resourceTypeDirectory);
462     }
463 
464     // create a File to representing the resource storage file
465     File resourceFile = new File(resourceTypeDirectory, (String)lrPersistenceId);
466     if(! resourceFile.exists() || ! resourceFile.isFile())
467       throw new PersistenceException("Can't find file " + resourceFile);
468 
469     // try and read the file and deserialise it
470     LanguageResource lr = null;
471     try {
472       InputStream is = new FileInputStream(resourceFile);
473 
474       // after 1.1 the serialised files are compressed
475       if(! currentProtocolVersion.equals("1.0"))
476         is = new GZIPInputStream(is);
477 
478       is=new BufferedInputStream(is);
479       
480       // Use an input stream that is aware of the GATE classloader
481       ObjectInputStream ois = new GateAwareObjectInputStream(is);
482       lr = (LanguageResourceois.readObject();
483       ois.close();
484     catch(IOException e) {
485       throw
486         new PersistenceException("Couldn't read file "+resourceFile+": "+e);
487     catch(ClassNotFoundException ee) {
488       throw
489         new PersistenceException("Couldn't find class "+lrClassName+": "+ee);
490     }
491 
492     // set the dataStore property of the LR (which is transient and therefore
493     // not serialised)
494     lr.setDataStore(this);
495     lr.setLRPersistenceId(lrPersistenceId);
496 
497     if (DEBUGOut.prln("LR read in memory: " + lr);
498 
499     return lr;
500   // getLr(id)
501 
502   /** Get a list of the types of LR that are present in the data store. */
503   public List getLrTypes() throws PersistenceException {
504     if(storageDir == null || ! storageDir.exists())
505       throw new PersistenceException("Can't read storage directory");
506 
507     // filter out the version file
508     String[] fileArray = filterIgnoredFileNames(storageDir.list());
509     List lrTypes = new ArrayList();
510     for(int i=0; i<fileArray.length; i++)
511       if(! fileArray[i].equals(versionFileName))
512         lrTypes.add(fileArray[i]);
513 
514     return lrTypes;
515   // getLrTypes()
516 
517   /** Get a list of the IDs of LRs of a particular type that are present. */
518   public List getLrIds(String lrTypethrows PersistenceException {
519     // a File to represent the directory for this type
520     File resourceTypeDir = new File(storageDir, lrType);
521     if(! resourceTypeDir.exists())
522       return Arrays.asList(new String[0]);
523 
524     return Arrays.asList(filterIgnoredFileNames(resourceTypeDir.list()));
525   // getLrIds(lrType)
526 
527   /** Get a list of the names of LRs of a particular type that are present. */
528   public List getLrNames(String lrTypethrows PersistenceException {
529     // the list of files storing LRs of this type; an array for the names
530     String[] lrFileNames = (String[]) getLrIds(lrType).toArray();
531     ArrayList lrNames = new ArrayList();
532 
533     // for each lr file name, munge its name and add to the lrNames list
534     for(int i = 0; i<lrFileNames.length; i++) {
535       String name = getLrName(lrFileNames[i]);
536       lrNames.add(name);
537     }
538 
539     return lrNames;
540   // getLrNames(lrType)
541 
542   /** Get the name of an LR from its ID. */
543   public String getLrName(Object lrId) {
544     int secondSeparator = ((StringlrId).lastIndexOf("___");
545     lrId = ((StringlrId).substring(0, secondSeparator);
546     int firstSeparator = ((StringlrId).lastIndexOf("___");
547 
548     return ((StringlrId).substring(0, firstSeparator);
549   // getLrName
550 
551   /** Set method for the autosaving behaviour of the data store.
552     <B>NOTE:</B> this type of datastore has no auto-save function,
553     * therefore this method throws an UnsupportedOperationException.
554     */
555   public void setAutoSaving(boolean autoSaving)
556   throws UnsupportedOperationException {
557     throw new UnsupportedOperationException(
558       "SerialDataStore has no auto-save capability"
559     );
560   // setAutoSaving
561 
562   /** Get the autosaving behaviour of the LR. */
563   public boolean isAutoSaving() { return autoSaving; }
564 
565   /** Flag for autosaving behaviour. */
566   protected boolean autoSaving = false;
567 
568   /** Generate a random integer between 0 and 9999 for file naming. */
569   protected static int random() {
570     return randomiser.nextInt(9999);
571   // random
572 
573   /** Random number generator */
574   protected static Random randomiser = new Random();
575   private transient Vector datastoreListeners;
576 
577   /** String representation */
578   public String toString() {
579     String nl = Strings.getNl();
580     StringBuffer s = new StringBuffer("SerialDataStore: ");
581     s.append("autoSaving: " + autoSaving);
582     s.append("; storageDir: " + storageDir);
583     s.append(nl);
584 
585     return s.toString();
586   // toString()
587 
588   /** Calculate a hash code based on the class and the storage dir. */
589   public int hashCode(){
590     return getClass().hashCode() ^ storageDir.hashCode();
591   // hashCode
592 
593   /** Equality: based on storage dir of other. */
594   public boolean equals(Object other) {
595 
596 
597     if ((other instanceof SerialDataStore))
598       return false;
599 
600     if (((SerialDataStore)other).storageDir.equals(storageDir))
601       return false;
602 
603     //check for the name. First with equals, because they can be both null
604     //in which case trying just with equals leads to a null pointer exception
605     if (((SerialDataStore)other).name == name)
606       return true;
607     else
608       return ((SerialDataStore)other).name.equals(name);
609   // equals
610 
611   public synchronized void removeDatastoreListener(DatastoreListener l) {
612     if (datastoreListeners != null && datastoreListeners.contains(l)) {
613       Vector v = (VectordatastoreListeners.clone();
614       v.removeElement(l);
615       datastoreListeners = v;
616     }
617   }
618   public synchronized void addDatastoreListener(DatastoreListener l) {
619     Vector v = datastoreListeners == null new Vector(2(VectordatastoreListeners.clone();
620     if (!v.contains(l)) {
621       v.addElement(l);
622       datastoreListeners = v;
623     }
624   }
625   protected void fireResourceAdopted(DatastoreEvent e) {
626     if (datastoreListeners != null) {
627       Vector listeners = datastoreListeners;
628       int count = listeners.size();
629       for (int i = 0; i < count; i++) {
630         ((DatastoreListenerlisteners.elementAt(i)).resourceAdopted(e);
631       }
632     }
633   }
634   protected void fireResourceDeleted(DatastoreEvent e) {
635     if (datastoreListeners != null) {
636       Vector listeners = datastoreListeners;
637       int count = listeners.size();
638       for (int i = 0; i < count; i++) {
639         ((DatastoreListenerlisteners.elementAt(i)).resourceDeleted(e);
640       }
641     }
642   }
643   protected void fireResourceWritten(DatastoreEvent e) {
644     if (datastoreListeners != null) {
645       Vector listeners = datastoreListeners;
646       int count = listeners.size();
647       for (int i = 0; i < count; i++) {
648         ((DatastoreListenerlisteners.elementAt(i)).resourceWritten(e);
649       }
650     }
651   }
652 
653   /**
654    * Returns the name of the icon to be used when this datastore is displayed
655    * in the GUI
656    */
657   public String getIconName(){
658     return "datastore";
659   }
660 
661   /**
662    * Returns the comment displayed by the GUI for this DataStore
663    */
664   public String getComment(){
665     return "GATE serial datastore";
666   }
667 
668   /**
669    * Checks if the user (identified by the sessionID)
670    *  has read access to the LR
671    */
672   public boolean canReadLR(Object lrID)
673     throws PersistenceException, gate.security.SecurityException{
674 
675     return true;
676   }
677   /**
678    * Checks if the user (identified by the sessionID)
679    * has write access to the LR
680    */
681   public boolean canWriteLR(Object lrID)
682     throws PersistenceException, gate.security.SecurityException{
683 
684     return true;
685   }
686 
687     /** Sets the name of this resource*/
688   public void setName(String name){
689     this.name = name;
690   }
691 
692   /** Returns the name of this resource*/
693   public String getName(){
694     return name;
695   }
696 
697 
698 
699   /** get security information for LR . */
700   public SecurityInfo getSecurityInfo(LanguageResource lr)
701     throws PersistenceException {
702 
703     throw new UnsupportedOperationException("security information is not supported "+
704                                             "for DatabaseDataStore");
705   }
706 
707   /** set security information for LR . */
708   public void setSecurityInfo(LanguageResource lr,SecurityInfo si)
709     throws PersistenceException, gate.security.SecurityException {
710 
711     throw new UnsupportedOperationException("security information is not supported "+
712                                             "for DatabaseDataStore");
713 
714   }
715 
716 
717   /** identify user using this datastore */
718   public void setSession(Session s)
719     throws gate.security.SecurityException {
720 
721     // do nothing
722   }
723 
724 
725 
726   /** identify user using this datastore */
727   public Session getSession(Session s)
728     throws gate.security.SecurityException {
729 
730     return null;
731   }
732 
733   /**
734    * Try to acquire exlusive lock on a resource from the persistent store.
735    * Always call unlockLR() when the lock is no longer needed
736    */
737   public boolean lockLr(LanguageResource lr)
738   throws PersistenceException,SecurityException {
739     return true;
740   }
741 
742   /**
743    * Releases the exlusive lock on a resource from the persistent store.
744    */
745   public void unlockLr(LanguageResource lr)
746   throws PersistenceException,SecurityException {
747     return;
748   }
749 
750   /** Get a list of LRs that satisfy some set or restrictions */
751   public List findLrIds(List constraintsthrows PersistenceException {
752     throw new UnsupportedOperationException(
753                               "Serial DataStore does not support document retrieval.");
754   }
755 
756   /**
757    *  Get a list of LRs that satisfy some set or restrictions and are
758    *  of a particular type
759    */
760   public List findLrIds(List constraints, String lrTypethrows PersistenceException {
761     throw new UnsupportedOperationException(
762                               "Serial DataStore does not support document retrieval.");
763   }
764 
765   /**
766    * This removes the names of all files from a list of file names for which
767    * we know that we want to ignore them.
768    * Currently, all names starting with a dot are ignored.
769    
770    @param fileNames
771    @return the list of file names with the ignored names removed
772    */
773   protected String[] filterIgnoredFileNames(String[] fileNames) {
774     if(fileNames == null || fileNames.length == 0) {
775       return fileNames;
776     }
777     Vector<String> filteredNames = new Vector<String>(fileNames.length);
778     for(String filname : fileNames) {
779       if(!filname.startsWith(".")) {
780         filteredNames.add(filname);
781       }
782     }
783     return filteredNames.toArray(new String[0]);
784   }
785 
786 
787 // class SerialDataStore