Переглянути джерело

增加重新加载类辅助类。

airhead 7 роки тому
батько
коміт
ba9aff8b9b

+ 133 - 0
hos-broker/src/main/java/com/yihu/hos/broker/util/Cols.java

@ -0,0 +1,133 @@
package com.yihu.hos.broker.util;
import com.yihu.hos.broker.util.funct.F0;
import com.yihu.hos.broker.util.funct.F1;
import java.util.*;
/**
 * Created by QuanLA
 * Date: Mar 2, 2006
 * Time: 9:10:49 AM
 */
@SuppressWarnings({"rawtypes","unchecked"})
public class Cols {
	/**
	 * If a collection is empty
	 * @param objs
	 * @return
	 */
	public static boolean isEmpty(Collection<?> objs) {
		return objs == null || objs.isEmpty();
	}
	/**
	 * If a collection is not empty
	 * @param col
	 * @return
	 */
    public static boolean isNotEmpty(Collection<?> col) {
        return !isEmpty(col);
    }
	
    /**
     * Get single element, or null if Col is empty
     * @param collection
     * @return
     */
    public static <A> A getSingle(
            Collection<A> collection) {
    	if (collection == null) {
    		return null;
    	}
        for (A a : collection) {
            return a;
        }
        return null;
    }
	
    public static <A> List<A> createList(int size, F0<A> f) {
        ArrayList<A> list = new ArrayList<A>(size);
        for (int i = 0; i < size; i++) {
            list.add(f.e());
        }
        return list;
    }
	
    /**
     * Create a string connecting all values in collection, separated with delimiter
     * @param objs
     * @param delimiter
     * @return
     */
	public static <A> String join(Iterable<A> objs, String delimiter) {
        if (objs == null) {
            return "";
        }
		StringBuilder sb = new StringBuilder();
		for (A a : objs) {
			sb.append(a).append(delimiter);
		}
		if (sb.length() > 0) {
			sb.setLength(sb.length() - delimiter.length());
		}
		return sb.toString();
	}
	
	
	public static <A,T> List<T> yield(List<A> col, F1<A, T> f1) {
        if (col!=null) {
            return yield(col, new ArrayList<T>(col.size()), f1);
        } else {
            return null;
        }
    }
	
	/**
	 * Apply function on every elements to get new collection of returned value
	 * @param <A>
	 * @param <T>
	 * @param <C>
	 * @param inputs
	 * @param col
	 * @param f1
	 * @return
	 */
	public static <A,T,C extends Collection<T>> C yield(Iterable<A> inputs, C col, F1<A, T> f1) {
//		ArrayList<T> list = new ArrayList<T>();
		if (inputs!=null) {
            for (A a : inputs) {
                T e = f1.e(a);
				if (e != null) {
					col.add(e);
				}
            }
		}
		return col;
	}
	/**
     * Create a map based on the Object... param. Each 2 values is an entry
     * which is a pair of key then value
     * @param objects The params that will be converted to map.
     * 					Format: [key1, value1, key2, value2]
     * @return The map after converted from param objects
     */
//    @SuppressWarnings({"unchecked"})
    public static <A, B> Map<A, B> map(Object... objects) {
    	if (objects==null) {
    		return null;
    	}
        Map<A, B> map = new LinkedHashMap<A, B>(objects.length / 2);
        for (int i = 0; i < objects.length; i+=2) {
            map.put((A)objects[i], (B)objects[i + 1]);
        }
        return map;
    }
}

+ 89 - 0
hos-broker/src/main/java/com/yihu/hos/broker/util/FileUtil.java

