Coverage Report - org.kuali.rice.core.resourceloader.SpringLoader
 
Classes in this File Line Coverage Branch Coverage Complexity
SpringLoader
0%
0/64
0%
0/22
2.308
 
 1  
 /*
 2  
  * Copyright 2005-2007 The Kuali Foundation
 3  
  *
 4  
  *
 5  
  * Licensed under the Educational Community License, Version 2.0 (the "License");
 6  
  * you may not use this file except in compliance with the License.
 7  
  * You may obtain a copy of the License at
 8  
  *
 9  
  * http://www.opensource.org/licenses/ecl2.php
 10  
  *
 11  
  * Unless required by applicable law or agreed to in writing, software
 12  
  * distributed under the License is distributed on an "AS IS" BASIS,
 13  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14  
  * See the License for the specific language governing permissions and
 15  
  * limitations under the License.
 16  
  */
 17  
 package org.kuali.rice.core.resourceloader;
 18  
 
 19  
 import org.apache.log4j.Logger;
 20  
 import org.kuali.rice.core.lifecycle.BaseLifecycle;
 21  
 import org.springframework.context.ApplicationContext;
 22  
 import org.springframework.context.ConfigurableApplicationContext;
 23  
 import org.springframework.context.support.ClassPathXmlApplicationContext;
 24  
 
 25  
 import javax.xml.namespace.QName;
 26  
 import java.util.Set;
 27  
 
 28  
 
 29  
 /**
 30  
  * ServiceLocator that starts and wraps the primary workflow Spring Application Context.
 31  
  *
 32  
  * @author Kuali Rice Team (rice.collab@kuali.org)
 33  
  *
 34  
  */
 35  0
 public final class SpringLoader extends BaseLifecycle implements ServiceLocator {
 36  
 
 37  0
     private static final Logger LOG = Logger.getLogger(SpringLoader.class);
 38  
 
 39  
     /**
 40  
      * The default top-level Spring configuration resource name
 41  
      */
 42  
     public static final String DEFAULT_SPRING_FILE = "Spring.xml";
 43  
 
 44  
     /* Conditions are used to ensure state integrity.  Various methods that modify state
 45  
      * are already synchronized so in some places these are redundant.  At some point we
 46  
      * should switch to java.util.concurrent Lock and Condition classes and implement this
 47  
      * correctly.
 48  
      */
 49  
 
 50  0
     private static final SpringLoader INSTANCE = new SpringLoader();
 51  
     
 52  
     /**
 53  
      * Separator character for list of Spring files.
 54  
      * <p>Value is ','
 55  
      */
 56  
     public static final String SPRING_SEPARATOR_CHARACTER = ",";
 57  
 
 58  
     /**
 59  
      * Condition that indicates whether Spring has completed initialization
 60  
      */
 61  0
     private final ContextualConfigLock SPRING_INIT_COMPLETE= new ContextualConfigLock("Spring has completed initialization");
 62  
     /**
 63  
      * Condition that indicates whether Spring has started initialization
 64  
      */
 65  0
     private final ContextualConfigLock SPRING_INIT_STARTED = new ContextualConfigLock("Spring has started initialization");
 66  
 
 67  0
     private String contextFiles = DEFAULT_SPRING_FILE;
 68  0
     private static Set<String> suppressedServices = null;
 69  
 
 70  
     /**
 71  
      * The Spring context
 72  
      */
 73  
     private ConfigurableApplicationContext appContext;
 74  
 
 75  
     public static SpringLoader getInstance() {
 76  0
             return INSTANCE;
 77  
     }
 78  
 
 79  
     public synchronized void start() throws Exception {
 80  0
             initializeAppContexts();
 81  0
             super.start();
 82  0
     }
 83  
 
 84  
     public synchronized void stop() throws Exception {
 85  0
             close();
 86  0
             super.stop();
 87  0
     }
 88  
 
 89  
     /**
 90  
      * Initializes Spring with the specified context resource name
 91  
      * @param rootContextFile the Spring context resource name
 92  
      */
 93  
     protected void initializeAppContexts() {
 94  0
         if (SPRING_INIT_STARTED.hasFired() || SPRING_INIT_COMPLETE.hasFired()) {
 95  0
                 return;
 96  
         }
 97  0
         SPRING_INIT_STARTED.fire();
 98  
 
 99  0
         LOG.info("Initializing Spring from resources: ");
 100  
         try {
 101  0
             if (!getContextFiles().contains(SPRING_SEPARATOR_CHARACTER)) {
 102  0
                 LOG.info( getContextFiles() );
 103  0
                 appContext = new ClassPathXmlApplicationContext(getContextFiles());
 104  
             } else {
 105  0
                 String[] contextFileLocations = getContextFiles().split( SPRING_SEPARATOR_CHARACTER );
 106  0
                 LOG.info( contextFileLocations );
 107  0
                 appContext = new ClassPathXmlApplicationContext( contextFileLocations );
 108  
             }
 109  0
                 appContext.getBeanFactory().preInstantiateSingletons();
 110  0
         } finally {
 111  
             // if an exception occurs we need to signal that init is complete
 112  
             // even though it is in error, so that close will be allowed
 113  0
             SPRING_INIT_COMPLETE.fire();
 114  0
         }
 115  0
     }
 116  
 
 117  
         public Object getService(QName qname) {
 118  0
                 return getBean(qname.toString());
 119  
         }
 120  
 
 121  
     /**
 122  
      * Obtains a bean from Spring
 123  
      *
 124  
      * @param serviceName the name of the bean
 125  
      * @return a bean from Spring
 126  
      */
 127  
     public Object getBean(String serviceName) {
 128  0
         initializeAppContexts();
 129  
 
 130  0
         if (appContext == null) {
 131  0
             throw new RuntimeException("Spring not initialized properly.  Initialization has completed and the application context is null.");
 132  
         }
 133  0
         if (appContext.containsBean(serviceName)) {
 134  0
                 return appContext.getBean(serviceName);
 135  
         }
 136  0
         return null;
 137  
     }
 138  
 
 139  
     public Class getType(String beanName) {
 140  0
             initializeAppContexts();
 141  0
         if (appContext == null) {
 142  0
             throw new RuntimeException("Spring not initialized properly.  Initialization has completed and the application context is null.");
 143  
         }
 144  0
         return appContext.getType(beanName);
 145  
     }
 146  
 
 147  
     public boolean isSingleton(String beanName) {
 148  0
             initializeAppContexts();
 149  0
         if (appContext == null) {
 150  0
             throw new RuntimeException("Spring not initialized properly.  Initialization has completed and the application context is null.");
 151  
         }
 152  0
         return appContext.isSingleton(beanName);
 153  
     }
 154  
 
 155  
     /**
 156  
      * Closes the Spring context if initialization has at least started.
 157  
      * If initialization has NOT started, this method returns immediately.
 158  
      * If initialization HAS started, then it awaits completion before closing
 159  
      */
 160  
     public synchronized void close() {
 161  0
         if (!SPRING_INIT_STARTED.hasFired()) {
 162  0
             return;
 163  
         }
 164  
         // this is not technically necessary at this time because both close and initialize* methods
 165  
         // are synchronized so initialization should always be complete if it has been started;
 166  
         // NOTE: although - let's think about error cases...if exception is thrown from init, then
 167  
         // SPRING_INIT_COMPLETE may never have fired - that is a good thing probably, but maybe it warrants
 168  
         // a separate SPRING_INIT_FAILED condition; don't want to get too complicated though
 169  0
         SPRING_INIT_COMPLETE.await();
 170  0
         if (appContext instanceof ConfigurableApplicationContext) {
 171  0
             ((ConfigurableApplicationContext)appContext).close();
 172  
         }
 173  0
         SPRING_INIT_STARTED.reset();
 174  0
         SPRING_INIT_COMPLETE.reset();
 175  0
         this.suppressedServices = null;
 176  0
     }
 177  
 
 178  
     /**
 179  
      * Returns the Spring context, waiting for initialization to start and complete
 180  
      * if it hasn't already
 181  
      * @return the intiailized Spring context
 182  
      */
 183  
     public ApplicationContext getApplicationContext() {
 184  0
         SPRING_INIT_COMPLETE.await();
 185  0
         return appContext;
 186  
     }
 187  
 
 188  
         public String getContents(String indent, boolean servicePerLine) {
 189  0
                 String contents = indent + "SpringLoader " + this + " services =";
 190  
 
 191  0
                 for (String beanName : appContext.getBeanDefinitionNames()) {
 192  0
                         if (servicePerLine) {
 193  0
                                 contents += indent + "+++" + beanName + "\n";
 194  
                         } else {
 195  0
                                 contents += beanName + ", ";
 196  
                         }
 197  
                 }
 198  
 
 199  0
                 return contents;
 200  
         }
 201  
 
 202  
         public String getContextFiles() {
 203  0
                 return contextFiles;
 204  
         }
 205  
 
 206  
         public void setContextFiles(String contextFiles) {
 207  0
                 this.contextFiles = contextFiles;
 208  0
         }
 209  
 
 210  
 }