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

jadex.bdi.model.BDIEnhancer Maven / Gradle / Ivy

The newest version!
package jadex.bdi.model;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import jadex.classreader.SClassReader;
import jadex.classreader.SClassReader.AnnotationInfo;
import jadex.classreader.SClassReader.ClassFileInfo;
import jadex.common.FileFilter;
import jadex.common.IFilter;
import jadex.common.SUtil;
import jadex.micro.annotation.Agent;

/**
 *  Helper class to enhance BDI classes at buildtime.
 *  
 *  Needs access the the BDI and dependent classes.
 *  
 *  Can be used as basis for custom build tool extensions (e.g. gradle task or maven plugin).
 */
public class BDIEnhancer
{
	/**
	 *  Enhance all BDI classes contained in a directory.
	 *  
	 *  If indir and outdir are the same (also outdir==null):
	 *  	- BDI classes are enhance in place and replace old classes. All other files are not changed.
	 *  	- Already enhanced BDI classes are detected and omitted.
	 *  
	 *  if outdir is different than indir:
	 * 		- BDI classes are enhanced and copied to the outdir.
	 * 		- All other files are copied without change to the outdir.
	 *  
	 *  @param indir The input directory (is recursivly scanned for BDI classes).
	 *  @param outdir The output directory (null for the same as indir).
	 */
	public static void enhanceBDIClasses(String indir, String outdir)
	{
		if(outdir==null)
			outdir = indir;
			
		URL inurl = null;
		try
		{
			inurl = Paths.get(indir).toUri().toURL();
		}
		catch(IOException e)
		{
			SUtil.throwUnchecked(e);
		}
		
		Set done = new HashSet();
		
		ClassLoader origcl = BDIEnhancer.class.getClassLoader();
		URLClassLoader cl = new URLClassLoader(new URL[]{inurl}, origcl);
		
		BDIModelLoader loader = new BDIModelLoader();
		ByteKeepingASMBDIClassGenerator gen = new ByteKeepingASMBDIClassGenerator();
		loader.setGenerator(gen);
		
		Set cis = new HashSet<>();
		FileFilter ff = new FileFilter(null, false, ".class");
		Set allcis = SClassReader.scanForClassFileInfos(new URL[]{inurl}, ff, new IFilter()
		{
			public boolean filter(ClassFileInfo ci)
			{
				AnnotationInfo ai = ci.getClassInfo().getAnnotation(Agent.class.getName());
				if(ai != null && ("bdi".equals(ai.getValue("type")) || ci.getFilename().toLowerCase().indexOf("bdi")!=-1))
				{
					cis.add(ci);
				}
				else if(ai!=null)
				{
					System.out.println("found non-bdi agent: "+ci.getFilename());
				}
				
				return true;
				//return ai!=null;
			}
		});
		
		Map classfiles = new HashMap<>();
		allcis.stream().forEach(ci -> classfiles.put(ci.getClassInfo().getClassName(), ci.getFilename()));
		
		for(ClassFileInfo ci : cis)
		{
			if(IBDIClassGenerator.isEnhanced(ci))
			{
				System.out.println("Already enhanced: "+ci.getFilename());
			}
			else
			{
				System.out.println("Processing: "+ci.getFilename());
				
				gen.clearRecentClassBytes();
				
                try
                {
                	loader.loadComponentModel(ci.getFilename(), null, null, null, cl, null);
                }
                catch(Exception e)
                {
                	SUtil.throwUnchecked(e);
                }

                for(Map.Entry entry: gen.getRecentClassBytes().entrySet())
                {
                	System.out.println("writing: "+entry.getKey());
                	
                    byte[] bytes = entry.getValue();
                    
                    Path p = Paths.get(indir);
                	Path p2 = Paths.get(classfiles.get(entry.getKey()));
                	Path relp = p.relativize(p2);
                	
                    // write enhanced class
                    File enhfile = new File(outdir, relp.toString());
                    enhfile.getParentFile().mkdirs();
                    
                    try(FileOutputStream fos = new FileOutputStream(enhfile))
                    {
                        fos.write(bytes);
                        done.add(enhfile.getPath());
                    }
                    catch(IOException e)
                    {
                    	SUtil.throwUnchecked(e);
                        // URLClassLoader.close() not in JDK 1.6
                        try{ ((URLClassLoader)cl).close(); } catch(IOException e2) {}
                    }
                }
			}
		}
		
		// copy all other files rest
        if(!indir.equals(outdir))
        {
        	final String foutdir = outdir;
        	try
        	{
        		Files.walk(Paths.get(indir))
        			.filter(file -> 
        			{ 
        				boolean ret = Files.isRegularFile(file) && !done.contains(file.toString());
        				if(!ret)
        					System.out.println("Not copying: "+file);
        				return ret;
        			})
        			.forEach(file ->
        			{
        	        	Path p = Paths.get(indir);
        	        	Path relp = p.relativize(file);
        	        	
        	            File f = new File(foutdir, relp.toString());
        	            if(!f.exists())
        	            {
        	            	f.getParentFile().mkdirs();
        	            	try
        	            	{
        	            		System.out.println("Copying: "+file);
        	            		SUtil.copyFile(new File(file.toString()), f);
        	            	}
        	            	catch(IOException e)
        	            	{
        	            		SUtil.throwUnchecked(e);
        	            	}
        	            }
        	            
        	            done.add(f.getPath());
        			});
        	}
        	catch(Exception e)
        	{
        		SUtil.throwUnchecked(e);
        	}
        }
		
	}
	
	/**
	 *  Main for testing.
	 */
	public static void main(String[] args) throws Exception
	{
		/*Map m = new HashMap<>();
		ClassInfo ci = SClassReader.getClassInfo(new FileInputStream("C:/tmp/bin/jadex/bdiv3/testcases/componentplans/ComponentPlanBDI.class"), true, true); 
		ClassInfo ci = SClassReader.getClassInfo(new FileInputStream("/home/jander/git/jadex/applications/bdiv3/bintest/main/jadex/bdiv3/testcases/componentplans/ComponentPlanBDI.class"), true, true); 
		for(MethodInfo mi: ci.getMethodInfos())
		{
//			System.out.println(mi.getMethodName()+" "+mi.getMethodDescriptor());
			if(m.containsKey(mi.getMethodName()+" " + mi.getMethodDescriptor()))
				System.out.println("Dup method: "+mi.getMethodName()+" "+mi.getMethodDescriptor());
			else
				m.put(mi.getMethodName()+" " + mi.getMethodDescriptor(), mi);
		}*/
		
		//String indir = "/home/jander/git/jadex/applications/bdiv3/bintest/main";
		String indir = "C:/tmp/bin";
		String outdir ="C:/tmp/bdienh";
		//String outdir = null;
		BDIEnhancer.enhanceBDIClasses(indir, outdir);
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy