org.gridkit.jvmtool.agent.SjkAgentLocator Maven / Gradle / Ivy
The newest version!
package org.gridkit.jvmtool.agent;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.jar.Attributes;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
public class SjkAgentLocator {
private static final Class> ANCHOR_CLASS = SjkAgent.class;
public static String getJarPath() throws IOException {
try {
URL url = ANCHOR_CLASS.getClassLoader().getResource(ANCHOR_CLASS.getName().replace('.', '/') + ".class");
if (url == null) {
throw new RuntimeException("Failed to locate jar path");
}
if (url.getProtocol().equals("jar") || url.getProtocol().equals("zip")) {
String path = url.toString();
path = path.substring("jar:".length());
int ch = path.lastIndexOf('!');
if (ch > 0) {
path = path.substring(0, ch);
}
try {
URI jarUri = new URI(path);
File file = new File(jarUri);
if (file.isFile()) {
return file.getAbsolutePath();
} else {
throw new RuntimeException("Failed to locate jar path");
}
} catch (URISyntaxException e) {
throw new RuntimeException("Failed to locate jar path");
}
} else {
File file = new File(url.toURI());
if (!file.isFile()) {
throw new RuntimeException("Failed to locate jar path");
}
File root = file;
String[] fqn = ANCHOR_CLASS.getName().split("[.]");
for (int i = 0; i != fqn.length; ++i) {
root = root.getParentFile();
}
return createTmpJar(root);
}
} catch (URISyntaxException e) {
throw new IOException(e);
}
}
private static String createTmpJar(File root) throws IOException {
File targetJar;
if (new File("target").isDirectory()) {
// build environment
new File("target/sjk-agent").mkdirs();
targetJar = new File("target/sjk-agent/sjk-agent-" + System.currentTimeMillis() + ".jar");
} else {
targetJar = File.createTempFile("sjk-agent", ".jar");
}
Manifest mf = new Manifest();
mf.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0");
mf.getMainAttributes().put(new Attributes.Name("Agent-Class"), ANCHOR_CLASS.getName());
mf.getMainAttributes().put(new Attributes.Name("Premain-Class"), ANCHOR_CLASS.getName());
mf.getMainAttributes().put(new Attributes.Name("Can-Redefine-Classes"), "false");
FileOutputStream fos = new FileOutputStream(targetJar);
fos.write(createBootstrapperJar(mf, root));
fos.close();
return targetJar.getAbsolutePath();
}
private static byte[] createBootstrapperJar(Manifest manifest, File root) throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ZipOutputStream jarOut = new ZipOutputStream(bos);
if (manifest != null) {
ZipEntry e = new ZipEntry(JarFile.MANIFEST_NAME);
e.setTime(0l); // this to ensure equal hash for equal content
jarOut.putNextEntry(e);
manifest.write(jarOut);
jarOut.closeEntry();
}
addFiles(jarOut, root, "");
jarOut.close();
byte[] jarFile = bos.toByteArray();
return jarFile;
}
private static void addFiles(ZipOutputStream jarOut, File path, String prefix) throws IOException, MalformedURLException {
File[] list = path.listFiles();
for(File fpath: list) {
String jpath = prefix + fpath.getName();
if (fpath.isDirectory()) {
addFiles(jarOut, fpath, jpath + "/");
} else {
if (jpath.equals(JarFile.MANIFEST_NAME)) {
continue;
}
ZipEntry entry = new ZipEntry(jpath);
entry.setTime(0); // this is to facilitate content cache
jarOut.putNextEntry(entry);
copy(new FileInputStream(fpath), jarOut);
jarOut.closeEntry();
}
}
}
private static void copy(InputStream in, OutputStream out) throws IOException {
try {
byte[] buf = new byte[1 << 12];
while(true) {
int n = in.read(buf);
if(n >= 0) {
out.write(buf, 0, n);
}
else {
break;
}
}
} finally {
try {
in.close();
}
catch(Exception e) {
// ignore
}
}
}
}