if (buf.length() == 0) {
return null;
}
LOG.debug("Creating jar file for coprocessor classes: " + buf.toString());
final Hasher hasher = Hashing.md5().newHasher();
final byte[] buffer = new byte[COPY_BUFFER_SIZE];
final Map<String, URL> dependentClasses = new HashMap<String, URL>();
for (Class<? extends Coprocessor> clz : classes) {
Dependencies.findClassDependencies(clz.getClassLoader(), new Dependencies.ClassAcceptor() {
@Override
public boolean accept(String className, final URL classUrl, URL classPathUrl) {
// Assuming the endpoint and protocol class doesn't have dependencies
// other than those comes with HBase and Java.
if (className.startsWith("co.cask")) {
if (!dependentClasses.containsKey(className)) {
dependentClasses.put(className, classUrl);
}
return true;
}
return false;
}
}, clz.getName());
}
if (!dependentClasses.isEmpty()) {
LOG.debug("Adding " + dependentClasses.size() + " classes to jar");
File jarFile = File.createTempFile(filePrefix, ".jar");
try {
JarOutputStream jarOutput = null;
try {
jarOutput = new JarOutputStream(new FileOutputStream(jarFile));
for (Map.Entry<String, URL> entry : dependentClasses.entrySet()) {
try {
jarOutput.putNextEntry(new JarEntry(entry.getKey().replace('.', File.separatorChar) + ".class"));
InputStream inputStream = entry.getValue().openStream();
try {
int len = inputStream.read(buffer);
while (len >= 0) {
hasher.putBytes(buffer, 0, len);
jarOutput.write(buffer, 0, len);
len = inputStream.read(buffer);
}
} finally {
inputStream.close();
}
} catch (IOException e) {
LOG.info("Error writing to jar", e);
throw Throwables.propagate(e);
}
}
} finally {
if (jarOutput != null) {
jarOutput.close();
}
}
// Copy jar file into HDFS
// Target path is the jarDir + jarMD5.jar
final Location targetPath = jarDir.append("coprocessor" + hasher.hash().toString() + ".jar");
// If the file exists and having same since, assume the file doesn't changed
if (targetPath.exists() && targetPath.length() == jarFile.length()) {
return targetPath;
}