@ -0,0 +1,89 @@
package com.yihu.hos.broker.util;
import com.yihu.hos.broker.util.funct.F1;
import com.yihu.hos.broker.util.funct.F2;
import com.yihu.hos.broker.util.funct.Fs;
import com.yihu.hos.broker.util.funct.P2;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
@SuppressWarnings("UnusedDeclaration")
public class FileUtil {
	/**
	 * 
	 * @param fileToRead
	 * @return
	 * @throws IOException
	 */
	public static byte[] readFileToBytes(File fileToRead) {
		try {
			return IOUtil.readData(new FileInputStream(fileToRead));
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
	}
    public static FileInputStream fileInputStream(File file) {
        try {
            return new FileInputStream(file);
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        }
    }
    public static FileInputStream fileInputStream(String file) {
        try {
            return new FileInputStream(file);
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        }
    }
	
    public static void eachFile(File path, P2<File, String> f) {
        eachFile(path, f, null);
    }
	
    public static void eachFile(File path, P2<File, String> f, F1<File, Boolean> exclude) {
    	eachFile(path, Fs.f2(f, true), exclude);
    }
	
    public static void eachFile(File path, F2<File, String,Boolean> f, F1<File, Boolean> exclude) {
        ArrayList<String> relPath = new ArrayList<>();
        if (path.isFile()) {
            f.e(path, Cols.join(relPath, File.separator));
        } else {
            if (!eachFileInDir(path, f, relPath, exclude)) return;
        }
    }
	
    private static boolean eachFileInDir(File path, F2<File, String,Boolean> f, ArrayList<String> relPath, F1<File, Boolean> exclude) {
        if (!path.exists() || !path.isDirectory()) {
            throw new RuntimeException("Invalid path: " + path);
        }
        for (File child : path.listFiles()) {
            if (exclude != null && exclude.e(child)) {
//            	System.out.println("Excluded " + child);
                continue;
            }
//        	System.out.println("Accepted " + child);
            if (child.isFile()) {
                if (!f.e(child, Cols.join(relPath, File.separator))) return false;
            } else {
                relPath.add(child.getName());
                if (!eachFileInDir(child, f, relPath, exclude)) return false;
                relPath.remove(relPath.size() - 1);
            }
        }
        return true;
    }
}

+ 188 - 0
hos-broker/src/main/java/com/yihu/hos/broker/util/IOUtil.java

@ -0,0 +1,188 @@
package com.yihu.hos.broker.util;
import java.io.*;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
 * Created by Quan on 22/12/2014.
 */
public class IOUtil {
	
	/**
	 * Read the stream into byte array
	 * @param inputStream
	 * @return
	 * @throws IOException
	 */
    public static byte[] readData(InputStream inputStream) {
        try {
			return readDataNice(inputStream);
		} finally {
        	close(inputStream);
		}
    }
    public static byte[] readDataNice(InputStream inputStream) {
		ByteArrayOutputStream boTemp = null;
        byte[] buffer = null;
        try {
            int read;
			buffer = new byte[8192];
            boTemp = new ByteArrayOutputStream();
            while ((read=inputStream.read(buffer, 0, 8192)) > -1) {
                boTemp.write(buffer, 0, read);
            }
            return boTemp.toByteArray();
        } catch (IOException e) {
			throw new RuntimeException(e);
        }
	}
	
	
    /**
     * Close streams (in or out)
     * @param stream
     */
    public static void close(Closeable stream) {
        if (stream != null) {
            try {
                if (stream instanceof Flushable) {
                    ((Flushable)stream).flush();
                }
                stream.close();
            } catch (IOException e) {
                // When the stream is closed or interupted, can ignore this exception
            }
        }
    }
	public static void close(Connection conn) {
        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException e) {
                // When the conn is closed or interupted, can ignore this exception
			}
        }
		
	}
    public static void close(ResultSet rs) {
    	if (rs != null) {
    		try {
    			rs.close();
    		} catch (SQLException e) {
    			// When the file is closed already, can ignore this exception
    		}
    	}
    }
    public static void close(PreparedStatement ps) {
    	if (ps != null) {
    		try {
    			ps.close();
    		} catch (SQLException e) {
    			// When the file is closed already, can ignore this exception
    		}
    	}
    }
	
	/**
	 * Will close stream
	 * @param in
	 * @param charSet
	 * @return
	 */
	public static String toString(InputStream in, String charSet) {
		return inputStreamToString_force(in, charSet);
	}
	
	/**
	 * Will close stream
	 * @param in
	 * @param charSet
	 * @return
	 */
	public static String inputStreamToString_force(InputStream in, String charSet) {
		try {
			return inputStreamToString(in, charSet);
		} catch (IOException e) {
			return null;
		}
	}
    /**
     * Reads in whole input stream and returns as a string<br>
     * Will close stream
     * @param in The input stream to read in, will be closed 
     * 				by this method at finish
     * @param charSet charset to convert the input bytes into string
     * @return the result string
     * @throws IOException
     */
	public static String inputStreamToString(InputStream in, String charSet) throws IOException {
		InputStreamReader inputStreamReader = null;
		try {
			inputStreamReader = charSet == null? new InputStreamReader(in) : new InputStreamReader(in, charSet);
			return toString(inputStreamReader);
		} catch (UnsupportedEncodingException e1) {
			throw new RuntimeException(e1);
		} finally {
			close(in);
		}
	}
	
    /**
     * Reads in whole input stream and returns as a string
     * @param reader The input reader to read in, will be closed 
     * 				by this method at finish
     * @return the result string
     * @throws IOException
     */
	public static String toString(Reader reader) {
		try {
			StringBuilder sb = new StringBuilder();
			char[] buffer = new char[4096];
			for (int read; (read = reader.read(buffer)) > -1;) {
				sb.append(buffer, 0, read);
			}
			return sb.toString();
		} catch (IOException e) {
			throw new RuntimeException(e);
		} finally {
			close(reader);
		}
	}
	/**
	 * Read the input stream and write to output stream
	 * @param inputStream
	 * @param out
	 * @return
	 * @throws IOException
	 */
    public static long connect(InputStream inputStream, OutputStream out) throws IOException {
        try {
            return dump(inputStream, out);
        } finally {
            close(inputStream);
        }
    }
    
    private static long dump(InputStream inputStream, OutputStream out) throws IOException {
        long total = 0;
        int read;
        int bufferSize = 8192;
        byte[] buffer = new byte[bufferSize];
        while ((read=inputStream.read(buffer, 0, bufferSize)) > -1) {
            out.write(buffer, 0, read);
            total+=read;
        }
        out.flush();
        return total;
    }
}

