001    /**
002     * Copyright 2005-2013 The Kuali Foundation
003     *
004     * Licensed under the Educational Community License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     * http://www.opensource.org/licenses/ecl2.php
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    package org.kuali.rice.core.api.resourceloader;
017    
018    import org.apache.commons.lang.StringUtils;
019    import org.kuali.rice.core.api.config.CoreConfigHelper;
020    import org.kuali.rice.core.api.exception.RiceRemoteServiceConnectionException;
021    import org.kuali.rice.core.api.exception.RiceRuntimeException;
022    import org.kuali.rice.core.api.reflect.ObjectDefinition;
023    import org.kuali.rice.core.api.util.ClassLoaderUtils;
024    
025    import javax.xml.namespace.QName;
026    import java.util.HashMap;
027    import java.util.Map;
028    
029    /**
030     * Wrapper on all the Resource loaders.  This is what programmers typically use to get in the resource loading
031     * framework.
032     *
033     * @author Kuali Rice Team (rice.collab@kuali.org)
034     */
035    public class GlobalResourceLoader {
036    
037            private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(GlobalResourceLoader.class);
038    
039            private static Map<ClassLoader, ResourceLoader> rootResourceLoaders = new HashMap<ClassLoader, ResourceLoader>();
040    
041            private static boolean initializing;
042    
043            public static synchronized ResourceLoader getResourceLoader() {
044                    ClassLoader classLoader = ClassLoaderUtils.getDefaultClassLoader();
045                    return getResourceLoaderCheckParent(classLoader);
046            }
047    
048            private static synchronized ResourceLoader getResourceLoaderCheckParent(ClassLoader classLoader) {
049            ResourceLoader resourceLoader = getResourceLoader(classLoader);
050    
051            if (resourceLoader != null && classLoader.getParent() != null) {
052                ResourceLoader parentResourceLoader = getResourceLoaderCheckParent(classLoader.getParent());
053    
054                if (parentResourceLoader != null) {
055                    resourceLoader = new ParentChildResourceLoader(parentResourceLoader, resourceLoader);
056                        }
057                }
058    
059                if (resourceLoader == null && classLoader.getParent() != null) {
060                        resourceLoader = getResourceLoaderCheckParent(classLoader.getParent());
061                }
062                return resourceLoader;
063            }
064    
065            public static synchronized ResourceLoader getResourceLoader(ClassLoader classloader) {
066                    return rootResourceLoaders.get(classloader);
067            }
068    
069            public static synchronized void start() throws Exception {
070                    try {
071                            initializing = true;
072                            ResourceLoader internalResourceLoader = getResourceLoader();
073                            if (internalResourceLoader == null) {
074                                    throw new RiceRuntimeException("Cannot start GlobalResourceLoader because no resource loaders have been added for the current ContextClassLoader :" + Thread.currentThread().getContextClassLoader());
075                            }
076                            internalResourceLoader.start();
077                    } finally {
078                            initializing = false;
079                    }
080            }
081    
082            public static synchronized void addResourceLoader(ResourceLoader resourceLoader) {
083                    initialize();
084                    if (resourceLoader == null) {
085                            throw new ResourceLoaderException("Attempted to add a null resource loader to the Global resource loader.");
086                    }
087                    LOG.info("Adding ResourceLoader " + resourceLoader.getName() + " to GlobalResourceLoader");
088                    getResourceLoader().addResourceLoader(resourceLoader);
089            }
090    
091            public static synchronized void addResourceLoaderFirst(ResourceLoader resourceLoader) {
092                    initialize();
093                    if (resourceLoader == null) {
094                            throw new ResourceLoaderException("Attempted to add a null resource loader to the Global resource loader.");
095                    }
096                    LOG.info("Adding ResourceLoader " + resourceLoader.getName() + " to GlobalResourceLoader");
097                    getResourceLoader().addResourceLoaderFirst(resourceLoader);
098            }
099    
100            protected static synchronized void initialize() {
101                    if (getResourceLoader(ClassLoaderUtils.getDefaultClassLoader()) == null) {
102                            LOG.info("Creating CompositeResourceLoader in GlobalResourceLoader");
103                            rootResourceLoaders.put(ClassLoaderUtils.getDefaultClassLoader(), new ResourceLoaderContainer(new QName(CoreConfigHelper.getApplicationId(), ResourceLoader.ROOT_RESOURCE_LOADER_NAME)));
104                    }
105            }
106    
107            public static synchronized ResourceLoader getResourceLoader(QName name) {
108                    return getResourceLoader().getResourceLoader(name);
109            }
110    
111            /**
112             * Stop the resource loader for the current context classloader.  Don't stop or clear them all
113             * because the stop was issued from the context of a single classloader.
114             *
115             * @throws Exception
116             */
117            public static synchronized void stop() throws Exception {
118                    LOG.info("Stopping the GlobalResourceLoader...");
119                    if (getResourceLoader(ClassLoaderUtils.getDefaultClassLoader()) != null) {
120                            LOG.info("Destroying GlobalResourceLoader");
121                            getResourceLoader(ClassLoaderUtils.getDefaultClassLoader()).stop();
122                            rootResourceLoaders.remove(ClassLoaderUtils.getDefaultClassLoader());
123                    }
124                    LOG.info("...GlobalResourceLoader successfully stopped.");
125            }
126    
127            public static <T extends Object> T getService(QName serviceName) {
128                    if (serviceName == null) {
129                            throw new IllegalArgumentException("The service name must be non-null.");
130                    }
131                    LOG.debug("GlobalResourceLoader fetching service " + serviceName);
132                    try {
133                            return getResourceLoader().<T>getService(serviceName);
134                    } catch (RiceRemoteServiceConnectionException ex) {
135                            LOG.warn(ex.getMessage());
136                            return null;
137                    }
138            }
139    
140            public static <T extends Object> T getService(String localServiceName) {
141                    if (StringUtils.isEmpty(localServiceName)) {
142                            throw new IllegalArgumentException("The service name must be non-null.");
143                    }
144                    return GlobalResourceLoader.<T>getService(new QName(localServiceName));
145            }
146    
147            public static <T extends Object> T getObject(ObjectDefinition objectDefinition) {
148                    return getResourceLoader().<T>getObject(objectDefinition);
149            }
150    
151            public static boolean isInitialized() {
152                    return getResourceLoader() != null;
153            }
154    
155            public static void logContents() {
156                    if (LOG.isInfoEnabled()) {
157                            LOG.info(getResourceLoader().getContents("", false));
158                    }
159            }
160            
161            public static void logAllContents() {
162                    if (LOG.isInfoEnabled()) {
163                            LOG.info("######################### Logging All Contents ###########################");
164                            for (ResourceLoader rl : rootResourceLoaders.values()) {
165                                    LOG.info("Logging contents for ResourceLoader: " + rl.getName() + "\n" + rl.getContents("  ", true));
166                            }
167                            LOG.info("###################### Done Logging All Contents #########################");
168                    }
169            }
170    
171            public static synchronized boolean isInitializing() {
172                    return initializing;
173            }
174    
175            public static synchronized void setInitializing(boolean initializing) {
176                    GlobalResourceLoader.initializing = initializing;
177            }
178    }