001: /*
002: * Copyright 2005-2006 The Kuali Foundation.
003: *
004: *
005: * Licensed under the Educational Community License, Version 1.0 (the "License");
006: * you may not use this file except in compliance with the License.
007: * You may obtain a copy of the License at
008: *
009: * http://www.opensource.org/licenses/ecl1.php
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.kuali.rice.core;
018:
019: import java.lang.ref.WeakReference;
020: import java.util.ArrayList;
021: import java.util.HashMap;
022: import java.util.List;
023: import java.util.Map;
024:
025: import org.apache.commons.lang.StringUtils;
026: import org.apache.log4j.Logger;
027: import org.kuali.rice.config.Config;
028: import org.kuali.rice.config.ConfigHolder;
029: import org.kuali.rice.config.ConfigurationException;
030: import org.kuali.rice.util.ClassLoaderUtils;
031:
032: /**
033: * Singleton that holds references to global engine objects.
034: *
035: *
036: * @author Kuali Rice Team (kuali-rice@googlegroups.com)
037: */
038: public class Core {
039: private static final Logger LOG = Logger.getLogger(Core.class);
040:
041: /**
042: * A convenience reference to what we should consider the "core" classloader. This is most likely
043: * going to be whatever webapp classloader the workflow engine resides in, but to make it crystal
044: * clear, this is defined here for easy reference. Note that this is NOT the institutional plugin
045: * classloader.
046: */
047: private static final WeakReference<ClassLoader> CORE_CLASSLOADER = new WeakReference<ClassLoader>(
048: Core.class.getClassLoader());
049:
050: /**
051: * Concurrency utility which allows other, loosely coupled, components to wait for configuration initialization
052: * to complete before proceeding (namely the SpringServiceLocator, before it initializes Spring)
053: */
054: private static ContextualConfigLock initialized = new ContextualConfigLock(
055: "ConfigurationInitialized");
056: private static Map<ClassLoader, Config> CONFIGS = new HashMap<ClassLoader, Config>();
057:
058: private Core() {
059: // nothing to do here
060: }
061:
062: /**
063: * Convenience method to return what all code should consider the "core" workflow engine classloader. Note that this is NOT
064: * the institutional plugin classloader.
065: * @return the "core" workflow engine classloader
066: */
067: public static ClassLoader getCoreClassLoader() {
068: return CORE_CLASSLOADER.get();
069: }
070:
071: /**
072: * Perform a one-time initialization of the Config system. This should only be performed by the applicable LifeCycle
073: * implementation.
074: * @param rootCfg the root config
075: */
076: public static void init(Config rootCfg) {
077: init(Thread.currentThread().getContextClassLoader(), rootCfg);
078: }
079:
080: /**
081: * Initializes the Core with the given Config and binds it to the given ClassLoader.
082: */
083: public static void init(ClassLoader classLoader, Config config) {
084: CONFIGS.put(classLoader, config);
085: initialized.fire();
086: }
087:
088: /**
089: * Destroy method (mostly to aid testing, as core needs to be torn down appropriately).
090: */
091: public static void destroy() {
092: if (!initialized.hasFired()) {
093: LOG.warn("Destroy on un-initialized Core was ignored.");
094: return;
095: }
096: CONFIGS.clear();
097: initialized.reset();
098: }
099:
100: /**
101: * Returns the "root" Config object
102: * @return the "root" Config object
103: * @deprecated this really isn't working as intended at the moment but it still needs to work the concept of a root config
104: * may need to go away
105: */
106: public static Config getRootConfig() {
107: return getCurrentContextConfig();
108: }
109:
110: /**
111: * Returns the Condition that allows waiting on configuration to complete
112: * @return the Condition that allows waiting on configuration to complete
113: */
114: public static ContextualConfigLock getInitializedCondition() {
115: return initialized;
116: }
117:
118: /**
119: * Runs a series of validation checks against the core configuration to ensure that required properties
120: * are present. For now, this just validates the message entity.
121: */
122: public static void validateCoreConfiguration() {
123: Config config = getRootConfig();
124: if (StringUtils.isEmpty(config.getMessageEntity())) {
125: throw new ConfigurationException("The "
126: + Config.MESSAGE_ENTITY
127: + " configuration parameter is required.");
128: }
129: }
130:
131: /**
132: * Utility method that all code should call to obtain its appropriate Config object.
133: * The Config object which is associated with the caller's context classloader will be
134: * returned, being created first if it does not yet exist.
135: * @return the Config object which is associated with the caller's context classloader
136: */
137: public synchronized static Config getCurrentContextConfig() {
138: return CONFIGS.get(Thread.currentThread()
139: .getContextClassLoader());
140: }
141:
142: public synchronized static Object getObjectFromConfigHierarchy(
143: String name) {
144: return getObjectFromClassLoader(name, ClassLoaderUtils
145: .getDefaultClassLoader());
146: }
147:
148: private static Object getObjectFromClassLoader(String name,
149: ClassLoader classLoader) {
150: if (classLoader instanceof ConfigHolder) {
151: Object object = ((ConfigHolder) classLoader).getConfig()
152: .getObject(name);
153: if (object != null) {
154: return object;
155: }
156: } else {
157: Object object = getRootConfig().getObject(name);
158: if (object != null) {
159: return object;
160: }
161: return null;
162: }
163: return getObjectFromClassLoader(name, classLoader.getParent());
164: }
165:
166: public static List<Object> getObjectsFromConfigHierarchy(String name) {
167: List<Object> objects = new ArrayList<Object>();
168: getObjectFromClassLoader(name, ClassLoaderUtils
169: .getDefaultClassLoader(), objects);
170: return objects;
171: }
172:
173: private static void getObjectFromClassLoader(String name,
174: ClassLoader classLoader, List<Object> objects) {
175: if (classLoader instanceof ConfigHolder) {
176: Object object = ((ConfigHolder) classLoader).getConfig()
177: .getObject(name);
178: if (object != null) {
179: objects.add(object);
180: }
181: } else {
182: Object object = getRootConfig().getObject(name);
183: if (object != null) {
184: objects.add(object);
185: }
186: return;
187: }
188: getObjectFromClassLoader(name, classLoader.getParent(), objects);
189: }
190:
191: /**
192: * Returns the map of config objects with their associated classloaders.
193: * Alter this map at your own risk. This map is the cornerstone of all
194: * service and resource acquisition.
195: *
196: * @return
197: */
198: public static Map<ClassLoader, Config> getCONFIGS() {
199: return CONFIGS;
200: }
201:
202: }
|