001: /*
002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: *
023: * Free Software Foundation, Inc.
024: * 59 Temple Place, Suite 330
025: * Boston, MA 02111-1307 USA
026: *
027: * @author Scott Ferguson
028: */
029:
030: package com.caucho.server.deploy;
031:
032: import com.caucho.config.program.ConfigProgram;
033: import com.caucho.config.ConfigException;
034: import com.caucho.config.types.PathBuilder;
035: import com.caucho.jmx.Jmx;
036: import com.caucho.loader.Environment;
037: import com.caucho.loader.EnvironmentClassLoader;
038: import com.caucho.loader.EnvironmentListener;
039: import com.caucho.util.L10N;
040: import com.caucho.vfs.Path;
041: import com.caucho.vfs.Vfs;
042:
043: import javax.el.ELException;
044: import javax.management.ObjectName;
045: import java.util.ArrayList;
046: import java.util.HashMap;
047: import java.util.LinkedHashMap;
048: import java.util.Map;
049: import java.util.logging.Level;
050: import java.util.logging.Logger;
051:
052: /**
053: * A deploy controller for an environment.
054: */
055: abstract public class EnvironmentDeployController<I extends EnvironmentDeployInstance, C extends DeployConfig>
056: extends ExpandDeployController<I> implements
057: EnvironmentListener {
058: private static final L10N L = new L10N(
059: EnvironmentDeployController.class);
060: private static final Logger log = Logger
061: .getLogger(EnvironmentDeployController.class.getName());
062:
063: // The JMX identity
064: private LinkedHashMap<String, String> _jmxContext;
065:
066: private Object _mbean;
067:
068: private ObjectName _objectName;
069:
070: // The default configurations
071: private ArrayList<C> _configDefaults = new ArrayList<C>();
072:
073: // The primary configuration
074: private C _config;
075: private DeployConfig _prologue;
076:
077: // The variable mapping
078: private HashMap<String, Object> _variableMap = new HashMap<String, Object>();
079:
080: // Config exception passed in from parent, e.g. .ear
081: private Throwable _configException;
082:
083: public EnvironmentDeployController() {
084: this ("", (Path) null);
085: }
086:
087: public EnvironmentDeployController(C config) {
088: this (config.getId(), config.calculateRootDirectory());
089:
090: setConfig(config);
091: }
092:
093: public EnvironmentDeployController(String id, C config) {
094: this (id, config.calculateRootDirectory());
095:
096: setConfig(config);
097: }
098:
099: public EnvironmentDeployController(String id, Path rootDirectory) {
100: super (id, null, rootDirectory);
101:
102: _jmxContext = Jmx.copyContextProperties(getParentClassLoader());
103: }
104:
105: /**
106: * Sets the primary configuration.
107: */
108: public void setConfig(C config) {
109: if (config == null)
110: return;
111:
112: if (_config != null && !_configDefaults.contains(_config))
113: addConfigDefault(_config);
114:
115: addConfigMode(config);
116:
117: _config = config;
118:
119: if (_prologue == null)
120: setPrologue(config.getPrologue());
121: }
122:
123: /**
124: * Gets the primary configuration
125: */
126: public C getConfig() {
127: return _config;
128: }
129:
130: /**
131: * Gets the prologue configuration
132: */
133: public DeployConfig getPrologue() {
134: return _prologue;
135: }
136:
137: /**
138: * Sets the prologue configuration
139: */
140: public void setPrologue(DeployConfig prologue) {
141: _prologue = prologue;
142: }
143:
144: /**
145: * Returns the configure exception.
146: */
147: @Override
148: public Throwable getConfigException() {
149: Throwable configException = super .getConfigException();
150:
151: if (configException == null)
152: configException = _configException;
153:
154: if (configException == null) {
155: DeployInstance deploy = getDeployInstance();
156:
157: if (deploy != null)
158: configException = deploy.getConfigException();
159: }
160:
161: return configException;
162: }
163:
164: /**
165: * Adds a default config.
166: */
167: public void addConfigDefault(C config) {
168: if (!_configDefaults.contains(config)) {
169: _configDefaults.add(config);
170:
171: addConfigMode(config);
172: }
173: }
174:
175: private void addConfigMode(C config) {
176: if (config.getStartupMode() != null)
177: setStartupMode(config.getStartupMode());
178:
179: if (config.getRedeployCheckInterval() != null)
180: setRedeployCheckInterval(config.getRedeployCheckInterval());
181:
182: if (config.getRedeployMode() != null)
183: setRedeployMode(config.getRedeployMode());
184: }
185:
186: /**
187: * Returns the path variable map.
188: */
189: public HashMap<String, Object> getVariableMap() {
190: return _variableMap;
191: }
192:
193: /**
194: * Returns the mbean.
195: */
196: public Object getMBean() {
197: return _mbean;
198: }
199:
200: /**
201: * Returns the object name.
202: */
203: public ObjectName getObjectName() {
204: return _objectName;
205: }
206:
207: /**
208: * Sets a parent config exception (e.g. from a .ear)
209: */
210: public void setConfigException(Throwable e) {
211: _configException = e;
212: }
213:
214: /**
215: * Initialize the controller.
216: */
217: @Override
218: protected void initEnd() {
219: super .initEnd();
220:
221: if (getDeployAdmin() != null)
222: getDeployAdmin().register();
223: }
224:
225: /**
226: * Returns true if the entry matches.
227: */
228: @Override
229: public boolean isNameMatch(String url) {
230: return url.equals(getId());
231: }
232:
233: /**
234: * Merges with the old controller.
235: */
236: @Override
237: protected void mergeController(DeployController oldControllerV) {
238: super .mergeController(oldControllerV);
239:
240: EnvironmentDeployController<I, C> oldController;
241: oldController = (EnvironmentDeployController) oldControllerV;
242: // setId(oldController.getId());
243:
244: _configDefaults.addAll(oldController._configDefaults);
245:
246: if (getConfig() == null)
247: setConfig(oldController.getConfig());
248: else if (oldController.getConfig() != null) {
249: _configDefaults.add(getConfig());
250:
251: setConfig(oldController.getConfig());
252: }
253:
254: if (getPrologue() == null)
255: setPrologue(oldController.getPrologue());
256: else if (oldController.getPrologue() != null) {
257: _configDefaults.add(0, (C) getPrologue()); // XXX: must be first
258:
259: setPrologue(oldController.getPrologue());
260: }
261:
262: if (oldController.getArchivePath() != null)
263: setArchivePath(oldController.getArchivePath());
264:
265: mergeStartupMode(oldController.getStartupMode());
266:
267: mergeRedeployCheckInterval(oldController
268: .getRedeployCheckInterval());
269:
270: mergeRedeployMode(oldController.getRedeployMode());
271: }
272:
273: /**
274: * Returns the application object.
275: */
276: @Override
277: public boolean destroy() {
278: if (!super .destroy())
279: return false;
280:
281: Environment.removeEnvironmentListener(this ,
282: getParentClassLoader());
283:
284: Thread thread = Thread.currentThread();
285: ClassLoader oldLoader = thread.getContextClassLoader();
286:
287: try {
288: thread.setContextClassLoader(getParentClassLoader());
289:
290: if (getDeployAdmin() != null)
291: getDeployAdmin().unregister();
292: } finally {
293: thread.setContextClassLoader(oldLoader);
294: }
295:
296: return true;
297: }
298:
299: /**
300: * Configures the instance.
301: */
302: @Override
303: protected void configureInstance(I instance) throws Throwable {
304: Thread thread = Thread.currentThread();
305: ClassLoader oldLoader = thread.getContextClassLoader();
306:
307: try {
308: ClassLoader classLoader = instance.getClassLoader();
309:
310: thread.setContextClassLoader(classLoader);
311:
312: log.fine(instance + " initializing");
313:
314: // set from external error, like .ear
315: instance.setConfigException(_configException);
316:
317: configureInstanceVariables(instance);
318:
319: extendJMXContext(_jmxContext);
320:
321: Jmx.setContextProperties(_jmxContext, classLoader);
322:
323: ArrayList<DeployConfig> initList = new ArrayList<DeployConfig>();
324:
325: if (getPrologue() != null)
326: initList.add(getPrologue());
327:
328: fillInitList(initList);
329:
330: thread.setContextClassLoader(instance.getClassLoader());
331: Vfs.setPwd(getRootDirectory());
332:
333: if (getArchivePath() != null)
334: Environment.addDependency(getArchivePath());
335:
336: for (DeployConfig config : initList) {
337: ConfigProgram program = config.getBuilderProgram();
338:
339: if (program != null)
340: program.configure(instance);
341: }
342:
343: instance.init();
344: } finally {
345: thread.setContextClassLoader(oldLoader);
346: }
347: }
348:
349: protected void extendJMXContext(Map<String, String> context) {
350: // _jmxContext.put(getMBeanTypeName(), getMBeanId());
351: }
352:
353: protected void fillInitList(ArrayList<DeployConfig> initList) {
354: boolean isSkipDefault = _config != null
355: && _config.isSkipDefaultConfig();
356:
357: if (!isSkipDefault) {
358: for (DeployConfig config : _configDefaults) {
359: DeployConfig prologue = config.getPrologue();
360:
361: if (prologue != null)
362: initList.add(prologue);
363: }
364:
365: initList.addAll(_configDefaults);
366: }
367:
368: if (_config != null && !initList.contains(_config))
369: initList.add(_config);
370: }
371:
372: protected void configureInstanceVariables(I instance)
373: throws Throwable {
374: Path rootDirectory = getRootDirectory();
375:
376: if (rootDirectory == null)
377: throw new NullPointerException("Null root directory");
378:
379: if (!rootDirectory.isFile()) {
380: } else if (rootDirectory.getPath().endsWith(".jar")
381: || rootDirectory.getPath().endsWith(".war")) {
382: throw new ConfigException(
383: L
384: .l(
385: "root-directory `{0}' must specify a directory. It may not be a .jar or .war.",
386: rootDirectory.getPath()));
387: } else
388: throw new ConfigException(
389: L
390: .l(
391: "root-directory `{0}' may not be a file. root-directory must specify a directory.",
392: rootDirectory.getPath()));
393: Vfs.setPwd(rootDirectory);
394:
395: if (log.isLoggable(Level.FINE))
396: log.fine(instance + " root-directory=" + rootDirectory);
397:
398: instance.setRootDirectory(rootDirectory);
399: }
400:
401: @Override
402: public Path getArchivePath() {
403: Path path = super .getArchivePath();
404:
405: if (path != null)
406: return path;
407:
408: if (_config != null) {
409: String pathString = _config.getArchivePath();
410:
411: if (pathString != null) {
412: try {
413: path = PathBuilder.lookupPath(pathString);
414: } catch (ELException e) {
415: throw new RuntimeException(e);
416: }
417: }
418:
419: setArchivePath(path);
420: }
421:
422: return path;
423: }
424:
425: /**
426: * Handles config phase.
427: */
428: public void environmentConfig(EnvironmentClassLoader loader) {
429: }
430:
431: /**
432: * Handles the case where the environment is starting (after init).
433: */
434: public void environmentStart(EnvironmentClassLoader loader) {
435: try {
436: start();
437: } catch (Exception e) {
438: log.log(Level.WARNING, e.toString(), e);
439: }
440: }
441:
442: /**
443: * Handles the case where the environment is stopping
444: */
445: public void environmentStop(EnvironmentClassLoader loader) {
446: stop();
447: }
448:
449: /**
450: * Returns a printable view.
451: */
452: @Override
453: public String toString() {
454: return getClass().getSimpleName() + "$"
455: + System.identityHashCode(this ) + "[" + getId() + "]";
456: }
457: }
|