001: /*
002: * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025: package sun.tools.attach;
026:
027: import com.sun.tools.attach.VirtualMachine;
028: import com.sun.tools.attach.VirtualMachineDescriptor;
029: import com.sun.tools.attach.AttachNotSupportedException;
030:
031: import java.util.ArrayList;
032: import java.util.List;
033: import java.io.IOException;
034: import java.net.InetAddress;
035: import java.net.UnknownHostException;
036:
037: public class WindowsAttachProvider extends HotSpotAttachProvider {
038:
039: public WindowsAttachProvider() {
040: String os = System.getProperty("os.name");
041: if (os.startsWith("Windows 9") || os.equals("Windows Me")) {
042: throw new RuntimeException(
043: "This provider is not supported on this version of Windows");
044: }
045: String arch = System.getProperty("os.arch");
046: if (!arch.equals("x86") && !arch.equals("amd64")) {
047: throw new RuntimeException(
048: "This provider is not supported on this processor architecture");
049: }
050: }
051:
052: public String name() {
053: return "sun";
054: }
055:
056: public String type() {
057: return "windows";
058: }
059:
060: public VirtualMachine attachVirtualMachine(String vmid)
061: throws AttachNotSupportedException, IOException {
062: checkAttachPermission();
063:
064: // AttachNotSupportedException will be thrown if the target VM can be determined
065: // to be not attachable.
066: testAttachable(vmid);
067:
068: return new WindowsVirtualMachine(this , vmid);
069: }
070:
071: public List<VirtualMachineDescriptor> listVirtualMachines() {
072: // If the temporary file system is secure then we use the default
073: // implementation, otherwise we create a list of Windows processes.
074: if (isTempPathSecure()) {
075: return super .listVirtualMachines();
076: } else {
077: return listJavaProcesses();
078: }
079: }
080:
081: /**
082: * Returns true if the temporary file system supports security
083: */
084: private static boolean isTempPathSecure() {
085: if (!wasTempPathChecked) {
086: synchronized (WindowsAttachProvider.class) {
087: if (!wasTempPathChecked) {
088: // get the value of TMP/TEMP, ignoring UNC, and paths that
089: // aren't absolute
090: String temp = tempPath();
091: if ((temp != null) && (temp.length() >= 3)
092: && (temp.charAt(1) == ':')
093: && (temp.charAt(2) == '\\')) {
094: // check if the volume supports security
095: long flags = volumeFlags(temp.substring(0, 3));
096: isTempPathSecure = ((flags & FS_PERSISTENT_ACLS) != 0);
097: }
098: wasTempPathChecked = true;
099: }
100: }
101: }
102:
103: return isTempPathSecure;
104: }
105:
106: // flag to indicate persistent ACLs are supported
107: private static final long FS_PERSISTENT_ACLS = 0x8L;
108:
109: // indicates if we've checked the temporary file system
110: private static volatile boolean wasTempPathChecked;
111:
112: // indicates if the temporary file system is secure (only valid when
113: // wasTempPathChecked is true)
114: private static boolean isTempPathSecure;
115:
116: // returns the value of TMP/TEMP
117: private static native String tempPath();
118:
119: // returns the flags for the given volume
120: private static native long volumeFlags(String volume);
121:
122: /**
123: * Returns a list of virtual machine descriptors derived from an enumeration
124: * of the process list.
125: */
126: private List<VirtualMachineDescriptor> listJavaProcesses() {
127: // ensure that process status helper is loaded (psapi.dll)
128: if (!isProcessStatusHelperInitialized) {
129: synchronized (WindowsAttachProvider.class) {
130: if (!isProcessStatusHelperInitialized) {
131: initializeProcessStatusHelper();
132: isProcessStatusHelperInitialized = true;
133: }
134: }
135: }
136:
137: ArrayList<VirtualMachineDescriptor> list = new ArrayList<VirtualMachineDescriptor>();
138:
139: // Use localhost in the display name
140: String host = "localhost";
141: try {
142: host = InetAddress.getLocalHost().getHostName();
143: } catch (UnknownHostException uhe) {
144: // ignore
145: }
146:
147: // Enumerate all processes.
148: // For those processes that have loaded a library named "jvm.dll"
149: // then we attempt to attach. If we succeed then we have a 6.0+ VM.
150: int processes[] = new int[1024];
151: int count = enumProcesses(processes, processes.length);
152: for (int i = 0; i < count; i++) {
153: if (isLibraryLoadedByProcess("jvm.dll", processes[i])) {
154: String pid = Integer.toString(processes[i]);
155: try {
156: new WindowsVirtualMachine(this , pid).detach();
157:
158: // FIXME - for now we don't have an appropriate display
159: // name so we use pid@hostname
160: String name = pid + "@" + host;
161:
162: list.add(new HotSpotVirtualMachineDescriptor(this ,
163: pid, name));
164: } catch (AttachNotSupportedException x) {
165: } catch (IOException ioe) {
166: }
167: }
168: }
169:
170: return list;
171: }
172:
173: // indicates if psapi.dll has been initialized
174: private static volatile boolean isProcessStatusHelperInitialized;
175:
176: // loads psapi
177: private static native void initializeProcessStatusHelper();
178:
179: // enumerates processes using psapi's EnumProcesses
180: private static native int enumProcesses(int[] processes, int max);
181:
182: // indicates if a library of a given name has been loaded by a process
183: private static native boolean isLibraryLoadedByProcess(
184: String library, int processId);
185:
186: // native functions in this library
187: static {
188: System.loadLibrary("attach");
189: }
190:
191: }
|