Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
package org.jolokia.jvmagent.client.util;
/*
* Copyright 2009-2013 Roland Huss
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.lang.management.ManagementFactory;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* A handler for dealing with VirtualMachine without directly referencing internally
* the class type. All lookup is done via reflection.
*
* @author roland
* @since 12.08.11
*/
public class VirtualMachineHandler {
private OptionsAndArgs options;
/**
* Constructor with options
*
* @param pOptions options for getting e.g. the process id to attach to
*
*/
public VirtualMachineHandler(OptionsAndArgs pOptions) {
options = pOptions;
}
/**
* Lookup and create a {@link com.sun.tools.attach.VirtualMachine} via reflection. First, a direct
* lookup via {@link Class#forName(String)} is done, which will succeed for JVM on OS X, since tools.jar
* is bundled there together with classes.zip. Next, tools.jar is tried to be found (by examine java.home)
* and an own classloader is created for looking up the VirtualMachine.
*
* If lookup fails, a message is printed out (except when '--quiet' is provided)
*
* @return the create virtual machine of null if none could be created
*/
public Object attachVirtualMachine() {
if (options.getPid() == null && options.getProcessPattern() == null) {
return null;
}
Class vmClass = lookupVirtualMachineClass();
try {
Method method = vmClass.getMethod("attach",String.class);
return method.invoke(null, getProcessId(options));
} catch (NoSuchMethodException e) {
throw new ProcessingException("Internal: No method 'attach' found on " + vmClass,e,options);
} catch (InvocationTargetException e) {
throw new ProcessingException("InvocationTarget " + vmClass,e,options);
} catch (IllegalAccessException e) {
throw new ProcessingException("IllegalAccess to " + vmClass,e,options);
} catch (IllegalArgumentException e) {
throw new ProcessingException("Illegal Argument",e,options);
}
}
/**
* Detach from the virtual machine
*
* @param pVm the virtual machine to detach from
*/
public void detachAgent(Object pVm) {
try {
if (pVm != null) {
Class clazz = pVm.getClass();
Method method = clazz.getMethod("detach");
method.invoke(pVm);
}
} catch (InvocationTargetException e) {
throw new ProcessingException("Error while detaching",e, options);
} catch (NoSuchMethodException e) {
throw new ProcessingException("Error while detaching",e, options);
} catch (IllegalAccessException e) {
throw new ProcessingException("Error while detaching",e, options);
}
}
/**
* Return a list of all Java processes
* @return list of java processes
* @throws NoSuchMethodException reflection error
* @throws InvocationTargetException reflection error
* @throws IllegalAccessException reflection error
*/
public List listProcesses() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
List ret = new ArrayList();
Class vmClass = lookupVirtualMachineClass();
Method method = vmClass.getMethod("list");
List vmDescriptors = (List) method.invoke(null);
for (Object descriptor : vmDescriptors) {
Method idMethod = descriptor.getClass().getMethod("id");
String id = (String) idMethod.invoke(descriptor);
Method displayMethod = descriptor.getClass().getMethod("displayName");
String display = (String) displayMethod.invoke(descriptor);
ret.add(new ProcessDescription(id, display));
}
return ret;
}
/**
* Filter the process list for a regular expression and returns the description. The process this
* JVM is running in is ignored. If more than one process or no process is found, an exception
* is raised.
*
* @param pPattern regular expression to match
* @return a process description of the one process found but never null
* @throws IllegalArgumentException if more than one or no process has been found.
*/
public ProcessDescription findProcess(Pattern pPattern)
throws InvocationTargetException, NoSuchMethodException, IllegalAccessException {
List ret = new ArrayList();
String ownId = getOwnProcessId();
for (ProcessDescription desc : listProcesses()) {
Matcher matcher = pPattern.matcher(desc.getDisplay());
if (!desc.getId().equals(ownId) && matcher.find()) {
ret.add(desc);
}
}
if (ret.size() == 1) {
return ret.get(0);
} else if (ret.size() == 0) {
throw new IllegalArgumentException("No attachable process found matching \"" + pPattern.pattern() + "\"");
} else {
StringBuilder buf = new StringBuilder();
for (ProcessDescription desc : ret) {
buf.append(desc.getId()).append(" (").append(desc.getDisplay()).append("),");
}
throw new IllegalArgumentException("More than one attachable process found matching \"" +
pPattern.pattern() + "\": " + buf.substring(0,buf.length()-1));
}
}
// ========================================================================================================
/**
* Get the process id, either directly from option's ID or by looking up a regular expression for java process name
* (but not this java process)
*
* @param pOpts used to get eithe the process Id ({@link OptionsAndArgs#getPid()} or the pattern for matching a
* process name ({@link OptionsAndArgs#getProcessPattern()})
* @return the numeric id as string
* @throws IllegalArgumentException if a pattern is used and no or more than one process name matches.
*/
private String getProcessId(OptionsAndArgs pOpts) throws InvocationTargetException, NoSuchMethodException, IllegalAccessException {
if (pOpts.getPid() != null) {
String pid = pOpts.getPid();
if (!isAttachable(pid)) {
throw new IllegalArgumentException("Cannot attach to process-ID " + pid + ".\nSee --help for possible reasons.");
}
return pid;
} else if (pOpts.getProcessPattern() != null) {
return findProcess(pOpts.getProcessPattern()).getId();
} else {
throw new IllegalArgumentException("No process ID and no process name pattern given");
}
}
// Check whether the given pid is in the list of attachable JVMs
private boolean isAttachable(String pPid) throws InvocationTargetException, NoSuchMethodException, IllegalAccessException {
for (ProcessDescription desc : listProcesses()) {
if (desc.getId().equals(pPid)) {
return true;
}
}
return false;
}
// Try to find out own process id. This is platform dependent and works on Sun/Oracl/OpeneJDKs like the
// whole agent, so it should be safe
private String getOwnProcessId() {
// Format of name is : @
String name = ManagementFactory.getRuntimeMXBean().getName();
int endIdx = name.indexOf('@');
return endIdx != -1 ? name.substring(0,endIdx) : name;
}
// lookup virtual machine class
private Class lookupVirtualMachineClass() {
try {
return ToolsClassFinder.lookupClass("com.sun.tools.attach.VirtualMachine");
} catch (ClassNotFoundException exp) {
throw new ProcessingException(
"Cannot find classes from tools.jar. The heuristics for loading tools.jar which contains\n" +
"essential classes for attaching to a running JVM could locate the necessary jar file.\n" +
"\n" +
"Please call this launcher with a qualified classpath on the command line like\n" +
"\n" +
" java -cp path/to/tools.jar:" + options.getJarFileName() + " org.jolokia.jvmagent.client.AgentLauncher [options] \n",
exp,
options);
}
}
}