+ 14 - 0
hos-broker/src/main/java/com/yihu/hos/broker/util/funct/F0.java

@ -0,0 +1,14 @@
package com.yihu.hos.broker.util.funct;
/**
 * Represent a function that accept no parameter and return value
 * @param <T> The return value
 */
public interface F0<T> {
    /**
     * Evaluate or execute the function
     * @return Result of execution
     */
    T e();
}

+ 15 - 0
hos-broker/src/main/java/com/yihu/hos/broker/util/funct/F1.java

@ -0,0 +1,15 @@
package com.yihu.hos.broker.util.funct;
/**
 * Represent a function that accept one parameter and return value
 * @param <A> The only parameter
 * @param <T> The return value
 */
public interface F1<A, T> {
    /**
     * Evaluate or execute the function
     * @param obj The parameter
     * @return Result of execution
     */
	T e(A obj);
}

+ 5 - 0
hos-broker/src/main/java/com/yihu/hos/broker/util/funct/F2.java

@ -0,0 +1,5 @@
package com.yihu.hos.broker.util.funct;
public interface F2<A, B, T>{
	T e(A a, B b);
}

+ 45 - 0
hos-broker/src/main/java/com/yihu/hos/broker/util/funct/Fs.java

@ -0,0 +1,45 @@
package com.yihu.hos.broker.util.funct;
import java.util.Collection;
import java.util.concurrent.atomic.AtomicReference;
/**
 * The utility that employ idea of functional programming
 *
 */
@SuppressWarnings({"unchecked", "rawtypes"})
public class Fs extends FsGenerated {
	
    public static Runnable runnable(final P0 action) {
        return new Runnable() {
            public void run() {
                action.e();
            }
        };
    }
	
	/**
	 * Just store the object to collection
	 * @param col
	 * @return
	 */
    public static <A> P1<A> store(final Collection<A> col) {
        return new P1<A>() {public void e(A a) {
            col.add(a);
        }};
    }
    
	public static <A> P1<A> setter(
			final AtomicReference<A> ref) {
		return new P1<A>() {public void e(A obj) {
			ref.set(obj);
		}};
	}
	
