001: /**
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
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: */package org.apache.openejb.loader;
017:
018: import java.util.Properties;
019: import java.util.HashMap;
020: import java.lang.annotation.Annotation;
021:
022: /**
023: * This class aims to be the one and only static in the entire system
024: * A static, singleton, instance of this class can be created with the {@link #init(Properties)} method
025: *
026: * It is assumed that only one singleton per classloader is possible in any given VM
027: * Thus loading this instance in a classloader will mean there can only be one OpenEJB
028: * instance for that classloader and all children classloaders.
029: *
030: * @version $Revision: 570634 $ $Date: 2007-08-28 21:31:49 -0700 $
031: *
032: * @org.apache.xbean.XBean element="system"
033: */
034: public class SystemInstance {
035:
036: private final long startTime = System.currentTimeMillis();
037:
038: /**
039: * Properties that have to be away from System (i.e. {@link System#setProperty(String, String)} must not be called)
040: */
041: private final Properties internalProperties = new Properties();
042:
043: /**
044: * Properties that need to be set to System via {@link System#setProperty(String, String)}
045: * FIXME: Some properties are doubled in internal and external prop sets, but it simplifies get's
046: */
047: private final Properties externalProperties = new Properties();
048:
049: private final FileUtils home;
050: private final FileUtils base;
051: private final ClassLoader classLoader;
052: private final HashMap<Class, Object> components;
053: private final ClassPath classPath;
054:
055: // FIXME: Why is Exception thrown at all? It's almost impossible that it'll happen.
056: private SystemInstance(Properties properties) throws Exception {
057: this .components = new HashMap<Class, Object>();
058:
059: this .internalProperties.putAll(System.getProperties());
060: this .internalProperties.putAll(properties);
061:
062: this .home = new FileUtils("openejb.home", "user.dir",
063: this .internalProperties);
064: this .base = new FileUtils("openejb.base", "openejb.home",
065: this .internalProperties);
066: this .classPath = ClassPathFactory
067: .createClassPath(this .internalProperties.getProperty(
068: "openejb.loader", "context"));
069: this .classLoader = classPath.getClassLoader();
070:
071: this .internalProperties.setProperty("openejb.home", home
072: .getDirectory().getCanonicalPath());
073: this .internalProperties.setProperty("openejb.base", base
074: .getDirectory().getCanonicalPath());
075: System.setProperty("derby.system.home", base.getDirectory()
076: .getCanonicalPath());
077: // set the magic system property that causes derby to use explicity
078: // file sync instead of relying on vm support for file open rws
079: System.setProperty("derby.storage.fileSyncTransactionLog",
080: "true");
081: }
082:
083: public long getStartTime() {
084: return startTime;
085: }
086:
087: public Properties getProperties() {
088: return internalProperties;
089: }
090:
091: public String getProperty(String key) {
092: return internalProperties.getProperty(key);
093: }
094:
095: public String getProperty(String key, String defaultValue) {
096: return internalProperties.getProperty(key, defaultValue);
097: }
098:
099: public Object setProperty(String key, String value) {
100: return setProperty(key, value, false);
101: }
102:
103: /**
104: * @param key property name
105: * @param value property value
106: * @param isExternalProperty should the property be set to System by {@link System#setProperty(String, String)}
107: * @return property value
108: */
109: public Object setProperty(String key, String value,
110: boolean isExternalProperty) {
111: if (isExternalProperty) {
112: this .externalProperties.setProperty(key, value);
113: System.setProperty(key, value);
114: }
115: return internalProperties.setProperty(key, value);
116: }
117:
118: public FileUtils getHome() {
119: return home;
120: }
121:
122: public FileUtils getBase() {
123: return base;
124: }
125:
126: public ClassPath getClassPath() {
127: return classPath;
128: }
129:
130: public ClassLoader getClassLoader() {
131: return classLoader;
132: }
133:
134: /**
135: * I'm not sure how this will play out, but I've used class instances instead of strings
136: * for lookups as class instances are classloader scoped and there is an implicit "namespace"
137: * associated with that. Theoretically, you can't lookup things that you can't already see
138: * in your classloader.
139: *
140: * @param type
141: * @return the object associated with the class type or null
142: * @throws IllegalStateException of the component isn't found
143: */
144: public <T> T getComponent(Class<T> type) {
145: return (T) components.get(type);
146: }
147:
148: public <T> T removeComponent(Class<T> type) {
149: return (T) components.remove(type);
150: }
151:
152: /**
153: * @param type the class type of the component required
154: */
155: public <T> T setComponent(Class<T> type, T value) {
156: return (T) components.put(type, value);
157: }
158:
159: private static SystemInstance system;
160:
161: static {
162: try {
163: system = new SystemInstance(System.getProperties());
164: } catch (Exception e) {
165: throw new RuntimeException(
166: "Failed to create default instance of SystemInstance",
167: e);
168: }
169: }
170:
171: private static boolean initialized;
172:
173: public static boolean isInitialized() {
174: return initialized;
175: }
176:
177: public static void init(Properties properties) throws Exception {
178: if (initialized)
179: return;
180: system = new SystemInstance(properties);
181: initialized = true;
182: }
183:
184: public static SystemInstance get() {
185: return system;
186: }
187:
188: /**
189: * @param propName property name
190: *
191: * @return true when property is set; false otherwise
192: */
193: public boolean hasProperty(String propName) {
194: return this.internalProperties.get(propName) != null;
195: }
196:
197: }
|