J. Duke | 319a3b9 | 2007-12-01 00:00:00 +0000 | [diff] [blame^] | 1 | /* |
| 2 | * Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved. |
| 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| 4 | * |
| 5 | * This code is free software; you can redistribute it and/or modify it |
| 6 | * under the terms of the GNU General Public License version 2 only, as |
| 7 | * published by the Free Software Foundation. Sun designates this |
| 8 | * particular file as subject to the "Classpath" exception as provided |
| 9 | * by Sun in the LICENSE file that accompanied this code. |
| 10 | * |
| 11 | * This code is distributed in the hope that it will be useful, but WITHOUT |
| 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| 14 | * version 2 for more details (a copy is included in the LICENSE file that |
| 15 | * accompanied this code). |
| 16 | * |
| 17 | * You should have received a copy of the GNU General Public License version |
| 18 | * 2 along with this work; if not, write to the Free Software Foundation, |
| 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| 20 | * |
| 21 | * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
| 22 | * CA 95054 USA or visit www.sun.com if you need additional information or |
| 23 | * have any questions. |
| 24 | */ |
| 25 | |
| 26 | package com.sun.tools.attach.spi; |
| 27 | |
| 28 | import java.io.IOException; |
| 29 | import java.util.Collections; |
| 30 | import java.util.Iterator; |
| 31 | import java.util.ArrayList; |
| 32 | import java.util.List; |
| 33 | import com.sun.tools.attach.VirtualMachine; |
| 34 | import com.sun.tools.attach.VirtualMachineDescriptor; |
| 35 | import com.sun.tools.attach.AttachPermission; |
| 36 | import com.sun.tools.attach.AttachNotSupportedException; |
| 37 | import java.util.ServiceLoader; |
| 38 | |
| 39 | /** |
| 40 | * Attach provider class for attaching to a Java virtual machine. |
| 41 | * |
| 42 | * <p> An attach provider is a concrete subclass of this class that has a |
| 43 | * zero-argument constructor and implements the abstract methods specified |
| 44 | * below. </p> |
| 45 | * |
| 46 | * <p> An attach provider implementation is typically tied to a Java virtual |
| 47 | * machine implementation, version, or even mode of operation. That is, a specific |
| 48 | * provider implementation will typically only be capable of attaching to |
| 49 | * a specific Java virtual machine implementation or version. For example, Sun's |
| 50 | * JDK implementation ships with provider implementations that can only attach to |
| 51 | * Sun's <i>HotSpot</i> virtual machine. In general, if an environment |
| 52 | * consists of Java virtual machines of different versions and from different |
| 53 | * vendors then there will be an attach provider implementation for each |
| 54 | * <i>family</i> of implementations or versions. </p> |
| 55 | * |
| 56 | * <p> An attach provider is identified by its {@link #name <i>name</i>} and |
| 57 | * {@link #type <i>type</i>}. The <i>name</i> is typically, but not required to |
| 58 | * be, a name that corresponds to the VM vendor. The Sun JDK implementation, |
| 59 | * for example, ships with attach providers that use the name <i>"sun"</i>. The |
| 60 | * <i>type</i> typically corresponds to the attach mechanism. For example, an |
| 61 | * implementation that uses the Doors inter-process communication mechanism |
| 62 | * might use the type <i>"doors"</i>. The purpose of the name and type is to |
| 63 | * identify providers in environments where there are multiple providers |
| 64 | * installed. </p> |
| 65 | * |
| 66 | * <p> AttachProvider implementations are loaded and instantiated at the first |
| 67 | * invocation of the {@link #providers() providers} method. This method |
| 68 | * attempts to load all provider implementations that are installed on the |
| 69 | * platform. </p> |
| 70 | * |
| 71 | * <p> All of the methods in this class are safe for use by multiple |
| 72 | * concurrent threads. </p> |
| 73 | * |
| 74 | * @since 1.6 |
| 75 | */ |
| 76 | |
| 77 | public abstract class AttachProvider { |
| 78 | |
| 79 | private static final Object lock = new Object(); |
| 80 | private static List<AttachProvider> providers = null; |
| 81 | |
| 82 | /** |
| 83 | * Initializes a new instance of this class. </p> |
| 84 | * |
| 85 | * @throws SecurityException |
| 86 | * If a security manager has been installed and it denies |
| 87 | * {@link com.sun.tools.attach.AttachPermission AttachPermission} |
| 88 | * <tt>("createAttachProvider")</tt> |
| 89 | */ |
| 90 | protected AttachProvider() { |
| 91 | SecurityManager sm = System.getSecurityManager(); |
| 92 | if (sm != null) |
| 93 | sm.checkPermission(new AttachPermission("createAttachProvider")); |
| 94 | } |
| 95 | |
| 96 | /** |
| 97 | * Return this provider's name. </p> |
| 98 | * |
| 99 | * @return The name of this provider |
| 100 | */ |
| 101 | public abstract String name(); |
| 102 | |
| 103 | /** |
| 104 | * Return this provider's type. </p> |
| 105 | * |
| 106 | * @return The type of this provider |
| 107 | */ |
| 108 | public abstract String type(); |
| 109 | |
| 110 | /** |
| 111 | * Attaches to a Java virtual machine. |
| 112 | * |
| 113 | * <p> A Java virtual machine is identified by an abstract identifier. The |
| 114 | * nature of this identifier is platform dependent but in many cases it will be the |
| 115 | * string representation of the process identifier (or pid). </p> |
| 116 | * |
| 117 | * <p> This method parses the identifier and maps the identifier to a Java |
| 118 | * virtual machine (in an implementation dependent manner). If the identifier |
| 119 | * cannot be parsed by the provider then an {@link |
| 120 | * com.sun.tools.attach.AttachNotSupportedException AttachNotSupportedException} |
| 121 | * is thrown. Once parsed this method attempts to attach to the Java virtual machine. |
| 122 | * If the provider detects that the identifier corresponds to a Java virtual machine |
| 123 | * that does not exist, or it corresponds to a Java virtual machine that does not support |
| 124 | * the attach mechanism implemented by this provider, or it detects that the |
| 125 | * Java virtual machine is a version to which this provider cannot attach, then |
| 126 | * an <code>AttachNotSupportedException</code> is thrown. </p> |
| 127 | * |
| 128 | * @param id |
| 129 | * The abstract identifier that identifies the Java virtual machine. |
| 130 | * |
| 131 | * @return VirtualMachine representing the target virtual machine. |
| 132 | * |
| 133 | * @throws SecurityException |
| 134 | * If a security manager has been installed and it denies |
| 135 | * {@link com.sun.tools.attach.AttachPermission AttachPermission} |
| 136 | * <tt>("attachVirtualMachine")</tt>, or other permission |
| 137 | * required by the implementation. |
| 138 | * |
| 139 | * @throws AttachNotSupportedException |
| 140 | * If the identifier cannot be parsed, or it corresponds to |
| 141 | * to a Java virtual machine that does not exist, or it |
| 142 | * corresponds to a Java virtual machine which this |
| 143 | * provider cannot attach. |
| 144 | * |
| 145 | * @throws IOException |
| 146 | * If some other I/O error occurs |
| 147 | * |
| 148 | * @throws NullPointerException |
| 149 | * If <code>id</code> is <code>null</code> |
| 150 | */ |
| 151 | public abstract VirtualMachine attachVirtualMachine(String id) |
| 152 | throws AttachNotSupportedException, IOException; |
| 153 | |
| 154 | /** |
| 155 | * Attaches to a Java virtual machine. |
| 156 | * |
| 157 | * <p> A Java virtual machine can be described using a {@link |
| 158 | * com.sun.tools.attach.VirtualMachineDescriptor VirtualMachineDescriptor}. |
| 159 | * This method invokes the descriptor's {@link |
| 160 | * com.sun.tools.attach.VirtualMachineDescriptor#provider() provider()} method |
| 161 | * to check that it is equal to this provider. It then attempts to attach to the |
| 162 | * Java virtual machine. |
| 163 | * |
| 164 | * @param vmd |
| 165 | * The virtual machine descriptor |
| 166 | * |
| 167 | * @return VirtualMachine representing the target virtual machine. |
| 168 | * |
| 169 | * @throws SecurityException |
| 170 | * If a security manager has been installed and it denies |
| 171 | * {@link com.sun.tools.attach.AttachPermission AttachPermission} |
| 172 | * <tt>("attachVirtualMachine")</tt>, or other permission |
| 173 | * required by the implementation. |
| 174 | * |
| 175 | * @throws AttachNotSupportedException |
| 176 | * If the descriptor's {@link |
| 177 | * com.sun.tools.attach.VirtualMachineDescriptor#provider() provider()} method |
| 178 | * returns a provider that is not this provider, or it does not correspond |
| 179 | * to a Java virtual machine to which this provider can attach. |
| 180 | * |
| 181 | * @throws IOException |
| 182 | * If some other I/O error occurs |
| 183 | * |
| 184 | * @throws NullPointerException |
| 185 | * If <code>vmd</code> is <code>null</code> |
| 186 | */ |
| 187 | public VirtualMachine attachVirtualMachine(VirtualMachineDescriptor vmd) |
| 188 | throws AttachNotSupportedException, IOException |
| 189 | { |
| 190 | if (vmd.provider() != this) { |
| 191 | throw new AttachNotSupportedException("provider mismatch"); |
| 192 | } |
| 193 | return attachVirtualMachine(vmd.id()); |
| 194 | } |
| 195 | |
| 196 | /** |
| 197 | * Lists the Java virtual machines known to this provider. |
| 198 | * |
| 199 | * <p> This method returns a list of {@link |
| 200 | * com.sun.tools.attach.VirtualMachineDescriptor} elements. Each |
| 201 | * <code>VirtualMachineDescriptor</code> describes a Java virtual machine |
| 202 | * to which this provider can <i>potentially</i> attach. There isn't any |
| 203 | * guarantee that invoking {@link #attachVirtualMachine(VirtualMachineDescriptor) |
| 204 | * attachVirtualMachine} on each descriptor in the list will succeed. |
| 205 | * |
| 206 | * @return The list of virtual machine descriptors which describe the |
| 207 | * Java virtual machines known to this provider (may be empty). |
| 208 | */ |
| 209 | public abstract List<VirtualMachineDescriptor> listVirtualMachines(); |
| 210 | |
| 211 | |
| 212 | /** |
| 213 | * Returns a list of the installed attach providers. |
| 214 | * |
| 215 | * <p> An AttachProvider is installed on the platform if: |
| 216 | * |
| 217 | * <ul> |
| 218 | * <li><p>It is installed in a JAR file that is visible to the defining |
| 219 | * class loader of the AttachProvider type (usually, but not required |
| 220 | * to be, the {@link java.lang.ClassLoader#getSystemClassLoader system |
| 221 | * class loader}).</p></li> |
| 222 | * |
| 223 | * <li><p>The JAR file contains a provider configuration named |
| 224 | * <tt>com.sun.tools.attach.spi.AttachProvider</tt> in the resource directory |
| 225 | * <tt>META-INF/services</tt>. </p></li> |
| 226 | * |
| 227 | * <li><p>The provider configuration file lists the full-qualified class |
| 228 | * name of the AttachProvider implementation. </p></li> |
| 229 | * </ul> |
| 230 | * |
| 231 | * <p> The format of the provider configuration file is one fully-qualified |
| 232 | * class name per line. Space and tab characters surrounding each class name, |
| 233 | * as well as blank lines are ignored. The comment character is |
| 234 | * <tt>'#'</tt> (<tt>0x23</tt>), and on each line all characters following |
| 235 | * the first comment character are ignored. The file must be encoded in |
| 236 | * UTF-8. </p> |
| 237 | * |
| 238 | * <p> AttachProvider implementations are loaded and instantiated |
| 239 | * (using the zero-arg constructor) at the first invocation of this method. |
| 240 | * The list returned by the first invocation of this method is the list |
| 241 | * of providers. Subsequent invocations of this method return a list of the same |
| 242 | * providers. The list is unmodifable.</p> |
| 243 | * |
| 244 | * @return A list of the installed attach providers. |
| 245 | */ |
| 246 | public static List<AttachProvider> providers() { |
| 247 | synchronized (lock) { |
| 248 | if (providers == null) { |
| 249 | providers = new ArrayList<AttachProvider>(); |
| 250 | |
| 251 | ServiceLoader<AttachProvider> providerLoader = |
| 252 | ServiceLoader.load(AttachProvider.class, |
| 253 | AttachProvider.class.getClassLoader()); |
| 254 | |
| 255 | Iterator<AttachProvider> i = providerLoader.iterator(); |
| 256 | |
| 257 | while (i.hasNext()) { |
| 258 | try { |
| 259 | providers.add(i.next()); |
| 260 | } catch (Throwable t) { |
| 261 | if (t instanceof ThreadDeath) { |
| 262 | ThreadDeath td = (ThreadDeath)t; |
| 263 | throw td; |
| 264 | } |
| 265 | // Ignore errors and exceptions |
| 266 | System.err.println(t); |
| 267 | } |
| 268 | } |
| 269 | } |
| 270 | return Collections.unmodifiableList(providers); |
| 271 | } |
| 272 | } |
| 273 | } |