| SerialDataStore |

    1   /*
    2    *  SerialDataStore.java
    3    *
    4    *  Copyright (c) 1998-2001, The University of Sheffield.
    5    *
    6    *  This file is part of GATE (see http://gate.ac.uk/), and is free
    7    *  software, licenced under the GNU Library General Public License,
    8    *  Version 2, June 1991 (in the distribution as file licence.html,
    9    *  and also available at http://gate.ac.uk/gate/licence.html).
    10   *
    11   *  Hamish Cunningham, 19/Jan/2001
    12   *
    13   *  $Id: SerialDataStore.java,v 1.44 2001/12/03 14:03:44 kalina Exp $
    14   */
    15
    16  package gate.persist;
    17
    18  import java.util.*;
    19  import java.util.zip.*;
    20  import java.net.*;
    21  import java.io.*;
    22
    23  import gate.*;
    24  import gate.creole.*;
    25  import gate.util.*;
    26  import gate.event.*;
    27  import gate.security.*;
    28  import gate.security.SecurityException;
    29  import gate.corpora.*;
    30
    31  /**
    32   * A data store based on Java serialisation.
    33   */
    34  public class SerialDataStore
    35  extends AbstractFeatureBearer implements DataStore {
    36
    37    /** Debug flag */
    38    private static final boolean DEBUG = false;
    39
    40    /** The name of the datastore */
    41    protected String name;
    42
    43    /**
    44     * Construction requires a file protocol URL
    45     * pointing to the storage directory used for
    46     * the serialised classes. <B>NOTE:</B> should not be called except by
    47     * GATE code.
    48     */
    49    public SerialDataStore(String storageDirUrl) throws PersistenceException {
    50      setStorageUrl(storageDirUrl);
    51    } // construction from URL
    52
    53    /**
    54     * Default construction. <B>NOTE:</B> should not be called except by
    55     * GATE code.
    56     */
    57    public SerialDataStore() { };
    58
    59    /**
    60     * The directory used for the serialised classes.
    61     */
    62    protected File storageDir;
    63
    64    /** Set method for storage URL */
    65    public void setStorageDir(File storageDir) { this.storageDir = storageDir; }
    66
    67    /** Get method for storage URL */
    68    public File getStorageDir() { return storageDir; }
    69
    70    /** Set the URL for the underlying storage mechanism. */
    71    public void setStorageUrl(String urlString) throws PersistenceException {
    72      URL storageUrl = null;
    73      try {
    74       storageUrl  = new URL(urlString);
    75      } catch (java.net.MalformedURLException ex) {
    76        throw new PersistenceException(
    77          "The URL passed is not correct: " + urlString
    78        );
    79      }
    80      if(! storageUrl.getProtocol().equalsIgnoreCase("file"))
    81        throw new PersistenceException(
    82          "A serial data store needs a file URL, not " + storageUrl
    83        );
    84      this.storageDir = new File(storageUrl.getFile());
    85    } // setStorageUrl
    86
    87    /** Get the URL for the underlying storage mechanism. */
    88    public String getStorageUrl() {
    89      if(storageDir == null) return null;
    90
    91      URL u = null;
    92      try { u = storageDir.toURL(); } catch(MalformedURLException e) {
    93        // we can assume that this never happens as storageUrl should always
    94        // be a valid file and therefore convertable to URL
    95      }
    96
    97      return u.toString();
    98    } // getStorageUrl()
    99
    100   /** Create a new data store. This tries to create a directory in
    101     * the local file system. If the directory already exists and is
    102     * non-empty, or is
    103     * a file, or cannot be created, PersistenceException is thrown.
    104     */
    105   public void create()
    106   throws PersistenceException {
    107     if(storageDir == null)
    108       throw new PersistenceException("null storage directory: cannot create");
    109
    110     if(! storageDir.exists()) { // if doesn't exist create it
    111       if(! storageDir.mkdir())
    112         throw new
    113           PersistenceException("cannot create directory " + storageDir);
    114     } else { // must be empty
    115       String[] existingFiles = storageDir.list();
    116       if(! (existingFiles == null || existingFiles.length == 0) )
    117         throw new PersistenceException(
    118           "directory "+ storageDir +" is not empty: cannot use for data store"
    119         );
    120     }
    121
    122     // dump the version file
    123     try {
    124       File versionFile = getVersionFile();
    125       OutputStreamWriter osw = new OutputStreamWriter(
    126         new FileOutputStream(versionFile)
    127       );
    128       osw.write(versionNumber + Strings.getNl());
    129       osw.close();
    130     } catch(IOException e) {
    131       throw new PersistenceException("couldn't write version file: " + e);
    132     }
    133   } // create()
    134
    135   /** The name of the version file */
    136   protected static String versionFileName = "__GATE_SerialDataStore__";
    137
    138   /** The protocol version of the currently open data store */
    139   protected static String currentProtocolVersion = null;
    140
    141   /** Get a File for the protocol version file. */
    142   protected File getVersionFile() throws IOException {
    143     return new File(storageDir, versionFileName);
    144   } // getVersionFile
    145
    146   /**
    147    * Version number for variations in the storage protocol.
    148    * Protocol versions:
    149    * <UL>
    150    * <LI>
    151    * 1.0: uncompressed. Originally had no version file - to read a 1.0
    152    * SerialDataStore that has no version file add a version file containing
    153    * the line "1.0".
    154    * <LI>
    155    * 1.1: has a version file. Uses GZIP compression.
    156    * </UL>
    157    * This variable stores the version of the current level of the
    158    * protocol, NOT the level in use in the currently open data store.
    159    */
    160   protected String versionNumber = "1.1";
    161
    162   /** List of valid protocol version numbers. */
    163   protected String[] protocolVersionNumbers = {
    164     "1.0",
    165     "1.1"
    166   }; // protocolVersionNumbers
    167
    168   /** Check a version number for validity. */
    169   protected boolean isValidProtocolVersion(String versionNumber) {
    170     if(versionNumber == null)
    171       return false;
    172
    173     for(int i = 0; i < protocolVersionNumbers.length; i++)
    174       if(protocolVersionNumbers[i].equals(versionNumber))
    175         return true;
    176
    177     return false;
    178   } // isValidProtocolVersion
    179
    180   /** Delete the data store.
    181     */
    182   public void delete() throws PersistenceException {
    183     if(storageDir == null || ! Files.rmdir(storageDir))
    184       throw new PersistenceException("couldn't delete " + storageDir);
    185
    186     Gate.getDataStoreRegister().remove(this);
    187   } // delete()
    188
    189   /** Delete a resource from the data store.
    190     */
    191   public void delete(String lrClassName, Object lrPersistenceId)
    192   throws PersistenceException {
    193
    194     // find the subdirectory for resources of this type
    195     File resourceTypeDirectory = new File(storageDir, lrClassName);
    196     if(
    197       (! resourceTypeDirectory.exists()) ||
    198       (! resourceTypeDirectory.isDirectory())
    199     ) {
    200       throw new PersistenceException("Can't find " + resourceTypeDirectory);
    201     }
    202
    203     // create a File to representing the resource storage file
    204     File resourceFile = new File(resourceTypeDirectory, (String)lrPersistenceId);
    205     if(! resourceFile.exists() || ! resourceFile.isFile())
    206       throw new PersistenceException("Can't find file " + resourceFile);
    207
    208     // delete the beast
    209     if(! resourceFile.delete())
    210       throw new PersistenceException("Can't delete file " + resourceFile);
    211
    212     // if there are no more resources of this type, delete the dir too
    213     if(resourceTypeDirectory.list().length == 0)
    214       if(! resourceTypeDirectory.delete())
    215         throw new PersistenceException("Can't delete " + resourceTypeDirectory);
    216
    217     //let the world know about it
    218     fireResourceDeleted(
    219       new DatastoreEvent(
    220         this, DatastoreEvent.RESOURCE_DELETED, null, (String) lrPersistenceId
    221       )
    222     );
    223   } // delete(lr)
    224
    225   /** Adopt a resource for persistence. */
    226   public LanguageResource adopt(LanguageResource lr,SecurityInfo secInfo)
    227   throws PersistenceException,gate.security.SecurityException {
    228
    229     //ignore security info
    230
    231     // check the LR's current DS
    232     DataStore currentDS = lr.getDataStore();
    233     if(currentDS == null) {  // an orphan - do the adoption
    234       LanguageResource res = lr;
    235
    236       if (lr instanceof Corpus) {
    237         FeatureMap features1 = Factory.newFeatureMap();
    238         features1.put("transientSource", lr);
    239         try {
    240           //here we create the persistent LR via Factory, so it's registered
    241           //in GATE
    242           res = (LanguageResource)
    243             Factory.createResource("gate.corpora.SerialCorpusImpl", features1);
    244           //Here the transient corpus is not deleted from the CRI, because
    245           //this might not always be the desired behaviour
    246           //since we chose that it is for the GUI, this functionality is
    247           //now move to the 'Save to' action code in NameBearerHandle
    248         } catch (gate.creole.ResourceInstantiationException ex) {
    249           throw new GateRuntimeException(ex.getMessage());
    250         }
    251
    252       }
    253
    254       res.setDataStore(this);
    255
    256       // let the world know
    257       fireResourceAdopted(
    258           new DatastoreEvent(this, DatastoreEvent.RESOURCE_ADOPTED, lr, null)
    259       );
    260       return res;
    261     } else if(currentDS.equals(this))         // adopted already here
    262       return lr;
    263     else {                      // someone else's child
    264       throw new PersistenceException(
    265         "Can't adopt a resource which is already in a different datastore"
    266       );
    267     }
    268
    269
    270   } // adopt(LR)
    271
    272   /** Open a connection to the data store. */
    273   public void open() throws PersistenceException {
    274     if(storageDir == null)
    275       throw new PersistenceException("Can't open: storage dir is null");
    276
    277     // check storage directory is readable
    278     if(! storageDir.canRead()) {
    279       throw new PersistenceException("Can't read " + storageDir);
    280     }
    281
    282     // check storage directory is a valid serial datastore
    283 // if we want to support old style:
    284 // String versionInVersionFile = "1.0";
    285 // (but this means it will open *any* directory)
    286     try {
    287       FileReader fis = new FileReader(getVersionFile());
    288       BufferedReader isr = new BufferedReader(fis);
    289       currentProtocolVersion = isr.readLine();
    290       if(DEBUG) Out.prln("opening SDS version " + currentProtocolVersion);
    291       isr.close();
    292     } catch(IOException e) {
    293       throw new PersistenceException(
    294         "Invalid storage directory: " + e
    295       );
    296     }
    297     if(! isValidProtocolVersion(currentProtocolVersion))
    298       throw new PersistenceException(
    299         "Invalid protocol version number: " + currentProtocolVersion
    300       );
    301
    302   } // open()
    303
    304   /** Close the data store. */
    305   public void close() throws PersistenceException {
    306     Gate.getDataStoreRegister().remove(this);
    307   } // close()
    308
    309   /** Save: synchonise the in-memory image of the LR with the persistent
    310     * image.
    311     */
    312   public void sync(LanguageResource lr) throws PersistenceException {
    313 //    Out.prln("SDS: LR sync called. Saving " + lr.getClass().getName());
    314
    315     // check that this LR is one of ours (i.e. has been adopted)
    316     if(lr.getDataStore() == null || ! lr.getDataStore().equals(this))
    317       throw new PersistenceException(
    318         "This LR is not stored in this DataStore"
    319       );
    320
    321     // find the resource data for this LR
    322     ResourceData lrData =
    323       (ResourceData) Gate.getCreoleRegister().get(lr.getClass().getName());
    324
    325     // create a subdirectory for resources of this type if none exists
    326     File resourceTypeDirectory = new File(storageDir, lrData.getClassName());
    327     if(
    328       (! resourceTypeDirectory.exists()) ||
    329       (! resourceTypeDirectory.isDirectory())
    330     ) {
    331       if(! resourceTypeDirectory.mkdir())
    332         throw new PersistenceException("Can't write " + resourceTypeDirectory);
    333     }
    334
    335     // create an indentifier for this resource
    336     String lrName = null;
    337     Object lrPersistenceId = null;
    338     lrName = lr.getName();
    339     lrPersistenceId = lr.getLRPersistenceId();
    340
    341     if(lrName == null)
    342       lrName = lrData.getName();
    343     if(lrPersistenceId == null) {
    344       lrPersistenceId = constructPersistenceId(lrName);
    345       lr.setLRPersistenceId(lrPersistenceId);
    346     }
    347
    348     //we're saving a corpus. I need to save it's documents first
    349     if (lr instanceof Corpus) {
    350       //check if the corpus is the one we support. CorpusImpl cannot be saved!
    351       if (! (lr instanceof SerialCorpusImpl))
    352         throw new PersistenceException("Can't save a corpus which " +
    353                                        "is not of type SerialCorpusImpl!");
    354       SerialCorpusImpl corpus = (SerialCorpusImpl) lr;
    355       //this is a list of the indexes of all newly-adopted documents
    356       //which will be used by the SerialCorpusImpl to update the
    357       //corresponding document IDs
    358       for (int i = 0; i < corpus.size(); i++) {
    359         //if the document is not in memory, there's little point in saving it
    360         if ( (!corpus.isDocumentLoaded(i)) && corpus.isPersistentDocument(i))
    361           continue;
    362         if (DEBUG)
    363           Out.prln("Saving document at position " + i);
    364         if (DEBUG)
    365           Out.prln("Document in memory " + corpus.isDocumentLoaded(i));
    366         if (DEBUG)
    367           Out.prln("is persistent? "+ corpus.isPersistentDocument(i));
    368         if (DEBUG)
    369           Out.prln("Document name at position" + corpus.getDocumentName(i));
    370         Document doc = (Document) corpus.get(i);
    371         try {
    372           //if the document is not already adopted, we need to do that first
    373           if (doc.getLRPersistenceId() == null) {
    374             if (DEBUG) Out.prln("Document adopted" + doc.getName());
    375             doc = (Document) this.adopt(doc, null);
    376             this.sync(doc);
    377             if (DEBUG) Out.prln("Document sync-ed");
    378             corpus.setDocumentPersistentID(i, doc.getLRPersistenceId());
    379             if (DEBUG) Out.prln("new document ID " + doc.getLRPersistenceId());
    380           } else //if it is adopted, just sync it
    381             this.sync(doc);
    382         } catch (Exception ex) {
    383           throw new PersistenceException("Error while saving corpus: "
    384                                          + corpus
    385                                          + "because of an error storing document "
    386                                          + ex.getMessage());
    387         }
    388       }//for loop through documents
    389     }
    390
    391     // create a File to store the resource in
    392     File resourceFile = new File(resourceTypeDirectory, (String) lrPersistenceId);
    393
    394     // dump the LR into the new File
    395     try {
    396       OutputStream os = new FileOutputStream(resourceFile);
    397
    398       // after 1.1 the serialised files are compressed
    399       if(! currentProtocolVersion.equals("1.0"))
    400         os = new GZIPOutputStream(os);
    401
    402       ObjectOutputStream oos = new ObjectOutputStream(os);
    403       oos.writeObject(lr);
    404       oos.close();
    405     } catch(IOException e) {
    406       throw new PersistenceException("Couldn't write to storage file: " + e);
    407     }
    408
    409     // let the world know about it
    410     fireResourceWritten(
    411       new DatastoreEvent(
    412         this, DatastoreEvent.RESOURCE_WRITTEN, lr, (String) lrPersistenceId
    413       )
    414     );
    415   } // sync(LR)
    416
    417   /** Create a persistent store Id from the name of a resource. */
    418   protected String constructPersistenceId(String lrName) {
    419     return lrName + "___" + new Date().getTime() + "___" + random();
    420   } // constructPersistenceId
    421
    422   /** Get a resource from the persistent store.
    423     * <B>Don't use this method - use Factory.createResource with
    424     * DataStore and DataStoreInstanceId parameters set instead.</B>
    425     * (Sometimes I wish Java had "friend" declarations...)
    426     */
    427   public LanguageResource getLr(String lrClassName, Object lrPersistenceId)
    428   throws PersistenceException,SecurityException {
    429
    430     // find the subdirectory for resources of this type
    431     File resourceTypeDirectory = new File(storageDir, lrClassName);
    432     if(
    433       (! resourceTypeDirectory.exists()) ||
    434       (! resourceTypeDirectory.isDirectory())
    435     ) {
    436         throw new PersistenceException("Can't find " + resourceTypeDirectory);
    437     }
    438
    439     // create a File to representing the resource storage file
    440     File resourceFile = new File(resourceTypeDirectory, (String)lrPersistenceId);
    441     if(! resourceFile.exists() || ! resourceFile.isFile())
    442       throw new PersistenceException("Can't find file " + resourceFile);
    443
    444     // try and read the file and deserialise it
    445     LanguageResource lr = null;
    446     try {
    447       InputStream is = new FileInputStream(resourceFile);
    448
    449       // after 1.1 the serialised files are compressed
    450       if(! currentProtocolVersion.equals("1.0"))
    451         is = new GZIPInputStream(is);
    452
    453       ObjectInputStream ois = new ObjectInputStream(is);
    454       lr = (LanguageResource) ois.readObject();
    455       ois.close();
    456     } catch(IOException e) {
    457       throw
    458         new PersistenceException("Couldn't read file "+resourceFile+": "+e);
    459     } catch(ClassNotFoundException ee) {
    460       throw
    461         new PersistenceException("Couldn't find class "+lrClassName+": "+ee);
    462     }
    463
    464     // set the dataStore property of the LR (which is transient and therefore
    465     // not serialised)
    466     lr.setDataStore(this);
    467     lr.setLRPersistenceId(lrPersistenceId);
    468
    469     if (DEBUG) Out.prln("LR read in memory: " + lr);
    470
    471     return lr;
    472   } // getLr(id)
    473
    474   /** Get a list of the types of LR that are present in the data store. */
    475   public List getLrTypes() throws PersistenceException {
    476     if(storageDir == null || ! storageDir.exists())
    477       throw new PersistenceException("Can't read storage directory");
    478
    479     // filter out the version file
    480     String[] fileArray = storageDir.list();
    481     List lrTypes = new ArrayList();
    482     for(int i=0; i<fileArray.length; i++)
    483       if(! fileArray[i].equals(versionFileName))
    484         lrTypes.add(fileArray[i]);
    485
    486     return lrTypes;
    487   } // getLrTypes()
    488
    489   /** Get a list of the IDs of LRs of a particular type that are present. */
    490   public List getLrIds(String lrType) throws PersistenceException {
    491     // a File to represent the directory for this type
    492     File resourceTypeDir = new File(storageDir, lrType);
    493     if(! resourceTypeDir.exists())
    494       return Arrays.asList(new String[0]);
    495
    496     return Arrays.asList(resourceTypeDir.list());
    497   } // getLrIds(lrType)
    498
    499   /** Get a list of the names of LRs of a particular type that are present. */
    500   public List getLrNames(String lrType) throws PersistenceException {
    501     // the list of files storing LRs of this type; an array for the names
    502     String[] lrFileNames = (String[]) getLrIds(lrType).toArray();
    503     ArrayList lrNames = new ArrayList();
    504
    505     // for each lr file name, munge its name and add to the lrNames list
    506     for(int i = 0; i<lrFileNames.length; i++) {
    507       String name = getLrName(lrFileNames[i]);
    508       lrNames.add(name);
    509     }
    510
    511     return lrNames;
    512   } // getLrNames(lrType)
    513
    514   /** Get the name of an LR from its ID. */
    515   public String getLrName(Object lrId) {
    516     int secondSeparator = ((String) lrId).lastIndexOf("___");
    517     lrId = ((String) lrId).substring(0, secondSeparator);
    518     int firstSeparator = ((String) lrId).lastIndexOf("___");
    519
    520     return ((String) lrId).substring(0, firstSeparator);
    521   } // getLrName
    522
    523   /** Set method for the autosaving behaviour of the data store.
    524     * <B>NOTE:</B> this type of datastore has no auto-save function,
    525     * therefore this method throws an UnsupportedOperationException.
    526     */
    527   public void setAutoSaving(boolean autoSaving)
    528   throws UnsupportedOperationException {
    529     throw new UnsupportedOperationException(
    530       "SerialDataStore has no auto-save capability"
    531     );
    532   } // setAutoSaving
    533
    534   /** Get the autosaving behaviour of the LR. */
    535   public boolean isAutoSaving() { return autoSaving; }
    536
    537   /** Flag for autosaving behaviour. */
    538   protected boolean autoSaving = false;
    539
    540   /** Generate a random integer between 0 and 9999 for file naming. */
    541   protected static int random() {
    542     return randomiser.nextInt(9999);
    543   } // random
    544
    545   /** Random number generator */
    546   protected static Random randomiser = new Random();
    547   private transient Vector datastoreListeners;
    548
    549   /** String representation */
    550   public String toString() {
    551     String nl = Strings.getNl();
    552     StringBuffer s = new StringBuffer("SerialDataStore: ");
    553     s.append("autoSaving: " + autoSaving);
    554     s.append("; storageDir: " + storageDir);
    555     s.append(nl);
    556
    557     return s.toString();
    558   } // toString()
    559
    560   /** Calculate a hash code based on the class and the storage dir. */
    561   public int hashCode(){
    562     return getClass().hashCode() ^ storageDir.hashCode();
    563   } // hashCode
    564
    565   /** Equality: based on storage dir of other. */
    566   public boolean equals(Object other) {
    567
    568
    569     if (! (other instanceof SerialDataStore))
    570       return false;
    571
    572     if (! ((SerialDataStore)other).storageDir.equals(storageDir))
    573       return false;
    574
    575     //check for the name. First with equals, because they can be both null
    576     //in which case trying just with equals leads to a null pointer exception
    577     if (((SerialDataStore)other).name == name)
    578       return true;
    579     else
    580       return ((SerialDataStore)other).name.equals(name);
    581   } // equals
    582
    583   public synchronized void removeDatastoreListener(DatastoreListener l) {
    584     if (datastoreListeners != null && datastoreListeners.contains(l)) {
    585       Vector v = (Vector) datastoreListeners.clone();
    586       v.removeElement(l);
    587       datastoreListeners = v;
    588     }
    589   }
    590   public synchronized void addDatastoreListener(DatastoreListener l) {
    591     Vector v = datastoreListeners == null ? new Vector(2) : (Vector) datastoreListeners.clone();
    592     if (!v.contains(l)) {
    593       v.addElement(l);
    594       datastoreListeners = v;
    595     }
    596   }
    597   protected void fireResourceAdopted(DatastoreEvent e) {
    598     if (datastoreListeners != null) {
    599       Vector listeners = datastoreListeners;
    600       int count = listeners.size();
    601       for (int i = 0; i < count; i++) {
    602         ((DatastoreListener) listeners.elementAt(i)).resourceAdopted(e);
    603       }
    604     }
    605   }
    606   protected void fireResourceDeleted(DatastoreEvent e) {
    607     if (datastoreListeners != null) {
    608       Vector listeners = datastoreListeners;
    609       int count = listeners.size();
    610       for (int i = 0; i < count; i++) {
    611         ((DatastoreListener) listeners.elementAt(i)).resourceDeleted(e);
    612       }
    613     }
    614   }
    615   protected void fireResourceWritten(DatastoreEvent e) {
    616     if (datastoreListeners != null) {
    617       Vector listeners = datastoreListeners;
    618       int count = listeners.size();
    619       for (int i = 0; i < count; i++) {
    620         ((DatastoreListener) listeners.elementAt(i)).resourceWritten(e);
    621       }
    622     }
    623   }
    624
    625   /**
    626    * Returns the name of the icon to be used when this datastore is displayed
    627    * in the GUI
    628    */
    629   public String getIconName(){
    630     return "ds.gif";
    631   }
    632
    633   /**
    634    * Returns the comment displayed by the GUI for this DataStore
    635    */
    636   public String getComment(){
    637     return "GATE serial datastore";
    638   }
    639
    640   /**
    641    * Checks if the user (identified by the sessionID)
    642    *  has read access to the LR
    643    */
    644   public boolean canReadLR(Object lrID)
    645     throws PersistenceException, gate.security.SecurityException{
    646
    647     return true;
    648   }
    649   /**
    650    * Checks if the user (identified by the sessionID)
    651    * has write access to the LR
    652    */
    653   public boolean canWriteLR(Object lrID)
    654     throws PersistenceException, gate.security.SecurityException{
    655
    656     return true;
    657   }
    658
    659     /** Sets the name of this resource*/
    660   public void setName(String name){
    661     this.name = name;
    662   }
    663
    664   /** Returns the name of this resource*/
    665   public String getName(){
    666     return name;
    667   }
    668
    669
    670
    671   /** get security information for LR . */
    672   public SecurityInfo getSecurityInfo(LanguageResource lr)
    673     throws PersistenceException {
    674
    675     throw new UnsupportedOperationException("security information is not supported "+
    676                                             "for DatabaseDataStore");
    677   }
    678
    679   /** set security information for LR . */
    680   public void setSecurityInfo(LanguageResource lr,SecurityInfo si)
    681     throws PersistenceException, gate.security.SecurityException {
    682
    683     throw new UnsupportedOperationException("security information is not supported "+
    684                                             "for DatabaseDataStore");
    685
    686   }
    687
    688
    689   /** identify user using this datastore */
    690   public void setSession(Session s)
    691     throws gate.security.SecurityException {
    692
    693     // do nothing
    694   }
    695
    696
    697
    698   /** identify user using this datastore */
    699   public Session getSession(Session s)
    700     throws gate.security.SecurityException {
    701
    702     return null;
    703   }
    704
    705   /**
    706    * Try to acquire exlusive lock on a resource from the persistent store.
    707    * Always call unlockLR() when the lock is no longer needed
    708    */
    709   public boolean lockLr(LanguageResource lr)
    710   throws PersistenceException,SecurityException {
    711     return true;
    712   }
    713
    714   /**
    715    * Releases the exlusive lock on a resource from the persistent store.
    716    */
    717   public void unlockLr(LanguageResource lr)
    718   throws PersistenceException,SecurityException {
    719     return;
    720   }
    721
    722
    723 } // class SerialDataStore
    724

| SerialDataStore |