001: /*
002: * ========================================================================
003: *
004: * Copyright 2001-2004 The Apache Software Foundation.
005: *
006: * Licensed under the Apache License, Version 2.0 (the "License");
007: * you may not use this file except in compliance with the License.
008: * You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing, software
013: * distributed under the License is distributed on an "AS IS" BASIS,
014: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015: * See the License for the specific language governing permissions and
016: * limitations under the License.
017: *
018: * ========================================================================
019: */
020: package org.apache.cactus.integration.ant.container.resin;
021:
022: import java.lang.reflect.Constructor;
023: import java.lang.reflect.Field;
024: import java.lang.reflect.Method;
025: import java.util.ArrayList;
026:
027: import org.apache.cactus.integration.ant.container.AbstractServerRun;
028:
029: /**
030: * Starts/stop Resin by setting up a listener socket. Supports Resin 2.0.x,
031: * 2.1.x and 3.x.
032: *
033: * @version $Id: ResinRun.java 238918 2004-04-18 12:21:50Z vmassol $
034: */
035: public class ResinRun extends AbstractServerRun {
036: /**
037: * The started Resin server class. We use <code>Object</code> instead of
038: * the Resin class so that we don't need the Resin jars in the classpath
039: * to compile this class.
040: */
041: private Object resinServer;
042:
043: /**
044: * @param theArgs the command line arguments
045: */
046: public ResinRun(String[] theArgs) {
047: super (theArgs);
048: }
049:
050: /**
051: * Entry point to start/stop the Resin server.
052: *
053: * @param theArgs the command line arguments
054: */
055: public static void main(String[] theArgs) {
056: ResinRun resin = new ResinRun(theArgs);
057:
058: resin.doRun();
059: }
060:
061: /**
062: * Start the Resin server. We use reflection so that the Resin jars do not
063: * need to be in the classpath to compile this class.
064: *
065: * @see AbstractServerRun#doStartServer
066: */
067: protected final Thread doStartServer(String[] theArgs) {
068: Thread runningThread = this ;
069:
070: try {
071: if (isResinVersion("2.0")) {
072: startResin20x(theArgs);
073: } else if (isResinVersion("2.1")) {
074: startResin21x(theArgs);
075: } else if (isResinVersion("3")) {
076: runningThread = startResin3x(theArgs);
077: } else {
078: throw new RuntimeException(
079: "Unsupported Resin version ["
080: + getResinVersion() + "]");
081: }
082: } catch (Exception e) {
083: e.printStackTrace();
084: throw new RuntimeException("Failed to start Resin server");
085: }
086:
087: return runningThread;
088: }
089:
090: /**
091: * Starts Resin 2.0.x
092: *
093: * @param theArgs the command line arguments for starting the server
094: * @throws Exception if an error happens when starting the server
095: */
096: private void startResin20x(String[] theArgs) throws Exception {
097: Class resinClass = Class
098: .forName("com.caucho.server.http.ResinServer");
099: Constructor constructor = resinClass
100: .getConstructor(new Class[] { theArgs.getClass(),
101: boolean.class });
102:
103: this .resinServer = constructor.newInstance(new Object[] {
104: theArgs, Boolean.TRUE });
105:
106: Method initMethod = this .resinServer.getClass().getMethod(
107: "init", new Class[] { boolean.class });
108:
109: initMethod.invoke(this .resinServer,
110: new Object[] { Boolean.TRUE });
111: }
112:
113: /**
114: * Starts Resin 2.1.x
115: *
116: * @param theArgs the command line arguments for starting the server
117: * @throws Exception if an error happens when starting the server
118: */
119: private void startResin21x(String[] theArgs) throws Exception {
120: Class resinClass = Class
121: .forName("com.caucho.server.http.ResinServer");
122: Constructor constructor = resinClass
123: .getConstructor(new Class[] { theArgs.getClass(),
124: boolean.class });
125:
126: this .resinServer = constructor.newInstance(new Object[] {
127: theArgs, Boolean.TRUE });
128:
129: Method initMethod = this .resinServer.getClass().getMethod(
130: "init", new Class[] { ArrayList.class });
131:
132: initMethod.invoke(this .resinServer, new Object[] { null });
133: }
134:
135: /**
136: * Starts Resin 3.x
137: *
138: * @return the thread in which the server has been started
139: * @param theArgs the command line arguments for starting the server
140: * @throws Exception if an error happens when starting the server
141: */
142: private Thread startResin3x(final String[] theArgs)
143: throws Exception {
144: // Start the server in another thread so that it doesn't block
145: // the current thread. It seems that Resin 3.x is acting differently
146: // than Resin 2.x which was not blocking and thus which did not need
147: // to be started in a separate thread.
148: Thread startThread = new Thread() {
149: public void run() {
150: try {
151: Class resinClass = Class
152: .forName("com.caucho.server.http.ResinServer");
153:
154: Method mainMethod = resinClass.getMethod("main",
155: new Class[] { String[].class });
156:
157: mainMethod.invoke(null, new Object[] { theArgs });
158: } catch (Exception e) {
159: e.printStackTrace();
160: throw new RuntimeException(
161: "Failed to start Resin 3.x. Error = ["
162: + e.getMessage() + "]");
163: }
164: }
165: };
166: startThread.start();
167:
168: return startThread;
169: }
170:
171: /**
172: * Stops the Resin server. We use reflection so that the Resin jars do not
173: * need to be in the classpath to compile this class.
174: *
175: * @see AbstractServerRun#doStopServer
176: */
177: protected final void doStopServer(String[] theArgs,
178: Thread theRunningServerThread) {
179: try {
180: if (isResinVersion("2.0")) {
181: stopResin20x(theArgs);
182: } else if (isResinVersion("2.1")) {
183: stopResin20x(theArgs);
184: } else if (isResinVersion("3")) {
185: stopResin3x(theArgs, theRunningServerThread);
186: } else {
187: throw new RuntimeException(
188: "Unsupported Resin version ["
189: + getResinVersion() + "]");
190: }
191: } catch (Exception e) {
192: e.printStackTrace();
193: throw new RuntimeException(
194: "Failed to stop the running Resin server");
195: }
196: }
197:
198: /**
199: * Stops Resin 2.0.x and 2.1.x versions.
200: *
201: * @param theArgs the command line arguments for starting the server
202: * @throws Exception if an error happens when starting the server
203: */
204: private void stopResin20x(String[] theArgs) throws Exception {
205: Method closeMethod = this .resinServer.getClass().getMethod(
206: "close", null);
207:
208: closeMethod.invoke(this .resinServer, null);
209: }
210:
211: /**
212: * Stops Resin 3.x.
213: *
214: * @param theArgs the command line arguments for starting the server
215: * @param theRunningServerThread the thread in which the server is running
216: * @throws Exception if an error happens when starting the server
217: */
218: private void stopResin3x(String[] theArgs,
219: Thread theRunningServerThread) throws Exception {
220: // As we don't know how to properly stop a running Resin server,
221: // we simply try to kill the thread in which it is running.
222: // Not clean...
223: theRunningServerThread.stop();
224: }
225:
226: /**
227: * @return the Resin version
228: */
229: private String getResinVersion() {
230: String version;
231:
232: try {
233: Class versionClass = Class.forName("com.caucho.Version");
234: Field versionField = versionClass.getField("VERSION");
235: version = (String) versionField.get(null);
236: } catch (Exception e) {
237: throw new RuntimeException(
238: "Cannot get Resin version. Error = ["
239: + e.getMessage() + "]");
240: }
241:
242: return version;
243: }
244:
245: /**
246: * @param theVersionPrefix the version prefix to test for
247: * @return true if the Resin version starts with versionPrefix
248: */
249: private boolean isResinVersion(String theVersionPrefix) {
250: return getResinVersion().startsWith(theVersionPrefix);
251: }
252: }
|