- Timestamp:
- 12/31/07 16:21:18 (11 months ago)
- Files:
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
openmrs/trunk/src/api/org/openmrs/api/context/ServiceContext.java
r1776 r2965 1 /** 2 * The contents of this file are subject to the OpenMRS Public License 3 * Version 1.0 (the "License"); you may not use this file except in 4 * compliance with the License. You may obtain a copy of the License at 5 * http://license.openmrs.org 6 * 7 * Software distributed under the License is distributed on an "AS IS" 8 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the 9 * License for the specific language governing rights and limitations 10 * under the License. 11 * 12 * Copyright (C) OpenMRS, LLC. All Rights Reserved. 13 */ 1 14 package org.openmrs.api.context; 2 15 … … 33 46 34 47 /** 35 * Represents an OpenMRS <code>Context</code>, which may be used to 36 * authenticate to the database and obtain services in order to interact with 37 * the system. 48 * Represents an OpenMRS <code>Service Context</code>, which returns the 49 * services represented throughout the system. 38 50 * 39 * Only one <code>User</code> may be authenticated within a context at any40 * given time.51 * This class should not be access directly, but rather used through the 52 * <code>Context</code> class. 41 53 * 42 * @author Burke Mamlin 43 * @version 1.0 54 * This class is essentially static and only one instance is kept because 55 * this is fairly heavy-weight. Spring takes care of filling in the actual 56 * service implementations via dependency injection. See the 57 * /metadata/api/spring/applicationContext-service.xml file. 58 * 59 * Module services are also accessed through this class. See 60 * {@link #getService(Class)} 61 * 62 * @see org.openmrs.api.context.Context 44 63 */ 45 64 public class ServiceContext { … … 50 69 private Boolean refreshingContext = new Boolean(false); 51 70 71 /** 72 * Static variable holding whether or not to use the system classloader. 73 * By default this is false so the openmrs classloader is used instead 74 */ 75 private boolean useSystemClassLoader = false; 76 52 77 // proxy factories used for programatically adding spring AOP 53 Map<Class, ProxyFactory> proxyFactories = new HashMap<Class, ProxyFactory>(); 54 55 /** 56 * Default constructor 78 @SuppressWarnings("unchecked") 79 Map<Class, ProxyFactory> proxyFactories = new HashMap<Class, ProxyFactory>(); 80 81 /** 82 * The default constructor is private so as to keep only one instance 83 * per java vm. 84 * 85 * @see ServiceContext#getInstance() 57 86 */ 58 87 private ServiceContext() { … … 60 89 } 61 90 91 /** 92 * There should only be one ServiceContext per openmrs (java virtual machine). 93 * 94 * This method should be used when wanting to fetch the service context 95 * 96 * Note: The ServiceContext shouldn't be used independently. All calls 97 * should go through the Context 98 * 99 * @return This VM's current ServiceContext. 100 * 101 * @see org.openmrs.api.context.Context 102 */ 62 103 public static ServiceContext getInstance() { 63 104 if (instance == null) … … 67 108 } 68 109 69 public static void destroyInstance() { 70 if (log.isErrorEnabled()) { 71 if (instance != null && instance.proxyFactories != null) { 110 /** 111 * Null out the current instance of the ServiceContext. This should be used 112 * when modules are refreshing (being added/removed) and/or openmrs is shutting down 113 */ 114 @SuppressWarnings("unchecked") 115 public static void destroyInstance() { 116 if (instance != null && instance.proxyFactories != null) { 117 if (log.isDebugEnabled()) { 72 118 for (Map.Entry<Class, ProxyFactory> entry : instance.proxyFactories.entrySet()) { 73 119 log.debug("Class:ProxyFactory - " + entry.getKey().getName() + ":" + entry.getValue()); 74 120 } 75 if (instance.proxyFactories != null) 76 instance.proxyFactories.clear(); 77 instance.proxyFactories = null; 78 } 121 } 79 122 123 if (instance.proxyFactories != null) 124 instance.proxyFactories.clear(); 125 126 instance.proxyFactories = null; 127 } 128 129 if (log.isDebugEnabled()) 80 130 log.debug("Destroying ServiceContext instance: " + instance); 81 }131 82 132 instance = null; 83 133 } … … 104 154 } 105 155 156 /** 157 * @return cohort related service 158 */ 106 159 public CohortService getCohortService() { 107 160 return (CohortService) getService(CohortService.class); 108 161 } 109 162 163 /** 164 * @param cohort related service 165 */ 110 166 public void setCohortService(CohortService cs) { 111 167 setService(CohortService.class, cs); … … 215 271 216 272 /** 217 * Get the message service.218 *219 * There are several ways to deal with the service layer objects.220 *221 * (1) Dependency injection (preferred) (2) Instantiate new instance within222 * service (current implementation) (3) Use bean factory to get reference to223 * bean (4) Use application context to get reference to bean224 *225 * NOTE: I prefer method (1) but will not be able to get it to work226 * correctly until I can refactor the Context class. The main issue is that227 * the Context object is instantiated all over the place instead of being228 * defined once in the bean definition file. Therefore, I cannot "inject"229 * the message service (or any other service) because the client has control230 * over instantiating the object. I don't like method (2) because I don't231 * want the context to instantiate as there is a lot of work that goes into232 * setting up the message service object. I couldn't figure out to get the233 * "openmrs-servlet.xml" resource so I abandoned method (3). Therefore, I234 * have decided to go with method (4) for now. It ties us (somewhat loosely)235 * to the spring framework as we now have the Context object implement236 * ApplicationContextAware. However, my plan is to make Context an interface237 * and implements this interface as the SpringContext so that certain Spring238 * services can be used (i.e. event publishing).239 *240 273 * @return message service 241 274 */ … … 378 411 * @return 379 412 */ 380 private ProxyFactory getFactory(Class cls) { 413 @SuppressWarnings("unchecked") 414 private ProxyFactory getFactory(Class cls) { 381 415 ProxyFactory factory = proxyFactories.get(cls); 382 416 if (factory == null) … … 390 424 * @param advisor 391 425 */ 392 public void addAdvisor(Class cls, Advisor advisor) { 426 @SuppressWarnings("unchecked") 427 public void addAdvisor(Class cls, Advisor advisor) { 393 428 ProxyFactory factory = getFactory(cls); 394 429 factory.addAdvisor(advisor); … … 400 435 * @param advice 401 436 */ 402 public void addAdvice(Class cls, Advice advice) { 437 @SuppressWarnings("unchecked") 438 public void addAdvice(Class cls, Advice advice) { 403 439 ProxyFactory factory = getFactory(cls); 404 440 factory.addAdvice(advice); … … 410 446 * @param advisor 411 447 */ 412 public void removeAdvisor(Class cls, Advisor advisor) { 448 @SuppressWarnings("unchecked") 449 public void removeAdvisor(Class cls, Advisor advisor) { 413 450 ProxyFactory factory = getFactory(cls); 414 451 factory.removeAdvisor(advisor); … … 420 457 * @param advice 421 458 */ 422 public void removeAdvice(Class cls, Advice advice) { 459 @SuppressWarnings("unchecked") 460 public void removeAdvice(Class cls, Advice advice) { 423 461 ProxyFactory factory = getFactory(cls); 424 462 factory.removeAdvice(advice); … … 432 470 * @return Object that is a proxy for the <code>cls</code> class 433 471 */ 434 public Object getService(Class cls) { 435 log.debug("Getting service: " + cls); 472 @SuppressWarnings("unchecked") 473 public Object getService(Class cls) { 474 if (log.isDebugEnabled()) 475 log.debug("Getting service: " + cls); 436 476 437 477 // if the context is refreshing, wait until it is … … 440 480 if (refreshingContext.booleanValue()) 441 481 try { 482 log.warn("Waiting to get service: " + cls + " while the context is being refreshed"); 442 483 refreshingContext.wait(); 484 log.warn("Finished waiting to get service " + cls + " while the context was being refreshed"); 443 485 } 444 486 catch (InterruptedException e) { … … 460 502 * @param classInstance the actual instance of the <code>cls</code> interface 461 503 */ 462 public void setService(Class cls, Object classInstance) { 504 @SuppressWarnings("unchecked") 505 public void setService(Class cls, Object classInstance) { 463 506 464 507 log.debug("Setting service: " + cls); … … 489 532 * @param list list of parameters 490 533 */ 491 public void setModuleService(List<Object> params) { 534 @SuppressWarnings("unchecked") 535 public void setModuleService(List<Object> params) { 492 536 String classString = (String)params.get(0); 493 537 Object classInstance = params.get(1); … … 499 543 Class cls = null; 500 544 545 // load the given 'classString' class from either the openmrs class 546 // loader or the system class loader depending on if we're in a testing 547 // environment or not (system == testing, openmrs == normal) 501 548 try { 502 //ModuleClassLoader mcl = ModuleFactory.getModuleClassLoader(moduleId);503 cls = OpenmrsClassLoader.getInstance().loadClass(classString);549 if (useSystemClassLoader == false) { 550 cls = OpenmrsClassLoader.getInstance().loadClass(classString); 504 551 505 try { 506 if (cls != null) 507 log.error("cls classloader: " + cls.getClass().getClassLoader() + " uid: " + cls.getClass().getClassLoader().hashCode()); 552 if (cls != null && log.isDebugEnabled()) { 553 try { 554 log.debug("cls classloader: " + cls.getClass().getClassLoader() + " uid: " + cls.getClass().getClassLoader().hashCode()); 555 } 556 catch (Exception e) { /*pass*/ } 557 } 508 558 } 509 catch (Exception e) { /*pass*/ } 510 try { 511 Class cls2 = Class.forName(classString); 512 log.error("cls2 classloader: " + cls2.getClass().getClassLoader() + " uid: " + cls.getClass().getClassLoader().hashCode()); 513 log.error("cls==cls2: " + String.valueOf(cls == cls2)); 559 else if (useSystemClassLoader == true) { 560 try { 561 cls = Class.forName(classString); 562 if (log.isDebugEnabled()) { 563 log.debug("cls2 classloader: " + cls.getClass().getClassLoader() + " uid: " + cls.getClass().getClassLoader().hashCode()); 564 log.debug("cls==cls2: " + String.valueOf(cls == cls)); 565 } 566 } 567 catch (Exception e) { /*pass*/ } 514 568 } 515 catch (Exception e) { /*pass*/ }516 569 } 517 570 catch (ClassNotFoundException e) { … … 519 572 } 520 573 574 // add this module service to the normal list of services 521 575 setService(cls, classInstance); 576 } 577 578 /** 579 * Set this service context to use the system class loader if the 580 * <code>useSystemClassLoader</code> is set to true. If false, the openmrs 581 * class loader is used to load module services 582 * 583 * @param useSystemClassLoader true/false whether to use the system class loader 584 */ 585 public void setUseSystemClassLoader(boolean useSystemClassLoader) { 586 this.useSystemClassLoader = useSystemClassLoader; 522 587 } 523 588 … … 547 612 } 548 613 614 /** 615 * Returns true/false whether startRefreshingContext() has been called 616 * without a subsequent call to doneRefreshingContext() yet. All methods 617 * involved in starting/stopping a module should call this if a service 618 * method is needed -- otherwise a deadlock will occur. 619 * 620 * @return true/false whether the services are currently blocking waiting 621 * for a call to doneRefreshingContext() 622 */ 623 public boolean isRefreshingContext() { 624 return refreshingContext.booleanValue(); 625 } 626 549 627 }