All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.openejb.loader.SystemInstance Maven / Gradle / Ivy

There is a newer version: 10.0.0-M3
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.openejb.loader;

import org.apache.openejb.loader.event.ComponentAdded;
import org.apache.openejb.loader.event.ComponentRemoved;
import org.apache.openejb.loader.provisining.ProvisioningResolver;
import org.apache.openejb.observer.ObserverManager;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.atomic.AtomicReference;

/**
 * This class aims to be the one and only static in the entire system
 * A static, singleton, instance of this class can be created with the {@link #init(Properties)} method
 * 

* It is assumed that only one singleton per classloader is possible in any given VM * Thus loading this instance in a classloader will mean there can only be one OpenEJB * instance for that classloader and all children classloaders. * * @version $Revision$ $Date$ * @org.apache.xbean.XBean element="system" */ public final class SystemInstance { private static final String PROFILE_PROP = "openejb.profile"; private static final String DEFAULT_PROFILE = "development"; private final long startTime = System.currentTimeMillis(); /** * Properties that have to be away from System (i.e. {@link System#setProperty(String, String)} must not be called) */ private final Properties internalProperties = new Properties(System.getProperties()); private final Options options; private final FileUtils home; private final FileUtils base; private final ClassLoader classLoader; private final Map components; private final ClassPath classPath; private final ObserverManager observerManager = new ObserverManager(); private SystemInstance(final Properties properties) { this.components = new HashMap(); // import JVM system property config (if a resource/container/... is set through this way) for (final String key : System.getProperties().stringPropertyNames()) { if (key.startsWith("sun.")) { continue; } if (key.startsWith("os.")) { continue; } if (key.startsWith("user.")) { continue; } if (key.startsWith("awt.")) { continue; } if (key.startsWith("java.")) { final String pkg = key.substring("java.".length()); if (pkg.startsWith("vm.")) { continue; } if (pkg.startsWith("runtime.")) { continue; } if (pkg.startsWith("awt.")) { continue; } if (pkg.startsWith("specification.")) { continue; } if (pkg.startsWith("class.")) { continue; } if (pkg.startsWith("library.")) { continue; } if (pkg.startsWith("ext.")) { continue; } if (pkg.startsWith("vendor.")) { continue; } if (pkg.startsWith("endorsed.")) { continue; } } final String value = System.getProperty(key); if (value != null) { this.internalProperties.put(key, value); } } this.internalProperties.putAll(properties); this.options = new Options(internalProperties, new Options(System.getProperties())); this.home = new FileUtils("openejb.home", "user.dir", this.internalProperties); this.base = new FileUtils("openejb.base", "openejb.home", this.internalProperties); this.classPath = ClassPathFactory.createClassPath(this.internalProperties.getProperty("openejb.loader", "context")); this.classLoader = classPath.getClassLoader(); final String homeDirCanonicalPath; final String baseDirCanonicalPath; try { homeDirCanonicalPath = home.getDirectory().getCanonicalPath(); baseDirCanonicalPath = base.getDirectory().getCanonicalPath(); } catch (final IOException e) { throw new LoaderRuntimeException("Failed to create default instance of SystemInstance", e); } this.internalProperties.setProperty("openejb.home", homeDirCanonicalPath); this.internalProperties.setProperty("openejb.base", baseDirCanonicalPath); System.setProperty("derby.system.home", System.getProperty("derby.system.home", baseDirCanonicalPath)); } public E fireEvent(final E event) { return observerManager.fireEvent(event); } public boolean addObserver(final Object observer) { return observerManager.addObserver(observer); } public boolean removeObserver(final Object observer) { return observerManager.removeObserver(observer); } @SuppressWarnings("unused") public long getStartTime() { return startTime; } public Options getOptions() { return options; } public Properties getProperties() { return internalProperties; } public String getProperty(final String key) { return internalProperties.getProperty(key); } public String getProperty(final String key, final String defaultValue) { return internalProperties.getProperty(key, defaultValue); } public Object setProperty(final String key, final String value) { return setProperty(key, value, false); } /** * @param key property name * @param value property value * @param isExternalProperty should the property be set to System by {@link System#setProperty(String, String)} * @return property value */ public Object setProperty(final String key, final String value, final boolean isExternalProperty) { if (isExternalProperty) { System.setProperty(key, value); } return internalProperties.setProperty(key, value); } public FileUtils getHome() { if (!isInitialized()) { return new FileUtils("openejb.home", "user.dir", System.getProperties()); } return home; } public FileUtils getBase() { if (!isInitialized()) { return new FileUtils("openejb.base", "openejb.home", System.getProperties()); } return base; } public ClassPath getClassPath() { return classPath; } public ClassLoader getClassLoader() { return classLoader; } /** * I'm not sure how this will play out, but I've used class instances instead of strings * for lookups as class instances are classloader scoped and there is an implicit "namespace" * associated with that. Theoretically, you can't lookup things that you can't already see * in your classloader. * * @param type Class * @return the object associated with the class type or null * @throws IllegalStateException of the component isn't found */ @SuppressWarnings("unchecked") public T getComponent(final Class type) { final T component = (T) components.get(type); if (component != null) { return component; } final String classname = getProperty(type.getName()); if (classname != null) { try { final T instance = type.cast(Thread.currentThread().getContextClassLoader() .loadClass(classname).newInstance()); components.put(type, instance); return instance; } catch (final Throwable e) { // no-op System.err.println("Failed to load class: " + classname); } } return null; } @SuppressWarnings("unchecked") public T removeComponent(final Class type) { final T component = (T) components.remove(type); if (component != null) { fireEvent(new ComponentRemoved(type, component)); } return component; } /** * @param type the class type of the component required */ @SuppressWarnings("unchecked") public T setComponent(final Class type, final T value) { final T removed = (T) components.put(type, value); if (removed != null) { fireEvent(new ComponentRemoved(type, value)); } if (value != null) { fireEvent(new ComponentAdded(type, value)); } return removed; } private static final AtomicReference system = new AtomicReference(); static { reset(); } private static boolean initialized; public static boolean isInitialized() { return initialized; } public static synchronized void reset() { try { System.clearProperty("openejb.loader"); system.set(new SystemInstance(new Properties())); // don't put system properties here, it is already done initialized = false; } catch (final Exception e) { throw new LoaderRuntimeException("Failed to create default instance of SystemInstance", e); } } public static synchronized void init(final Properties properties) throws Exception { if (initialized) { return; } system.set(new SystemInstance(properties)); // WARNING: reverse order since we don't overwrite existing entries readSystemProperties(get().currentProfile()); readSystemProperties(); readUserSystemProperties(); // if the user read System.getProperties() instead of our properties, used in bval-tomee tck for instance System.getProperties().putAll(system.get().getProperties()); initialized = true; get().setProperty("openejb.profile.custom", Boolean.toString(!get().isDefaultProfile())); initDefaultComponents(); } private static void initDefaultComponents() { system.get().components.put(ProvisioningResolver.class, new ProvisioningResolver()); } private static void readUserSystemProperties() { final File file = new File(System.getProperty("user.home"), ".openejb/system.properties"); addSystemProperties(file); } public File getConf(final String subPath) { File conf = null; final FileUtils base = system.get().getBase(); try { conf = base.getDirectory("conf"); } catch (final IOException e) { // no-op } if (conf == null || !conf.exists()) { try { conf = base.getDirectory("etc"); } catch (final IOException e) { // no-op } } if (conf == null || !conf.exists()) { return new File(base.getDirectory(), "conf"); } if (subPath == null) { return conf; } return new File(conf, subPath); } private static void readSystemProperties(final String prefix) { final String completePrefix; if (prefix != null && !prefix.isEmpty()) { completePrefix = prefix + "."; } else { completePrefix = ""; } // Read in and apply the conf/system.properties final File conf = system.get().getConf(completePrefix + "system.properties"); if (conf != null && conf.exists()) { addSystemProperties(conf); } } private static void readSystemProperties() { readSystemProperties(null); } private static void addSystemProperties(final File file) { if (!file.exists()) { return; } final Properties systemProperties; try { systemProperties = IO.readProperties(file); } catch (final IOException e) { return; } for (final String key : systemProperties.stringPropertyNames()) { final SystemInstance systemInstance = system.get(); if (systemInstance.getProperty(key) == null) { systemInstance.setProperty(key, systemProperties.getProperty(key)); } } // don't override system props // system.getProperties().putAll(systemProperties); } public static SystemInstance get() { return system.get(); } public String currentProfile() { return getProperty(PROFILE_PROP, DEFAULT_PROFILE); } public boolean isDefaultProfile() { return DEFAULT_PROFILE.equals(currentProfile()); } /** * @param propName property name * @return true when property is set; false otherwise */ public boolean hasProperty(final String propName) { return this.internalProperties.get(propName) != null; } public void removeObservers() { observerManager.destroy(); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy