| Factory |

    1   /*
    2    *  Factory.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, 25/May/2000
    12   *
    13   *  $Id: Factory.java,v 1.74 2001/11/13 17:09:34 marin Exp $
    14   */
    15
    16  package gate;
    17
    18  import java.util.*;
    19  import java.net.*;
    20  import java.io.*;
    21  import java.beans.*;
    22  import java.lang.reflect.*;
    23
    24  import gate.corpora.*;
    25  import gate.util.*;
    26  import gate.annotation.*;
    27  import gate.creole.*;
    28  import gate.persist.*;
    29  import gate.security.*;
    30  import gate.security.SecurityException;
    31  import gate.event.*;
    32
    33  /** Provides static methods for the creation of Resources.
    34    */
    35  public abstract class Factory {
    36    /** Debug flag */
    37    private static final boolean DEBUG = false;
    38
    39    /** The CREOLE register */
    40    private static CreoleRegister reg = Gate.getCreoleRegister();
    41
    42    /** The DataStore register */
    43    private static DataStoreRegister dsReg = Gate.getDataStoreRegister();
    44
    45    /** An object to source events from. */
    46    private static CreoleProxy creoleProxy;
    47
    48    /** An object to source events from. */
    49    private static HashMap accessControllerPool;
    50
    51    /** Create an instance of a resource using default parameter values.
    52      * @see #createResource(String,FeatureMap)
    53      */
    54    public static Resource createResource(String resourceClassName)
    55    throws ResourceInstantiationException
    56    {
    57      // get the resource metadata
    58      ResourceData resData = (ResourceData) reg.get(resourceClassName);
    59      if(resData == null)
    60        throw new ResourceInstantiationException(
    61          "Couldn't get resource data for " + resourceClassName
    62        );
    63
    64      // get the parameter list and default values
    65      ParameterList paramList = resData.getParameterList();
    66      FeatureMap parameterValues = null;
    67      try {
    68        parameterValues = paramList.getInitimeDefaults();
    69      } catch(ParameterException e) {
    70        throw new ResourceInstantiationException(
    71          "Couldn't get default parameters for " + resourceClassName + ": " + e
    72        );
    73      }
    74
    75      return createResource(resourceClassName, parameterValues);
    76    } // createResource(resClassName)
    77
    78    /** Create an instance of a resource, and return it.
    79      * Callers of this method are responsible for
    80      * querying the resource's parameter lists, putting together a set that
    81      * is complete apart from runtime parameters, and passing a feature map
    82      * containing these parameter settings.
    83      *
    84      * @param resourceClassName the name of the class implementing the resource.
    85      * @param parameterValues the feature map containing intialisation time
    86      *   parameterValues for the resource.
    87      * @param listeners The listeners to be registered with the resource during
    88      * its initialisation. A {@link java.util.Map} that maps from fully
    89      * qualified class name (as a string) to listener (of the type declared by
    90      * the key).
    91      * @return an instantiated resource.
    92      */
    93    public static Resource createResource(
    94      String resourceClassName, FeatureMap parameterValues
    95    ) throws ResourceInstantiationException
    96    {
    97      return createResource(resourceClassName, parameterValues, null, null);
    98    } // createResource(resClassName, paramVals, listeners)
    99
    100   /** Create an instance of a resource, and return it.
    101     * Callers of this method are responsible for
    102     * querying the resource's parameter lists, putting together a set that
    103     * is complete apart from runtime parameters, and passing a feature map
    104     * containing these parameter settings.
    105     *
    106     * @param resourceClassName the name of the class implementing the resource.
    107     * @param parameterValues the feature map containing intialisation time
    108     *   parameterValues for the resource.
    109     * @param features the features for the new resource
    110     * @return an instantiated resource.
    111     */
    112   public static Resource createResource(
    113     String resourceClassName, FeatureMap parameterValues,
    114     FeatureMap features
    115     ) throws ResourceInstantiationException
    116    {
    117       return createResource(resourceClassName, parameterValues,
    118                             features, null);
    119    }
    120
    121   /** Create an instance of a resource, and return it.
    122     * Callers of this method are responsible for
    123     * querying the resource's parameter lists, putting together a set that
    124     * is complete apart from runtime parameters, and passing a feature map
    125     * containing these parameter settings.
    126     *
    127     * In the case of ProcessingResources they will have their runtime parameters
    128     * initialised to their default values.
    129     *
    130     * @param resourceClassName the name of the class implementing the resource.
    131     * @param parameterValues the feature map containing intialisation time
    132     *   parameterValues for the resource.
    133     * @param listeners The listeners to be registered with the resource during
    134     * its initialisation. A {@link java.util.Map} that maps freom fully
    135     * qualified class name (as a string) to listener (of the type declared by
    136     * the key).
    137     * @param features the features for the new resource
    138     * @return an instantiated resource.
    139     */
    140   public static Resource createResource(
    141     String resourceClassName, FeatureMap parameterValues,
    142     FeatureMap features, String resourceName
    143   ) throws ResourceInstantiationException
    144    {
    145     // get the resource metadata
    146     ResourceData resData = (ResourceData) reg.get(resourceClassName);
    147     if(resData == null)
    148       throw new ResourceInstantiationException(
    149         "Couldn't get resource data for " + resourceClassName
    150       );
    151     // get the default implementation class
    152     Class resClass = null;
    153     try {
    154       resClass = resData.getResourceClass();
    155     } catch(ClassNotFoundException e) {
    156       throw new ResourceInstantiationException(
    157         "Couldn't get resource class from the resource data:"+Strings.getNl()+e
    158       );
    159     }
    160
    161     //create a pointer for the resource
    162     Resource res = null;
    163
    164     //if the object is an LR and it should come from a DS then create that way
    165     DataStore dataStore;
    166     if(LanguageResource.class.isAssignableFrom(resClass) &&
    167        ((dataStore = (DataStore)parameterValues.
    168                      get(DataStore.DATASTORE_FEATURE_NAME)) != null)
    169       ){
    170       //ask the datastore to create our object
    171       if(dataStore instanceof SerialDataStore) {
    172         // SDS doesn't need a wrapper class; just check for serialisability
    173         if(! (resClass instanceof Serializable))
    174           throw new ResourceInstantiationException(
    175             "Resource cannot be (de-)serialized: " + resClass.getName()
    176           );
    177       }
    178
    179       // get the datastore instance id and retrieve the resource
    180       Object instanceId = parameterValues.get(DataStore.LR_ID_FEATURE_NAME);
    181       if(instanceId == null)
    182         throw new
    183           ResourceInstantiationException("No instance id for " + resClass);
    184       try {
    185         res = dataStore.getLr(resClass.getName(), instanceId);
    186       } catch(PersistenceException pe) {
    187         throw new ResourceInstantiationException("Bad read from DB: " + pe);
    188       } catch(SecurityException se) {
    189         throw new ResourceInstantiationException("Insufficient permissions: " + se);
    190       }
    191       resData.addInstantiation(res);
    192       if(features != null){
    193         if(res.getFeatures() == null){
    194           res.setFeatures(newFeatureMap());
    195         }
    196         res.getFeatures().putAll(features);
    197       }
    198
    199       //set the name
    200       if(res.getName() == null){
    201         res.setName(resourceName == null ?
    202                     resData.getName() + "_" + Gate.genSym() :
    203                     resourceName);
    204       }
    205
    206       // fire the event
    207       creoleProxy.fireResourceLoaded(
    208         new CreoleEvent(res, CreoleEvent.RESOURCE_LOADED)
    209       );
    210
    211       return res;
    212     }
    213
    214     //The resource is not a persistent LR; use a constructor
    215
    216     // create an object using the resource's default constructor
    217     try {
    218       if(DEBUG) Out.prln("Creating resource " + resClass.getName());
    219       res = (Resource) resClass.newInstance();
    220     } catch(IllegalAccessException e) {
    221       throw new ResourceInstantiationException(
    222         "Couldn't create resource instance, access denied: " + e
    223       );
    224     } catch(InstantiationException e) {
    225       throw new ResourceInstantiationException(
    226         "Couldn't create resource instance due to newInstance() failure: " + e
    227       );
    228     }
    229
    230     //set the name
    231     if(resourceName == null){
    232       resourceName = resData.getName() + "_" + Gate.genSym();
    233     }
    234     res.setName(resourceName);
    235
    236     if(LanguageResource.class.isAssignableFrom(resClass)) {
    237       // type-specific stuff for LRs
    238       if(DEBUG) Out.prln(resClass.getName() + " is a LR");
    239     } else if(ProcessingResource.class.isAssignableFrom(resClass)) {
    240       // type-specific stuff for PRs
    241       if(DEBUG) Out.prln(resClass.getName() + " is a PR");
    242       //set the runtime parameters to their defaults
    243       try{
    244         FeatureMap parameters = newFeatureMap();
    245         parameters.putAll(resData.getParameterList().getRuntimeDefaults());
    246         res.setParameterValues(parameters);
    247       }catch(ParameterException pe){
    248         throw new ResourceInstantiationException(
    249                   "Could not set the runtime parameters " +
    250                   "to their default values for: " + res.getClass().getName() +
    251                   " :\n" + pe.toString()
    252                   );
    253       }
    254     // type-specific stuff for VRs
    255     } else if(VisualResource.class.isAssignableFrom(resClass)) {
    256       if(DEBUG) Out.prln(resClass.getName() + " is a VR");
    257
    258     // we have a resource which is not an LR, PR or VR
    259     } else if(Controller.class.isAssignableFrom(resClass)){
    260       //type specific stuff for Controllers
    261     } else {
    262       Err.prln("WARNING: instantiating resource which is not a PR, LR or VR:");
    263       Err.prln(resData + "END OF WARNING" + Strings.getNl());
    264     }
    265
    266
    267
    268     //set the parameterValues of the resource
    269     try{
    270       FeatureMap parameters = newFeatureMap();
    271       //put the defaults
    272       parameters.putAll(resData.getParameterList().getInitimeDefaults());
    273       //overwrite the defaults with the user provided values
    274       parameters.putAll(parameterValues);
    275       res.setParameterValues(parameters);
    276     }catch(ParameterException pe){
    277         throw new ResourceInstantiationException(
    278                     "Could not set the init parameters for: " +
    279                     res.getClass().getName() + " :\n" + pe.toString()
    280                   );
    281     }
    282
    283
    284     Map listeners = new HashMap(gate.gui.MainFrame.getListeners());
    285     // set the listeners if any
    286     if(listeners != null && !listeners.isEmpty()) {
    287       try {
    288         if(DEBUG) Out.prln("Setting the listeners for  " + res.toString());
    289         AbstractResource.setResourceListeners(res, listeners);
    290       } catch(Exception e) {
    291         if(DEBUG) Out.prln("Failed to set listeners for " + res.toString());
    292         throw new
    293           ResourceInstantiationException("Parameterisation failure" + e);
    294       }
    295     }
    296
    297     // if the features of the resource have not been explicitly set,
    298     // set them to the features of the resource data
    299     if(res.getFeatures() == null || res.getFeatures().isEmpty()){
    300       FeatureMap fm = newFeatureMap();
    301       fm.putAll(resData.getFeatures());
    302       res.setFeatures(fm);
    303     }
    304
    305     // initialise the resource
    306     if(DEBUG) Out.prln("Initialising resource " + res.toString());
    307     res = res.init();
    308
    309     // remove the listeners if any
    310     if(listeners != null && !listeners.isEmpty()) {
    311       try {
    312         if(DEBUG) Out.prln("Removing the listeners for  " + res.toString());
    313         AbstractResource.removeResourceListeners(res, listeners);
    314       } catch(Exception e) {
    315         if (DEBUG) Out.prln(
    316           "Failed to remove the listeners for " + res.toString()
    317         );
    318         throw new
    319           ResourceInstantiationException("Parameterisation failure" + e);
    320       }
    321     }
    322
    323     // record the instantiation on the resource data's stack
    324     resData.addInstantiation(res);
    325
    326     // add the features specified by the user
    327     if(features != null) res.getFeatures().putAll(features);
    328
    329     // fire the event
    330     creoleProxy.fireResourceLoaded(
    331       new CreoleEvent(res, CreoleEvent.RESOURCE_LOADED)
    332     );
    333
    334     return res;
    335   } // create(resourceClassName, parameterValues, features, listeners)
    336
    337   /** Delete an instance of a resource. This involves removing it from
    338     * the stack of instantiations maintained by this resource type's
    339     * resource data. Deletion does not guarantee that the resource will
    340     * become a candidate for garbage collection, just that the GATE framework
    341     * is no longer holding references to the resource.
    342     *
    343     * @param resource the resource to be deleted.
    344     */
    345   public static void deleteResource(Resource resource) {
    346     ResourceData rd =
    347       (ResourceData) reg.get(resource.getClass().getName());
    348     if(rd!= null)
    349       rd.removeInstantiation(resource);
    350     resource.cleanup();
    351     creoleProxy.fireResourceUnloaded(
    352       new CreoleEvent(resource, CreoleEvent.RESOURCE_UNLOADED)
    353     );
    354   } // deleteResource
    355
    356   /** Create a new transient Corpus. */
    357   public static Corpus newCorpus(String name)
    358                                           throws ResourceInstantiationException
    359   {
    360     FeatureMap parameterValues = newFeatureMap();
    361     parameterValues.put("name", name);
    362 //    parameterValues.put("features", Factory.newFeatureMap());
    363     return (Corpus) createResource("gate.corpora.CorpusImpl", parameterValues);
    364   } // newCorpus
    365
    366   /** Create a new transient Document from a URL. */
    367   public static Document newDocument(URL sourceUrl)
    368                                           throws ResourceInstantiationException
    369   {
    370     FeatureMap parameterValues = newFeatureMap();
    371     parameterValues.put("sourceUrl", sourceUrl);
    372     return
    373       (Document) createResource("gate.corpora.DocumentImpl", parameterValues);
    374   } // newDocument(URL)
    375
    376   /** Create a new transient Document from a URL and an encoding. */
    377   public static Document newDocument(URL sourceUrl, String encoding)
    378                                           throws ResourceInstantiationException
    379   {
    380     FeatureMap parameterValues = newFeatureMap();
    381     parameterValues.put("sourceUrl", sourceUrl);
    382     parameterValues.put("encoding", encoding);
    383     return
    384       (Document) createResource("gate.corpora.DocumentImpl", parameterValues);
    385   } // newDocument(URL)
    386
    387   /** Create a new transient textual Document from a string. */
    388   public static Document newDocument(String content)
    389                                           throws ResourceInstantiationException
    390   {
    391     FeatureMap params = newFeatureMap();
    392     params.put("stringContent", content);
    393     Document doc =
    394       (Document) createResource("gate.corpora.DocumentImpl", params);
    395 /*
    396     // laziness: should fit this into createResource by adding a new
    397     // document parameter, but haven't time right now...
    398     doc.setContent(new DocumentContentImpl(content));
    399 */
    400     // various classes are in the habit of assuming that a document
    401     // inevitably has a source URL...  so give it a dummy one
    402 /*    try {
    403       doc.setSourceUrl(new URL("http://localhost/"));
    404     } catch(MalformedURLException e) {
    405       throw new ResourceInstantiationException(
    406         "Couldn't create dummy URL in newDocument(String): " + e
    407       );
    408     }
    409 */
    410     doc.setSourceUrl(null);
    411     return doc;
    412   } // newDocument(String)
    413
    414   /** Create a new FeatureMap. */
    415   public static FeatureMap newFeatureMap() {
    416     return new SimpleFeatureMapImpl();
    417   } // newFeatureMap
    418
    419   /** Open an existing DataStore. */
    420   public static DataStore openDataStore(
    421     String dataStoreClassName, String storageUrl
    422   ) throws PersistenceException {
    423     DataStore ds = instantiateDataStore(dataStoreClassName, storageUrl);
    424     ds.open();
    425     if(dsReg.add(ds))
    426       creoleProxy.fireDatastoreOpened(
    427         new CreoleEvent(ds, CreoleEvent.DATASTORE_OPENED)
    428       );
    429
    430     return ds;
    431   } // openDataStore()
    432
    433   /** Create a new DataStore and open it. <B>NOTE:</B> for some data stores
    434     * creation is an system administrator task; in such cases this
    435     * method will throw an UnsupportedOperationException.
    436     */
    437   public static DataStore createDataStore(
    438     String dataStoreClassName, String storageUrl
    439   ) throws PersistenceException, UnsupportedOperationException {
    440     DataStore ds = instantiateDataStore(dataStoreClassName, storageUrl);
    441     ds.create();
    442     ds.open();
    443     if(dsReg.add(ds))
    444       creoleProxy.fireDatastoreCreated(
    445         new CreoleEvent(ds, CreoleEvent.DATASTORE_CREATED)
    446       );
    447
    448     return ds;
    449   } // createDataStore()
    450
    451   /** Instantiate a DataStore (not open or created). */
    452   protected static DataStore instantiateDataStore(
    453     String dataStoreClassName, String storageUrl
    454   ) throws PersistenceException {
    455     DataStore godfreyTheDataStore = null;
    456     try {
    457       godfreyTheDataStore =
    458         (DataStore) Gate.getClassLoader().
    459                     loadClass(dataStoreClassName).newInstance();
    460     } catch(Exception e) {
    461       throw new PersistenceException("Couldn't create DS class: " + e);
    462     }
    463
    464     if(dsReg == null) // static init ran before Gate.init....
    465       dsReg = Gate.getDataStoreRegister();
    466     godfreyTheDataStore.setStorageUrl(storageUrl.toString());
    467
    468     return godfreyTheDataStore;
    469   } // instantiateDS(dataStoreClassName, storageURL)
    470
    471   /** Add a listener */
    472   public static synchronized void addCreoleListener(CreoleListener l){
    473     creoleProxy.addCreoleListener(l);
    474   } // addCreoleListener(CreoleListener)
    475
    476   /** Static initialiser to set up the CreoleProxy event source object */
    477   static {
    478     creoleProxy = new CreoleProxy();
    479     accessControllerPool = new HashMap();
    480   } // static initialiser
    481
    482
    483   /**
    484    * Creates and opens a new AccessController (if not available in the pool).
    485   */
    486   public static synchronized AccessController createAccessController(String jdbcURL)
    487     throws PersistenceException {
    488
    489     if (false == accessControllerPool.containsKey(jdbcURL)) {
    490       AccessController ac = new AccessControllerImpl(jdbcURL);
    491       ac.open();
    492       accessControllerPool.put(jdbcURL,ac);
    493     }
    494
    495     return (AccessController)accessControllerPool.get(jdbcURL);
    496   } // createAccessController()
    497
    498 } // abstract Factory
    499
    500
    501 /**
    502  * Factory is basically a collection of static methods but events need to
    503  * have as source an object and not a class. The CreolProxy class addresses
    504  * this issue acting as source for all events fired by the Factory class.
    505  */
    506 class CreoleProxy {
    507
    508   public synchronized void removeCreoleListener(CreoleListener l) {
    509     if (creoleListeners != null && creoleListeners.contains(l)) {
    510       Vector v = (Vector) creoleListeners.clone();
    511       v.removeElement(l);
    512       creoleListeners = v;
    513     }// if
    514   }// removeCreoleListener(CreoleListener l)
    515
    516   public synchronized void addCreoleListener(CreoleListener l) {
    517     Vector v =
    518       creoleListeners == null ? new Vector(2) : (Vector) creoleListeners.clone();
    519     if (!v.contains(l)) {
    520       v.addElement(l);
    521       creoleListeners = v;
    522     }// if
    523   }// addCreoleListener(CreoleListener l)
    524
    525   protected void fireResourceLoaded(CreoleEvent e) {
    526     if (creoleListeners != null) {
    527       Vector listeners = creoleListeners;
    528       int count = listeners.size();
    529       for (int i = 0; i < count; i++) {
    530         ((CreoleListener) listeners.elementAt(i)).resourceLoaded(e);
    531       }// for
    532     }// if
    533   }// fireResourceLoaded(CreoleEvent e)
    534
    535   protected void fireResourceUnloaded(CreoleEvent e) {
    536     if (creoleListeners != null) {
    537       Vector listeners = creoleListeners;
    538       int count = listeners.size();
    539       for (int i = 0; i < count; i++) {
    540         ((CreoleListener) listeners.elementAt(i)).resourceUnloaded(e);
    541       }// for
    542     }// if
    543   }// fireResourceUnloaded(CreoleEvent e)
    544
    545   protected void fireDatastoreOpened(CreoleEvent e) {
    546     if (creoleListeners != null) {
    547       Vector listeners = creoleListeners;
    548       int count = listeners.size();
    549       for (int i = 0; i < count; i++) {
    550         ((CreoleListener) listeners.elementAt(i)).datastoreOpened(e);
    551       }// for
    552     }// if
    553   }// fireDatastoreOpened(CreoleEvent e)
    554
    555   protected void fireDatastoreCreated(CreoleEvent e) {
    556     if (creoleListeners != null) {
    557       Vector listeners = creoleListeners;
    558       int count = listeners.size();
    559       for (int i = 0; i < count; i++) {
    560         ((CreoleListener) listeners.elementAt(i)).datastoreCreated(e);
    561       }// for
    562     }// if
    563   }// fireDatastoreCreated(CreoleEvent e)
    564
    565   protected void fireDatastoreClosed(CreoleEvent e) {
    566     if (creoleListeners != null) {
    567       Vector listeners = creoleListeners;
    568       int count = listeners.size();
    569       for (int i = 0; i < count; i++) {
    570         ((CreoleListener) listeners.elementAt(i)).datastoreClosed(e);
    571       }// for
    572     }// if
    573   }// fireDatastoreClosed(CreoleEvent e)
    574
    575
    576   private transient Vector creoleListeners;
    577 }//class CreoleProxy
    578

| Factory |