|
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.77 2003/05/13 14:09:17 valyt 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 Map listeners = new HashMap(gate.gui.MainFrame.getListeners()); 284 // set the listeners if any 285 if(listeners != null && !listeners.isEmpty()) { 286 try { 287 if(DEBUG) Out.prln("Setting the listeners for " + res.toString()); 288 AbstractResource.setResourceListeners(res, listeners); 289 } catch(Exception e) { 290 if(DEBUG) Out.prln("Failed to set listeners for " + res.toString()); 291 throw new 292 ResourceInstantiationException("Parameterisation failure" + e); 293 } 294 } 295 296 // if the features of the resource have not been explicitly set, 297 // set them to the features of the resource data 298 if(res.getFeatures() == null || res.getFeatures().isEmpty()){ 299 FeatureMap fm = newFeatureMap(); 300 fm.putAll(resData.getFeatures()); 301 res.setFeatures(fm); 302 } 303 304 // initialise the resource 305 if(DEBUG) Out.prln("Initialising resource " + res.toString()); 306 res = res.init(); 307 308 // remove the listeners if any 309 if(listeners != null && !listeners.isEmpty()) { 310 try { 311 if(DEBUG) Out.prln("Removing the listeners for " + res.toString()); 312 AbstractResource.removeResourceListeners(res, listeners); 313 } catch(Exception e) { 314 if (DEBUG) Out.prln( 315 "Failed to remove the listeners for " + res.toString() 316 ); 317 throw new 318 ResourceInstantiationException("Parameterisation failure" + e); 319 } 320 } 321 // record the instantiation on the resource data's stack 322 resData.addInstantiation(res); 323 // add the features specified by the user 324 if(features != null) res.getFeatures().putAll(features); 325 // fire the event 326 creoleProxy.fireResourceLoaded( 327 new CreoleEvent(res, CreoleEvent.RESOURCE_LOADED) 328 ); 329 return res; 330 } // create(resourceClassName, parameterValues, features, listeners) 331 332 /** Delete an instance of a resource. This involves removing it from 333 * the stack of instantiations maintained by this resource type's 334 * resource data. Deletion does not guarantee that the resource will 335 * become a candidate for garbage collection, just that the GATE framework 336 * is no longer holding references to the resource. 337 * 338 * @param resource the resource to be deleted. 339 */ 340 public static void deleteResource(Resource resource) { 341 ResourceData rd = 342 (ResourceData) reg.get(resource.getClass().getName()); 343 if(rd!= null) 344 rd.removeInstantiation(resource); 345 creoleProxy.fireResourceUnloaded( 346 new CreoleEvent(resource, CreoleEvent.RESOURCE_UNLOADED) 347 ); 348 resource.cleanup(); 349 } // deleteResource 350 351 /** Create a new transient Corpus. */ 352 public static Corpus newCorpus(String name) 353 throws ResourceInstantiationException 354 { 355 FeatureMap parameterValues = newFeatureMap(); 356 parameterValues.put(Corpus.CORPUS_NAME_PARAMETER_NAME, name); 357 // parameterValues.put("features", Factory.newFeatureMap()); 358 return (Corpus) createResource("gate.corpora.CorpusImpl", parameterValues); 359 } // newCorpus 360 361 /** Create a new transient Document from a URL. */ 362 public static Document newDocument(URL sourceUrl) 363 throws ResourceInstantiationException 364 { 365 FeatureMap parameterValues = newFeatureMap(); 366 parameterValues.put(Document.DOCUMENT_URL_PARAMETER_NAME, sourceUrl); 367 return 368 (Document) createResource("gate.corpora.DocumentImpl", parameterValues); 369 } // newDocument(URL) 370 371 /** Create a new transient Document from a URL and an encoding. */ 372 public static Document newDocument(URL sourceUrl, String encoding) 373 throws ResourceInstantiationException 374 { 375 FeatureMap parameterValues = newFeatureMap(); 376 parameterValues.put(Document.DOCUMENT_URL_PARAMETER_NAME, sourceUrl); 377 parameterValues.put(Document.DOCUMENT_ENCODING_PARAMETER_NAME, encoding); 378 return 379 (Document) createResource("gate.corpora.DocumentImpl", parameterValues); 380 } // newDocument(URL) 381 382 /** Create a new transient textual Document from a string. */ 383 public static Document newDocument(String content) 384 throws ResourceInstantiationException 385 { 386 FeatureMap params = newFeatureMap(); 387 params.put(Document.DOCUMENT_STRING_CONTENT_PARAMETER_NAME, content); 388 Document doc = 389 (Document) createResource("gate.corpora.DocumentImpl", params); 390 /* 391 // laziness: should fit this into createResource by adding a new 392 // document parameter, but haven't time right now... 393 doc.setContent(new DocumentContentImpl(content)); 394 */ 395 // various classes are in the habit of assuming that a document 396 // inevitably has a source URL... so give it a dummy one 397 /* try { 398 doc.setSourceUrl(new URL("http://localhost/")); 399 } catch(MalformedURLException e) { 400 throw new ResourceInstantiationException( 401 "Couldn't create dummy URL in newDocument(String): " + e 402 ); 403 } 404 */ 405 doc.setSourceUrl(null); 406 return doc; 407 } // newDocument(String) 408 409 /** Create a new FeatureMap. */ 410 public static FeatureMap newFeatureMap() { 411 return new SimpleFeatureMapImpl(); 412 } // newFeatureMap 413 414 /** Open an existing DataStore. */ 415 public static DataStore openDataStore( 416 String dataStoreClassName, String storageUrl 417 ) throws PersistenceException { 418 DataStore ds = instantiateDataStore(dataStoreClassName, storageUrl); 419 ds.open(); 420 if(dsReg.add(ds)) 421 creoleProxy.fireDatastoreOpened( 422 new CreoleEvent(ds, CreoleEvent.DATASTORE_OPENED) 423 ); 424 425 return ds; 426 } // openDataStore() 427 428 /** Create a new DataStore and open it. <B>NOTE:</B> for some data stores 429 * creation is an system administrator task; in such cases this 430 * method will throw an UnsupportedOperationException. 431 */ 432 public static DataStore createDataStore( 433 String dataStoreClassName, String storageUrl 434 ) throws PersistenceException, UnsupportedOperationException { 435 DataStore ds = instantiateDataStore(dataStoreClassName, storageUrl); 436 ds.create(); 437 ds.open(); 438 if(dsReg.add(ds)) 439 creoleProxy.fireDatastoreCreated( 440 new CreoleEvent(ds, CreoleEvent.DATASTORE_CREATED) 441 ); 442 443 return ds; 444 } // createDataStore() 445 446 /** Instantiate a DataStore (not open or created). */ 447 protected static DataStore instantiateDataStore( 448 String dataStoreClassName, String storageUrl 449 ) throws PersistenceException { 450 DataStore godfreyTheDataStore = null; 451 try { 452 godfreyTheDataStore = 453 (DataStore) Gate.getClassLoader(). 454 loadClass(dataStoreClassName).newInstance(); 455 } catch(Exception e) { 456 throw new PersistenceException("Couldn't create DS class: " + e); 457 } 458 459 if(dsReg == null) // static init ran before Gate.init.... 460 dsReg = Gate.getDataStoreRegister(); 461 godfreyTheDataStore.setStorageUrl(storageUrl.toString()); 462 463 return godfreyTheDataStore; 464 } // instantiateDS(dataStoreClassName, storageURL) 465 466 /** Add a listener */ 467 public static synchronized void addCreoleListener(CreoleListener l){ 468 creoleProxy.addCreoleListener(l); 469 } // addCreoleListener(CreoleListener) 470 471 /** Static initialiser to set up the CreoleProxy event source object */ 472 static { 473 creoleProxy = new CreoleProxy(); 474 accessControllerPool = new HashMap(); 475 } // static initialiser 476 477 478 /** 479 * Creates and opens a new AccessController (if not available in the pool). 480 */ 481 public static synchronized AccessController createAccessController(String jdbcURL) 482 throws PersistenceException { 483 484 if (false == accessControllerPool.containsKey(jdbcURL)) { 485 AccessController ac = new AccessControllerImpl(jdbcURL); 486 ac.open(); 487 accessControllerPool.put(jdbcURL,ac); 488 } 489 490 return (AccessController)accessControllerPool.get(jdbcURL); 491 } // createAccessController() 492 493 } // abstract Factory 494 495 496 /** 497 * Factory is basically a collection of static methods but events need to 498 * have as source an object and not a class. The CreolProxy class addresses 499 * this issue acting as source for all events fired by the Factory class. 500 */ 501 class CreoleProxy { 502 503 public synchronized void removeCreoleListener(CreoleListener l) { 504 if (creoleListeners != null && creoleListeners.contains(l)) { 505 Vector v = (Vector) creoleListeners.clone(); 506 v.removeElement(l); 507 creoleListeners = v; 508 }// if 509 }// removeCreoleListener(CreoleListener l) 510 511 public synchronized void addCreoleListener(CreoleListener l) { 512 Vector v = 513 creoleListeners == null ? new Vector(2) : (Vector) creoleListeners.clone(); 514 if (!v.contains(l)) { 515 v.addElement(l); 516 creoleListeners = v; 517 }// if 518 }// addCreoleListener(CreoleListener l) 519 520 protected void fireResourceLoaded(CreoleEvent e) { 521 if (creoleListeners != null) { 522 Vector listeners = creoleListeners; 523 int count = listeners.size(); 524 for (int i = 0; i < count; i++) { 525 ((CreoleListener) listeners.elementAt(i)).resourceLoaded(e); 526 }// for 527 }// if 528 }// fireResourceLoaded(CreoleEvent e) 529 530 protected void fireResourceUnloaded(CreoleEvent e) { 531 if (creoleListeners != null) { 532 Vector listeners = creoleListeners; 533 int count = listeners.size(); 534 for (int i = 0; i < count; i++) { 535 ((CreoleListener) listeners.elementAt(i)).resourceUnloaded(e); 536 }// for 537 }// if 538 }// fireResourceUnloaded(CreoleEvent e) 539 540 protected void fireDatastoreOpened(CreoleEvent e) { 541 if (creoleListeners != null) { 542 Vector listeners = creoleListeners; 543 int count = listeners.size(); 544 for (int i = 0; i < count; i++) { 545 ((CreoleListener) listeners.elementAt(i)).datastoreOpened(e); 546 }// for 547 }// if 548 }// fireDatastoreOpened(CreoleEvent e) 549 550 protected void fireDatastoreCreated(CreoleEvent e) { 551 if (creoleListeners != null) { 552 Vector listeners = creoleListeners; 553 int count = listeners.size(); 554 for (int i = 0; i < count; i++) { 555 ((CreoleListener) listeners.elementAt(i)).datastoreCreated(e); 556 }// for 557 }// if 558 }// fireDatastoreCreated(CreoleEvent e) 559 560 protected void fireDatastoreClosed(CreoleEvent e) { 561 if (creoleListeners != null) { 562 Vector listeners = creoleListeners; 563 int count = listeners.size(); 564 for (int i = 0; i < count; i++) { 565 ((CreoleListener) listeners.elementAt(i)).datastoreClosed(e); 566 }// for 567 }// if 568 }// fireDatastoreClosed(CreoleEvent e) 569 570 private transient Vector creoleListeners; 571 }//class CreoleProxy 572
|
Factory |
|