/* * Copyright (c) 1998-2011 Caucho Technology -- all rights reserved * * This file is part of Resin(R) Open Source * * Each copy or derived work must preserve the copyright notice and this * notice unmodified. * * Resin Open Source is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Resin Open Source is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty * of NON-INFRINGEMENT. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License * along with Resin Open Source; if not, write to the * * Free Software Foundation, Inc. * 59 Temple Place, Suite 330 * Boston, MA 02111-1307 USA * * @author Scott Ferguson */ package com.caucho.env.deploy; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; import javax.el.ELException; import javax.management.ObjectName; import com.caucho.config.ConfigException; import com.caucho.config.inject.InjectManager; import com.caucho.config.program.ConfigProgram; import com.caucho.config.types.PathBuilder; import com.caucho.env.repository.RepositoryTagEntry; import com.caucho.jmx.Jmx; import com.caucho.loader.Environment; import com.caucho.loader.EnvironmentClassLoader; import com.caucho.loader.EnvironmentListener; import com.caucho.util.L10N; import com.caucho.vfs.Path; import com.caucho.vfs.Vfs; /** * A deploy controller for an environment. */ abstract public class EnvironmentDeployController<I extends EnvironmentDeployInstance, C extends DeployConfig> extends ExpandDeployController<I> implements EnvironmentListener { private static final L10N L = new L10N(EnvironmentDeployController.class); private static final Logger log = Logger.getLogger(EnvironmentDeployController.class.getName()); // The JMX identity private LinkedHashMap<String,String> _jmxContext; private Object _mbean; private ObjectName _objectName; // The default configurations private ArrayList<C> _configDefaults = new ArrayList<C>(); // The primary configuration private C _config; private DeployConfig _prologue; // The variable mapping private HashMap<String,Object> _variableMap = new HashMap<String,Object>(); // Config exception passed in from parent, e.g. .ear private Throwable _configException; public EnvironmentDeployController(String id, Path rootDirectory) { this(id, rootDirectory, null, null); } public EnvironmentDeployController(String id, Path rootDirectory, C config, DeployContainerApi<?> container) { super(id, null, rootDirectory, container); _jmxContext = Jmx.copyContextProperties(getParentClassLoader()); setConfig(config); } /** * Sets the primary configuration. */ public void setConfig(C config) { if (config == null) return; if (_config != null && ! _configDefaults.contains(_config)) addConfigDefault(_config); addConfigController(config); _config = config; if (_prologue == null) setPrologue(config.getPrologue()); } /** * Gets the primary configuration */ public C getConfig() { return _config; } /** * Gets the prologue configuration */ public DeployConfig getPrologue() { return _prologue; } /** * Sets the prologue configuration */ public void setPrologue(DeployConfig prologue) { _prologue = prologue; } /** * Returns the error message */ public String getErrorMessage() { Throwable exn = getConfigException(); if (exn instanceof ConfigException) { exn.printStackTrace(); return exn.getMessage(); } else if (exn != null) { exn.printStackTrace(); return exn.toString(); } else return null; } /** * Returns the configure exception. */ @Override public Throwable getConfigException() { Throwable configException = super.getConfigException(); if (configException == null) configException = _configException; if (configException == null) { DeployInstance deploy = getDeployInstance(); if (deploy != null) configException = deploy.getConfigException(); } return configException; } /** * Adds a default config. */ public void addConfigDefault(C config) { if (! _configDefaults.contains(config)) { _configDefaults.add(config); addConfigController(config); } } private void addConfigController(C config) { if (config.getStartupMode() != null) setStartupMode(config.getStartupMode()); if (config.getRedeployCheckInterval() != null) setRedeployCheckInterval(config.getRedeployCheckInterval()); if (config.getRedeployMode() != null) setRedeployMode(config.getRedeployMode()); if (config.getExpandCleanupFileset() != null) addExpandCleanupFileSet(config.getExpandCleanupFileset()); } /** * Returns the path variable map. */ public HashMap<String,Object> getVariableMap() { return _variableMap; } /** * Returns the mbean. */ public Object getMBean() { return _mbean; } /** * Returns the object name. */ public ObjectName getObjectName() { return _objectName; } /** * Sets a parent config exception (e.g. from a .ear) */ public void setConfigException(Throwable e) { _configException = e; if (getDeployInstance() != null) getDeployInstance().setConfigException(e); } /** * Initialize the controller. */ @Override protected void initEnd() { super.initEnd(); if (getDeployAdmin() != null) { getDeployAdmin().register(); } } /** * Returns true if the entry matches. */ @Override public boolean isNameMatch(String url) { return url.equals(getId()); } protected String getMBeanTypeName() { return getDeployInstance().getClass().getSimpleName(); } protected String getMBeanId() { String name = getId(); if (name == null || name.equals("")) name = "default"; return name; } /** * Merges with the old controller. */ /* @Override protected void mergeController(DeployController oldControllerV) { super.mergeController(oldControllerV); EnvironmentDeployController<I,C> oldController; oldController = (EnvironmentDeployController) oldControllerV; // setId(oldController.getId()); ArrayList<C> configDefaults = new ArrayList<C>(); if (getPrologue() == null) setPrologue(oldController.getPrologue()); else if (oldController.getPrologue() != null) { configDefaults.add(0, (C) getPrologue()); // XXX: must be first setPrologue(oldController.getPrologue()); } configDefaults.addAll(oldController._configDefaults); if (getConfig() == null) setConfig(oldController.getConfig()); else if (oldController.getConfig() != null) { configDefaults.add(getConfig()); setConfig(oldController.getConfig()); } for (C config : _configDefaults) { if (! configDefaults.contains(config)) configDefaults.add(config); } _configDefaults = configDefaults; mergeStartupMode(oldController.getStartupMode()); mergeRedeployCheckInterval(oldController.getRedeployCheckInterval()); mergeRedeployMode(oldController.getRedeployMode()); } */ @Override public void merge(DeployControllerApi<I> oldControllerV) { EnvironmentDeployController<I,C> oldController; oldController = (EnvironmentDeployController<I,C>) oldControllerV; // server/10l4 if (! getRootDirectory().equals(oldController.getRootDirectory())) return; super.merge(oldControllerV); // setId(oldController.getId()); ArrayList<C> configDefaults = new ArrayList<C>(); if (getPrologue() == null) setPrologue(oldController.getPrologue()); else if (oldController.getPrologue() != null) { configDefaults.add(0, (C) getPrologue()); // XXX: must be first setPrologue(oldController.getPrologue()); } configDefaults.addAll(oldController._configDefaults); if (getConfig() == null) setConfig(oldController.getConfig()); else if (oldController.getConfig() != null) { configDefaults.add(getConfig()); setConfig(oldController.getConfig()); } for (C config : _configDefaults) { if (! configDefaults.contains(config)) configDefaults.add(config); } _configDefaults = configDefaults; // mergeStartupMode(oldController.getStartupMode()); // mergeRedeployCheckInterval(oldController.getRedeployCheckInterval()); // mergeRedeployMode(oldController.getRedeployMode()); } protected DeployControllerAdmin<?> getDeployAdmin() { return null; } /** * Returns the application object. */ @Override public boolean destroy() { if (! super.destroy()) return false; Environment.removeEnvironmentListener(this, getParentClassLoader()); Thread thread = Thread.currentThread(); ClassLoader oldLoader = thread.getContextClassLoader(); try { thread.setContextClassLoader(getParentClassLoader()); if (getDeployAdmin() != null) getDeployAdmin().unregister(); } finally { thread.setContextClassLoader(oldLoader); } return true; } /** * Configures the instance. */ @Override protected void configureInstance(I instance) throws Exception { Thread thread = Thread.currentThread(); ClassLoader oldLoader = thread.getContextClassLoader(); try { ClassLoader classLoader = instance.getClassLoader(); thread.setContextClassLoader(classLoader); log.fine(instance + " initializing"); super.configureInstance(instance); // set from external error, like .ear instance.setConfigException(_configException); extendJMXContext(_jmxContext); Jmx.setContextProperties(_jmxContext, classLoader); configureInstanceVariables(instance); ArrayList<DeployConfig> initList = new ArrayList<DeployConfig>(); if (getPrologue() != null) initList.add(getPrologue()); thread.setContextClassLoader(instance.getClassLoader()); Vfs.setPwd(getRootDirectory()); addDependencies(); instance.preConfigInit(); fillInitList(initList); InjectManager cdiManager = InjectManager.getCurrent(); cdiManager.setEnableAutoUpdate(false); try { for (DeployConfig config : initList) { ConfigProgram program = config.getClassLoaderProgram(); if (program != null) program.configure(instance); } } finally { cdiManager.setEnableAutoUpdate(true); } for (DeployConfig config : initList) { ConfigProgram program = config.getBuilderProgram(); if (program != null) program.configure(instance); } instance.init(); } finally { thread.setContextClassLoader(oldLoader); } } protected void extendJMXContext(Map<String,String> context) { // _jmxContext.put(getMBeanTypeName(), getMBeanId()); } protected void fillInitList(ArrayList<DeployConfig> initList) { boolean isSkipDefault = _config != null && _config.isSkipDefaultConfig(); if (isSkipDefault) { initList.clear(); } else { for (DeployConfig config : _configDefaults) { DeployConfig prologue = config.getPrologue(); if (prologue != null) initList.add(prologue); } initList.addAll(_configDefaults); } if (_config != null && ! initList.contains(_config)) initList.add(_config); } protected void configureInstanceVariables(I instance) { Path rootDirectory = getRootDirectory(); if (rootDirectory == null) throw new NullPointerException("Null root directory"); if (! rootDirectory.isFile()) { } else if (rootDirectory.getPath().endsWith(".jar") || rootDirectory.getPath().endsWith(".war")) { throw new ConfigException(L.l("root-directory `{0}' must specify a directory. It may not be a .jar or .war.", rootDirectory.getPath())); } else throw new ConfigException(L.l("root-directory `{0}' may not be a file. root-directory must specify a directory.", rootDirectory.getPath())); Vfs.setPwd(rootDirectory); if (log.isLoggable(Level.FINE)) log.fine(instance + " root-directory=" + rootDirectory); // instance.setRootDirectory(rootDirectory); } public Map<String,String> getRepositoryMetaData() { HashMap<String,String> map = new HashMap<String,String>(); Map<String,RepositoryTagEntry> tagMap = getRepository().getTagMap(); RepositoryTagEntry entry = tagMap.get(getId()); if (entry == null && getAutoDeployTag() != null) { entry = tagMap.get(getAutoDeployTag()); } if (entry != null) { map.putAll(entry.getAttributeMap()); } return map; } @Override public Path getArchivePath() { Path path = super.getArchivePath(); if (path != null) return path; if (_config != null) { String pathString = _config.getArchivePath(); if (pathString != null) { try { path = PathBuilder.lookupPath(pathString); } catch (ELException e) { throw new RuntimeException(e); } } setArchivePath(path); } return path; } /** * Handles config phase. */ @Override public void environmentConfigure(EnvironmentClassLoader loader) { } /** * Handles bind phase. */ @Override public void environmentBind(EnvironmentClassLoader loader) { } /** * Handles the case where the environment is starting (after init). */ @Override public void environmentStart(EnvironmentClassLoader loader) { try { start(); } catch (Exception e) { log.log(Level.WARNING, e.toString(), e); } } /** * Handles the case where the environment is stopping */ @Override public void environmentStop(EnvironmentClassLoader loader) { stop(); } /** * Returns a printable view. */ @Override public String toString() { return getClass().getSimpleName() + "$" + System.identityHashCode(this) + "[" + getId() + "]"; } }