Source Code Cross Referenced for ProcessStarter.java in  » Aspect-oriented » aspectwerkz-2.0 » org » codehaus » aspectwerkz » hook » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Aspect oriented » aspectwerkz 2.0 » org.codehaus.aspectwerkz.hook 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /**************************************************************************************
002:         * Copyright (c) Jonas BonŽr, Alexandre Vasseur. All rights reserved.                 *
003:         * http://aspectwerkz.codehaus.org                                                    *
004:         * ---------------------------------------------------------------------------------- *
005:         * The software in this package is published under the terms of the LGPL license      *
006:         * a copy of which has been included with this distribution in the license.txt file.  *
007:         **************************************************************************************/package org.codehaus.aspectwerkz.hook;
008:
009:        import com.sun.jdi.VirtualMachine;
010:
011:        import java.io.File;
012:        import java.io.IOException;
013:        import java.util.StringTokenizer;
014:
015:        /**
016:         * ProcessStarter uses JPDA JDI api to start a VM with a runtime modified java.lang.ClassLoader, or transparently use a
017:         * Xbootclasspath style (java 1.3 detected or forced) <p/>
018:         * <p/>
019:         * <h2>Important note</h2>
020:         * Due to a JPDA issue in LauchingConnector, this implementation is based on Process forking. If Xbootclasspath is not
021:         * used the target VM is started with JDWP options <i>transport=dt_socket,address=9300 </i> unless other specified.
022:         * <br/>It is possible after the short startup sequence to attach a debugger or any other JPDA attaching connector. It
023:         * has been validated against a WebLogic 7 startup and is the <i>must use </i> implementation.
024:         * </p>
025:         * <p/>
026:         * <p/>
027:         * <h2>Implementation Note</h2>
028:         * See http://java.sun.com/products/jpda/ <br/>See http://java.sun.com/j2se/1.4.1/docs/guide/jpda/jdi/index.html <br/>
029:         * </p>
030:         * <p/><p/>For java 1.3, it launch the target VM using a modified java.lang.ClassLoader by generating it and putting it
031:         * in the bootstrap classpath of the target VM. The java 1.3 version should only be run for experimentation since it
032:         * breaks the Java 2 Runtime Environment binary code license by overriding a class of rt.jar
033:         * </p>
034:         * <p/><p/>For java 1.4, it hotswaps java.lang.ClassLoader with a runtime patched version, wich is compatible with the
035:         * Java 2 Runtime Environment binary code license. For JVM not supporting the class hotswapping, the same mechanism as
036:         * for java 1.3 is used.
037:         * </p>
038:         * <p/>
039:         * <p/>
040:         * <h2>Usage</h2>
041:         * Use it as a replacement of "java" :<br/><code>java [target jvm option] [target classpath]
042:         * targetMainClass [targetMainClass args]</code>
043:         * <br/>should be called like: <br/><code>java [jvm option] [classpath]
044:         * org.codehaus.aspectwerkz.hook.ProcessStarter [target jvm option] [target classpath] targetMainClass [targetMainClass
045:         * args]</code>
046:         * <br/><b>[classpath] must contain %JAVA_HOME%/tools.jar for HotSwap support </b> <br/>[target jvm option] can contain
047:         * JDWP options, transport and address are preserved if specified.
048:         * </p>
049:         * <p/>
050:         * <p/>
051:         * <h2>Options</h2>
052:         * [classpath] must contain %JAVA_HOME%/tools.jar and the jar you want for bytecode modification (asm, bcel, ...)
053:         * <br/>The java.lang.ClassLoader is patched using the <code>-Daspectwerkz.classloader.clpreprocessor=...</code> in
054:         * [jvm option]. Specify the FQN of your implementation of hook.ClassLoaderPreProcessor. See {@link
055:         * org.codehaus.aspectwerkz.hook.ClassLoaderPreProcessor} If not given, the default AspectWerkz layer 1 ASM
056:         * implementation hook.impl.* is used, which is equivalent to
057:         * <code>-Daspectwerkz.classloader.clpreprocessor=org.codehaus.aspectwerkz.hook.impl.ClassLoaderPreProcessorImpl</code>
058:         * <br/>Use -Daspectwerkz.classloader.wait=2 in [jvm option] to force a pause of 2 seconds between process fork and JPDA
059:         * connection for HotSwap. Defaults to no wait.
060:         * </p>
061:         * <p/>
062:         * <p/>
063:         * <h2>Disabling HotSwap</h2>
064:         * You disable HotSwap and thus force the use of -Xbootclasspath (like in java 1.3 mode) and specify the directory where
065:         * the modified class loader bytecode will be stored using in [jvm option]
066:         * <code>-Daspectwerkz.classloader.clbootclasspath=...</code>. Specify the directory where you want the patched
067:         * java.lang.ClassLoader to be stored. Default is "./_boot". The directory is created if needed (with the subdirectories
068:         * corresponding to package names). <br/>The directory is <b>automatically </b> incorporated in the -Xbootclasspath
069:         * option of [target jvm option]. <br/>You shoud use this option mainly for debuging purpose, or if you need to start
070:         * different jvm with different classloader preprocessor implementations.
071:         * </p>
072:         * <p/>
073:         * <p/>
074:         * <h2>Option for AspectWerkz layer 1 ASM implementation</h2>
075:         * When using the default AspectWerkz layer 1 ASM implementation
076:         * <code>org.codehaus.aspectwerkz.hook.impl.ClassLoaderPreProcessorImpl</code>, java.lang.ClassLoader is modified to
077:         * call a class preprocessor at each class load (except for class loaded by the bootstrap classloader). <br/>The
078:         * effective class preprocessor is defined with <code>-Daspectwerkz.classloader.preprocessor=...</code> in [target jvm
079:         * option]. Specify the FQN of your implementation of org.codehaus.aspectwerkz.hook.ClassPreProcessor interface. <br/>If
080:         * this parameter is not given, the default AspectWerkz layer 2
081:         * org.codehaus.aspectwerkz.transform.AspectWerkzPreProcessor is used. <br/>
082:         * </p>
083:         *
084:         * @author <a href="mailto:alex@gnilux.com">Alexandre Vasseur </a>
085:         */
086:        public class ProcessStarter {
087:            /**
088:             * option for classloader preprocessor target
089:             */
090:            final static String CL_PRE_PROCESSOR_CLASSNAME_PROPERTY = "aspectwerkz.classloader.clpreprocessor";
091:
092:            /**
093:             * default dir when -Xbootclasspath is forced or used (java 1.3)
094:             */
095:            private final static String CL_BOOTCLASSPATH_FORCE_DEFAULT = "."
096:                    + File.separatorChar + "_boot";
097:
098:            /**
099:             * option for target dir when -Xbootclasspath is forced or used (java 1.3)
100:             */
101:            private final static String CL_BOOTCLASSPATH_FORCE_PROPERTY = "aspectwerkz.classloader.clbootclasspath";
102:
103:            /**
104:             * option for seconds to wait before connecting
105:             */
106:            private final static String CONNECTION_WAIT_PROPERTY = "aspectwerkz.classloader.wait";
107:
108:            /**
109:             * target process
110:             */
111:            private Process process = null;
112:
113:            /**
114:             * used if target VM exits before launching VM
115:             */
116:            private boolean executeShutdownHook = true;
117:
118:            /**
119:             * thread to redirect streams of target VM in launching VM
120:             */
121:            private Thread inThread;
122:
123:            /**
124:             * thread to redirect streams of target VM in launching VM
125:             */
126:            private Thread outThread;
127:
128:            /**
129:             * thread to redirect streams of target VM in launching VM
130:             */
131:            private Thread errThread;
132:
133:            /**
134:             * Test if current java installation supports HotSwap
135:             */
136:            private static boolean hasCanRedefineClass() {
137:                try {
138:                    VirtualMachine.class.getMethod("canRedefineClasses",
139:                            new Class[] {});
140:                } catch (NoSuchMethodException e) {
141:                    return false;
142:                }
143:                return true;
144:            }
145:
146:            private int run(String[] args) {
147:                // retrieve options and main
148:                String[] javaArgs = parseJavaCommandLine(args);
149:                String optionArgs = javaArgs[0];
150:                String cpArgs = javaArgs[1];
151:                String mainArgs = javaArgs[2];
152:                String options = optionArgs + " -cp " + cpArgs;
153:                String clp = System
154:                        .getProperty(CL_PRE_PROCESSOR_CLASSNAME_PROPERTY,
155:                                "org.codehaus.aspectwerkz.hook.impl.ClassLoaderPreProcessorImpl");
156:
157:                // if java version does not support method "VirtualMachine.canRedefineClass"
158:                // or if bootclasspath is forced, transform optionsArg
159:                if (!hasCanRedefineClass()
160:                        || (System.getProperty(CL_BOOTCLASSPATH_FORCE_PROPERTY) != null)) {
161:                    String bootDir = System.getProperty(
162:                            CL_BOOTCLASSPATH_FORCE_PROPERTY,
163:                            CL_BOOTCLASSPATH_FORCE_DEFAULT);
164:                    if (System.getProperty(CL_BOOTCLASSPATH_FORCE_PROPERTY) != null) {
165:                        System.out
166:                                .println("HotSwap deactivated, using bootclasspath: "
167:                                        + bootDir);
168:                    } else {
169:                        System.out
170:                                .println("HotSwap not supported by this java version, using bootclasspath: "
171:                                        + bootDir);
172:                    }
173:                    ClassLoaderPatcher.patchClassLoader(clp, bootDir);
174:                    BootClasspathStarter starter = new BootClasspathStarter(
175:                            options, mainArgs, bootDir);
176:                    try {
177:                        process = starter.launchVM();
178:                    } catch (IOException e) {
179:                        System.err.println("failed to launch process :"
180:                                + starter.getCommandLine());
181:                        e.printStackTrace();
182:                        return -1;
183:                    }
184:
185:                    // attach stdout VM streams to this streams
186:                    // this is needed early to support -verbose:class like options
187:                    redirectStdoutStreams();
188:                } else {
189:                    // lauch VM in suspend mode
190:                    JDWPStarter starter = new JDWPStarter(options, mainArgs,
191:                            "dt_socket", "9300");
192:                    try {
193:                        process = starter.launchVM();
194:                    } catch (IOException e) {
195:                        System.err.println("failed to launch process :"
196:                                + starter.getCommandLine());
197:                        e.printStackTrace();
198:                        return -1;
199:                    }
200:
201:                    // attach stdout VM streams to this streams
202:                    // this is needed early to support -verbose:class like options
203:                    redirectStdoutStreams();
204:
205:                    // override class loader in VM thru an attaching connector
206:                    int secondsToWait = 0;
207:                    try {
208:                        secondsToWait = Integer.parseInt(System.getProperty(
209:                                CONNECTION_WAIT_PROPERTY, "0"));
210:                    } catch (NumberFormatException nfe) {
211:                        ;
212:                    }
213:                    VirtualMachine vm = ClassLoaderPatcher.hotswapClassLoader(
214:                            clp, starter.getTransport(), starter.getAddress(),
215:                            secondsToWait);
216:                    if (vm == null) {
217:                        process.destroy();
218:                    } else {
219:                        vm.resume();
220:                        vm.dispose();
221:                    }
222:                }
223:
224:                // attach VM other streams to this streams
225:                redirectOtherStreams();
226:
227:                // add a shutdown hook to "this" to shutdown VM
228:                Thread shutdownHook = new Thread() {
229:                    public void run() {
230:                        shutdown();
231:                    }
232:                };
233:                try {
234:                    Runtime.getRuntime().addShutdownHook(shutdownHook);
235:                    int exitCode = process.waitFor();
236:                    executeShutdownHook = false;
237:                    return exitCode;
238:                } catch (Exception e) {
239:                    executeShutdownHook = false;
240:                    e.printStackTrace();
241:                    return -1;
242:                }
243:            }
244:
245:            /**
246:             * shutdown target VM (used by shutdown hook of lauching VM)
247:             */
248:            private void shutdown() {
249:                if (executeShutdownHook) {
250:                    process.destroy();
251:                }
252:                try {
253:                    outThread.join();
254:                    errThread.join();
255:                } catch (InterruptedException e) {
256:                    ;
257:                }
258:            }
259:
260:            /**
261:             * Set up stream redirection in target VM for stdout
262:             */
263:            private void redirectStdoutStreams() {
264:                outThread = new StreamRedirectThread("out.redirect", process
265:                        .getInputStream(), System.out);
266:                outThread.start();
267:            }
268:
269:            /**
270:             * Set up stream redirection in target VM for stderr and stdin
271:             */
272:            private void redirectOtherStreams() {
273:                inThread = new StreamRedirectThread("in.redirect", System.in,
274:                        process.getOutputStream());
275:                inThread.setDaemon(true);
276:                errThread = new StreamRedirectThread("err.redirect", process
277:                        .getErrorStream(), System.err);
278:                inThread.start();
279:                errThread.start();
280:            }
281:
282:            public static void main(String[] args) {
283:                System.exit((new ProcessStarter()).run(args));
284:            }
285:
286:            private static String escapeWhiteSpace(String s) {
287:                if (s.indexOf(' ') > 0) {
288:                    StringBuffer sb = new StringBuffer();
289:                    StringTokenizer st = new StringTokenizer(s, " ", true);
290:                    String current = null;
291:                    while (st.hasMoreTokens()) {
292:                        current = st.nextToken();
293:                        if (" ".equals(current)) {
294:                            sb.append("\\ ");
295:                        } else {
296:                            sb.append(current);
297:                        }
298:                    }
299:                    return sb.toString();
300:                } else {
301:                    return s;
302:                }
303:            }
304:
305:            /**
306:             * Remove first and last " or ' if any
307:             *
308:             * @param s string to handle
309:             * @return s whitout first and last " or ' if any
310:             */
311:            public static String removeEmbracingQuotes(String s) {
312:                if ((s.length() >= 2) && (s.charAt(0) == '"')
313:                        && (s.charAt(s.length() - 1) == '"')) {
314:                    return s.substring(1, s.length() - 1);
315:                } else if ((s.length() >= 2) && (s.charAt(0) == '\'')
316:                        && (s.charAt(s.length() - 1) == '\'')) {
317:                    return s.substring(1, s.length() - 1);
318:                } else {
319:                    return s;
320:                }
321:            }
322:
323:            /**
324:             * Analyse the args[] as a java command line
325:             *
326:             * @param args
327:             * @return String[] [0]:jvm options except -cp|-classpath, [1]:classpath without -cp, [2]: mainClass + mainOptions
328:             */
329:            public String[] parseJavaCommandLine(String[] args) {
330:                StringBuffer optionsArgB = new StringBuffer();
331:                StringBuffer cpOptionsArgB = new StringBuffer();
332:                StringBuffer mainArgB = new StringBuffer();
333:                String previous = null;
334:                boolean foundMain = false;
335:                for (int i = 0; i < args.length; i++) {
336:                    //System.out.println("" + i + " " + args[i]);
337:                    if (args[i].startsWith("-") && !foundMain) {
338:                        if (!("-cp".equals(args[i]))
339:                                && !("-classpath").equals(args[i])) {
340:                            optionsArgB.append(args[i]).append(" ");
341:                        }
342:                    } else if (!foundMain
343:                            && ("-cp".equals(previous) || "-classpath"
344:                                    .equals(previous))) {
345:                        if (cpOptionsArgB.length() > 0) {
346:                            cpOptionsArgB
347:                                    .append((System.getProperty("os.name", "")
348:                                            .toLowerCase().indexOf("windows") >= 0) ? ";"
349:                                            : ":");
350:                        }
351:                        cpOptionsArgB.append(removeEmbracingQuotes(args[i]));
352:                    } else {
353:                        foundMain = true;
354:                        mainArgB.append(args[i]).append(" ");
355:                    }
356:                    previous = args[i];
357:                }
358:
359:                // restore quote around classpath or escape whitespace depending on win*/*nix
360:                StringBuffer classPath = new StringBuffer();
361:                if (System.getProperty("os.name", "").toLowerCase().indexOf(
362:                        "windows") >= 0) {
363:                    classPath = classPath.append("\"").append(
364:                            cpOptionsArgB.toString()).append("\"");
365:                } else {
366:                    classPath = classPath.append(escapeWhiteSpace(cpOptionsArgB
367:                            .toString()));
368:                }
369:                String[] res = new String[] { optionsArgB.toString(),
370:                        classPath.toString(), mainArgB.toString() };
371:                return res;
372:            }
373:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.