1 /***************************************************************************************
2 * Copyright (c) Jonas Bon?r, Alexandre Vasseur. All rights reserved. *
3 * http://aspectwerkz.codehaus.org *
4 * ---------------------------------------------------------------------------------- *
5 * The software in this package is published under the terms of the LGPL license *
6 * a copy of which has been included with this distribution in the license.txt file. *
7 **************************************************************************************/
8 package org.codehaus.aspectwerkz.hook;
9
10 import com.sun.jdi.VirtualMachine;
11 import com.sun.jdi.Bootstrap;
12 import com.sun.jdi.connect.AttachingConnector;
13 import com.sun.jdi.connect.Connector;
14 import com.sun.jdi.connect.IllegalConnectorArgumentsException;
15
16 import java.util.Map;
17 import java.util.Iterator;
18 import java.io.IOException;
19
20 /***
21 * Isolation of JDWP dependancies to Plug online mode in a running / remote VM.
22 * See Plug.
23 *
24 * @author <a href="mailto:alex@gnilux.com">Alexandre Vasseur</a>
25 */
26 public class JDWPPlug {
27
28 /***
29 * transport jdwp option
30 */
31 private final static String TRANSPORT_JDWP = "transport";
32
33 /***
34 * address jdwp option
35 */
36 private final static String ADDRESS_JDWP = "address";
37
38 /***
39 * Connects to a remote JVM using the jdwp options specified in jdwp
40 *
41 * @param jdwp
42 * @return VirtualMachine or null if failure
43 * @throws Exception
44 */
45 private VirtualMachine connect(Map jdwp) throws Exception {
46 String transport = (String) jdwp.get(TRANSPORT_JDWP);
47 String address = (String) jdwp.get(ADDRESS_JDWP);
48 String name = null;
49 if ("dt_socket".equals(transport)) {
50 name = "com.sun.jdi.SocketAttach";
51 } else if ("dt_shmem".equals(transport)) {
52 name = "com.sun.jdi.SharedMemoryAttach";
53 }
54 AttachingConnector connector = null;
55 for (Iterator i = Bootstrap.virtualMachineManager().attachingConnectors().iterator(); i.hasNext();) {
56 AttachingConnector aConnector = (AttachingConnector) i.next();
57 if (aConnector.name().equals(name)) {
58 connector = aConnector;
59 break;
60 }
61 }
62 if (connector == null) {
63 throw new Exception("no AttachingConnector for transport: " + transport);
64 }
65 Map args = connector.defaultArguments();
66 if ("dt_socket".equals(transport)) {
67 ((Connector.Argument) args.get("port")).setValue(address);
68 } else if ("dt_shmem".equals(transport)) {
69 ((Connector.Argument) args.get("name")).setValue(address);
70 }
71 try {
72 VirtualMachine vm = connector.attach(args);
73 return vm;
74 } catch (IllegalConnectorArgumentsException e) {
75 System.err.println("failed to attach to VM (" + transport + ", " + address + "):");
76 e.printStackTrace();
77 for (Iterator i = e.argumentNames().iterator(); i.hasNext();) {
78 System.err.println("wrong or missing argument - " + i.next());
79 }
80 return null;
81 } catch (IOException e) {
82 System.err.println("failed to attach to VM (" + transport + ", " + address + "):");
83 e.printStackTrace();
84 return null;
85 }
86 }
87
88 /***
89 * Resume the remote JVM, without hotswapping classes
90 *
91 * @param jdwp
92 * @throws Exception
93 */
94 public void resume(Map jdwp) throws Exception {
95 VirtualMachine vm = connect(jdwp);
96 if (vm != null) {
97 vm.resume();
98 vm.dispose();
99 }
100 }
101
102 /***
103 * Prints information about the remote JVM and resume
104 *
105 * @param jdwp
106 * @throws Exception
107 */
108 public void info(Map jdwp) throws Exception {
109 VirtualMachine vm = connect(jdwp);
110 if (vm != null) {
111 System.out.println("java.vm.name = " + vm.name());
112 System.out.println("java.version = " + vm.version());
113 System.out.println(vm.description());
114 vm.resume();
115 vm.dispose();
116 }
117 }
118
119 /***
120 * Hotswaps the java.lang.ClassLoader of the remote JVM and resume
121 *
122 * @param jdwp
123 * @throws Exception
124 */
125 public void hotswap(Map jdwp) throws Exception {
126
127 VirtualMachine vm = ClassLoaderPatcher.hotswapClassLoader(
128 System.getProperty(
129 ProcessStarter.CL_PRE_PROCESSOR_CLASSNAME_PROPERTY,
130 org.codehaus.aspectwerkz.hook.impl.ClassLoaderPreProcessorImpl.class.getName()
131 ), (String) jdwp
132 .get(TRANSPORT_JDWP), (String) jdwp.get(ADDRESS_JDWP)
133 );
134 if (vm != null) {
135 vm.resume();
136 vm.dispose();
137 }
138 }
139
140
141 }