/* This file is part of VoltDB.
* Copyright (C) 2008-2017 VoltDB Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with VoltDB. If not, see <http://www.gnu.org/licenses/>.
*/
package org.voltdb.compiler;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;
import org.voltdb.utils.InMemoryJarfile;
import org.voltdb.utils.InMemoryJarfile.JarLoader;
public class VoltCompilerUtils
{
/**
* Read a file from a jar in the form path/to/jar.jar!/path/to/file.ext
*/
static String readFileFromJarfile(String fulljarpath) throws IOException {
assert (fulljarpath.contains(".jar!"));
String[] paths = fulljarpath.split("!");
if (paths[0].startsWith("file:"))
paths[0] = paths[0].substring("file:".length());
paths[1] = paths[1].substring(1);
return readFileFromJarfile(paths[0], paths[1]);
}
static String readFileFromJarfile(String jarfilePath, String entryPath) throws IOException {
InputStream fin = null;
try {
URL jar_url = new URL(jarfilePath);
fin = jar_url.openStream();
} catch (MalformedURLException ex) {
// Invalid URL. Try as a file.
fin = new FileInputStream(jarfilePath);
}
JarInputStream jarIn = new JarInputStream(fin);
JarEntry catEntry = jarIn.getNextJarEntry();
while ((catEntry != null) && (catEntry.getName().equals(entryPath) == false)) {
catEntry = jarIn.getNextJarEntry();
}
if (catEntry == null) {
jarIn.close();
return null;
}
byte[] bytes = InMemoryJarfile.readFromJarEntry(jarIn);
return new String(bytes, "UTF-8");
}
private static String classNameToPackagePath(String className) {
return className.replace('.', '/') + ".class";
}
public static boolean addClassToJar(InMemoryJarfile jarOutput, final Class<?> cls)
throws IOException
{
String packagePath = classNameToPackagePath(cls.getName());
String realName = cls.getName();
realName = realName.substring(realName.lastIndexOf('.') + 1);
realName += ".class";
byte [] classBytes = null;
try {
classBytes = getClassAsBytes(cls);
} catch (Exception e) {
final String msg = "Unable to locate classfile for " + realName;
throw new IOException(msg);
}
jarOutput.put(packagePath, classBytes);
return true;
}
public static boolean containsClassName(InMemoryJarfile jarOutput, String className) {
String packagePath = classNameToPackagePath(className);
return jarOutput.get(packagePath) != null;
}
public static byte[] getClassAsBytes(final Class<?> c) throws IOException {
ClassLoader cl = c.getClassLoader();
if (cl == null) {
cl = Thread.currentThread().getContextClassLoader();
}
String classAsPath = classNameToPackagePath(c.getName());
if (cl instanceof JarLoader) {
InMemoryJarfile memJar = ((JarLoader) cl).getInMemoryJarfile();
return memJar.get(classAsPath);
}
else {
BufferedInputStream cis = null;
ByteArrayOutputStream baos = null;
try {
cis = new BufferedInputStream(cl.getResourceAsStream(classAsPath));
baos = new ByteArrayOutputStream();
byte [] buf = new byte[1024];
int rsize = 0;
while ((rsize=cis.read(buf)) != -1) {
baos.write(buf, 0, rsize);
}
} finally {
try { if (cis != null) cis.close();} catch (Exception ignoreIt) {}
try { if (baos != null) baos.close();} catch (Exception ignoreIt) {}
}
return baos.toByteArray();
}
}
public static InMemoryJarfile createClassesJar(Class<?>... classes) throws IOException {
InMemoryJarfile jarMem = new InMemoryJarfile();
for (Class<?> cls : classes) {
addClassToJar(jarMem, cls);
}
return jarMem;
}
}