	public static <A> void invokeAll(final Collection<P1<A>> col, A a) {
		for (P1<A> p1 : col) {
			p1.e(a);
		}
	}
}

+ 40 - 0
hos-broker/src/main/java/com/yihu/hos/broker/util/funct/FsGenerated.java

@ -0,0 +1,40 @@
package com.yihu.hos.broker.util.funct;
public class FsGenerated {
	/**
	 * Convert from a p0 to p1
	 * @return p1
	 */
	public static <A> P1<A> p1(final P0 p0) {
		return new P1<A>(){public void e(final A a) {
			p0.e();
		}};
	}
	
	/**
	 * Call to p and return fixed value
	 * @param p1 the function to call before return value
	 * @param ret the fixed value to return
	 * @return ret
	 */
	public static <A, R> F1<A, R> f1(final P1<A> p1, final R ret) {
		return new F1<A, R>(){public R e(final A a) {
			p1.e(a);
			return ret;
		}};
	}
	
	/**
	 * Call to p and return fixed value
	 * @param p2 the function to call before return value
	 * @param ret the fixed value to return
	 * @return ret
	 */
	public static <A, B, R> F2<A, B, R> f2(final P2<A, B> p2, final R ret) {
		return new F2<A, B, R>(){public R e(final A a, final B b) {
			p2.e(a, b);
			return ret;
		}};
	}
}

+ 5 - 0
hos-broker/src/main/java/com/yihu/hos/broker/util/funct/P0.java

@ -0,0 +1,5 @@
package com.yihu.hos.broker.util.funct;
public interface P0 {
	void e();
}

+ 11 - 0
hos-broker/src/main/java/com/yihu/hos/broker/util/funct/P1.java

@ -0,0 +1,11 @@
package com.yihu.hos.broker.util.funct;
/**
 * Function that accept 1 objects and return nothing
 * @author QuanLA
 *
 * @param <A>
 */
public interface P1<A> {
	void e(A obj);
}

+ 12 - 0
hos-broker/src/main/java/com/yihu/hos/broker/util/funct/P2.java

@ -0,0 +1,12 @@
package com.yihu.hos.broker.util.funct;
/**
 * Function that accept 2 objects and return nothing
 * @author QuanLA
 *
 * @param <A>
 * @param <B>
 */
public interface P2<A, B> {
	void e(A a, B b);
}

+ 5 - 0
hos-broker/src/main/java/com/yihu/hos/broker/util/funct/P3.java

@ -0,0 +1,5 @@
package com.yihu.hos.broker.util.funct;
public interface P3<A, B, C> {
	void e(A a, B b, C c);
}

+ 65 - 0
hos-broker/src/main/java/com/yihu/hos/broker/util/lang/AggressiveClassLoader.java

@ -0,0 +1,65 @@
package com.yihu.hos.broker.util.lang;
import java.util.HashSet;
import java.util.Set;
/**
 * Load all classes it can, leave the rest to the Parent ClassLoader
 */
public abstract class AggressiveClassLoader extends ClassLoader {
	Set<String> loadedClasses = new HashSet<>();
	Set<String> unavaiClasses = new HashSet<>();
    private ClassLoader parent = AggressiveClassLoader.class.getClassLoader();
    @Override
	public Class<?> loadClass(String name) throws ClassNotFoundException {
		if (loadedClasses.contains(name) || unavaiClasses.contains(name)) {
			return super.loadClass(name); // Use default CL cache
		}
		byte[] newClassData = loadNewClass(name);
		if (newClassData != null) {
			loadedClasses.add(name);
			return loadClass(newClassData, name);
		} else {
			unavaiClasses.add(name);
			return parent.loadClass(name);
		}
	}
//    public AggressiveClassLoader setParent(ClassLoader parent) {
//        this.parent = parent;
//        return this;
//    }
	
	/**
	 * Handle exception
	 * @param name
	 * @return
	 */
	public Class<?> load(String name) {
		try {
			return loadClass(name);
		} catch (ClassNotFoundException e) {
			throw new RuntimeException(e);
		}
	}
	
	protected abstract byte[] loadNewClass(String name);
	public Class<?> loadClass(byte[] classData, String name) {
		Class<?> clazz = defineClass(name, classData, 0, classData.length);
		if (clazz != null) {
			if (clazz.getPackage() == null) {
				definePackage(name.replaceAll("\\.\\w+$", ""), null, null, null, null, null, null, null);
			}
			resolveClass(clazz);
		}
		return clazz;
	}
	public static String toFilePath(String name) {
		return name.replaceAll("\\.", "/") + ".class";
	}
}

+ 110 - 0
hos-broker/src/main/java/com/yihu/hos/broker/util/lang/DynamicClassLoader.java

@ -0,0 +1,110 @@
package com.yihu.hos.broker.util.lang;
//import qj.util.FileUtil;
//import qj.util.IOUtil;
//import qj.util.funct.F1;
import com.yihu.hos.broker.util.FileUtil;
import com.yihu.hos.broker.util.IOUtil;
import com.yihu.hos.broker.util.funct.F1;
import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.LinkedList;
import java.util.jar.JarFile;
import java.util.zip.ZipEntry;
public class DynamicClassLoader extends AggressiveClassLoader {
    LinkedList<F1<String, byte[]>> loaders = new LinkedList<>();
    public DynamicClassLoader(String... paths) {
        for (String path : paths) {
            File file = new File(path);
            F1<String, byte[]> loader = loader(file);
            if (loader == null) {
                throw new RuntimeException("Path not exists " + path);
            }
            loaders.add(loader);
        }
    }
    @SuppressWarnings("UnusedDeclaration")
    public DynamicClassLoader(Collection<File> paths) {
        for (File file : paths) {
            F1<String, byte[]> loader = loader(file);
            if (loader == null) {
                throw new RuntimeException("Path not exists " + file.getPath());
            }
            loaders.add(loader);
        }
    }
    public static F1<String, byte[]> loader(File file) {
        if (!file.exists()) {
            return null;
        } else if (file.isDirectory()) {
            return dirLoader(file);
        } else {
            try {
                final JarFile jarFile = new JarFile(file);
                return jarLoader(jarFile);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }
    private static File findFile(String filePath, File classPath) {
        File file = new File(classPath, filePath);
        return file.exists() ? file : null;
    }
    public static F1<String, byte[]> dirLoader(final File dir) {
        return filePath -> {
            File file = findFile(filePath, dir);
            if (file == null) {
                return null;
            }
            return FileUtil.readFileToBytes(file);
        };
    }
    private static F1<String, byte[]> jarLoader(final JarFile jarFile) {
        return new F1<String, byte[]>() {
            public byte[] e(String filePath) {
                ZipEntry entry = jarFile.getJarEntry(filePath);
                if (entry == null) {
                    return null;
                }
                try {
                    return IOUtil.readData(jarFile.getInputStream(entry));
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            @Override
            protected void finalize() throws Throwable {
                IOUtil.close(jarFile);
                super.finalize();
            }
        };
    }
    @Override
    protected byte[] loadNewClass(String name) {
//		System.out.println("Loading class " + name);
        for (F1<String, byte[]> loader : loaders) {
            byte[] data = loader.e(AggressiveClassLoader.toFilePath(name));
            if (data != null) {
                return data;
            }
        }
        return null;
    }
}

+ 28 - 0
hos-broker/src/main/java/com/yihu/hos/broker/util/lang/ExceptingClassLoader.java

@ -0,0 +1,28 @@
package com.yihu.hos.broker.util.lang;
import com.yihu.hos.broker.util.funct.F1;
/**
 * This class loader will not load certain classes, instead delegate to parent
 * class loader to do the job
 */
@SuppressWarnings("UnusedDeclaration")
public class ExceptingClassLoader extends DynamicClassLoader {
	private F1<String, Boolean> except;
	public ExceptingClassLoader(F1<String, Boolean> except, String... paths) {
		super(paths);
		this.except = except;
	}
	@Override
	protected byte[] loadNewClass(String name) {
		if (except.e(name)) {
            return null;
		}
		return super.loadNewClass(name);
	}
}