Downloads Documentation Community Contribute Demo






Show Sidebar
Login | Register
Show
Ignore:
Timestamp:
12/31/07 16:21:18 (11 months ago)
Author:
bwolfe
Message:

Merging alpha to trunk [1776]:[2964] for OpenMRS 1.2 release

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 */ 
    114package org.openmrs.api.context; 
    215 
     
    3346 
    3447/** 
    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.   
    3850 *  
    39  * Only one <code>User</code> may be authenticated within a context at any 
    40  * given time
     51 * This class should not be access directly, but rather used through the 
     52 * <code>Context</code> class
    4153 *  
    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 
    4463 */ 
    4564public class ServiceContext { 
     
    5069        private Boolean refreshingContext = new Boolean(false); 
    5170         
     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         
    5277        // 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() 
    5786         */ 
    5887        private ServiceContext() {  
     
    6089        } 
    6190         
     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         */ 
    62103        public static ServiceContext getInstance() { 
    63104                if (instance == null) 
     
    67108        } 
    68109         
    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()) { 
    72118                                for (Map.Entry<Class, ProxyFactory> entry : instance.proxyFactories.entrySet()) { 
    73119                                        log.debug("Class:ProxyFactory - " + entry.getKey().getName() + ":" + entry.getValue()); 
    74120                                } 
    75                                 if (instance.proxyFactories != null) 
    76                                         instance.proxyFactories.clear(); 
    77                                 instance.proxyFactories = null; 
    78                                 } 
     121                        } 
    79122                         
     123                        if (instance.proxyFactories != null) 
     124                                instance.proxyFactories.clear(); 
     125                         
     126                        instance.proxyFactories = null; 
     127                } 
     128                 
     129                if (log.isDebugEnabled()) 
    80130                        log.debug("Destroying ServiceContext instance: " + instance); 
    81                 } 
     131                 
    82132                instance = null; 
    83133        } 
     
    104154        } 
    105155         
     156        /** 
     157         * @return cohort related service 
     158         */ 
    106159        public CohortService getCohortService() { 
    107160                return (CohortService) getService(CohortService.class); 
    108161        } 
    109162         
     163        /** 
     164         * @param cohort related service 
     165         */ 
    110166        public void setCohortService(CohortService cs) { 
    111167                setService(CohortService.class, cs); 
     
    215271         
    216272        /** 
    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 within 
    222          * service (current implementation) (3) Use bean factory to get reference to 
    223          * bean (4) Use application context to get reference to bean 
    224          *  
    225          * NOTE: I prefer method (1) but will not be able to get it to work 
    226          * correctly until I can refactor the Context class. The main issue is that 
    227          * the Context object is instantiated all over the place instead of being 
    228          * defined once in the bean definition file. Therefore, I cannot "inject" 
    229          * the message service (or any other service) because the client has control 
    230          * over instantiating the object. I don't like method (2) because I don't 
    231          * want the context to instantiate as there is a lot of work that goes into 
    232          * setting up the message service object. I couldn't figure out to get the 
    233          * "openmrs-servlet.xml" resource so I abandoned method (3). Therefore, I 
    234          * 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 implement 
    236          * ApplicationContextAware. However, my plan is to make Context an interface 
    237          * and implements this interface as the SpringContext so that certain Spring 
    238          * services can be used (i.e. event publishing). 
    239          *  
    240273         * @return message service 
    241274         */ 
     
    378411         * @return 
    379412         */ 
    380         private ProxyFactory getFactory(Class cls) { 
     413        @SuppressWarnings("unchecked") 
     414    private ProxyFactory getFactory(Class cls) { 
    381415                ProxyFactory factory = proxyFactories.get(cls); 
    382416                if (factory == null) 
     
    390424         * @param advisor 
    391425         */ 
    392         public void addAdvisor(Class cls, Advisor advisor) { 
     426        @SuppressWarnings("unchecked") 
     427    public void addAdvisor(Class cls, Advisor advisor) { 
    393428                ProxyFactory factory = getFactory(cls); 
    394429                factory.addAdvisor(advisor); 
     
    400435         * @param advice 
    401436         */ 
    402         public void addAdvice(Class cls, Advice advice) { 
     437        @SuppressWarnings("unchecked") 
     438    public void addAdvice(Class cls, Advice advice) { 
    403439                ProxyFactory factory = getFactory(cls); 
    404440                factory.addAdvice(advice); 
     
    410446         * @param advisor 
    411447         */ 
    412         public void removeAdvisor(Class cls, Advisor advisor) { 
     448        @SuppressWarnings("unchecked") 
     449    public void removeAdvisor(Class cls, Advisor advisor) { 
    413450                ProxyFactory factory = getFactory(cls); 
    414451                factory.removeAdvisor(advisor); 
     
    420457         * @param advice 
    421458         */ 
    422         public void removeAdvice(Class cls, Advice advice) { 
     459        @SuppressWarnings("unchecked") 
     460    public void removeAdvice(Class cls, Advice advice) { 
    423461                ProxyFactory factory = getFactory(cls); 
    424462                factory.removeAdvice(advice); 
     
    432470         * @return Object that is a proxy for the <code>cls</code> class  
    433471         */ 
    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); 
    436476                 
    437477                // if the context is refreshing, wait until it is  
     
    440480                        if (refreshingContext.booleanValue()) 
    441481                                try { 
     482                                        log.warn("Waiting to get service: " + cls + " while the context is being refreshed"); 
    442483                                        refreshingContext.wait(); 
     484                                        log.warn("Finished waiting to get service " + cls + " while the context was being refreshed"); 
    443485                                } 
    444486                                catch (InterruptedException e) { 
     
    460502         * @param classInstance the actual instance of the <code>cls</code> interface 
    461503         */ 
    462         public void setService(Class cls, Object classInstance) { 
     504        @SuppressWarnings("unchecked") 
     505    public void setService(Class cls, Object classInstance) { 
    463506                 
    464507                log.debug("Setting service: " + cls); 
     
    489532         * @param list list of parameters 
    490533         */ 
    491         public void setModuleService(List<Object> params) { 
     534        @SuppressWarnings("unchecked") 
     535    public void setModuleService(List<Object> params) { 
    492536                String classString = (String)params.get(0); 
    493537                Object classInstance = params.get(1); 
     
    499543                Class cls = null; 
    500544                 
     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) 
    501548                try { 
    502                         //ModuleClassLoader mcl = ModuleFactory.getModuleClassLoader(moduleId); 
    503                         cls = OpenmrsClassLoader.getInstance().loadClass(classString); 
     549                        if (useSystemClassLoader == false) { 
     550                               cls = OpenmrsClassLoader.getInstance().loadClass(classString); 
    504551                         
    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                                } 
    508558                        } 
    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*/ } 
    514568                        } 
    515                         catch (Exception e) { /*pass*/ } 
    516569                } 
    517570                catch (ClassNotFoundException e) { 
     
    519572                } 
    520573                 
     574                // add this module service to the normal list of services 
    521575                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; 
    522587        } 
    523588         
     
    547612        } 
    548613         
     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         
    549627}