001: /*
002: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright
003: * notice. All rights reserved.
004: */
005: package com.tc.test.server.appserver.cargo;
006:
007: import org.apache.tools.ant.BuildException;
008: import org.apache.tools.ant.Location;
009: import org.apache.tools.ant.Project;
010: import org.apache.tools.ant.RuntimeConfigurable;
011: import org.apache.tools.ant.Target;
012: import org.apache.tools.ant.taskdefs.Java;
013: import org.apache.tools.ant.types.CommandlineJava;
014: import org.apache.tools.ant.types.Environment;
015: import org.apache.tools.ant.types.Path;
016: import org.apache.tools.ant.types.Reference;
017: import org.apache.tools.ant.types.Commandline.Argument;
018: import org.apache.tools.ant.types.Environment.Variable;
019:
020: import com.tc.test.TestConfigObject;
021:
022: import java.io.File;
023: import java.io.IOException;
024: import java.lang.reflect.Field;
025: import java.util.ArrayList;
026: import java.util.Iterator;
027: import java.util.List;
028: import java.util.jar.Attributes;
029: import java.util.jar.JarFile;
030: import java.util.jar.Manifest;
031:
032: /**
033: * This class is used in the process of patching CARGO to allow it's child processes to know whether the parent process
034: * is still alive and kill themselves off if need be. It is a decorator for the ANT Java task which calls
035: * {@link CargoLinkedChildProcess} which in turn spawns the desired appserver instance.
036: */
037: public final class CargoJava extends Java {
038:
039: private static final boolean DEBUG = false;
040:
041: // this static thing is TERRIBLE, but trying to get tigher integration with Cargo is worse
042: public static final Link LINK = new Link();
043:
044: private Java java;
045: private Path classpath;
046: private String className;
047: private List args;
048: private boolean dirSet = false;
049:
050: public CargoJava(Java java) {
051: this .java = java;
052: this .args = new ArrayList();
053: }
054:
055: private void wrapProcess() {
056: Args linkArgs;
057: try {
058: linkArgs = Link.take();
059: } catch (InterruptedException e) {
060: throw new RuntimeException(e);
061: }
062:
063: File dir = linkArgs.instancePath;
064:
065: String logFile = new File(dir.getParent(), dir.getName()
066: + ".log").getAbsolutePath();
067:
068: if (!dirSet) {
069: setDir(dir);
070: }
071:
072: java.setOutput(new File(logFile));
073: java.setAppend(true);
074: java.setFailonerror(true);
075:
076: assignWrappedArgs(linkArgs);
077: TestConfigObject config = TestConfigObject.getInstance();
078: classpath.setPath(classpath.toString() + File.pathSeparatorChar
079: + config.linkedChildProcessClasspath());
080: java.setClassname(CargoLinkedChildProcess.class.getName());
081: // java.setMaxmemory("128m");
082: Environment.Variable envVar = new Environment.Variable();
083: envVar.setKey("JAVA_HOME");
084: envVar.setValue(System.getProperty("java.home"));
085: java.addEnv(envVar);
086: // Argument argument = java.createJvmarg();
087: // argument.setValue("-verbose:gc");
088:
089: if (DEBUG) {
090: CommandlineJava cmdLineJava = getCommandLine(this .java);
091: System.err.println(cmdLineJava.describeCommand());
092: }
093:
094: java.createJvmarg().setValue("-DNODE=" + dir.getName());
095:
096: java.execute();
097: }
098:
099: private static CommandlineJava getCommandLine(Java j) {
100: // more utter gross-ness
101: try {
102: Field f = j.getClass().getDeclaredField("cmdl");
103: f.setAccessible(true);
104: return (CommandlineJava) f.get(j);
105: } catch (Exception e) {
106: throw new RuntimeException(e);
107: }
108: }
109:
110: private void assignWrappedArgs(Args linkArgs) {
111: java.clearArgs();
112: java.createArg().setValue(this .className);
113: java.createArg().setValue(Integer.toString(linkArgs.port));
114: java.createArg().setValue(
115: linkArgs.instancePath.getAbsolutePath());
116:
117: Iterator iter = this .args.iterator();
118: while (iter.hasNext()) {
119: String[] parts = ((Argument) iter.next()).getParts();
120: for (int i = 0; i < parts.length; ++i)
121: java.createArg().setValue(parts[i]);
122: }
123: }
124:
125: public void addEnv(Variable arg0) {
126: this .java.addEnv(arg0);
127: }
128:
129: public void addSysproperty(Variable arg0) {
130: this .java.addSysproperty(arg0);
131: }
132:
133: public void clearArgs() {
134: this .java.clearArgs();
135: }
136:
137: public Argument createArg() {
138: Argument out = this .java.createArg();
139: this .args.add(out);
140: return out;
141: }
142:
143: public Path createClasspath() {
144: Path path = this .java.createClasspath();
145: this .classpath = path;
146: return path;
147: }
148:
149: public Argument createJvmarg() {
150: return this .java.createJvmarg();
151: }
152:
153: public boolean equals(Object obj) {
154: return this .java.equals(obj);
155: }
156:
157: public void execute() throws BuildException {
158: wrapProcess();
159: }
160:
161: public int executeJava() throws BuildException {
162: return this .java.executeJava();
163: }
164:
165: public String getDescription() {
166: return this .java.getDescription();
167: }
168:
169: public Location getLocation() {
170: return this .java.getLocation();
171: }
172:
173: public Target getOwningTarget() {
174: return this .java.getOwningTarget();
175: }
176:
177: public Project getProject() {
178: return this .java.getProject();
179: }
180:
181: public RuntimeConfigurable getRuntimeConfigurableWrapper() {
182: return this .java.getRuntimeConfigurableWrapper();
183: }
184:
185: public String getTaskName() {
186: return this .java.getTaskName();
187: }
188:
189: public int hashCode() {
190: return this .java.hashCode();
191: }
192:
193: public void init() throws BuildException {
194: this .java.init();
195: }
196:
197: public void log(String arg0, int arg1) {
198: this .java.log(arg0, arg1);
199: }
200:
201: public void log(String arg0) {
202: this .java.log(arg0);
203: }
204:
205: public void maybeConfigure() throws BuildException {
206: this .java.maybeConfigure();
207: }
208:
209: public void setAppend(boolean arg0) {
210: this .java.setAppend(arg0);
211: }
212:
213: public void setArgs(String arg0) {
214: this .java.setArgs(arg0);
215: }
216:
217: public void setClassname(String arg0) throws BuildException {
218: this .className = arg0;
219: this .java.setClassname(arg0);
220: }
221:
222: public void setClasspath(Path arg0) {
223: this .java.setClasspath(arg0);
224: }
225:
226: public void setClasspathRef(Reference arg0) {
227: this .java.setClasspathRef(arg0);
228: }
229:
230: public void setDescription(String arg0) {
231: this .java.setDescription(arg0);
232: }
233:
234: public void setDir(File arg0) {
235: this .java.setDir(arg0);
236: dirSet = true;
237: }
238:
239: public void setFailonerror(boolean arg0) {
240: this .java.setFailonerror(arg0);
241: }
242:
243: public void setFork(boolean arg0) {
244: this .java.setFork(arg0);
245: }
246:
247: public void setJar(File arg0) throws BuildException {
248: try {
249: String absPath = arg0.getCanonicalFile().getParentFile()
250: .getParent();
251: JarFile jar = new JarFile(arg0);
252: Manifest manifest = jar.getManifest();
253: Attributes attrib = manifest.getMainAttributes();
254:
255: String classPathAttrib = attrib.getValue("Class-Path");
256: String absClassPath = classPathAttrib.replaceAll("^\\.\\.",
257: absPath).replaceAll("\\s\\.\\.",
258: File.pathSeparatorChar + absPath);
259: this .classpath.setPath(classpath.toString()
260: + File.pathSeparatorChar + absClassPath);
261: this .classpath.setPath(classpath.toString()
262: + File.pathSeparator + arg0);
263:
264: // TODO: make sysprops
265: // this.classpath.setPath(classpath.toString() + createExtraManifestClassPath("Endorsed-Dirs", attrib, absPath));
266: // this.classpath.setPath(classpath.toString() + createExtraManifestClassPath("Extension-Dirs", attrib, absPath));
267:
268: setClassname(attrib.getValue("Main-Class"));
269:
270: } catch (IOException ioe) {
271: throw new BuildException("problem reading manifest");
272: }
273: }
274:
275: // private String createExtraManifestClassPath(String attributeName, Attributes attrib, String absPath) {
276: // String extraDirAttrib = attrib.getValue(attributeName);
277: // File absExtraDir = new File(absPath + File.separator + extraDirAttrib);
278: // String[] extraJars = absExtraDir.list(new FilenameFilter() {
279: // public boolean accept(File dir, String name) {
280: // return (name.endsWith(".jar")) ? true : false;
281: // }
282: // });
283: // String extraClassPath = "";
284: // for (int i = 0; i < extraJars.length; i++) {
285: // extraClassPath += File.pathSeparatorChar + absExtraDir.toString() + File.separator + extraJars[i];
286: // }
287: // return extraClassPath;
288: // }
289:
290: public void setJvm(String arg0) {
291: this .java.setJvm(arg0);
292: }
293:
294: public void setJvmargs(String arg0) {
295: this .java.setJvmargs(arg0);
296: }
297:
298: public void setJVMVersion(String arg0) {
299: this .java.setJVMVersion(arg0);
300: }
301:
302: public void setLocation(Location arg0) {
303: this .java.setLocation(arg0);
304: }
305:
306: public void setMaxmemory(String arg0) {
307: this .java.setMaxmemory(arg0);
308: }
309:
310: public void setNewenvironment(boolean arg0) {
311: this .java.setNewenvironment(arg0);
312: }
313:
314: public void setOutput(File arg0) {
315: this .java.setOutput(arg0);
316: }
317:
318: public void setOwningTarget(Target arg0) {
319: this .java.setOwningTarget(arg0);
320: }
321:
322: public void setProject(Project arg0) {
323: this .java.setProject(arg0);
324: }
325:
326: public void setRuntimeConfigurableWrapper(RuntimeConfigurable arg0) {
327: this .java.setRuntimeConfigurableWrapper(arg0);
328: }
329:
330: public void setTaskName(String arg0) {
331: this .java.setTaskName(arg0);
332: }
333:
334: public void setTimeout(Long arg0) {
335: this .java.setTimeout(arg0);
336: }
337:
338: public String toString() {
339: return this .java.toString();
340: }
341:
342: public static class Args {
343: final File instancePath;
344: final int port;
345:
346: public Args(int port, File instancePath) {
347: this .port = port;
348: this .instancePath = instancePath;
349: }
350: }
351:
352: public static class Link {
353: private static Args args = null;
354: private static final Object lock = new Object();
355:
356: public static Args take() throws InterruptedException {
357: synchronized (lock) {
358: while (args == null) {
359: lock.wait();
360: }
361: Args rv = args;
362: args = null;
363: lock.notifyAll();
364: return rv;
365: }
366: }
367:
368: public static void put(Args putArgs)
369: throws InterruptedException {
370: synchronized (lock) {
371: while (args != null) {
372: lock.wait();
373: }
374:
375: args = putArgs;
376: lock.notifyAll();
377: }
378: }
379: }
380:
381: }
|