/* | 
|
 * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. | 
|
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | 
|
 * | 
|
 * This code is free software; you can redistribute it and/or modify it | 
|
 * under the terms of the GNU General Public License version 2 only, as | 
|
 * published by the Free Software Foundation.  Oracle designates this | 
|
 * particular file as subject to the "Classpath" exception as provided | 
|
 * by Oracle in the LICENSE file that accompanied this code. | 
|
 * | 
|
 * This code is distributed in the hope that it will be useful, but WITHOUT | 
|
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | 
|
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License | 
|
 * version 2 for more details (a copy is included in the LICENSE file that | 
|
 * accompanied this code). | 
|
 * | 
|
 * You should have received a copy of the GNU General Public License version | 
|
 * 2 along with this work; if not, write to the Free Software Foundation, | 
|
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | 
|
 * | 
|
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | 
|
 * or visit www.oracle.com if you need additional information or have any | 
|
 * questions. | 
|
*/  | 
|
package com.sun.tools.attach.spi;  | 
|
import java.io.IOException;  | 
|
import java.util.Collections;  | 
|
import java.util.Iterator;  | 
|
import java.util.ArrayList;  | 
|
import java.util.List;  | 
|
import com.sun.tools.attach.VirtualMachine;  | 
|
import com.sun.tools.attach.VirtualMachineDescriptor;  | 
|
import com.sun.tools.attach.AttachPermission;  | 
|
import com.sun.tools.attach.AttachNotSupportedException;  | 
|
import java.util.ServiceLoader;  | 
|
/**  | 
|
* Attach provider class for attaching to a Java virtual machine.  | 
|
*  | 
|
* <p> An attach provider is a concrete subclass of this class that has a  | 
|
* zero-argument constructor and implements the abstract methods specified  | 
|
* below. </p>  | 
|
*  | 
|
* <p> An attach provider implementation is typically tied to a Java virtual  | 
|
* machine implementation, version, or even mode of operation. That is, a specific  | 
|
* provider implementation will typically only be capable of attaching to  | 
|
* a specific Java virtual machine implementation or version. For example, Sun's  | 
|
* JDK implementation ships with provider implementations that can only attach to  | 
|
* Sun's <i>HotSpot</i> virtual machine. In general, if an environment  | 
|
* consists of Java virtual machines of different versions and from different  | 
|
* vendors then there will be an attach provider implementation for each  | 
|
* <i>family</i> of implementations or versions. </p>  | 
|
*  | 
|
 * <p> An attach provider is identified by its {@link #name <i>name</i>} and | 
|
 * {@link #type <i>type</i>}. The <i>name</i> is typically, but not required to | 
|
* be, a name that corresponds to the VM vendor. The Sun JDK implementation,  | 
|
* for example, ships with attach providers that use the name <i>"sun"</i>. The  | 
|
* <i>type</i> typically corresponds to the attach mechanism. For example, an  | 
|
* implementation that uses the Doors inter-process communication mechanism  | 
|
* might use the type <i>"doors"</i>. The purpose of the name and type is to  | 
|
* identify providers in environments where there are multiple providers  | 
|
* installed. </p>  | 
|
*  | 
|
* <p> AttachProvider implementations are loaded and instantiated at the first  | 
|
 * invocation of the {@link #providers() providers} method. This method | 
|
* attempts to load all provider implementations that are installed on the  | 
|
* platform. </p>  | 
|
*  | 
|
* <p> All of the methods in this class are safe for use by multiple  | 
|
* concurrent threads. </p>  | 
|
*  | 
|
* @since 1.6  | 
|
*/  | 
|
@jdk.Exported  | 
|
public abstract class AttachProvider { | 
|
private static final Object lock = new Object();  | 
|
private static List<AttachProvider> providers = null;  | 
|
    /** | 
|
     * Initializes a new instance of this class.  </p> | 
|
     * | 
|
     * @throws  SecurityException | 
|
     *          If a security manager has been installed and it denies | 
|
     *          {@link com.sun.tools.attach.AttachPermission AttachPermission} | 
|
     *          <tt>("createAttachProvider")</tt> | 
|
*/  | 
|
    protected AttachProvider() { | 
|
SecurityManager sm = System.getSecurityManager();  | 
|
if (sm != null)  | 
|
sm.checkPermission(new AttachPermission("createAttachProvider"));  | 
|
}  | 
|
    /** | 
|
     * Return this provider's name. </p> | 
|
     * | 
|
     * @return  The name of this provider | 
|
*/  | 
|
public abstract String name();  | 
|
    /** | 
|
     * Return this provider's type. </p> | 
|
     * | 
|
     * @return  The type of this provider | 
|
*/  | 
|
public abstract String type();  | 
|
    /** | 
|
     * Attaches to a Java virtual machine. | 
|
     * | 
|
     * <p> A Java virtual machine is identified by an abstract identifier. The | 
|
     * nature of this identifier is platform dependent but in many cases it will be the | 
|
     * string representation of the process identifier (or pid). </p> | 
|
     * | 
|
     * <p> This method parses the identifier and maps the identifier to a Java | 
|
     * virtual machine (in an implementation dependent manner). If the identifier | 
|
     * cannot be parsed by the provider then an {@link | 
|
     * com.sun.tools.attach.AttachNotSupportedException AttachNotSupportedException} | 
|
     * is thrown. Once parsed this method attempts to attach to the Java virtual machine. | 
|
     * If the provider detects that the identifier corresponds to a Java virtual machine | 
|
     * that does not exist, or it corresponds to a Java virtual machine that does not support | 
|
     * the attach mechanism implemented by this provider, or it detects that the | 
|
     * Java virtual machine is a version to which this provider cannot attach, then | 
|
     * an <code>AttachNotSupportedException</code> is thrown. </p> | 
|
     * | 
|
     * @param  id | 
|
     *         The abstract identifier that identifies the Java virtual machine. | 
|
     * | 
|
     * @return  VirtualMachine representing the target virtual machine. | 
|
     * | 
|
     * @throws  SecurityException | 
|
     *          If a security manager has been installed and it denies | 
|
     *          {@link com.sun.tools.attach.AttachPermission AttachPermission} | 
|
     *          <tt>("attachVirtualMachine")</tt>, or other permission | 
|
     *          required by the implementation. | 
|
     * | 
|
     * @throws  AttachNotSupportedException | 
|
     *          If the identifier cannot be parsed, or it corresponds to | 
|
     *          to a Java virtual machine that does not exist, or it | 
|
     *          corresponds to a Java virtual machine which this | 
|
     *          provider cannot attach. | 
|
     * | 
|
     * @throws  IOException | 
|
     *          If some other I/O error occurs | 
|
     * | 
|
     * @throws  NullPointerException | 
|
     *          If <code>id</code> is <code>null</code> | 
|
*/  | 
|
public abstract VirtualMachine attachVirtualMachine(String id)  | 
|
throws AttachNotSupportedException, IOException;  | 
|
    /** | 
|
     * Attaches to a Java virtual machine. | 
|
     * | 
|
     * <p> A Java virtual machine can be described using a {@link | 
|
     * com.sun.tools.attach.VirtualMachineDescriptor VirtualMachineDescriptor}. | 
|
     * This method invokes the descriptor's {@link | 
|
     * com.sun.tools.attach.VirtualMachineDescriptor#provider() provider()} method | 
|
     * to check that it is equal to this provider. It then attempts to attach to the | 
|
     * Java virtual machine. | 
|
     * | 
|
     * @param  vmd | 
|
     *         The virtual machine descriptor | 
|
     * | 
|
     * @return  VirtualMachine representing the target virtual machine. | 
|
     * | 
|
     * @throws  SecurityException | 
|
     *          If a security manager has been installed and it denies | 
|
     *          {@link com.sun.tools.attach.AttachPermission AttachPermission} | 
|
     *          <tt>("attachVirtualMachine")</tt>, or other permission | 
|
     *          required by the implementation. | 
|
     * | 
|
     * @throws  AttachNotSupportedException | 
|
     *          If the descriptor's {@link | 
|
     *          com.sun.tools.attach.VirtualMachineDescriptor#provider() provider()} method | 
|
     *          returns a provider that is not this provider, or it does not correspond | 
|
     *          to a Java virtual machine to which this provider can attach. | 
|
     * | 
|
     * @throws  IOException | 
|
     *          If some other I/O error occurs | 
|
     * | 
|
     * @throws  NullPointerException | 
|
     *          If <code>vmd</code> is <code>null</code> | 
|
*/  | 
|
public VirtualMachine attachVirtualMachine(VirtualMachineDescriptor vmd)  | 
|
throws AttachNotSupportedException, IOException  | 
|
    { | 
|
if (vmd.provider() != this) {  | 
|
throw new AttachNotSupportedException("provider mismatch");  | 
|
}  | 
|
return attachVirtualMachine(vmd.id());  | 
|
}  | 
|
    /** | 
|
     * Lists the Java virtual machines known to this provider. | 
|
     * | 
|
     * <p> This method returns a list of {@link | 
|
     * com.sun.tools.attach.VirtualMachineDescriptor} elements. Each | 
|
     * <code>VirtualMachineDescriptor</code> describes a Java virtual machine | 
|
     * to which this provider can <i>potentially</i> attach.  There isn't any | 
|
     * guarantee that invoking {@link #attachVirtualMachine(VirtualMachineDescriptor) | 
|
     * attachVirtualMachine} on each descriptor in the list will succeed. | 
|
     * | 
|
     * @return  The list of virtual machine descriptors which describe the | 
|
     *          Java virtual machines known to this provider (may be empty). | 
|
*/  | 
|
public abstract List<VirtualMachineDescriptor> listVirtualMachines();  | 
|
    /** | 
|
     * Returns a list of the installed attach providers. | 
|
     * | 
|
     * <p> An AttachProvider is installed on the platform if: | 
|
     * | 
|
     * <ul> | 
|
     *   <li><p>It is installed in a JAR file that is visible to the defining | 
|
     *   class loader of the AttachProvider type (usually, but not required | 
|
     *   to be, the {@link java.lang.ClassLoader#getSystemClassLoader system | 
|
     *   class loader}).</p></li> | 
|
     * | 
|
     *   <li><p>The JAR file contains a provider configuration named | 
|
     *   <tt>com.sun.tools.attach.spi.AttachProvider</tt> in the resource directory | 
|
     *   <tt>META-INF/services</tt>. </p></li> | 
|
     * | 
|
     *   <li><p>The provider configuration file lists the full-qualified class | 
|
     *   name of the AttachProvider implementation. </p></li> | 
|
     * </ul> | 
|
     * | 
|
     * <p> The format of the provider configuration file is one fully-qualified | 
|
     * class name per line. Space and tab characters surrounding each class name, | 
|
     * as well as blank lines are ignored. The comment character is | 
|
     *  <tt>'#'</tt> (<tt>0x23</tt>), and on each line all characters following | 
|
     * the first comment character are ignored. The file must be encoded in | 
|
     * UTF-8. </p> | 
|
     * | 
|
     * <p> AttachProvider implementations are loaded and instantiated | 
|
     * (using the zero-arg constructor) at the first invocation of this method. | 
|
     * The list returned by the first invocation of this method is the list | 
|
     * of providers. Subsequent invocations of this method return a list of the same | 
|
     * providers. The list is unmodifable.</p> | 
|
     * | 
|
     * @return  A list of the installed attach providers. | 
|
*/  | 
|
public static List<AttachProvider> providers() {  | 
|
synchronized (lock) {  | 
|
if (providers == null) {  | 
|
providers = new ArrayList<AttachProvider>();  | 
|
ServiceLoader<AttachProvider> providerLoader =  | 
|
ServiceLoader.load(AttachProvider.class,  | 
|
AttachProvider.class.getClassLoader());  | 
|
Iterator<AttachProvider> i = providerLoader.iterator();  | 
|
while (i.hasNext()) {  | 
|
                    try { | 
|
providers.add(i.next());  | 
|
} catch (Throwable t) {  | 
|
if (t instanceof ThreadDeath) {  | 
|
ThreadDeath td = (ThreadDeath)t;  | 
|
throw td;  | 
|
}  | 
|
                        // Ignore errors and exceptions | 
|
System.err.println(t);  | 
|
}  | 
|
}  | 
|
}  | 
|
return Collections.unmodifiableList(providers);  | 
|
}  | 
|
}  | 
|
}  |