All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.distributeme.agents.AgentPackageUtility Maven / Gradle / Ivy

There is a newer version: 4.0.2
Show newest version
package org.distributeme.agents;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamClass;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class AgentPackageUtility {
	public static AgentPackage pack(Agent agent){
		AgentPackage ret = new AgentPackage();
	
		try{
			ret.setRootClazzName(agent.getClass().getName());
			ret.setSerializedData(serializeAgent(agent));
			List> classes = scanForCustomClasses(agent);
			for (Class c : classes){
				ret.addClazzDefinition(c.getName(), readClass(c));
			}
		}catch(IOException e){
			throw new RuntimeException("Couldn't pack agent "+agent, e);
		}
		return ret;
	}
	
	private static byte[] readClass(Class c){
		InputStream in = null;
		try{
			String path = c.getSimpleName()+".class";
			in = c.getResourceAsStream(path);
			byte[] clazzData = new byte[in.available()];
			in.read(clazzData);
			return clazzData;
		}catch(IOException e){
			throw new RuntimeException("Couldn't load class "+c, e);
		}finally{
			if (in!=null){
				try{
					in.close();
				}catch(IOException ignored){}
			}
		}
	}
	
	public static Agent unpack(AgentPackage pack){
		try{
			AgentPackageUtilClassLoader loader = new AgentPackageUtilClassLoader(pack);
			//force loading
			Class myAgent = Class.forName(pack.getRootClazzName(), true, loader);
			Agent agent = deserializeAgent(pack.getSerializedData(), loader);
			return agent;
		}catch (Exception e){
			e.printStackTrace();
		}
		
		return null;
	}
	
	static class AgentPackageUtilClassLoader extends ClassLoader{
		private Map classDefs;
		
		private Map cache = new HashMap();;
		
		public AgentPackageUtilClassLoader(AgentPackage pack) {
			classDefs = pack.getClazzDefinitions();
		}
		
		protected synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException{
//			System.out.println("-- loadClass "+name);
			Class fromCache = cache.get(name);
			if (fromCache!=null){
//				System.out.println("--> from cache! ");
				return fromCache;
			}
			if (classDefs.get(name)==null){
				return super.loadClass(name, resolve);
			}
//			System.out.println(" -- defining "+name);
			byte[] data = classDefs.get(name);
			Class c = defineClass(name, data, 0, data.length);
			cache.put(name, c);
			return c;
		}

	}
	
	private static byte[] serializeAgent(Agent obj) throws IOException{
		ByteArrayOutputStream bOut = null;
		ObjectOutputStream oOut = null;
		try{
			bOut = new ByteArrayOutputStream();
			oOut = new ObjectOutputStream(bOut);
			oOut.writeObject(obj);
			return bOut.toByteArray();
		}finally{ 
			if (oOut!=null)
				try{
					oOut.close();
				}catch(Exception ignored){}//NOPMD
		}
	}
	
	private static Agent deserializeAgent(final byte[] data, final AgentPackageUtilClassLoader loader) throws IOException{
		ByteArrayInputStream bIn = null;
		ObjectInputStream oIn = null;
		try{
			bIn = new ByteArrayInputStream(data);
			oIn = new ObjectInputStream(bIn){

				@Override
				protected Class resolveClass(ObjectStreamClass desc)
						throws IOException, ClassNotFoundException {
					
					System.out.println("Resolve class "+desc.getName()+" with loader "+loader);
					return loader.loadClass(desc.getName(), false);

				}
				
			};
			return (Agent)oIn.readObject();
		}catch(ClassNotFoundException e){
			throw new IOException("deserialization failed: "+e.getMessage());
		}finally{
			if (oIn!=null){
				try{
					oIn.close();
				}catch(Exception ignored){}
			}
		}
	}
	
	static List> scanForCustomClasses(Agent agent){
		
		ArrayList> ret = new ArrayList>();
		
		scanForCustomClassesInternally(agent.getClass(), ret);
		
		return ret;
	}
	
	@SuppressWarnings("unchecked")
	private static void scanForCustomClassesInternally(Class toScan, List> foundClasses){
		
		if (toScan.isPrimitive())
			return;
		
		foundClasses.add(toScan);
		
		Field[] fields = toScan.getDeclaredFields();
		if (fields==null || fields.length==0)
			return;
		
		for (Field f : fields){
			if (f.getType().isPrimitive()){
				continue;
			}
			if (f.getType().getName().startsWith("java.")){
				continue;
			}
			
			
			if (!foundClasses.contains(f.getType()))
				scanForCustomClassesInternally(f.getType(), foundClasses);
		}
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy