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.boot;
031:
032: import com.caucho.config.*;
033: import com.caucho.config.program.*;
034: import com.caucho.server.admin.HessianHmuxProxy;
035: import com.caucho.util.*;
036: import com.caucho.Version;
037: import com.caucho.vfs.Path;
038: import com.caucho.vfs.Vfs;
039:
040: import java.io.File;
041: import java.io.IOException;
042: import java.io.InputStream;
043: import java.io.OutputStream;
044: import java.lang.reflect.*;
045: import java.net.*;
046: import java.util.ArrayList;
047: import java.util.HashMap;
048: import java.util.Map;
049: import java.util.logging.Level;
050: import java.util.logging.Logger;
051:
052: /**
053: * Client to a watchdog-manager, i.e. ResinBoot code to ask the
054: * watchdog-manager to do something.
055: */
056: public class WatchdogClient {
057: private static final L10N L = new L10N(WatchdogClient.class);
058: private static final Logger log = Logger
059: .getLogger(WatchdogClient.class.getName());
060:
061: private final BootManager _bootManager;
062: private String _id = "";
063:
064: private WatchdogConfig _config;
065: private Watchdog _watchdog;
066:
067: private Boot _jniBoot;
068:
069: WatchdogClient(BootManager bootManager, WatchdogConfig config) {
070: _bootManager = bootManager;
071: _config = config;
072: _id = config.getId();
073: }
074:
075: public String getId() {
076: return _id;
077: }
078:
079: public String getAdminCookie() {
080: return _bootManager.getAdminCookie();
081: }
082:
083: public int getWatchdogPort() {
084: return _config.getWatchdogPort();
085: }
086:
087: String[] getArgv() {
088: return _config.getArgv();
089: }
090:
091: Path getPwd() {
092: return _config.getPwd();
093: }
094:
095: Path getResinHome() {
096: return _bootManager.getResinHome();
097: }
098:
099: Path getRootDirectory() {
100: return _bootManager.getRootDirectory();
101: }
102:
103: boolean hasXmx() {
104: return _config.hasXmx();
105: }
106:
107: boolean hasXss() {
108: return _config.hasXss();
109: }
110:
111: boolean is64bit() {
112: return _config.is64bit();
113: }
114:
115: boolean isVerbose() {
116: return _config.isVerbose();
117: }
118:
119: public String getGroupName() {
120: return _config.getGroupName();
121: }
122:
123: public String getUserName() {
124: return _config.getUserName();
125: }
126:
127: public Path getLogDirectory() {
128: return _bootManager.getLogDirectory();
129: }
130:
131: public long getShutdownWaitTime() {
132: return _config.getShutdownWaitTime();
133: }
134:
135: public String statusWatchdog() throws IOException {
136: WatchdogAPI watchdog = getProxy();
137:
138: try {
139: return watchdog.status(getAdminCookie());
140: } catch (ConfigException e) {
141: throw e;
142: } catch (IllegalStateException e) {
143: throw e;
144: } catch (Exception e) {
145: Throwable e1 = e;
146:
147: while (e1.getCause() != null)
148: e1 = e1.getCause();
149:
150: log.log(Level.FINE, e.toString(), e);
151:
152: return e1.toString();
153: }
154: }
155:
156: public void startWatchdog(String[] argv) throws ConfigException,
157: IOException {
158: if (getUserName() != null && !hasBoot()) {
159: throw new ConfigException(
160: L
161: .l("<user-name> requires Resin Professional and compiled JNI. Check the $RESIN_HOME/libexec or $RESIN_HOME/libexec64 directory for libresin.so and check for a valid license in $RESIN_HOME/licenses."));
162: }
163:
164: if (getGroupName() != null && !hasBoot()) {
165: throw new ConfigException(
166: L
167: .l("<group-name> requires Resin Professional and compiled JNI. Check the $RESIN_HOME/libexec or $RESIN_HOME/libexec64 directory for libresin.so and check for a valid license in $RESIN_HOME/licenses."));
168: }
169:
170: WatchdogAPI watchdog = getProxy();
171:
172: try {
173: watchdog.start(getAdminCookie(), argv);
174:
175: return;
176: } catch (ConfigException e) {
177: throw e;
178: } catch (IllegalStateException e) {
179: throw e;
180: } catch (ConnectException e) {
181: log.log(Level.FINER, e.toString(), e);
182: } catch (Exception e) {
183: log.log(Level.FINE, e.toString(), e);
184: }
185:
186: launchManager(argv);
187: }
188:
189: public void stopWatchdog() throws IOException {
190: WatchdogAPI watchdog = getProxy();
191:
192: try {
193: watchdog.stop(getAdminCookie(), getId());
194: } catch (ConfigException e) {
195: throw e;
196: } catch (IllegalStateException e) {
197: throw e;
198: } catch (IOException e) {
199: throw new IllegalStateException(L.l(
200: "Can't connect to ResinWatchdogManager.\n{1}",
201: Version.VERSION, e.toString()), e);
202: } catch (Exception e) {
203: log.log(Level.FINE, e.toString(), e);
204: }
205: }
206:
207: public void killWatchdog() throws IOException {
208: WatchdogAPI watchdog = getProxy();
209:
210: try {
211: watchdog.kill(getAdminCookie(), getId());
212: } catch (ConfigException e) {
213: throw e;
214: } catch (IllegalStateException e) {
215: throw e;
216: } catch (IOException e) {
217: throw new IllegalStateException(L.l(
218: "Can't connect to ResinWatchdogManager.\n{1}",
219: Version.VERSION, e.toString()), e);
220: } catch (Exception e) {
221: log.log(Level.FINE, e.toString(), e);
222: }
223: }
224:
225: public void restartWatchdog(String[] argv) throws IOException {
226: try {
227: stopWatchdog();
228: } catch (Exception e) {
229: log.log(Level.FINE, e.toString(), e);
230: }
231:
232: startWatchdog(argv);
233: }
234:
235: public int startSingle() throws IOException {
236: if (_watchdog == null)
237: _watchdog = new Watchdog(_config);
238:
239: return _watchdog.startSingle();
240: }
241:
242: public boolean shutdown() throws IOException {
243: WatchdogAPI watchdog = getProxy();
244:
245: try {
246: return watchdog.shutdown(getAdminCookie());
247: } catch (ConfigException e) {
248: throw e;
249: } catch (IllegalStateException e) {
250: throw e;
251: } catch (IOException e) {
252: throw new IllegalStateException(L.l(
253: "Can't connect to ResinWatchdogManager.\n{1}",
254: Version.VERSION, e.toString()), e);
255: } catch (Exception e) {
256: log.log(Level.FINE, e.toString(), e);
257:
258: return false;
259: }
260: }
261:
262: private WatchdogAPI getProxy() {
263: String url = ("hmux://127.0.0.1:" + getWatchdogPort() + "/watchdog");
264:
265: HashMap<String, Object> attr = new HashMap<String, Object>();
266: attr.put("host", "resin-admin");
267:
268: Path path = Vfs.lookup(url, attr);
269:
270: return HessianHmuxProxy.create(path, WatchdogAPI.class);
271: }
272:
273: public void launchManager(String[] argv) throws IOException {
274: log.fine(this + " starting ResinWatchdogManager");
275:
276: Path resinHome = getResinHome();
277: Path resinRoot = getRootDirectory();
278:
279: ProcessBuilder builder = new ProcessBuilder();
280:
281: builder.directory(new File(resinRoot.getNativePath()));
282:
283: Map<String, String> env = builder.environment();
284:
285: env.putAll(System.getenv());
286:
287: String classPath = WatchdogArgs.calculateClassPath(resinHome);
288:
289: env.put("CLASSPATH", classPath);
290:
291: String ldLibraryPath = env.get("LD_LIBRARY_PATH");
292: String dyldLibraryPath = env.get("DYLD_LIBRARY_PATH");
293:
294: String libexecPath;
295:
296: if (is64bit())
297: libexecPath = resinHome.lookup("libexec64").getNativePath();
298: else
299: libexecPath = resinHome.lookup("libexec").getNativePath();
300:
301: if (ldLibraryPath == null || "".equals(ldLibraryPath))
302: ldLibraryPath += libexecPath;
303: else if (ldLibraryPath.indexOf(libexecPath) < 0)
304: ldLibraryPath += File.pathSeparatorChar + libexecPath;
305:
306: if (dyldLibraryPath == null || "".equals(dyldLibraryPath))
307: dyldLibraryPath += libexecPath;
308: else if (ldLibraryPath.indexOf(libexecPath) < 0)
309: dyldLibraryPath += File.pathSeparatorChar + libexecPath;
310:
311: env.put("LD_LIBRARY_PATH", ldLibraryPath);
312: env.put("DYLD_LIBRARY_PATH", dyldLibraryPath);
313:
314: ArrayList<String> list = new ArrayList<String>();
315:
316: list.add(_config.getJavaExe());
317: list
318: .add("-Djava.util.logging.manager=com.caucho.log.LogManagerImpl");
319: list
320: .add("-Djavax.management.builder.initial=com.caucho.jmx.MBeanServerBuilderImpl");
321: list.add("-Djava.awt.headless=true");
322: list.add("-Dresin.home=" + resinHome.getPath());
323: list.add("-Dresin.root=" + resinRoot.getPath());
324:
325: for (int i = 0; i < argv.length; i++) {
326: if (argv[i].startsWith("-Djava.class.path=")) {
327: // IBM JDK startup issues
328: } else if (argv[i].startsWith("-J")) {
329: list.add(argv[i].substring(2));
330: }
331: }
332:
333: if (!_config.hasWatchdogXss())
334: list.add("-Xss256k");
335: if (!_config.hasWatchdogXmx())
336: list.add("-Xmx32m");
337:
338: list.addAll(_config.getWatchdogJvmArgs());
339:
340: if (!list.contains("-d32") && !list.contains("-d64")
341: && is64bit())
342: list.add("-d64");
343:
344: list.add("com.caucho.boot.WatchdogManager");
345:
346: for (int i = 0; i < argv.length; i++) {
347: if (argv[i].equals("-conf") || argv[i].equals("--conf")) {
348: list.add(argv[i]);
349: list.add(resinHome.lookup(argv[i + 1]).getNativePath());
350: i++;
351: } else
352: list.add(argv[i]);
353: }
354:
355: builder = builder.command(list);
356:
357: builder.redirectErrorStream(true);
358:
359: Process process = builder.start();
360:
361: InputStream stdIs = process.getInputStream();
362: OutputStream stdOs = process.getOutputStream();
363:
364: stdIs.close();
365: stdOs.close();
366: }
367:
368: @Override
369: public String toString() {
370: return getClass().getSimpleName() + "[" + getId() + "]";
371: }
372:
373: Boot getJniBoot() {
374: if (_jniBoot != null)
375: return _jniBoot.isValid() ? _jniBoot : null;
376:
377: try {
378: ClassLoader loader = Thread.currentThread()
379: .getContextClassLoader();
380:
381: Class cl = Class.forName("com.caucho.boot.JniBoot", false,
382: loader);
383:
384: _jniBoot = (Boot) cl.newInstance();
385: } catch (ClassNotFoundException e) {
386: log.fine(e.toString());
387: } catch (IllegalStateException e) {
388: log.fine(e.toString());
389: } catch (Throwable e) {
390: log.log(Level.FINE, e.toString(), e);
391: }
392:
393: return _jniBoot != null && _jniBoot.isValid() ? _jniBoot : null;
394: }
395:
396: private boolean hasBoot() {
397: try {
398: Boot boot = getJniBoot();
399:
400: return boot.isValid();
401: } catch (Throwable e) {
402: log.log(Level.FINE, e.toString(), e);
403: }
404:
405: return false;
406: }
407: }
|