/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.
*/
package org.apache.blur.command.stream;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.HashSet;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarOutputStream;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.output.ByteArrayOutputStream;
import com.google.common.base.Splitter;
public class StreamUtil {
private static final String UTF_8 = "UTF-8";
private static final char JAR_END = '!';
private static final String JAR_START = "jar:";
private static final String TMP_BLUR_JOB = "tmp-blur-job_";
private static final String JAR = ".jar";
private static final String SEP = "/";
private static final String PATH_SEPARATOR = "path.separator";
private static final String JAVA_CLASS_PATH = "java.class.path";
public static void writeString(DataOutput output, String s) throws IOException {
try {
byte[] bs = s.getBytes(UTF_8);
output.writeInt(bs.length);
output.write(bs);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("Does not supported UTF-8?", e);
}
}
public static String readString(DataInput input) throws IOException {
int length = input.readInt();
byte[] buf = new byte[length];
input.readFully(buf);
return new String(buf, UTF_8);
}
public static byte[] toBytes(Serializable s) throws IOException {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(outputStream);
out.writeObject(s);
out.close();
return outputStream.toByteArray();
}
public static String[] getJarPaths(Class<?>... clazzes) throws IOException {
Set<String> classPathThatNeedsToBeIncluded = findJarFiles(clazzes);
Set<String> jars = new HashSet<String>();
for (String s : classPathThatNeedsToBeIncluded) {
if (isJarFile(s)) {
jars.add(s);
} else {
jars.add(createJar(s));
}
}
return jars.toArray(new String[jars.size()]);
}
private static Set<String> findJarFiles(Class<?>[] clazzes) {
Set<String> result = new HashSet<String>();
for (Class<?> c : clazzes) {
result.add(findJarFile(c));
}
return result;
}
private static String findJarFile(Class<?> c) {
String resourceName = "/" + c.getName().replace('.', '/') + ".class";
URL url = StreamUtil.class.getResource(resourceName);
try {
URI uri = url.toURI();
if (uri.getScheme().equals("file")) {
return findFileInClassFileUri(uri);
} else if (uri.getScheme().equals("jar")) {
return findFileInJarFileUri(uri);
} else {
throw new RuntimeException("Unsupported schema [" + uri.getScheme() + "] for uri [" + uri + "]");
}
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
}
private static String findFileInClassFileUri(URI uri) {
String classPath = System.getProperty(JAVA_CLASS_PATH);
String pathSeparator = System.getProperty(PATH_SEPARATOR);
Splitter splitter = Splitter.on(pathSeparator);
Iterable<String> split = splitter.split(classPath);
String path = uri.getPath();
for (String s : split) {
if (path.startsWith(s)) {
return new File(s).getAbsolutePath();
}
}
throw new RuntimeException("Uri [" + uri + "] was not found on the classpath.");
}
private static String findFileInJarFileUri(URI uri) throws URISyntaxException {
String s = uri.toString();
int indexOf1 = s.indexOf(JAR_START);
int indexOf2 = s.indexOf(JAR_END);
return new File(new URI(s.substring(indexOf1 + JAR_START.length(), indexOf2))).getAbsolutePath();
}
private static String createJar(String s) throws IOException {
File sourceFile = new File(s);
if (sourceFile.isDirectory()) {
File file = File.createTempFile(TMP_BLUR_JOB, JAR);
OutputStream outputStream = new BufferedOutputStream(new FileOutputStream(file));
JarOutputStream jarOut = new JarOutputStream(outputStream);
for (File f : sourceFile.listFiles()) {
pack(sourceFile, f, jarOut);
}
jarOut.close();
file.deleteOnExit();
return file.getAbsolutePath();
}
throw new RuntimeException("File [" + s + "] is not a directory.");
}
private static void pack(File rootPath, File source, JarOutputStream target) throws IOException {
String name = getName(rootPath, source);
if (source.isDirectory()) {
if (!SEP.equals(name)) {
JarEntry entry = new JarEntry(name);
entry.setTime(source.lastModified());
target.putNextEntry(entry);
target.closeEntry();
}
for (File f : source.listFiles()) {
pack(rootPath, f, target);
}
} else {
JarEntry entry = new JarEntry(name);
entry.setTime(source.lastModified());
target.putNextEntry(entry);
BufferedInputStream in = new BufferedInputStream(new FileInputStream(source));
IOUtils.copy(in, target);
in.close();
target.closeEntry();
}
}
private static String getName(File rootPath, File source) {
String rootStr = rootPath.toURI().toString();
String sourceStr = source.toURI().toString();
if (sourceStr.startsWith(rootStr)) {
String result = sourceStr.substring(rootStr.length());
if (source.isDirectory() && !result.endsWith(SEP)) {
result += SEP;
}
return result;
} else {
throw new RuntimeException("Not sure what happened.");
}
}
private static boolean isJarFile(String s) {
if (s.endsWith(JAR) || s.endsWith(".zip")) {
return true;
}
return false;
}
}