package net.sf.lab3f.util;
import java.io.File;
import java.io.InputStream;
import java.io.IOException;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.MalformedURLException;
import java.nio.channels.Channels;
import java.nio.channels.WritableByteChannel;
import java.security.MessageDigest;
/**
* Реализация интерфейсов TuttiFruttiable и Groovyable. Обратите
* внимание, что вследствие слишком большого объема jar-библиотеки
* Groovy включить ее в бандл не удалось, поэтому метод содержит
* специфический ClassLoader.
*/
public class Main implements /*Groovyable,*/ TuttiFruttiable{
private Object groovyShell;
private ClassLoader groovyRootLoader;
public String join(String[] sa, String j){
StringBuffer sb = new StringBuffer();
for(String s : sa)sb.append(s + j);
String ret = sb.toString();
return ret.substring(0, ret.lastIndexOf(j));
}
public Object eval(InputStream is)throws Exception {
return getGroovyEvalMethod(InputStream.class).invoke(groovyShell, new Object[]{is});
}
public Object eval(File f)throws Exception {
return getGroovyEvalMethod(File.class).invoke(groovyShell, new Object[]{f});
}
public Object eval(String script)throws Exception {
return getGroovyEvalMethod(String.class).invoke(groovyShell, new Object[]{script});
}
private class GroovyLoader extends ClassLoader{
private URL jarUrl;
public Class findClass(String cln){
try{
if(jarUrl == null)jarUrl = new URL("jar:file:lib/groovy.jar!/");
URL url = new URL(jarUrl, cln.replace('.', '/') + ".class");
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
final WritableByteChannel wbch = Channels.newChannel(baos);
ch2ch(Channels.newChannel(url.openStream()), wbch);
final byte[] ba = baos.toByteArray();
return defineClass(cln, ba, 0, ba.length);
}
catch(IOException ex){return null;}
}
protected final URL findResource(String name){
try{return new URL(jarUrl, name);}
catch(MalformedURLException ex){return null;}
}
}
public byte[] getMd5Bytes(byte[] ba){
try{
MessageDigest digest = MessageDigest.getInstance("MD5");
digest.update(ba);
return digest.digest();
}
catch(java.security.NoSuchAlgorithmException ex){return null;}
}
public String getMd5String(String s){
try{
MessageDigest digest = MessageDigest.getInstance("MD5");
digest.update(s.getBytes());
return toHexString(digest.digest());
}
catch(java.security.NoSuchAlgorithmException ex){return null;}
}
public String toHexString(byte[] block) {
StringBuffer buf = new StringBuffer();
char[] hexChars = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'A', 'B', 'C', 'D', 'E', 'F' };
int len = block.length;
int high = 0;
int low = 0;
for (int i = 0; i < len; i++) {
high = ((block[i] & 0xf0) >> 4);
low = (block[i] & 0x0f);
buf.append(hexChars[high]);
buf.append(hexChars[low]);
}
return buf.toString();
}
public final String stream2string(InputStream is) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
stream2stream(is, baos);
byte[] ba = baos.toByteArray();
return new String(ba, "UTF8");
}
public final void stream2stream(InputStream is, OutputStream os) throws IOException {
ch2ch(Channels.newChannel(is), Channels.newChannel(os));
is.close();
os.close();
}
public final void ch2ch(final ReadableByteChannel src, final WritableByteChannel dest) throws IOException {
final ByteBuffer buffer = ByteBuffer.allocateDirect(16 * 1024);
while (src.read(buffer) != -1) {
buffer.flip();
dest.write(buffer);
buffer.compact();
}
buffer.flip();
while (buffer.hasRemaining())dest.write(buffer);
}
private final String Base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
public byte[] decodeB64(String str) {
if (str.length() % 4 != 0) return null;
ByteArrayOutputStream bs = new ByteArrayOutputStream();
DataOutputStream ds = new DataOutputStream(bs);
for (int i = 0; i < (str.length() + 3) / 4; i++) {
short [] s = new short[4];
short [] t = new short[3];
for (int j = 0; j < 4; j++)
s[j] = (short) Base64.indexOf(str.charAt(i*4+j));
t[0] = (short) ((s[0] << 2) + (s[1] >> 4));
if (s[2] == 64) t[1] = t[2] = (short) (-1);
else if (s[3] == 64) {
t[1] = (short) (((s[1] << 4) + (s[2] >> 2)) & 0xFF);
t[2] = (short) (-1);
}
else {
t[1] = (short) (((s[1] << 4) + (s[2] >> 2)) & 0xFF);
t[2] = (short) (((s[2] << 6) + s[3]) & 0xFF);
}
try {for (int j = 0; j < 3; j++) if (t[j] >= 0) ds.writeByte(t[j]);}
catch (IOException e) {}
}
return bs.toByteArray();
}
public final String encodeB64(byte [] b) {
ByteArrayOutputStream os = new ByteArrayOutputStream();
for (int i = 0; i < (b.length + 2) / 3; i++) {
short [] s = new short[3];
short [] t = new short[4];
for (int j = 0; j < 3; j++) {
if ((i * 3 + j) < b.length)
s[j] = (short) (b[i*3+j] & 0xFF);
else s[j] = -1;
}
t[0] = (short) (s[0] >> 2);
if (s[1] == -1) t[1] = (short) (((s[0] & 0x3) << 4));
else t[1] = (short) (((s[0] & 0x3) << 4) + (s[1] >> 4));
if (s[1] == -1) t[2] = t[3] = 64;
else if (s[2] == -1) {
t[2] = (short) (((s[1] & 0xF) << 2));
t[3] = 64;
}
else {
t[2] = (short) (((s[1] & 0xF) << 2) + (s[2] >> 6));
t[3] = (short) (s[2] & 0x3F);
}
for (int j = 0; j < 4; j++) os.write(Base64.charAt(t[j]));
}
return new String(os.toByteArray());
}
private Method getGroovyEvalMethod(Class cl) throws Exception {
if(groovyShell == null){
GroovyLoader gl = new GroovyLoader();
Class lcClass = Class.forName("org.codehaus.groovy.tools.LoaderConfiguration", true, gl);
Class rlClass = Class.forName("org.codehaus.groovy.tools.RootLoader", true, gl);
Constructor rlConstr = rlClass.getConstructor(lcClass);
Object lcObj = lcClass.newInstance();
Method addCp = lcClass.getMethod("addClassPath", String.class);
addCp.invoke(lcObj, new Object[]{"../_classes/raw"});
ClassLoader groovyRootLoader = (ClassLoader)rlConstr.newInstance(lcObj);
Class shClass = Class.forName("groovy.lang.GroovyShell", true, groovyRootLoader);
groovyShell = shClass.newInstance();
}
return groovyShell.getClass().getMethod("evaluate", cl);
}
}