|
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.76 2002/03/06 17:15:37 kalina 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 creoleProxy.fireResourceUnloaded( 351 new CreoleEvent(resource, CreoleEvent.RESOURCE_UNLOADED) 352 ); 353 resource.cleanup(); 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(Corpus.CORPUS_NAME_PARAMETER_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(Document.DOCUMENT_URL_PARAMETER_NAME, 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(Document.DOCUMENT_URL_PARAMETER_NAME, sourceUrl); 382 parameterValues.put(Document.DOCUMENT_ENCODING_PARAMETER_NAME, 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(Document.DOCUMENT_STRING_CONTENT_PARAMETER_NAME, 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 |
|