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.host;
031:
032: import com.caucho.config.ConfigException;
033: import com.caucho.config.types.PathBuilder;
034: import com.caucho.el.EL;
035: import com.caucho.log.Log;
036: import com.caucho.management.server.HostMXBean;
037: import com.caucho.server.deploy.DeployController;
038: import com.caucho.server.deploy.DeployControllerAdmin;
039: import com.caucho.server.deploy.EnvironmentDeployController;
040: import com.caucho.server.e_app.EarConfig;
041: import com.caucho.server.webapp.WebAppConfig;
042: import com.caucho.util.L10N;
043: import com.caucho.vfs.Depend;
044: import com.caucho.vfs.Dependency;
045: import com.caucho.vfs.Path;
046: import com.caucho.vfs.Vfs;
047: import com.caucho.webbeans.manager.*;
048:
049: import java.util.ArrayList;
050: import java.util.HashMap;
051: import java.util.Map;
052: import java.util.logging.Level;
053: import java.util.logging.Logger;
054: import java.util.regex.Matcher;
055: import java.util.regex.Pattern;
056: import javax.webbeans.*;
057:
058: /**
059: * A configuration entry for a host
060: */
061: public class HostController extends
062: EnvironmentDeployController<Host, HostConfig> {
063: private static final Logger log = Logger
064: .getLogger(HostController.class.getName());
065: private static final L10N L = new L10N(HostController.class);
066:
067: private HostContainer _container;
068:
069: // The host name is the canonical name
070: private String _hostName;
071: // The regexp name is the matching name of the regexp
072: private String _regexpName;
073:
074: private Pattern _regexp;
075: private String _rootDirectoryPattern;
076:
077: // Any host aliases.
078: private ArrayList<String> _entryHostAliases = new ArrayList<String>();
079: private ArrayList<Pattern> _entryHostAliasRegexps = new ArrayList<Pattern>();
080:
081: private ArrayList<String> _hostAliases = new ArrayList<String>();
082:
083: // The host variables.
084: private final Var _hostVar = new Var();
085: private final HostAdmin _admin = new HostAdmin(this );
086:
087: private ArrayList<Dependency> _dependList = new ArrayList<Dependency>();
088:
089: HostController(String id, HostConfig config,
090: HostContainer container, Map<String, Object> varMap) {
091: super (id, config);
092:
093: setHostName(id);
094:
095: if (varMap != null)
096: getVariableMap().putAll(varMap);
097:
098: getVariableMap().put("host", _hostVar);
099:
100: setContainer(container);
101:
102: setRootDirectory(config
103: .calculateRootDirectory(getVariableMap()));
104: }
105:
106: HostController(String id, Path rootDirectory,
107: HostContainer container) {
108: super (id, rootDirectory);
109:
110: addHostAlias(id);
111: setHostName(id);
112:
113: getVariableMap().put("name", id);
114: getVariableMap().put("host", _hostVar);
115:
116: setContainer(container);
117: }
118:
119: public void setContainer(HostContainer container) {
120: _container = container;
121:
122: if (_container != null) {
123: for (HostConfig defaultConfig : _container
124: .getHostDefaultList())
125: addConfigDefault(defaultConfig);
126: }
127: }
128:
129: /**
130: * Returns the Resin host name.
131: */
132: public String getName() {
133: String name = super .getId();
134:
135: if (name != null)
136: return name;
137: else
138: return getHostName();
139: }
140:
141: /**
142: * Returns the host's canonical name
143: */
144: public String getHostName() {
145: return _hostName;
146: }
147:
148: /**
149: * Sets the host's canonical name
150: */
151: public void setHostName(String name) {
152: if (name != null)
153: name = name.trim();
154:
155: if (name == null || name.equals("*"))
156: name = "";
157:
158: name = name.toLowerCase();
159:
160: _hostName = name;
161: }
162:
163: /**
164: * Returns the host's canonical name
165: */
166: public void setRegexpName(String name) {
167: _regexpName = name.toLowerCase();
168: }
169:
170: /**
171: * Adds a host alias.
172: */
173: public void addHostAlias(String name) {
174: if (name != null)
175: name = name.trim();
176:
177: if (name == null || name.equals("*"))
178: name = ""; // XXX: default?
179:
180: name = name.toLowerCase();
181:
182: if (!_entryHostAliases.contains(name))
183: _entryHostAliases.add(name);
184:
185: addExtHostAlias(name);
186: }
187:
188: /**
189: * Adds an extension host alias, e.g. from a resin:import
190: */
191: public void addExtHostAlias(String name) {
192: if (!_hostAliases.contains(name))
193: _hostAliases.add(name);
194: }
195:
196: /**
197: * Returns the host aliases.
198: */
199: public ArrayList<String> getHostAliases() {
200: return _hostAliases;
201: }
202:
203: /**
204: * Sets the regexp pattern
205: */
206: public void setRegexp(Pattern regexp) {
207: _regexp = regexp;
208: }
209:
210: /**
211: * Sets the root directory pattern
212: */
213: public void setRootDirectoryPattern(String rootDirectoryPattern) {
214: _rootDirectoryPattern = rootDirectoryPattern;
215: }
216:
217: /**
218: * Adds a dependent file.
219: */
220: public void addDepend(Path depend) {
221: if (!_dependList.contains(depend))
222: _dependList.add(new Depend(depend));
223: }
224:
225: /**
226: * Returns the host admin.
227: */
228: public HostMXBean getAdmin() {
229: return _admin;
230: }
231:
232: /**
233: * Returns the deploy admin.
234: */
235: protected DeployControllerAdmin getDeployAdmin() {
236: return _admin;
237: }
238:
239: /**
240: * Initialize the entry.
241: */
242: protected void initBegin() {
243: try {
244: try {
245: if (getConfig() == null || getHostName() != null) {
246: } else if (getConfig().getHostName() != null)
247: setHostName(EL.evalString(
248: getConfig().getHostName(), EL
249: .getEnvironment()));
250: } catch (Exception e) {
251: log.log(Level.WARNING, e.toString(), e);
252: }
253:
254: if (_regexpName != null && _hostName == null)
255: _hostName = _regexpName;
256:
257: if (_hostName == null)
258: _hostName = "";
259:
260: ArrayList<String> aliases = null;
261:
262: if (getConfig() != null) {
263: aliases = getConfig().getHostAliases();
264:
265: _entryHostAliasRegexps.addAll(getConfig()
266: .getHostAliasRegexps());
267: }
268:
269: for (int i = 0; aliases != null && i < aliases.size(); i++) {
270: String alias = aliases.get(i);
271:
272: alias = EL.evalString(alias, EL.getEnvironment());
273:
274: addHostAlias(alias);
275: }
276: } catch (Exception e) {
277: log.log(Level.WARNING, e.toString(), e);
278: }
279:
280: super .initBegin();
281: }
282:
283: /**
284: * Returns the "name" property.
285: */
286: protected String getMBeanId() {
287: String name = _hostName;
288:
289: if (name == null)
290: name = "";
291: else if (name.indexOf(':') >= 0)
292: name = name.replace(':', '-');
293:
294: if (name.equals(""))
295: return "default";
296: else
297: return name;
298: }
299:
300: /**
301: * Returns true for a matching name.
302: */
303: public boolean isNameMatch(String name) {
304: if (_hostName.equalsIgnoreCase(name))
305: return true;
306:
307: for (int i = _hostAliases.size() - 1; i >= 0; i--) {
308: if (name.equalsIgnoreCase(_hostAliases.get(i)))
309: return true;
310: }
311:
312: for (int i = _entryHostAliasRegexps.size() - 1; i >= 0; i--) {
313: Pattern alias = _entryHostAliasRegexps.get(i);
314:
315: if (alias.matcher(name).find())
316: return true;
317: }
318:
319: if (_regexp != null) {
320: // server/0523
321:
322: Matcher matcher = _regexp.matcher(name);
323:
324: if (matcher.matches()) {
325: Path rootDirectory = calculateRoot(matcher);
326:
327: if (getRootDirectory().equals(rootDirectory))
328: return true;
329: }
330: }
331:
332: return false;
333: }
334:
335: private Path calculateRoot(Matcher matcher) {
336: // XXX: duplicates HostRegexp
337:
338: Thread thread = Thread.currentThread();
339: ClassLoader oldLoader = thread.getContextClassLoader();
340:
341: try {
342: thread.setContextClassLoader(getParentClassLoader());
343:
344: if (_rootDirectoryPattern == null) {
345: // server/129p
346: return Vfs.lookup();
347: }
348:
349: int length = matcher.end() - matcher.start();
350:
351: ArrayList<String> vars = new ArrayList<String>();
352:
353: HashMap<String, Object> varMap = new HashMap<String, Object>();
354:
355: for (int j = 0; j <= matcher.groupCount(); j++) {
356: vars.add(matcher.group(j));
357: varMap.put("host" + j, matcher.group(j));
358: }
359:
360: varMap.put("regexp", vars);
361: varMap.put("host", new TestVar(matcher.group(0), vars));
362:
363: Path path = PathBuilder.lookupPath(_rootDirectoryPattern,
364: varMap);
365:
366: return path;
367: } catch (Exception e) {
368: log.log(Level.FINE, e.toString(), e);
369:
370: // XXX: not quite right
371: return Vfs.lookup(_rootDirectoryPattern);
372: } finally {
373: thread.setContextClassLoader(oldLoader);
374: }
375: }
376:
377: /**
378: * Merges two entries.
379: */
380: protected HostController merge(HostController newController) {
381: if (getConfig() != null && getConfig().getRegexp() != null)
382: return newController;
383: else if (newController.getConfig() != null
384: && newController.getConfig().getRegexp() != null)
385: return this ;
386: else {
387: Thread thread = Thread.currentThread();
388: ClassLoader oldLoader = thread.getContextClassLoader();
389:
390: try {
391: thread.setContextClassLoader(getParentClassLoader());
392:
393: HostController mergedController = new HostController(
394: newController.getHostName(),
395: getRootDirectory(), _container);
396:
397: mergedController.mergeController(this );
398: mergedController.mergeController(newController);
399:
400: if (!getHostName().equals(newController.getHostName())) {
401: ConfigException e;
402:
403: e = new ConfigException(
404: L
405: .l(
406: "Illegal merge of {0} and {1}. Both hosts have the same root-directory '{2}'.",
407: getHostName(),
408: newController.getHostName(),
409: getRootDirectory()));
410:
411: log.warning(e.getMessage());
412: log.log(Level.FINEST, e.toString(), e);
413:
414: mergedController.setConfigException(e);
415: }
416:
417: return mergedController;
418: } catch (Throwable e) {
419: log.log(Level.FINE, e.toString(), e);
420:
421: return null;
422: } finally {
423: thread.setContextClassLoader(oldLoader);
424: }
425: }
426: }
427:
428: /**
429: * Merges with the old controller.
430: */
431: protected void mergeController(DeployController oldControllerV) {
432: super .mergeController(oldControllerV);
433:
434: HostController oldController = (HostController) oldControllerV;
435:
436: _entryHostAliases.addAll(oldController._entryHostAliases);
437: if (!oldController.getHostName().equals(""))
438: _entryHostAliases.add(oldController.getHostName());
439: _entryHostAliasRegexps
440: .addAll(oldController._entryHostAliasRegexps);
441: _hostAliases.addAll(oldController._hostAliases);
442:
443: if (_regexp == null) {
444: _regexp = oldController._regexp;
445: _rootDirectoryPattern = oldController._rootDirectoryPattern;
446: }
447: }
448:
449: /**
450: * Creates a new instance of the host object.
451: */
452: protected Host instantiateDeployInstance() {
453: return new Host(_container, this , _hostName);
454: }
455:
456: /**
457: * Creates the host.
458: */
459: protected void configureInstance(Host host) throws Throwable {
460: _hostAliases.clear();
461: _hostAliases.addAll(_entryHostAliases);
462:
463: WebBeansContainer webBeans = WebBeansContainer.create();
464: //webBeans.addSingleton(_hostVar, "host", Standard.class);
465:
466: for (Map.Entry<String, Object> entry : getVariableMap()
467: .entrySet()) {
468: Object value = entry.getValue();
469:
470: if (value != null)
471: webBeans.addSingleton(value, entry.getKey(),
472: Standard.class);
473: }
474: // getVariableMap().put("host-root", getRootDirectory());
475:
476: if (_container != null) {
477: for (EarConfig config : _container.getEarDefaultList())
478: host.addEarDefault(config);
479:
480: for (WebAppConfig config : _container
481: .getWebAppDefaultList())
482: host.addWebAppDefault(config);
483: }
484:
485: super .configureInstance(host);
486: }
487:
488: protected void extendJMXContext(Map<String, String> context) {
489: context.put("Host", getMBeanId());
490: }
491:
492: /**
493: * Returns the appropriate log for debugging.
494: */
495: protected Logger getLog() {
496: return log;
497: }
498:
499: /**
500: * Returns equality.
501: */
502: public boolean equals(Object o) {
503: if (!(o instanceof HostController))
504: return false;
505:
506: HostController entry = (HostController) o;
507:
508: return _hostName.equals(entry._hostName);
509: }
510:
511: /**
512: * Returns a printable view.
513: */
514: public String toString() {
515: return "HostController[" + getName() + "]";
516: }
517:
518: /**
519: * EL variables for the host.
520: */
521: public class Var {
522: public String getName() {
523: return HostController.this .getName();
524: }
525:
526: public String getHostName() {
527: return HostController.this .getHostName();
528: }
529:
530: public String getUrl() {
531: Host host = getDeployInstance();
532:
533: if (host != null)
534: return host.getURL();
535: else if (_hostName.equals(""))
536: return "";
537: else if (_hostName.startsWith("http:")
538: || _hostName.startsWith("https:"))
539: return _hostName;
540: else
541: return "http://" + _hostName;
542: }
543:
544: public ArrayList getRegexp() {
545: return (ArrayList) getVariableMap().get("regexp");
546: }
547:
548: public Path getRoot() {
549: Host host = getDeployInstance();
550:
551: if (host != null)
552: return host.getRootDirectory();
553: else
554: return HostController.this .getRootDirectory();
555: }
556:
557: /**
558: * @deprecated
559: */
560: public Path getRootDir() {
561: return getRoot();
562: }
563:
564: /**
565: * @deprecated
566: */
567: public Path getRootDirectory() {
568: return getRoot();
569: }
570:
571: public Path getDocumentDirectory() {
572: Host host = getDeployInstance();
573:
574: if (host != null)
575: return host.getDocumentDirectory();
576: else
577: return null;
578: }
579:
580: public Path getDocDir() {
581: return getDocumentDirectory();
582: }
583:
584: public Path getWarDirectory() {
585: Host host = getDeployInstance();
586:
587: if (host != null)
588: return host.getWarDir();
589: else
590: return null;
591: }
592:
593: public Path getWarDir() {
594: return getWarDirectory();
595: }
596:
597: public Path getWarExpandDirectory() {
598: Host host = getDeployInstance();
599:
600: if (host != null)
601: return host.getWarExpandDir();
602: else
603: return null;
604: }
605:
606: public Path getWarExpandDir() {
607: return getWarExpandDirectory();
608: }
609:
610: public String toString() {
611: return "Host[" + getId() + "]";
612: }
613: }
614:
615: /**
616: * EL variables for the host, when testing for regexp identity .
617: */
618: public class TestVar {
619: private String _name;
620: private ArrayList<String> _regexp;
621:
622: TestVar(String name, ArrayList<String> regexp) {
623: _name = name;
624: _regexp = regexp;
625: }
626:
627: public String getName() {
628: return _name;
629: }
630:
631: public String getHostName() {
632: return _name;
633: }
634:
635: public ArrayList<String> getRegexp() {
636: // server/13t0
637: return _regexp;
638: }
639: }
640: }
|