diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..07f050a --- /dev/null +++ b/pom.xml @@ -0,0 +1,71 @@ + + 4.0.0 + sacha + infra + 0.1 + sacha infra + + + + junit + junit + 4.11 + + + org.hamcrest + hamcrest-core + + + + + org.hamcrest + hamcrest-core + 1.3 + + + fr.inria.gforge.spoon + spoon-core + 4.2.0 + + + + + srcs/main + bin + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.7 + 1.7 + + **/*.* + + + + + org.codehaus.mojo + build-helper-maven-plugin + 1.1 + + + add-source + generate-sources + + add-source + + + + srcs/framework + srcs/processors + srcs/utils + + + + + + + + + \ No newline at end of file diff --git a/srcs/framework/bcornu/resi/AbnormalExecutionError.java b/srcs/framework/bcornu/resi/AbnormalExecutionError.java new file mode 100644 index 0000000..bc597e1 --- /dev/null +++ b/srcs/framework/bcornu/resi/AbnormalExecutionError.java @@ -0,0 +1,13 @@ +package bcornu.resi; + +public class AbnormalExecutionError extends Error { + + public AbnormalExecutionError(){ + super(); + } + + public AbnormalExecutionError(String string) { + super(string); + } + +} diff --git a/srcs/framework/bcornu/resi/CallChecker.java b/srcs/framework/bcornu/resi/CallChecker.java new file mode 100644 index 0000000..81b5df7 --- /dev/null +++ b/srcs/framework/bcornu/resi/CallChecker.java @@ -0,0 +1,66 @@ +package bcornu.resi; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +import bcornu.resi.context.MethodeContext; +import bcornu.resi.strategies.NoStrat; + + + @SuppressWarnings("all") +public class CallChecker { + + public static Strategy strat; + + private static Stack> stack = new Stack>(); + + private static Strategy getStrat(){ + return strat==null?new NoStrat():strat; + } + + public static T isCalled(T o, Class clazz) { + if (o == null && ExceptionStack.isStoppable(NullPointerException.class)) + return null; + return getStrat().isCalled(o, clazz); + } + + public static boolean beforeDeref(Object called) { + if (called == null && ExceptionStack.isStoppable(NullPointerException.class)) + return true; + return getStrat().beforeDeref(called); + } + + public static T init(Class clazz) { + return getStrat().init(clazz); + } + + public static T returned(Class clazz) { + return getStrat().returned(clazz); + } + + public static T varAssign(Object table) { + if(! stack.isEmpty() && ! stack.peek().contains(table)) + stack.peek().add(table); + return (T) table; + } + + public static T varInit(Object table) { + if(! stack.isEmpty()) + stack.peek().add(table); + return (T) table; + } + + public static void methodStart() { + stack.push(new ArrayList()); + } + + public static void methodEnd() { + stack.pop(); + } + + public static List getCurrentVars(){ + return stack.peek(); + } + +} diff --git a/srcs/framework/bcornu/resi/ExceptionStack.java b/srcs/framework/bcornu/resi/ExceptionStack.java new file mode 100644 index 0000000..6945652 --- /dev/null +++ b/srcs/framework/bcornu/resi/ExceptionStack.java @@ -0,0 +1,36 @@ +package bcornu.resi; + +import java.util.ArrayList; +import java.util.List; + +import bcornu.resi.context.TryContext; + +public class ExceptionStack { + + private static List tryContexts = new ArrayList<>(); + + public static void register(TryContext tc) { + tryContexts.add(tc); + } + + public static void unregister(TryContext tc){ + if(tryContexts.isEmpty()) + return; + if(tryContexts.get(tryContexts.size()-1).equals(tc)){ + tryContexts.remove(tryContexts.size()-1); + }else{ + System.err.println("oops?"); + } + } + + public static boolean isStoppable(Class c){ + for (TryContext tryContext : tryContexts) { + for (Class clazz : tryContext.getTypes()) { + if(clazz.isAssignableFrom(c)){ + return true; + } + } + } + return false; + } +} diff --git a/srcs/framework/bcornu/resi/ForceReturn.java b/srcs/framework/bcornu/resi/ForceReturn.java new file mode 100644 index 0000000..874ee42 --- /dev/null +++ b/srcs/framework/bcornu/resi/ForceReturn.java @@ -0,0 +1,6 @@ +package bcornu.resi; + + +public class ForceReturn extends RuntimeException { + +} diff --git a/srcs/framework/bcornu/resi/Strategy.java b/srcs/framework/bcornu/resi/Strategy.java new file mode 100644 index 0000000..0a6717e --- /dev/null +++ b/srcs/framework/bcornu/resi/Strategy.java @@ -0,0 +1,113 @@ +package bcornu.resi; + +import java.lang.reflect.Constructor; +import java.util.Comparator; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public abstract class Strategy { + + public abstract T isCalled(T o, Class clazz); + + public abstract T returned(Class clazz); + + public abstract boolean beforeDeref(Object called); + + protected T obtain(Class clazz) { + if(clazz==null) + return null; + List vars = CallChecker.getCurrentVars(); + for (Object object : vars) { + if(object!=null && object.getClass()!=null && object.getClass().isAssignableFrom(clazz)){ + System.out.println("var found!"); + return (T) object; + } + } + throw new AbnormalExecutionError("cannot found var: "+clazz); + } + + public T init(Class clazz) { + if(clazz==null) + return null; + if(clazz.isPrimitive()){ + return initPrimitive(clazz); + } + return null; + } + + protected T initPrimitive(Class clazz){ + if(clazz == int.class){ + return (T) new Integer(0); + } + if(clazz == char.class){ + return (T) new Character(' '); + } + if(clazz == boolean.class){ + return (T) new Boolean(false); + } + if(clazz == float.class){ + return (T) new Float(0); + } + if(clazz == double.class){ + return (T) new Double(0); + } + if(clazz == long.class){ + return (T) new Long(0); + } + throw new AbnormalExecutionError("missing primitive:"+clazz); + } + + protected T initNotNull(Class clazz){ + if(clazz==null) + return null; + if(clazz.isPrimitive()){ + return initPrimitive(clazz); + } + if(clazz.isInterface()){ + if(clazz.isAssignableFrom(Set.class)){ + return (T) new HashSet(); + } + if(clazz.isAssignableFrom(Comparator.class)){ + return (T) new Comparator() { + public int compare(Object o1, Object o2) { + return 0; + } + }; + } + else throw new AbnormalExecutionError("missing interface"+clazz); + } + Object res = null; + try { + res = (T) clazz.newInstance(); + } catch (InstantiationException | IllegalAccessException e) { + System.err.println("cannot new instance "+clazz); + try{ + for (Constructor constructor : clazz.getConstructors()) { + try{ + Class[] types = constructor.getParameterTypes(); + Object[] params = new Object[types.length]; + for (int i = 0; i < types.length; i++) { + try{ + if(types[i]==clazz) + params[i]=null; + else + params[i] = init(types[i]); + }catch (Throwable t){ + t.printStackTrace(); + } + } + res = (T) constructor.newInstance(params); + return (T) res; + }catch (Throwable t){ + t.printStackTrace(); + } + } + }catch (Throwable t){ + t.printStackTrace(); + } + } + return (T) res; + } + +} diff --git a/srcs/framework/bcornu/resi/context/MethodeContext.java b/srcs/framework/bcornu/resi/context/MethodeContext.java new file mode 100644 index 0000000..6affe6b --- /dev/null +++ b/srcs/framework/bcornu/resi/context/MethodeContext.java @@ -0,0 +1,20 @@ +package bcornu.resi.context; + +import bcornu.resi.CallChecker; + +public class MethodeContext { + + public MethodeContext() { + CallChecker.methodStart(); + } + + public T methodSkip() { + // TODO Auto-generated method stub + return null; + } + + public void methodEnd() { + CallChecker.methodEnd(); + } + +} diff --git a/srcs/framework/bcornu/resi/context/TryContext.java b/srcs/framework/bcornu/resi/context/TryContext.java new file mode 100644 index 0000000..1612ce9 --- /dev/null +++ b/srcs/framework/bcornu/resi/context/TryContext.java @@ -0,0 +1,42 @@ +package bcornu.resi.context; + +import bcornu.resi.ExceptionStack; + +public class TryContext { + + private int id = -1; + private Class[] types; + + public TryContext(int id, String... types) { + this.id=id; + this.types = new Class[types.length]; + int i=0; + for (String str : types) { + try { + this.types[i++]=Class.forName(str); + } catch (ClassNotFoundException e) { + //throw new RuntimeException(e); + } + } + ExceptionStack.register(this); + } + + public void catchStart(int i) { + ExceptionStack.unregister(this); + } + + public void finallyStart(int i) { + ExceptionStack.unregister(this); + } + + @Override + public boolean equals(Object o) { + if(!(o instanceof TryContext))return false; + return this.id == ((TryContext)o).id; + } + + public Class[] getTypes() { + return types; + } + +} diff --git a/srcs/framework/bcornu/resi/strategies/NoStrat.java b/srcs/framework/bcornu/resi/strategies/NoStrat.java new file mode 100644 index 0000000..f61af59 --- /dev/null +++ b/srcs/framework/bcornu/resi/strategies/NoStrat.java @@ -0,0 +1,20 @@ +package bcornu.resi.strategies; + +import bcornu.resi.AbnormalExecutionError; +import bcornu.resi.Strategy; + +public class NoStrat extends Strategy{ + + public T isCalled(T o, Class clazz) { + return (T) o; + } + + public boolean beforeDeref(Object called) { + return true; + } + + @Override + public T returned(Class clazz) { + throw new AbnormalExecutionError("should not call return"); + } +} diff --git a/srcs/framework/bcornu/resi/strategies/ReturnType.java b/srcs/framework/bcornu/resi/strategies/ReturnType.java new file mode 100644 index 0000000..360a28a --- /dev/null +++ b/srcs/framework/bcornu/resi/strategies/ReturnType.java @@ -0,0 +1,5 @@ +package bcornu.resi.strategies; + +public enum ReturnType { + NULL, NEW, VAR; +} diff --git a/srcs/framework/bcornu/resi/strategies/Strat1A.java b/srcs/framework/bcornu/resi/strategies/Strat1A.java new file mode 100644 index 0000000..452ffb7 --- /dev/null +++ b/srcs/framework/bcornu/resi/strategies/Strat1A.java @@ -0,0 +1,43 @@ +package bcornu.resi.strategies; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; + +import bcornu.resi.AbnormalExecutionError; +import bcornu.resi.Strategy; +/** + * b.foo + * @author bcornu + * + */ +public class Strat1A extends Strategy{ + + +// public static void main(String[] args) throws IllegalArgumentException, IllegalAccessException { +// Class c = Strat1A.class; +// Method m = c.getDeclaredMethods()[0]; +// Class mR = Method.class; +// for (Field f : mR.getDeclaredFields()) { +// f.setAccessible(true); +// System.out.println(f.getGenericType() +" "+f.getName() + " = " + f.get(m)); +// } +// +// +// } + + public T isCalled(T o, Class clazz) { + if(o==null) + return obtain(clazz); + return (T) o; + } + + public boolean beforeDeref(Object called) { + return true; + } + + + @Override + public T returned(Class clazz) { + throw new AbnormalExecutionError("should not call return"); + } +} diff --git a/srcs/framework/bcornu/resi/strategies/Strat1B.java b/srcs/framework/bcornu/resi/strategies/Strat1B.java new file mode 100644 index 0000000..37b87a6 --- /dev/null +++ b/srcs/framework/bcornu/resi/strategies/Strat1B.java @@ -0,0 +1,26 @@ +package bcornu.resi.strategies; + +import bcornu.resi.AbnormalExecutionError; +import bcornu.resi.Strategy; +/** + * a=b + * @author bcornu + * + */ +public class Strat1B extends Strategy{ + + public T isCalled(T o, Class clazz) { + if(o==null) + o = obtain(clazz); + return (T) o;} + + public boolean beforeDeref(Object called) { + return true; + } + + + @Override + public T returned(Class clazz) { + throw new AbnormalExecutionError("should not call return"); + } +} diff --git a/srcs/framework/bcornu/resi/strategies/Strat2A.java b/srcs/framework/bcornu/resi/strategies/Strat2A.java new file mode 100644 index 0000000..082280b --- /dev/null +++ b/srcs/framework/bcornu/resi/strategies/Strat2A.java @@ -0,0 +1,88 @@ +package bcornu.resi.strategies; + +import java.lang.reflect.Constructor; +import java.util.Comparator; +import java.util.HashSet; +import java.util.Set; + +import bcornu.resi.AbnormalExecutionError; +import bcornu.resi.ExceptionStack; +import bcornu.resi.ForceReturn; +import bcornu.resi.Strategy; +/** + * new A.foo + * @author bcornu + * + */ +public class Strat2A extends Strategy{ + + @SuppressWarnings("rawtypes") + public T isCalled(T o, Class clazz) { + if (o == null) { + if (ExceptionStack.isStoppable(NullPointerException.class)) { + return null; + } + + if(clazz.isPrimitive()){ + return initPrimitive(clazz); + } + if(clazz.isInterface()){ + if(clazz.isAssignableFrom(Set.class)){ + return (T) new HashSet(); + } + if(clazz.isAssignableFrom(Comparator.class)){ + return (T) new Comparator() { + public int compare(Object o1, Object o2) { + return 0; + } + }; + } + else throw new AbnormalExecutionError("missing interface"+clazz); + } + Object res = null; + try { + res = (T) clazz.newInstance(); + } catch (InstantiationException | IllegalAccessException e) { + System.err.println("cannot new instance "+clazz); + try{ + Constructor[] consts = clazz.getConstructors(); + for (Constructor constructor : consts) { + try{ + Class[] types = constructor.getParameterTypes(); + Object[] params = new Object[types.length]; + for (int i = 0; i < types.length; i++) { + try{ + if(types[i].equals(clazz)) + throw new ForceReturn(); + else + params[i] = init(types[i]); + }catch (Throwable t){ + t.printStackTrace(); + } + } + res = (T) constructor.newInstance(params); + System.out.println("constructed value :"+ clazz); + return (T) res; + }catch (Throwable t){ + t.printStackTrace(); + } + } + }catch (Throwable t){ + t.printStackTrace(); + } + } + return (T) res; + } + return (T) o; + } + + public boolean beforeDeref(Object called) { + return true; + } + + + @Override + public T returned(Class clazz) { + throw new AbnormalExecutionError("should not call return"); + } +} diff --git a/srcs/framework/bcornu/resi/strategies/Strat2B.java b/srcs/framework/bcornu/resi/strategies/Strat2B.java new file mode 100644 index 0000000..52bf2b3 --- /dev/null +++ b/srcs/framework/bcornu/resi/strategies/Strat2B.java @@ -0,0 +1,83 @@ +package bcornu.resi.strategies; + +import java.lang.reflect.Constructor; +import java.util.Comparator; +import java.util.HashSet; +import java.util.Set; + +import bcornu.resi.AbnormalExecutionError; +import bcornu.resi.ExceptionStack; +import bcornu.resi.ForceReturn; +import bcornu.resi.Strategy; +/** + * a=new A + * @author bcornu + * + */ +public class Strat2B extends Strategy{ + + public T isCalled(T o, Class clazz) { + if (o == null) { + if (ExceptionStack.isStoppable(NullPointerException.class)) { + return null; + } + if(clazz.isPrimitive()){ + o = initPrimitive(clazz); + return o; + } + if(clazz.isInterface()){ + if(clazz.isAssignableFrom(Set.class)){ + o= (T) new HashSet(); + }else + if(clazz.isAssignableFrom(Comparator.class)){ + o= (T) new Comparator() { + public int compare(Object o1, Object o2) { + return 0; + } + }; + } + else throw new AbnormalExecutionError("missing interface"+clazz); + } + try { + o = (T) clazz.newInstance(); + } catch (InstantiationException | IllegalAccessException e) { + System.err.println("cannot new instance "+clazz); + try{ + for (Constructor constructor : clazz.getConstructors()) { + try{ + Class[] types = constructor.getParameterTypes(); + Object[] params = new Object[types.length]; + for (int i = 0; i < types.length; i++) { + try{ + if(types[i].equals(clazz)) + throw new ForceReturn(); + else + params[i] = init(types[i]); + }catch (Throwable t){ + t.printStackTrace(); + } + } + o = (T) constructor.newInstance(params); + return (T) o; + }catch (Throwable t){ + t.printStackTrace(); + } + } + }catch (Throwable t){ + t.printStackTrace(); + } + } + } + return (T) o; + } + + public boolean beforeDeref(Object called) { + return true; + } + + + @Override + public T returned(Class clazz) { + throw new AbnormalExecutionError("should not call return"); + } +} diff --git a/srcs/framework/bcornu/resi/strategies/Strat3.java b/srcs/framework/bcornu/resi/strategies/Strat3.java new file mode 100644 index 0000000..a5181ff --- /dev/null +++ b/srcs/framework/bcornu/resi/strategies/Strat3.java @@ -0,0 +1,24 @@ +package bcornu.resi.strategies; + +import bcornu.resi.AbnormalExecutionError; +import bcornu.resi.Strategy; +/** + * if != null + * @author bcornu + * + */ +public class Strat3 extends Strategy{ + + public T isCalled(T o, Class clazz) { + return o; + } + + public boolean beforeDeref(Object called) { + return called!=null; + } + + @Override + public T returned(Class clazz) { + throw new AbnormalExecutionError("should not call return"); + } +} diff --git a/srcs/framework/bcornu/resi/strategies/Strat4.java b/srcs/framework/bcornu/resi/strategies/Strat4.java new file mode 100644 index 0000000..4516976 --- /dev/null +++ b/srcs/framework/bcornu/resi/strategies/Strat4.java @@ -0,0 +1,47 @@ +package bcornu.resi.strategies; + +import bcornu.resi.AbnormalExecutionError; +import bcornu.resi.ForceReturn; +import bcornu.resi.Strategy; +/** + * return null + * @author bcornu + * + */ +public class Strat4 extends Strategy{ + + private ReturnType rt; + + public Strat4(ReturnType rt) { + this.rt=rt; + } + + public T isCalled(T o, Class clazz) { + if(o==null) + throw new ForceReturn(); + return o; + } + + public boolean beforeDeref(Object called) { + if(called==null) + throw new ForceReturn(); + return true; + } + + @Override + public T returned(Class clazz) { + switch (rt) { + case NULL: + System.out.println("return null"); + return null; + case NEW: + System.out.println("return new"); + return initNotNull(clazz); + case VAR: + System.out.println("return var"); + return obtain(clazz); + default: + throw new AbnormalExecutionError(); + } + } +} diff --git a/srcs/main/run/MainRun.java b/srcs/main/run/MainRun.java new file mode 100644 index 0000000..7255a03 --- /dev/null +++ b/srcs/main/run/MainRun.java @@ -0,0 +1,110 @@ +package run; + +import org.junit.runner.Result; +import org.junit.runner.notification.Failure; + +import sacha.impl.TestRunnerCore; +import sacha.interfaces.ITestResult; +import sacha.runner.utils.TestInfo; +import bcornu.resi.CallChecker; +import bcornu.resi.strategies.NoStrat; +import bcornu.resi.strategies.ReturnType; +import bcornu.resi.strategies.Strat1A; +import bcornu.resi.strategies.Strat1B; +import bcornu.resi.strategies.Strat2A; +import bcornu.resi.strategies.Strat2B; +import bcornu.resi.strategies.Strat3; +import bcornu.resi.strategies.Strat4; + +public class MainRun { + + public static void main(String[] args) { + +// String[] toto = new String[]{}; +// +// System.out.println(toto[0]); + + TestRunnerCore runner = new TestRunnerCore(); + runner.setEclipseMetadataFolder("/home/bcornu/workspace/.metadata/"); + runner.setEclipseProject("01-Mckoi-th"); +// runner.setEclipseProject("01-Mckoi-o"); +// runner.setEclipseProject("02-freemarker-o"); +// runner.setEclipseProject("03-jfreechart-o"); +// runner.setEclipseProject("collections-331-o"); +// runner.setEclipseProject("lang-304-o"); +// runner.setEclipseProject("lang-587-o"); +// runner.setEclipseProject("lang-703-o"); +// runner.setEclipseProject("math-290-o"); +// runner.setEclipseProject("math-305-o"); +// runner.setEclipseProject("math-369-o"); +// runner.setEclipseProject("math-988a-o"); +// runner.setEclipseProject("math-988b-o"); +// runner.setEclipseProject("math-1115-o"); +// runner.setEclipseProject("math-1117-o"); + + CallChecker.strat = new NoStrat(); + // runs the test folder + System.out.print("sans strat -> "); + ITestResult res = runner.runAllTestsInClasspath(); + System.out.println(res.getNbFailedTests() +"/"+ res.getNbRunTests()); + boolean noStrat = res.getNbFailedTests()==0; + + CallChecker.strat = new Strat1A(); + System.out.print("s1a -> "); + res = runner.runAllTestsInClasspath(); + System.out.println(res.getNbFailedTests()); + boolean s1a = res.getNbFailedTests()==0; + + CallChecker.strat = new Strat1B(); + System.out.print("s1b -> "); + res = runner.runAllTestsInClasspath(); + System.out.println(res.getNbFailedTests()); + boolean s1b = res.getNbFailedTests()==0; + + CallChecker.strat = new Strat2A(); + System.out.print("s2a -> "); + res = runner.runAllTestsInClasspath(); + System.out.println(res.getNbFailedTests()); + boolean s2a = res.getNbFailedTests()==0; + + CallChecker.strat = new Strat2B(); + System.out.print("s2b -> "); + res = runner.runAllTestsInClasspath(); + System.out.println(res.getNbFailedTests()); + boolean s2b = res.getNbFailedTests()==0; + + CallChecker.strat = new Strat3(); + System.out.print("s3 -> "); + res = runner.runAllTestsInClasspath(); + System.out.println(res.getNbFailedTests()); + boolean s3 = res.getNbFailedTests()==0; + + CallChecker.strat = new Strat4(ReturnType.NULL); + System.out.print("s4a -> "); + res = runner.runAllTestsInClasspath(); + System.out.println(res.getNbFailedTests()); + boolean s4a = res.getNbFailedTests()==0; + + CallChecker.strat = new Strat4(ReturnType.NEW); + System.out.print("s4b -> "); + res = runner.runAllTestsInClasspath(); + System.out.println(res.getNbFailedTests()); + boolean s4b = res.getNbFailedTests()==0; + + CallChecker.strat = new Strat4(ReturnType.VAR); + System.out.print("s4c -> "); + res = runner.runAllTestsInClasspath(); + System.out.println(res.getNbFailedTests()); + boolean s4c = res.getNbFailedTests()==0; + + System.out.println("base -> "+noStrat); + System.out.println("s1a -> "+s1a); + System.out.println("s1b -> "+s1b); + System.out.println("s2a -> "+s2a); + System.out.println("s2b -> "+s2b); + System.out.println("s3 -> "+s3); + System.out.println("s4a -> "+s4a); + System.out.println("s4b -> "+s4b); + System.out.println("s4c -> "+s4c); + } +} diff --git a/srcs/main/spoon/MainSpoon.java b/srcs/main/spoon/MainSpoon.java new file mode 100644 index 0000000..7512124 --- /dev/null +++ b/srcs/main/spoon/MainSpoon.java @@ -0,0 +1,100 @@ +package spoon; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.swing.JOptionPane; + +import sacha.impl.DefaultSpooner; +import sacha.interfaces.ISpooner; + + +public class MainSpoon { + + public static void main(String[] args) { + try{ + BufferedReader br = null; + Object selection = null; + String[] arg = null; + try { + File targetsFile = new File("targets"); + if(targetsFile.exists()){ + Map targets = new HashMap(); + List options = new ArrayList<>(); + br = new BufferedReader(new InputStreamReader( + new FileInputStream(targetsFile))); + String line; + while ((line = br.readLine()) != null) { + if(line.startsWith("#"))continue; + String[] lineB = line.split(":",2); + String[] arguments = lineB[1].split("\\s"); + targets.put(lineB[0],arguments); + options.add(lineB[0]); + } + Collections.sort(options); + Object[] selectionValues = options.toArray(); + selection = JOptionPane.showInputDialog(null, "Which project?", "spoon", + JOptionPane.QUESTION_MESSAGE, null, selectionValues, "test"); + arg=targets.get(selection); + } + } finally { + if(br!=null) + br.close(); + } + ISpooner spooner = new DefaultSpooner(); + //project config + spooner.setEclipseProject(arg[0]); + spooner.setEclipseMetadataFolder("/home/bcornu/workspace/.metadata"); + String[] srcs = arg[1].split(":"); + //spoon config + spooner.setSourceFolder(srcs); + spooner.setProcessors( + "bcu.transformer.processors.ForceNullInit", + "bcu.transformer.processors.TargetIfAdder", + "bcu.transformer.processors.TargetModifier", + "bcu.transformer.processors.TryRegister", + "bcu.transformer.processors.MethodEncapsulation", + "bcu.transformer.processors.VarRetrieveAssign", + "bcu.transformer.processors.VarRetrieveInit" + ); + spooner.setOutputFolder(arg[2]); + if(arg[0].equals("test")) + spooner.setGraphicalOutput(true); + cleanOutput(new File(arg[2])); + + spooner.spoon(); + System.err.println("spoon done"); + }catch(Throwable t){ + t.printStackTrace(); + } + } + + private static void cleanOutput(File outputFolder) { + if (outputFolder.exists()) { + recursifDeleteJavaFiles(outputFolder); + } + } + + private static boolean recursifDeleteJavaFiles(File file) { + boolean delete = true; + if (file.exists()) { + if (file.isDirectory()) + for (File child : file.listFiles()) { + delete &= recursifDeleteJavaFiles(child); + } + if(!delete || (file.isFile() && !file.getName().endsWith(".java"))){ + return false; + } + file.delete(); + } + return delete; + } + +} diff --git a/srcs/processors/bcu/transformer/processors/ForceNullInit.java b/srcs/processors/bcu/transformer/processors/ForceNullInit.java new file mode 100644 index 0000000..786064e --- /dev/null +++ b/srcs/processors/bcu/transformer/processors/ForceNullInit.java @@ -0,0 +1,78 @@ +package bcu.transformer.processors; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import spoon.processing.AbstractProcessor; +import spoon.reflect.code.CtBlock; +import spoon.reflect.code.CtCatch; +import spoon.reflect.code.CtCatchVariable; +import spoon.reflect.code.CtConstructorCall; +import spoon.reflect.code.CtExpression; +import spoon.reflect.code.CtForEach; +import spoon.reflect.code.CtInvocation; +import spoon.reflect.code.CtLiteral; +import spoon.reflect.code.CtLocalVariable; +import spoon.reflect.code.CtReturn; +import spoon.reflect.code.CtStatement; +import spoon.reflect.code.CtTry; +import spoon.reflect.declaration.CtMethod; +import spoon.reflect.declaration.ModifierKind; +import spoon.reflect.reference.CtArrayTypeReference; +import spoon.reflect.reference.CtExecutableReference; +import spoon.reflect.reference.CtFieldReference; +import spoon.reflect.reference.CtTypeReference; +import spoon.support.reflect.code.CtFieldAccessImpl; +import spoon.support.reflect.code.CtInvocationImpl; +import spoon.support.reflect.code.CtVariableAccessImpl; +import spoon.support.reflect.reference.CtFieldReferenceImpl; +import bcu.transformer.utils.IConstants; + +/** + * @author bcornu + * + */ +@SuppressWarnings("all") +public class ForceNullInit extends AbstractProcessor { + + @Override + public void process(CtLocalVariable element) { + if(element.getDefaultExpression()!=null + || element.getParent() instanceof CtForEach) + return; + if(element.hasModifier(ModifierKind.FINAL)){ + element.removeModifier(ModifierKind.FINAL); + } + CtTypeReference tmp2 = element.getType(); + + CtExpression arg = null; + if(tmp2 instanceof CtArrayTypeReference){ + tmp2=((CtArrayTypeReference)tmp2).getDeclaringType(); + } + if(tmp2==null || tmp2.isAnonymous() || tmp2.getSimpleName()==null || (tmp2.getPackage()==null && tmp2.getSimpleName().length()==1)){ + arg = getFactory().Core().createLiteral(); + arg.setType(getFactory().Type().nullType()); + }else{ + tmp2 = getFactory().Type().createReference(tmp2.getQualifiedName()); + CtFieldReference ctfe = new CtFieldReferenceImpl(); + ctfe.setSimpleName("class"); + ctfe.setDeclaringType(tmp2); + + arg = new CtFieldAccessImpl(); + ((CtFieldAccessImpl) arg).setVariable(ctfe); + } + + CtExecutableReference execref = getFactory().Core().createExecutableReference(); + execref.setDeclaringType(getFactory().Type().createReference("bcornu.resi.CallChecker")); + execref.setSimpleName("init"); + execref.setStatic(true); + + CtInvocationImpl invoc = (CtInvocationImpl) getFactory().Core().createInvocation(); + invoc.setExecutable(execref); + invoc.setArguments(Arrays.asList(new CtExpression[]{arg})); + + element.setDefaultExpression(invoc); + } + +} diff --git a/srcs/processors/bcu/transformer/processors/MethodEncapsulation.java b/srcs/processors/bcu/transformer/processors/MethodEncapsulation.java new file mode 100644 index 0000000..a2f8e7e --- /dev/null +++ b/srcs/processors/bcu/transformer/processors/MethodEncapsulation.java @@ -0,0 +1,148 @@ +package bcu.transformer.processors; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import spoon.processing.AbstractProcessor; +import spoon.reflect.code.CtBlock; +import spoon.reflect.code.CtCatch; +import spoon.reflect.code.CtCatchVariable; +import spoon.reflect.code.CtConstructorCall; +import spoon.reflect.code.CtExpression; +import spoon.reflect.code.CtInvocation; +import spoon.reflect.code.CtLiteral; +import spoon.reflect.code.CtLocalVariable; +import spoon.reflect.code.CtReturn; +import spoon.reflect.code.CtStatement; +import spoon.reflect.code.CtTry; +import spoon.reflect.declaration.CtMethod; +import spoon.reflect.reference.CtArrayTypeReference; +import spoon.reflect.reference.CtExecutableReference; +import spoon.reflect.reference.CtFieldReference; +import spoon.reflect.reference.CtTypeReference; +import spoon.support.reflect.code.CtFieldAccessImpl; +import spoon.support.reflect.code.CtInvocationImpl; +import spoon.support.reflect.code.CtVariableAccessImpl; +import spoon.support.reflect.reference.CtFieldReferenceImpl; +import bcu.transformer.utils.IConstants; + +/** + * ajoute les try catch autour des methodes + * @author bcornu + * + */ +@SuppressWarnings("all") +public class MethodEncapsulation extends AbstractProcessor { + + private static int methodNumber = 0; + + public static int getCpt(){ + return methodNumber; + } + + @Override + public void process(CtMethod ctMethode) { + methodNumber++; + if(ctMethode.getBody()==null) + return; + + CtLocalVariable methodVar = getNewMethodcontext(); + + CtTypeReference tmpref = getFactory().Core().clone(ctMethode.getType()); + if(!(tmpref instanceof CtArrayTypeReference)){ + tmpref = tmpref.box(); + }else if(((CtArrayTypeReference)tmpref).getComponentType()!=null){ + ((CtArrayTypeReference)tmpref).getComponentType().setActualTypeArguments(null); + } +// tmpref.setActualTypeArguments(null); + + CtTry coreTry = createTry(methodVar,tmpref); + coreTry.setBody(getFactory().Core().createBlock()); + coreTry.getBody().setStatements(ctMethode.getBody().getStatements()); + + List stats = new ArrayList(); + stats.add(methodVar); + stats.add(coreTry); + + ctMethode.getBody().setStatements(stats); + } + + private CtTry createTry(CtLocalVariable methodVar, CtTypeReference tmpref){ + CtVariableAccessImpl methodAccess = new CtVariableAccessImpl(); + methodAccess.setVariable(methodVar.getReference()); + + CtReturn ret = getFactory().Core().createReturn(); + if(tmpref.getActualClass()!=java.lang.Void.class){ + CtTypeReference tmp2 = tmpref; + CtExpression arg = null; + if(tmp2 instanceof CtArrayTypeReference){ + tmp2=((CtArrayTypeReference)tmp2).getDeclaringType(); + } + if(tmp2==null || tmp2.isAnonymous() || tmp2.getSimpleName()==null || (tmp2.getPackage()==null && tmp2.getSimpleName().length()==1)){ + arg = getFactory().Core().createLiteral(); + arg.setType(getFactory().Type().nullType()); + }else{ + tmp2 = getFactory().Type().createReference(tmp2.getQualifiedName()); + CtFieldReference ctfe = new CtFieldReferenceImpl(); + ctfe.setSimpleName("class"); + ctfe.setDeclaringType(tmp2); + + arg = new CtFieldAccessImpl(); + ((CtFieldAccessImpl) arg).setVariable(ctfe); + } + + CtExecutableReference execref = getFactory().Core().createExecutableReference(); + execref.setDeclaringType(getFactory().Type().createReference("bcornu.resi.CallChecker")); + execref.setSimpleName("returned"); + execref.setStatic(true); + + CtInvocationImpl invoc = (CtInvocationImpl) getFactory().Core().createInvocation(); + invoc.setExecutable(execref); + invoc.setArguments(Arrays.asList(new CtExpression[]{arg})); + + ret.setReturnedExpression(invoc); + } + + CtCatchVariable parameter = getFactory().Core().createCatchVariable(); + parameter.setType(getFactory().Type().createReference("bcornu.resi.ForceReturn")); + parameter.setSimpleName("_bcornu_return_t"); + + CtCatch localCatch = getFactory().Core().createCatch(); + localCatch.setParameter(parameter); + localCatch.setBody(getFactory().Core().createBlock()); + localCatch.getBody().addStatement(ret); + + CtExecutableReference executableRef = getFactory().Core().createExecutableReference(); + executableRef.setSimpleName("methodEnd"); + + CtInvocation invoc = getFactory().Core().createInvocation(); + invoc.setExecutable(executableRef); + invoc.setTarget(methodAccess); + + CtBlock finalizer = getFactory().Core().createBlock(); + finalizer.addStatement(invoc); + + CtTry e = getFactory().Core().createTry(); + e.addCatcher(localCatch); + e.setFinalizer(finalizer); + return e; + } + + private CtLocalVariable getNewMethodcontext() { + CtConstructorCall ctx = getFactory().Core().createConstructorCall(); + ctx.setType(getFactory().Type().createReference(IConstants.Class.METHODE_CONTEXT)); + + List args = new ArrayList<>(); + + CtLiteral tryNum = getFactory().Core().createLiteral(); + tryNum.setValue(methodNumber); + args.add(tryNum); + + CtLocalVariable context = getFactory().Core().createLocalVariable(); + context.setSimpleName(IConstants.Var.METHODE_CONTEXT+ methodNumber); + context.setType(getFactory().Type().createReference(IConstants.Class.METHODE_CONTEXT)); + context.setDefaultExpression(ctx); + return context; + } +} diff --git a/srcs/processors/bcu/transformer/processors/TargetIfAdder.java b/srcs/processors/bcu/transformer/processors/TargetIfAdder.java new file mode 100644 index 0000000..00ba003 --- /dev/null +++ b/srcs/processors/bcu/transformer/processors/TargetIfAdder.java @@ -0,0 +1,188 @@ +package bcu.transformer.processors; + +import java.util.Arrays; + +import spoon.processing.AbstractProcessor; +import spoon.reflect.code.CtAssignment; +import spoon.reflect.code.CtBlock; +import spoon.reflect.code.CtCatch; +import spoon.reflect.code.CtConstructorCall; +import spoon.reflect.code.CtExpression; +import spoon.reflect.code.CtFieldAccess; +import spoon.reflect.code.CtIf; +import spoon.reflect.code.CtInvocation; +import spoon.reflect.code.CtLocalVariable; +import spoon.reflect.code.CtLoop; +import spoon.reflect.code.CtReturn; +import spoon.reflect.code.CtStatement; +import spoon.reflect.code.CtStatementList; +import spoon.reflect.code.CtSuperAccess; +import spoon.reflect.code.CtTargetedExpression; +import spoon.reflect.code.CtThisAccess; +import spoon.reflect.code.CtThrow; +import spoon.reflect.code.CtTypeAccess; +import spoon.reflect.declaration.CtConstructor; +import spoon.reflect.declaration.CtElement; +import spoon.reflect.declaration.ModifierKind; +import spoon.reflect.declaration.ParentNotInitializedException; +import spoon.reflect.reference.CtArrayTypeReference; +import spoon.reflect.reference.CtExecutableReference; +import spoon.reflect.reference.CtFieldReference; +import spoon.reflect.reference.CtTypeReference; +import spoon.support.reflect.code.CtFieldAccessImpl; +import spoon.support.reflect.code.CtInvocationImpl; +import spoon.support.reflect.code.CtVariableAccessImpl; +import spoon.support.reflect.reference.CtFieldReferenceImpl; + +@SuppressWarnings("all") +public class TargetIfAdder extends AbstractProcessor{ + + private int i=0; + private int j=0; + @Override + public void processingDone() { + System.out.println("if -->"+i +" (failed:"+j+")"); + } + + + @Override + public void process(CtTargetedExpression element) { + + if(element.getTarget()==null) + return; + if(element.getTarget() instanceof CtThisAccess + || element.getTarget() instanceof CtSuperAccess + || element.getTarget() instanceof CtTypeAccess) + return; + CtElement line = element; + try{ + i++; + CtElement parent; + boolean found = false; + boolean needElse = false; + try{ + while (!found) { + parent=line.getParent(); + if(parent == null || parent.getParent()==null){ + return; + }else if(parent.getParent() instanceof CtConstructor && line instanceof CtInvocation + && ((CtInvocation)line).getExecutable().getSimpleName().equals("")){ + return;//premiere ligne constructeur + }else if(parent instanceof CtReturn || parent instanceof CtThrow){ + line=parent; + needElse = true; + }else if(parent instanceof CtBlock){ + found=true; + }else if(parent instanceof CtStatementList){ + found=true; + }else if(parent instanceof CtCatch){ + found=true; + }else if(parent instanceof CtIf){ + line=parent; + needElse = true; + }else if(parent instanceof CtAssignment + && ((CtAssignment) parent).getAssigned() instanceof CtFieldAccess){ + return; + }else if(parent instanceof CtLoop){ + return; + }else{ + line=parent; + } + } + }catch(ParentNotInitializedException pni){ + System.out.println(line); + pni.printStackTrace(); + j++; + } + if(line instanceof CtLocalVariable && ((CtLocalVariable) line).hasModifier(ModifierKind.FINAL)) + return; + + CtExecutableReference execif = getFactory().Core().createExecutableReference(); + execif.setDeclaringType(getFactory().Type().createReference("bcornu.resi.CallChecker")); + execif.setSimpleName("beforeDeref"); + execif.setStatic(true); + + CtInvocationImpl ifInvoc = (CtInvocationImpl) getFactory().Core().createInvocation(); + ifInvoc.setExecutable(execif); + ifInvoc.setArguments(Arrays.asList(new CtExpression[]{element.getTarget()})); + + CtIf encaps = getFactory().Core().createIf(); + encaps.setCondition(ifInvoc); + + CtBlock thenBloc = getFactory().Core().createBlock(); + + //add var init + if(line instanceof CtLocalVariable){ + CtLocalVariable localVar = (CtLocalVariable) line; + + CtAssignment assign = getFactory().Core().createAssignment(); + + CtVariableAccessImpl va = new CtVariableAccessImpl(); + va.setVariable(localVar.getReference()); + + assign.setAssigned(va); + assign.setAssignment(localVar.getDefaultExpression()); + + CtLocalVariable previous = getFactory().Core().createLocalVariable(); + previous.setType(localVar.getType()); + previous.setSimpleName(localVar.getSimpleName()); + + CtTypeReference tmp2 = localVar.getType(); + + CtExpression arg = null; + if(tmp2 instanceof CtArrayTypeReference){ + tmp2=((CtArrayTypeReference)tmp2).getDeclaringType(); + } + if(tmp2==null || tmp2.isAnonymous() || tmp2.getSimpleName()==null || (tmp2.getPackage()==null && tmp2.getSimpleName().length()==1)){ + arg = getFactory().Core().createLiteral(); + arg.setType(getFactory().Type().nullType()); + }else{ + tmp2 = getFactory().Type().createReference(tmp2.getQualifiedName()); + CtFieldReference ctfe = new CtFieldReferenceImpl(); + ctfe.setSimpleName("class"); + ctfe.setDeclaringType(tmp2); + + arg = new CtFieldAccessImpl(); + ((CtFieldAccessImpl) arg).setVariable(ctfe); + } + CtExecutableReference execref = getFactory().Core().createExecutableReference(); + execref.setDeclaringType(getFactory().Type().createReference("bcornu.resi.CallChecker")); + execref.setSimpleName("init"); + execref.setStatic(true); + + CtInvocationImpl invoc = (CtInvocationImpl) getFactory().Core().createInvocation(); + invoc.setExecutable(execref); + invoc.setArguments(Arrays.asList(new CtExpression[]{arg})); + + previous.setDefaultExpression(invoc); + + ((CtLocalVariable) line).insertBefore(previous); + + + thenBloc.addStatement(assign); + encaps.setThenStatement(thenBloc); + line.replace(encaps); + }else{ + line.replace(encaps); + encaps.setThenStatement(thenBloc); + thenBloc.addStatement((CtStatement)line); + } + + if(needElse){ + CtConstructorCall npe = getFactory().Core().createConstructorCall(); + npe.setType(getFactory().Type().createReference("bcornu.resi.AbnormalExecutionError")); + + CtThrow thrower = getFactory().Core().createThrow(); + thrower.setThrownExpression(npe); + + encaps.setElseStatement(thrower); + } + + }catch(Throwable t){ + System.out.println(line+"-->"+element); + t.printStackTrace(); + j++; + } + } + +} diff --git a/srcs/processors/bcu/transformer/processors/TargetModifier.java b/srcs/processors/bcu/transformer/processors/TargetModifier.java new file mode 100644 index 0000000..721df6b --- /dev/null +++ b/srcs/processors/bcu/transformer/processors/TargetModifier.java @@ -0,0 +1,93 @@ +package bcu.transformer.processors; + +import java.util.Arrays; + +import spoon.processing.AbstractProcessor; +import spoon.reflect.code.CtAssignment; +import spoon.reflect.code.CtConditional; +import spoon.reflect.code.CtExpression; +import spoon.reflect.code.CtIf; +import spoon.reflect.code.CtLocalVariable; +import spoon.reflect.code.CtStatement; +import spoon.reflect.code.CtSuperAccess; +import spoon.reflect.code.CtTargetedExpression; +import spoon.reflect.code.CtThisAccess; +import spoon.reflect.code.CtVariableAccess; +import spoon.reflect.declaration.CtVariable; +import spoon.reflect.reference.CtArrayTypeReference; +import spoon.reflect.reference.CtExecutableReference; +import spoon.reflect.reference.CtFieldReference; +import spoon.reflect.reference.CtTypeReference; +import spoon.support.reflect.code.CtFieldAccessImpl; +import spoon.support.reflect.code.CtInvocationImpl; +import spoon.support.reflect.code.CtVariableAccessImpl; +import spoon.support.reflect.reference.CtFieldReferenceImpl; + +@SuppressWarnings("all") +public class TargetModifier extends AbstractProcessor{ + + private int i=0; + private int j=0; + @Override + public void processingDone() { + System.out.println("target-->"+i +" (failed:"+j+")"); + } + @Override + public void process(CtTargetedExpression element) { + if(element.getTarget()==null) + return; + if(element.getTarget() instanceof CtThisAccess + || element.getTarget() instanceof CtSuperAccess) + return; + + String sign = ""; + if (element.getTarget() instanceof CtVariableAccess) { + sign = ((CtVariableAccess)element.getTarget()).getVariable().getSimpleName(); + } + try{ + i++; + CtTypeReference tmp = element.getTarget().getType(); + if(sign.equals("class")){ + tmp = getFactory().Type().createReference(Class.class); + } + if(element.getTarget().getTypeCasts()!=null && element.getTarget().getTypeCasts().size()>0){ + tmp = (CtTypeReference) element.getTarget().getTypeCasts().get(0); + } + + CtExpression arg = null; + if(tmp instanceof CtArrayTypeReference){ + tmp=((CtArrayTypeReference)tmp).getDeclaringType(); + } + if(tmp==null || tmp.isAnonymous() || tmp.getSimpleName()==null || (tmp.getPackage()==null && tmp.getSimpleName().length()==1)){ + arg = getFactory().Core().createLiteral(); + arg.setType(getFactory().Type().nullType()); + }else{ + tmp = getFactory().Type().createReference(tmp.getQualifiedName()); + CtFieldReference ctfe = new CtFieldReferenceImpl(); + ctfe.setSimpleName("class"); + ctfe.setDeclaringType(tmp.box()); + + arg = new CtFieldAccessImpl(); + ((CtFieldAccessImpl) arg).setVariable(ctfe); + } + + CtExecutableReference execref = getFactory().Core().createExecutableReference(); + execref.setDeclaringType(getFactory().Type().createReference("bcornu.resi.CallChecker")); + execref.setSimpleName("isCalled"); + execref.setStatic(true); + + CtInvocationImpl invoc = (CtInvocationImpl) getFactory().Core().createInvocation(); + invoc.setExecutable(execref); + invoc.setArguments(Arrays.asList(new CtExpression[]{element.getTarget(),arg})); + + element.setTarget((CtExpression)invoc); + + + + }catch(Throwable t){ + t.printStackTrace(); + j++; + } + } + +} diff --git a/srcs/processors/bcu/transformer/processors/TryRegister.java b/srcs/processors/bcu/transformer/processors/TryRegister.java new file mode 100644 index 0000000..8dcd699 --- /dev/null +++ b/srcs/processors/bcu/transformer/processors/TryRegister.java @@ -0,0 +1,105 @@ +package bcu.transformer.processors; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import spoon.processing.AbstractProcessor; +import spoon.reflect.code.CtCatch; +import spoon.reflect.code.CtConstructorCall; +import spoon.reflect.code.CtInvocation; +import spoon.reflect.code.CtLiteral; +import spoon.reflect.code.CtLocalVariable; +import spoon.reflect.code.CtStatement; +import spoon.reflect.code.CtTry; +import spoon.reflect.code.CtVariableAccess; +import spoon.reflect.reference.CtExecutableReference; +import spoon.reflect.reference.CtTypeReference; +import spoon.support.reflect.code.CtVariableAccessImpl; +import bcu.transformer.utils.IConstants; + +@SuppressWarnings({ "unchecked", "rawtypes" }) +public class TryRegister extends AbstractProcessor { + + private int tryNumber = 0; + private CtVariableAccess mainContextVar = null; + + @Override + public void process(CtTry element) { + tryNumber++; + List catchables = new ArrayList<>(); + for (CtCatch catchArg : element.getCatchers()) { + catchables.add(catchArg.getParameter().getReference().getType()); + } + CtLocalVariable tryVar = getNewTrycontext(catchables); + + element.insertBefore(tryVar); + + mainContextVar = new CtVariableAccessImpl(); + mainContextVar.setVariable(tryVar.getReference()); + + for (CtCatch catchArg : element.getCatchers()) { + catchArg.getBody().insertBegin(getCatchStart(tryVar)); + } + + if(element.getFinalizer()==null){ + element.setFinalizer(getFactory().Core().createBlock()); + } + element.getFinalizer().insertBegin(getFinallyStart(tryVar)); + + } + + private CtStatement getFinallyStart(CtLocalVariable tryVar) { + CtExecutableReference executableRef = getFactory().Core().createExecutableReference(); + executableRef.setSimpleName("finallyStart"); + + CtLiteral tryNum = getFactory().Core().createLiteral(); + tryNum.setValue(tryNumber); + + CtInvocation invoc = getFactory().Core().createInvocation(); + invoc.setExecutable(executableRef); + invoc.setTarget(mainContextVar); + invoc.setArguments(Arrays.asList(new CtLiteral[]{tryNum})); + return invoc; + } + + private CtInvocation getCatchStart(CtLocalVariable tryVar) { + CtExecutableReference executableRef = getFactory().Core().createExecutableReference(); + executableRef.setSimpleName("catchStart"); + + CtLiteral tryNum = getFactory().Core().createLiteral(); + tryNum.setValue(tryNumber); + + CtInvocation invoc = getFactory().Core().createInvocation(); + invoc.setExecutable(executableRef); + invoc.setTarget(mainContextVar); + invoc.setArguments(Arrays.asList(new CtLiteral[]{tryNum})); + return invoc; + } + + private CtLocalVariable getNewTrycontext(List catchables) { + CtConstructorCall ctx = getFactory().Core().createConstructorCall(); + ctx.setType(getFactory().Type().createReference(IConstants.Class.TRY_CONTEXT)); + + List args = new ArrayList<>(); + + CtLiteral tryNum = getFactory().Core().createLiteral(); + tryNum.setValue(tryNumber); + args.add(tryNum); + + for (CtTypeReference type : catchables) { + CtLiteral literal = getFactory().Core().createLiteral(); + literal.setValue(type.getQualifiedName()); + args.add(literal); + } + ctx.setArguments(args); + + CtLocalVariable context = getFactory().Core().createLocalVariable(); + context.setSimpleName(IConstants.Var.TRY_CONTEXT_PREFIX + tryNumber); + context.setType(getFactory().Type().createReference(IConstants.Class.TRY_CONTEXT)); + context.setDefaultExpression(ctx); + + return context; + } + +} diff --git a/srcs/processors/bcu/transformer/processors/VarRetrieveAssign.java b/srcs/processors/bcu/transformer/processors/VarRetrieveAssign.java new file mode 100644 index 0000000..820f58a --- /dev/null +++ b/srcs/processors/bcu/transformer/processors/VarRetrieveAssign.java @@ -0,0 +1,40 @@ +package bcu.transformer.processors; + +import java.util.Arrays; + +import spoon.processing.AbstractProcessor; +import spoon.reflect.code.CtAssignment; +import spoon.reflect.code.CtExpression; +import spoon.reflect.reference.CtExecutableReference; +import spoon.support.reflect.code.CtInvocationImpl; + +public class VarRetrieveAssign extends AbstractProcessor { + + int i=0; + int j=0; + + @Override + public void process(CtAssignment element) { + try{ + j++; + CtExecutableReference execref = getFactory().Core().createExecutableReference(); + execref.setDeclaringType(getFactory().Type().createReference("bcornu.resi.CallChecker")); + execref.setSimpleName("varAssign"); + execref.setStatic(true); + + CtInvocationImpl invoc = (CtInvocationImpl) getFactory().Core().createInvocation(); + invoc.setExecutable(execref); + invoc.setArguments(Arrays.asList(new CtExpression[]{element.getAssigned()})); + + element.insertAfter(invoc); + }catch(Throwable t){ + i++; + } + } + + @Override + public void processingDone() { + System.out.println("assign --> "+j+" (failed: "+i+")"); + } + +} diff --git a/srcs/processors/bcu/transformer/processors/VarRetrieveInit.java b/srcs/processors/bcu/transformer/processors/VarRetrieveInit.java new file mode 100644 index 0000000..7a166e6 --- /dev/null +++ b/srcs/processors/bcu/transformer/processors/VarRetrieveInit.java @@ -0,0 +1,34 @@ +package bcu.transformer.processors; + +import java.util.Arrays; + +import spoon.processing.AbstractProcessor; +import spoon.reflect.code.CtExpression; +import spoon.reflect.code.CtFor; +import spoon.reflect.code.CtForEach; +import spoon.reflect.code.CtLocalVariable; +import spoon.reflect.reference.CtExecutableReference; +import spoon.support.reflect.code.CtInvocationImpl; + +public class VarRetrieveInit extends AbstractProcessor { + + @Override + public void process(CtLocalVariable element) { + + if(element.getParent() instanceof CtForEach + || element.getParent() instanceof CtFor) + return; + + CtExecutableReference execref = getFactory().Core().createExecutableReference(); + execref.setDeclaringType(getFactory().Type().createReference("bcornu.resi.CallChecker")); + execref.setSimpleName("varInit"); + execref.setStatic(true); + + CtInvocationImpl invoc = (CtInvocationImpl) getFactory().Core().createInvocation(); + invoc.setExecutable(execref); + invoc.setArguments(Arrays.asList(new CtExpression[]{element.getDefaultExpression()})); + + element.setDefaultExpression(invoc); + } + +} diff --git a/srcs/processors/bcu/transformer/utils/CtThrowGenerated.java b/srcs/processors/bcu/transformer/utils/CtThrowGenerated.java new file mode 100644 index 0000000..3c591af --- /dev/null +++ b/srcs/processors/bcu/transformer/utils/CtThrowGenerated.java @@ -0,0 +1,12 @@ +package bcu.transformer.utils; + +import spoon.support.reflect.code.CtThrowImpl; + +public class CtThrowGenerated extends CtThrowImpl{ + + /** + * generated + */ + private static final long serialVersionUID = 5737541619010329164L; + +} diff --git a/srcs/processors/bcu/transformer/utils/CtTryGenerated.java b/srcs/processors/bcu/transformer/utils/CtTryGenerated.java new file mode 100644 index 0000000..48924e8 --- /dev/null +++ b/srcs/processors/bcu/transformer/utils/CtTryGenerated.java @@ -0,0 +1,12 @@ +package bcu.transformer.utils; + +import spoon.support.reflect.code.CtTryImpl; + +public class CtTryGenerated extends CtTryImpl { + + /** + * + */ + private static final long serialVersionUID = 1L; + +} diff --git a/srcs/processors/bcu/transformer/utils/IConstants.java b/srcs/processors/bcu/transformer/utils/IConstants.java new file mode 100644 index 0000000..09ecfa1 --- /dev/null +++ b/srcs/processors/bcu/transformer/utils/IConstants.java @@ -0,0 +1,65 @@ +package bcu.transformer.utils; + +public interface IConstants{ + public interface Class { + public static final String THROWABLE = "java.lang.Throwable"; + public static final String SUBMARINE_EXCEPTION = "bcornu.resi.exception.SubMarineException"; + public static final String INJECTED_EXCEPTION = "bcornu.resi.exception.InjectedException"; + public static final String CONSTRUCTOR_MANAGER = "bcornu.resi.manager.ConstructorManager"; + public static final String ACTION_PERFORMED_MANAGER = "bcornu.resi.manager.ActionPerformedManager"; + public static final String FAULT_INJECTOR ="bcornu.resi.manager.FaultInjector"; + public static final String RESILIENCE_MANAGER ="bcornu.resi.manager.ResilienceManager"; + public static final String FAKE_EXCEPTION_THROWER ="bcornu.resi.utils.FakeExceptionThrower"; + public static final String STATIC_MANAGER ="bcornu.resi.manager.StaticManager"; + public static final String SUBMARINE_MANAGER ="bcornu.resi.manager.SubMarineManager"; + public static final String EXCEPTION_CREATOR ="bcornu.resi.utils.ExceptionCreator"; + public static final String ABEND_MANAGER ="bcornu.resi.manager.AbendManager"; + public static final String CATCH_MANAGER ="bcornu.resi.manager.CatchManager"; + public static final String TRY_CONTEXT = "bcornu.resi.context.TryContext"; + public static final String TRY_CONTEXT_IMPL = "bcornu.resi.context.TryContextImpl"; + public static final String FINALLY_MANAGER = "bcornu.resi.manager.FinallyManager"; + public static final String BLOCK_CONTEXT = "bcornu.resi.context.BlockContext"; + public static final String STATIC_CONTEXT = "bcornu.resi.context.StaticContext"; + public static final String CONSTRUCTOR_CONTEXT = "bcornu.resi.context.ConstructorContext"; + public static final String METHODE_CONTEXT = "bcornu.resi.context.MethodeContext"; + public static final String FAKE_INITIALIZER = "bcornu.resi.utils.FakeInitializer"; + public static final String THROW_MANAGER = "bcornu.resi.context.ThrowManager"; + } + public interface Method{ + public static final String CONTEXT_LEARN_TRY_THROWN_EXCEPTION = "learnsThatTryHasThrownTheException"; + public static final String CONTEXT_CATCH_ACTIVATED = "setCatchActivated"; + public static final String CONTEXT_CATCH_VISITED = "setCatchVisited"; + public static final String CONTEXT_FINALLY_VISITED = "setFinallyVisited"; + public static final String CONTEXT_FINALLY_ACTIVATED = "setFinallyActivated"; + public static final String CONTEXT_LEARN_FINALLY_THROWN_EXCEPTION = "learnsThatFinallyHasThrownTheException"; + public static final String CONTEXT_TRY_FINISHED = "learnsThatTryHasFinished"; + public static final String BLOCK_CONTEXT_THROWS = "blockThrows"; + public static final String BLOCK_CONTEXT_COMPUTE = "compute"; + public static final String BLOCK_CONTEXT_START = "blockStart"; + public static final String BLOCK_CONTEXT_END = "blockEnd"; + public static final String TRY_CONTEXT_COMPUTE_ALL = "computeAll"; + public static final String TRY_CONTEXT_TRY_START = "tryStart"; + public static final String TRY_CONTEXT_TRY_THROWS = "tryThrows"; + public static final String TRY_CONTEXT_TRY_END = "tryEnd"; + public static final String TRY_CONTEXT_TRY_COMPUTE = "tryCompute"; + public static final String TRY_CONTEXT_CATCH_START = "catchStart"; + public static final String TRY_CONTEXT_CATCH_THROWS = "catchThrows"; + public static final String TRY_CONTEXT_CATCH_END = "catchEnd"; + public static final String TRY_CONTEXT_CATCH_COMPUTE = "catchCompute"; + public static final String TRY_CONTEXT_FINALLY_START = "finallyStart"; + public static final String TRY_CONTEXT_FINALLY_THROWS = "finallyThrows"; + public static final String TRY_CONTEXT_FINALLY_END = "finallyEnd"; + public static final String TRY_CONTEXT_FINALLY_COMPUTE = "finallyCompute"; + public static final String FAKE_INITIALIZER_INITALIZE = "initialize"; + public static final String TRY_CONTEXT_ALL_THROWS = "allThrows"; + } + public interface Var{ + public static final String DEFAULT_THROWABLE = "_bcornu_t"; + public static final String TRY_CONTEXT_PREFIX = "_bcornu_try_context_"; + public static final String STATIC_CONTEXT = "_bcornu_static_context"; + public static final String METHODE_CONTEXT = "_bcornu_methode_context"; + public static final String CONSTRUCTOR_CONTEXT = "_bcornu_constructor_context"; + public static final String THROW_CONTEXT = "_bcornu_throw_context"; + } + +} diff --git a/srcs/utils/org/eclipse/core/internal/localstore/ILocalStoreConstants.java b/srcs/utils/org/eclipse/core/internal/localstore/ILocalStoreConstants.java new file mode 100644 index 0000000..63d6538 --- /dev/null +++ b/srcs/utils/org/eclipse/core/internal/localstore/ILocalStoreConstants.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2000, 2005 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.core.internal.localstore; + +public interface ILocalStoreConstants { + + /** Common constants for History Store classes. */ + public final static int SIZE_LASTMODIFIED = 8; + public static final int SIZE_COUNTER = 1; + public static final int SIZE_KEY_SUFFIX = SIZE_LASTMODIFIED + SIZE_COUNTER; + + /** constants for safe chunky streams */ + + // 40b18b8123bc00141a2596e7a393be1e + public static final byte[] BEGIN_CHUNK = {64, -79, -117, -127, 35, -68, 0, 20, 26, 37, -106, -25, -93, -109, -66, 30}; + + // c058fbf323bc00141a51f38c7bbb77c6 + public static final byte[] END_CHUNK = {-64, 88, -5, -13, 35, -68, 0, 20, 26, 81, -13, -116, 123, -69, 119, -58}; + + /** chunk delimiter size */ + // BEGIN_CHUNK and END_CHUNK must have the same length + public static final int CHUNK_DELIMITER_SIZE = BEGIN_CHUNK.length; +} \ No newline at end of file diff --git a/srcs/utils/org/eclipse/core/internal/localstore/SafeChunkyInputStream.java b/srcs/utils/org/eclipse/core/internal/localstore/SafeChunkyInputStream.java new file mode 100644 index 0000000..7205404 --- /dev/null +++ b/srcs/utils/org/eclipse/core/internal/localstore/SafeChunkyInputStream.java @@ -0,0 +1,181 @@ +/******************************************************************************* + * Copyright (c) 2000, 2005 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.core.internal.localstore; + +import java.io.*; + +/** + * @see SafeChunkyOutputStream + */ + +public class SafeChunkyInputStream extends InputStream { + protected static final int BUFFER_SIZE = 8192; + protected byte[] buffer; + protected int bufferLength = 0; + protected byte[] chunk; + protected int chunkLength = 0; + protected boolean endOfFile = false; + protected InputStream input; + protected int nextByteInBuffer = 0; + protected int nextByteInChunk = 0; + + public SafeChunkyInputStream(File target) throws IOException { + this(target, BUFFER_SIZE); + } + + public SafeChunkyInputStream(File target, int bufferSize) throws IOException { + input = new FileInputStream(target); + buffer = new byte[bufferSize]; + } + + protected void accumulate(byte[] data, int start, int end) { + byte[] result = new byte[chunk.length + end - start]; + System.arraycopy(chunk, 0, result, 0, chunk.length); + System.arraycopy(data, start, result, chunk.length, end - start); + chunk = result; + chunkLength = chunkLength + end - start; + } + + public int available() throws IOException { + return chunkLength - nextByteInChunk; + } + + protected void buildChunk() throws IOException { + //read buffer loads of data until an entire chunk is accumulated + while (true) { + if (nextByteInBuffer + ILocalStoreConstants.CHUNK_DELIMITER_SIZE > bufferLength) + shiftAndFillBuffer(); + int end = find(ILocalStoreConstants.END_CHUNK, nextByteInBuffer, bufferLength, true); + if (end != -1) { + accumulate(buffer, nextByteInBuffer, end); + nextByteInBuffer = end + ILocalStoreConstants.CHUNK_DELIMITER_SIZE; + return; + } + accumulate(buffer, nextByteInBuffer, bufferLength); + bufferLength = input.read(buffer); + nextByteInBuffer = 0; + if (bufferLength == -1) { + endOfFile = true; + return; + } + } + } + + public void close() throws IOException { + input.close(); + } + + protected boolean compare(byte[] source, byte[] target, int startIndex) { + for (int i = 0; i < target.length; i++) { + if (source[startIndex] != target[i]) + return false; + startIndex++; + } + return true; + } + + protected int find(byte[] pattern, int startIndex, int endIndex, boolean accumulate) throws IOException { + int pos = findByte(pattern[0], startIndex, endIndex); + if (pos == -1) + return -1; + if (pos + ILocalStoreConstants.CHUNK_DELIMITER_SIZE > bufferLength) { + if (accumulate) + accumulate(buffer, nextByteInBuffer, pos); + nextByteInBuffer = pos; + pos = 0; + shiftAndFillBuffer(); + } + if (compare(buffer, pattern, pos)) + return pos; + return find(pattern, pos + 1, endIndex, accumulate); + } + + protected int findByte(byte target, int startIndex, int endIndex) { + while (startIndex < endIndex) { + if (buffer[startIndex] == target) + return startIndex; + startIndex++; + } + return -1; + } + + protected void findChunkStart() throws IOException { + if (nextByteInBuffer + ILocalStoreConstants.CHUNK_DELIMITER_SIZE > bufferLength) + shiftAndFillBuffer(); + int begin = find(ILocalStoreConstants.BEGIN_CHUNK, nextByteInBuffer, bufferLength, false); + if (begin != -1) { + nextByteInBuffer = begin + ILocalStoreConstants.CHUNK_DELIMITER_SIZE; + return; + } + bufferLength = input.read(buffer); + nextByteInBuffer = 0; + if (bufferLength == -1) { + resetChunk(); + endOfFile = true; + return; + } + findChunkStart(); + } + + public int read() throws IOException { + if (endOfFile) + return -1; + // if there are bytes left in the chunk, return the first available + if (nextByteInChunk < chunkLength) + return chunk[nextByteInChunk++] & 0xFF; + // Otherwise the chunk is empty so clear the current one, get the next + // one and recursively call read. Need to recur as the chunk may be + // real but empty. + resetChunk(); + findChunkStart(); + if (endOfFile) + return -1; + buildChunk(); + refineChunk(); + return read(); + } + + /** + * Skip over any begin chunks in the current chunk. This could be optimized + * to skip at the same time as we are scanning the buffer. + */ + protected void refineChunk() { + int start = chunkLength - ILocalStoreConstants.CHUNK_DELIMITER_SIZE; + if (start < 0) + return; + for (int i = start; i >= 0; i--) { + if (compare(chunk, ILocalStoreConstants.BEGIN_CHUNK, i)) { + nextByteInChunk = i + ILocalStoreConstants.CHUNK_DELIMITER_SIZE; + return; + } + } + } + + protected void resetChunk() { + chunk = new byte[0]; + chunkLength = 0; + nextByteInChunk = 0; + } + + protected void shiftAndFillBuffer() throws IOException { + int length = bufferLength - nextByteInBuffer; + System.arraycopy(buffer, nextByteInBuffer, buffer, 0, length); + nextByteInBuffer = 0; + bufferLength = length; + int read = input.read(buffer, bufferLength, buffer.length - bufferLength); + if (read != -1) + bufferLength += read; + else { + resetChunk(); + endOfFile = true; + } + } +} \ No newline at end of file diff --git a/srcs/utils/sacha/classloader/enrich/EnrichableClassloader.java b/srcs/utils/sacha/classloader/enrich/EnrichableClassloader.java new file mode 100644 index 0000000..6207748 --- /dev/null +++ b/srcs/utils/sacha/classloader/enrich/EnrichableClassloader.java @@ -0,0 +1,236 @@ +package sacha.classloader.enrich; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.List; +import java.util.MissingResourceException; +import java.util.Set; +import java.util.TreeSet; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + +public class EnrichableClassloader extends URLClassLoader{ + + List addedUrls = new ArrayList<>(); + private String M2REPO = null; + private File metadataFolder = null; + + public EnrichableClassloader(URL[] urls) { + super(urls,Thread.currentThread().getContextClassLoader()); + } + + public void addURL(String url){ + try { + addURL(new File(url).toURI().toURL()); + } catch (MalformedURLException e) { + e.printStackTrace(); + } + } + + @Override + public Class loadClass(String name) throws ClassNotFoundException { + return super.loadClass(name); + } + + public void addEclipseMetadata(File metadataFolder) { + this.metadataFolder=metadataFolder; + } + + public void addEclipseProject(String path){ + String classpathEntries = getEclipseClassPath(path); + for (String classpathEntry : classpathEntries.split(File.pathSeparator)) { + if(classpathEntry.endsWith(".jar") && !(classpathEntry.endsWith("/") || classpathEntry.endsWith("\\"))){ + addURL(classpathEntry); + addedUrls.add(classpathEntry); + } + else{ + addURL(classpathEntry+File.separator); + addedUrls.add(classpathEntry+File.separator); + } + } + } + + private String getM2REPO() throws FileNotFoundException { + return M2REPO==null?setM2REPO():M2REPO; + } + + private String setM2REPO() throws FileNotFoundException { + String prefsFile = metadataFolder.getAbsolutePath()+File.separator+".plugins/org.eclipse.core.runtime/.settings/org.eclipse.jdt.core.prefs"; + File file = new File(prefsFile); + if(!file.exists() || !file.canRead()){ + throw new FileNotFoundException("cannot find or read "+prefsFile); + } + BufferedReader isr = new BufferedReader(new InputStreamReader(new FileInputStream(file))); + try { + String line = null; + while((line = isr.readLine())!=null){ + if(line.startsWith("org.eclipse.jdt.core.classpathVariable.M2_REPO=")){ + M2REPO = line.replace("org.eclipse.jdt.core.classpathVariable.M2_REPO=", ""); + return M2REPO; + } + } + } catch (IOException e) { + e.printStackTrace(); + }finally{ + try { + isr.close(); + } catch (IOException e) { + } + } + throw new MissingResourceException("cannot find org.eclipse.jdt.core.classpathVariable.M2_REPO" + + " in file "+file,"org.eclipse.jdt.core.prefs","org.eclipse.jdt.core.classpathVariable.M2_REPO"); + }//org.eclipse.jdt.core.classpathVariable.M2_REPO=/home/bcornu/.m2/repository + + private String getEclipseClassPath(String srcFolderPath,String... ignoredPaths) { + String classpaths = null; + try{ + if(srcFolderPath==null || srcFolderPath.replaceAll("\\s", "").isEmpty())return "."; + String[] folderPaths = srcFolderPath.split(File.pathSeparator); + if(folderPaths.length>1){ + String tmp; + Set paths = new TreeSet(); + for (String folderPath : folderPaths) { + tmp = getEclipseClassPath(folderPath,folderPaths); + if(tmp!=null && !tmp.isEmpty()) + for (String entry : tmp.split(File.pathSeparator)) { + paths.add(entry); + } + } + String res = "."; + for (String path : paths) { + res+=File.pathSeparator+path; + } + return res; + } + File currentPath = new File(srcFolderPath); + String workspaceLoc = null; + if(currentPath.isFile()) + currentPath = currentPath.getParentFile(); + while(currentPath!=null && currentPath.exists()){ + for (File file : currentPath.listFiles()) { + if(file.getName().equals(".classpath")){ + if(workspaceLoc==null) + workspaceLoc = currentPath.getParent(); + FileInputStream reader = new FileInputStream(file); + Element cpElement; + try { + DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + cpElement = parser.parse(new InputSource(reader)).getDocumentElement(); + } catch (SAXException e) { + throw new IOException("bad format"); + } catch (ParserConfigurationException e) { + throw new IOException("bad format"); + } finally { + reader.close(); + } + + if (!cpElement.getNodeName().equalsIgnoreCase("classpath")) { + throw new IOException("bad format"); + } + NodeList list = cpElement.getElementsByTagName("classpathentry"); + int length = list.getLength(); + Node node; + for (int i = 0; i < length; ++i) { + if ((node = list.item(i)).getNodeType() == Node.ELEMENT_NODE){ + if("output".equalsIgnoreCase(node.getAttributes().getNamedItem("kind").getNodeValue()) + || "lib".equalsIgnoreCase(node.getAttributes().getNamedItem("kind").getNodeValue())){ + String currentPathString = node.getAttributes().getNamedItem("path").getNodeValue(); + if(!(currentPathString.startsWith("/") || currentPathString.startsWith("\\"))) + currentPathString=currentPath.getAbsolutePath()+File.separator+currentPathString; + if(classpaths == null) + classpaths = currentPathString; + else + classpaths+= File.pathSeparator+currentPathString; + }else if("var".equalsIgnoreCase(node.getAttributes().getNamedItem("kind").getNodeValue())){ + String currentPathString = node.getAttributes().getNamedItem("path").getNodeValue(); + if(currentPathString.contains("M2_REPO")) + currentPathString = currentPathString.replaceFirst("M2_REPO", getM2REPO()); + else{ + System.err.println("cannot resolve : "+currentPathString); + continue; + } + if(!(currentPathString.startsWith("/") || currentPathString.startsWith("\\"))) + currentPathString=currentPath.getAbsolutePath()+File.separator+currentPathString; + if(classpaths == null) + classpaths = currentPathString; + else + classpaths+= File.pathSeparator+currentPathString; + }else if("src".equalsIgnoreCase(node.getAttributes().getNamedItem("kind").getNodeValue())){ + String currentPathString = node.getAttributes().getNamedItem("path").getNodeValue(); + boolean perform = currentPathString.startsWith("/"); + if(perform && ignoredPaths!=null) + { + currentPathString = workspaceLoc+currentPathString; + for (String ignoredPath : ignoredPaths) + if(ignoredPath.equalsIgnoreCase(currentPathString)) + perform=false; + } + if(perform){ + File projectFolder=new File(currentPathString); + if(projectFolder.exists() && projectFolder.isDirectory()){ + for (File file1 : projectFolder.listFiles()) { + if(file1.getName().equals(".classpath")){ + FileInputStream reader1 = new FileInputStream(file1); + Element cpElement1; + try { + DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + cpElement1 = parser.parse(new InputSource(reader1)).getDocumentElement(); + } catch (SAXException e) { + throw new IOException("bad format"); + } catch (ParserConfigurationException e) { + throw new IOException("bad format"); + } finally { + reader1.close(); + } + if (!cpElement1.getNodeName().equalsIgnoreCase("classpath")) { + throw new IOException("bad format"); + } + NodeList list1 = cpElement1.getElementsByTagName("classpathentry"); + int length1 = list1.getLength(); + Node node1; + for (int i1 = 0; i1 < length1; ++i1) { + if ((node1 = list1.item(i1)).getNodeType() == Node.ELEMENT_NODE + && "output".equalsIgnoreCase(node1.getAttributes().getNamedItem("kind").getNodeValue())){ + String outputPathString = projectFolder.getAbsolutePath()+File.separator+node1.getAttributes().getNamedItem("path").getNodeValue(); + if(classpaths == null) + classpaths = outputPathString; + else + classpaths+= File.pathSeparator+outputPathString; + } + } + } + } + } + } + } + } + } + } + } + if(classpaths==null) + currentPath = currentPath.getParentFile(); + else break; + } + }catch(Exception e){ + System.err.println("will use default classpath due to :"+e); + } + return classpaths; + } + +} diff --git a/srcs/utils/sacha/classloader/factory/ClassloaderFactory.java b/srcs/utils/sacha/classloader/factory/ClassloaderFactory.java new file mode 100644 index 0000000..d1c6119 --- /dev/null +++ b/srcs/utils/sacha/classloader/factory/ClassloaderFactory.java @@ -0,0 +1,30 @@ +package sacha.classloader.factory; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import sacha.classloader.enrich.EnrichableClassloader; + +public class ClassloaderFactory { + + public static EnrichableClassloader getEnrichableClassloader(){ + String classPath = System.getProperty("java.class.path"); + List urls = new ArrayList<>(); + for (String classpathElement : splitClassPath(classPath)) { + try { + urls.add(new URL("file://"+classpathElement)); + } catch (MalformedURLException e) { + e.printStackTrace(); + } + } + return new EnrichableClassloader(urls.toArray(new URL[0])); + } + + private static List splitClassPath(String classPath) { + final String separator = System.getProperty("path.separator"); + return Arrays.asList(classPath.split(separator)); + } +} diff --git a/srcs/utils/sacha/finder/classes/ClassFinder.java b/srcs/utils/sacha/finder/classes/ClassFinder.java new file mode 100644 index 0000000..8a9a807 --- /dev/null +++ b/srcs/utils/sacha/finder/classes/ClassFinder.java @@ -0,0 +1,6 @@ +package sacha.finder.classes; + +public interface ClassFinder { + + String[] getClasses(); +} diff --git a/srcs/utils/sacha/finder/classes/impl/ClassloaderFinder.java b/srcs/utils/sacha/finder/classes/impl/ClassloaderFinder.java new file mode 100644 index 0000000..385f440 --- /dev/null +++ b/srcs/utils/sacha/finder/classes/impl/ClassloaderFinder.java @@ -0,0 +1,28 @@ +package sacha.finder.classes.impl; + +import java.io.File; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.List; + +import sacha.finder.classes.ClassFinder; + +public class ClassloaderFinder implements ClassFinder { + + private URLClassLoader urlClassloader; + public ClassloaderFinder(URLClassLoader urlClassloader) { + this.urlClassloader = urlClassloader; + } + + @Override + public String[] getClasses() { + List classes = new ArrayList<>(); + for (URL url : urlClassloader.getURLs()) { + if(new File(url.getPath()).isDirectory()) + classes.addAll(SourceFolderFinder.getClassesLoc(new File(url.getPath()), null)); + } + return classes.toArray(new String[0]); + } + +} diff --git a/srcs/utils/sacha/finder/classes/impl/ClasspathFinder.java b/srcs/utils/sacha/finder/classes/impl/ClasspathFinder.java new file mode 100644 index 0000000..bad67ca --- /dev/null +++ b/srcs/utils/sacha/finder/classes/impl/ClasspathFinder.java @@ -0,0 +1,32 @@ +package sacha.finder.classes.impl; + +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import sacha.finder.classes.ClassFinder; + + +public class ClasspathFinder implements ClassFinder{ + + @Override + public String[] getClasses() { + String classPath = System.getProperty("java.class.path"); + return findClassesInRoots(splitClassPath(classPath)).toArray(new String[0]); + } + + private List splitClassPath(String classPath) { + final String separator = System.getProperty("path.separator"); + return Arrays.asList(classPath.split(separator)); + } + + private List findClassesInRoots(List roots) { + List classes = new ArrayList<>(); + for (String root : roots) { + if(new File(root).isDirectory()) + classes.addAll(SourceFolderFinder.getClassesLoc(new File(root), null)); + } + return classes; + } +} diff --git a/srcs/utils/sacha/finder/classes/impl/ProjectFinder.java b/srcs/utils/sacha/finder/classes/impl/ProjectFinder.java new file mode 100644 index 0000000..07a49eb --- /dev/null +++ b/srcs/utils/sacha/finder/classes/impl/ProjectFinder.java @@ -0,0 +1,28 @@ +package sacha.finder.classes.impl; + +import java.io.File; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; + +import sacha.classloader.enrich.EnrichableClassloader; +import sacha.finder.classes.ClassFinder; + +public class ProjectFinder implements ClassFinder { + + private EnrichableClassloader urlClassloader; + public ProjectFinder(EnrichableClassloader urlClassloader) { + this.urlClassloader = urlClassloader; + } + + @Override + public String[] getClasses() { + List classes = new ArrayList<>(); + for (URL url : urlClassloader.getURLs()) { + if(new File(url.getPath()).isDirectory()) + classes.addAll(SourceFolderFinder.getClassesLoc(new File(url.getPath()), null)); + } + return classes.toArray(new String[0]); + } + +} diff --git a/srcs/utils/sacha/finder/classes/impl/SourceFolderFinder.java b/srcs/utils/sacha/finder/classes/impl/SourceFolderFinder.java new file mode 100644 index 0000000..0306819 --- /dev/null +++ b/srcs/utils/sacha/finder/classes/impl/SourceFolderFinder.java @@ -0,0 +1,40 @@ +package sacha.finder.classes.impl; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import sacha.finder.classes.ClassFinder; + + +public class SourceFolderFinder implements ClassFinder { + + private String srcFolder; + + public SourceFolderFinder(String srcFolder) { + this.srcFolder = srcFolder; + } + + @Override + public String[] getClasses() { + return getClassesLoc(new File(srcFolder),null).toArray(new String[0]); + } + + static List getClassesLoc(File testSrcFolder,String pack) { + List classes = new ArrayList<>(); + for (File file : testSrcFolder.listFiles()) { + if(file.isDirectory()) + classes.addAll(getClassesLoc(file, pack==null?file.getName():pack+'.'+file.getName())); + else if(file.getName().endsWith(".java")){ + String className= pack==null?file.getName():pack+'.'+file.getName(); + className = className.substring(0, className.length()); + classes.add(className); + }else if(file.getName().endsWith(".class")){ + String className= pack==null?file.getName():pack+'.'+file.getName(); + className = className.substring(0, className.length()); + classes.add(className); + } + } + return classes; + } +} diff --git a/srcs/utils/sacha/finder/filters/ClassFilter.java b/srcs/utils/sacha/finder/filters/ClassFilter.java new file mode 100644 index 0000000..0bf093b --- /dev/null +++ b/srcs/utils/sacha/finder/filters/ClassFilter.java @@ -0,0 +1,8 @@ +package sacha.finder.filters; + +public interface ClassFilter { + boolean acceptClass(Class clazz); + boolean acceptClassName(String className); + boolean acceptInnerClass(); + boolean searchInJars(); +} \ No newline at end of file diff --git a/srcs/utils/sacha/finder/filters/impl/AcceptAllFilter.java b/srcs/utils/sacha/finder/filters/impl/AcceptAllFilter.java new file mode 100644 index 0000000..09e190c --- /dev/null +++ b/srcs/utils/sacha/finder/filters/impl/AcceptAllFilter.java @@ -0,0 +1,28 @@ +/* + * @author Johannes Link (business@johanneslink.net) + * + * Published under GNU General Public License 2.0 (http://www.gnu.org/licenses/gpl.html) + */ +package sacha.finder.filters.impl; + +import sacha.finder.filters.ClassFilter; + +public class AcceptAllFilter implements ClassFilter { + + public boolean acceptClassName(String className) { + return true; + } + + public boolean acceptInnerClass() { + return true; + } + + public boolean acceptClass(Class clazz) { + return true; + } + + public boolean searchInJars() { + return true; + } + +} \ No newline at end of file diff --git a/srcs/utils/sacha/finder/filters/impl/TestFilter.java b/srcs/utils/sacha/finder/filters/impl/TestFilter.java new file mode 100644 index 0000000..8559ac9 --- /dev/null +++ b/srcs/utils/sacha/finder/filters/impl/TestFilter.java @@ -0,0 +1,113 @@ +package sacha.finder.filters.impl; + +import java.lang.reflect.*; +import java.util.*; + +import junit.framework.TestCase; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import sacha.finder.filters.ClassFilter; +import sacha.finder.filters.utils.TestType; + + +/** + * ClassTester implementation to retrieve JUnit4 test classes in the classpath. + * You can specify if you want to include jar files in the search and you can + * give a set of regex expression to specify the class names to include. + * + */ +public class TestFilter implements ClassFilter { + + private final boolean searchInJars; + + private final TestType[] testTypes; + + public TestFilter() { + this.searchInJars = true; + this.testTypes = new TestType[]{TestType.JUNIT38_TEST_CLASSES,TestType.RUN_WITH_CLASSES,TestType.TEST_CLASSES}; + } + + public TestFilter(boolean searchInJars) { + this.searchInJars = searchInJars; + this.testTypes = new TestType[]{TestType.JUNIT38_TEST_CLASSES,TestType.RUN_WITH_CLASSES,TestType.TEST_CLASSES}; + } + + public TestFilter(TestType[] suiteTypes) { + this.searchInJars = true; + this.testTypes = suiteTypes; + } + + public TestFilter(boolean searchInJars, + TestType[] suiteTypes) { + this.searchInJars = searchInJars; + this.testTypes = suiteTypes; + } + + public boolean acceptClass(Class clazz) { + if (isInSuiteTypes(TestType.TEST_CLASSES)) { + if (acceptTestClass(clazz)) { + return true; + } + + } + if (isInSuiteTypes(TestType.JUNIT38_TEST_CLASSES)) { + if (acceptJUnit38Test(clazz)) { + return true; + } + } + if (isInSuiteTypes(TestType.RUN_WITH_CLASSES)) { + return acceptRunWithClass(clazz); + } + + return false; + } + + private boolean acceptJUnit38Test(Class clazz) { + if (isAbstractClass(clazz)) { + return false; + } + return TestCase.class.isAssignableFrom(clazz); + } + + private boolean acceptRunWithClass(Class clazz) { + return clazz.isAnnotationPresent(RunWith.class); + } + + private boolean isInSuiteTypes(TestType testType) { + return Arrays.asList(testTypes).contains(testType); + } + + private boolean acceptTestClass(Class clazz) { + if (isAbstractClass(clazz)) { + return false; + } + try { + for (Method method : clazz.getMethods()) { + if (method.getAnnotation(Test.class) != null) { + return true; + } + } + } catch (NoClassDefFoundError ignore) { + } + return false; + } + + private boolean isAbstractClass(Class clazz) { + return (clazz.getModifiers() & Modifier.ABSTRACT) != 0; + } + + public boolean acceptInnerClass() { + return true; + } + + public boolean searchInJars() { + return searchInJars; + } + + public boolean acceptClassName(String className) { + return true; + } + +} diff --git a/srcs/utils/sacha/finder/filters/utils/TestType.java b/srcs/utils/sacha/finder/filters/utils/TestType.java new file mode 100644 index 0000000..01cd69a --- /dev/null +++ b/srcs/utils/sacha/finder/filters/utils/TestType.java @@ -0,0 +1,5 @@ +package sacha.finder.filters.utils; + +public enum TestType { + TEST_CLASSES, RUN_WITH_CLASSES, JUNIT38_TEST_CLASSES +} \ No newline at end of file diff --git a/srcs/utils/sacha/finder/main/Main.java b/srcs/utils/sacha/finder/main/Main.java new file mode 100644 index 0000000..fdd0a4f --- /dev/null +++ b/srcs/utils/sacha/finder/main/Main.java @@ -0,0 +1,19 @@ +package sacha.finder.main; + +import java.io.File; + +public abstract class Main { + + protected static String checkFolder(String testFolder) { + if(testFolder.endsWith("/")||testFolder.endsWith("\\")) + testFolder=testFolder.substring(0, testFolder.length()); + + File testSrcFolder = new File(testFolder); + if(!testSrcFolder.exists() || !testSrcFolder.isDirectory() || !testSrcFolder.canRead()) + throw new IllegalArgumentException("cannot found "+testFolder+" or is not a directory or is not readable"); + + return testFolder; + + } + +} diff --git a/srcs/utils/sacha/finder/main/TestClassFinder.java b/srcs/utils/sacha/finder/main/TestClassFinder.java new file mode 100644 index 0000000..5e3fd40 --- /dev/null +++ b/srcs/utils/sacha/finder/main/TestClassFinder.java @@ -0,0 +1,20 @@ +package sacha.finder.main; + +import sacha.classloader.enrich.EnrichableClassloader; +import sacha.finder.classes.impl.ProjectFinder; +import sacha.finder.filters.impl.TestFilter; +import sacha.finder.processor.Processor; + +public class TestClassFinder{ + + private EnrichableClassloader urlClassloader; + + public TestClassFinder(EnrichableClassloader classloader) { + this.urlClassloader=classloader; + } + + public Class[] findTestClasses(){ + return new Processor(new ProjectFinder(urlClassloader), new TestFilter()).process(); + } + +} diff --git a/srcs/utils/sacha/finder/main/TestInClasspath.java b/srcs/utils/sacha/finder/main/TestInClasspath.java new file mode 100644 index 0000000..f509629 --- /dev/null +++ b/srcs/utils/sacha/finder/main/TestInClasspath.java @@ -0,0 +1,13 @@ +package sacha.finder.main; + +import sacha.finder.classes.impl.ClasspathFinder; +import sacha.finder.filters.impl.TestFilter; +import sacha.finder.processor.Processor; + +public class TestInClasspath{ + + public Class[] find(){ + return new Processor(new ClasspathFinder(), new TestFilter()).process(); + } + +} diff --git a/srcs/utils/sacha/finder/main/TestInFolder.java b/srcs/utils/sacha/finder/main/TestInFolder.java new file mode 100644 index 0000000..d77743b --- /dev/null +++ b/srcs/utils/sacha/finder/main/TestInFolder.java @@ -0,0 +1,19 @@ +package sacha.finder.main; + +import sacha.finder.classes.impl.SourceFolderFinder; +import sacha.finder.filters.impl.TestFilter; +import sacha.finder.processor.Processor; + +public class TestInFolder{ + + private String testFolder = null; + + public TestInFolder(String testFolder) { + this.testFolder=testFolder; + } + + public Class[] find(){ + return new Processor(new SourceFolderFinder(testFolder), new TestFilter()).process(); + } + +} diff --git a/srcs/utils/sacha/finder/main/TestInURLClassloader.java b/srcs/utils/sacha/finder/main/TestInURLClassloader.java new file mode 100644 index 0000000..8ae9ae4 --- /dev/null +++ b/srcs/utils/sacha/finder/main/TestInURLClassloader.java @@ -0,0 +1,21 @@ +package sacha.finder.main; + +import java.net.URLClassLoader; + +import sacha.finder.classes.impl.ClassloaderFinder; +import sacha.finder.filters.impl.TestFilter; +import sacha.finder.processor.Processor; + +public class TestInURLClassloader{ + + private URLClassLoader urlClassloader; + + public TestInURLClassloader(URLClassLoader classloader) { + this.urlClassloader=classloader; + } + + public Class[] find(){ + return new Processor(new ClassloaderFinder(urlClassloader), new TestFilter()).process(); + } + +} diff --git a/srcs/utils/sacha/finder/main/TestMain.java b/srcs/utils/sacha/finder/main/TestMain.java new file mode 100644 index 0000000..f016b00 --- /dev/null +++ b/srcs/utils/sacha/finder/main/TestMain.java @@ -0,0 +1,20 @@ +package sacha.finder.main; + +import sacha.finder.classes.impl.SourceFolderFinder; +import sacha.finder.filters.impl.TestFilter; +import sacha.finder.processor.Processor; + +public class TestMain extends Main{ + + public static Class[] findTest(String testFolder){ + return getTestsClasses(checkFolder(testFolder)); + } + + private static Class[] getTestsClasses(String testFolder) { + return new Processor(new SourceFolderFinder(testFolder), new TestFilter()).process(); + } + + + + +} diff --git a/srcs/utils/sacha/finder/processor/Processor.java b/srcs/utils/sacha/finder/processor/Processor.java new file mode 100644 index 0000000..fde68d1 --- /dev/null +++ b/srcs/utils/sacha/finder/processor/Processor.java @@ -0,0 +1,120 @@ +package sacha.finder.processor; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +import sacha.finder.classes.ClassFinder; +import sacha.finder.filters.ClassFilter; + + + +public class Processor { + + static final int CLASS_SUFFIX_LENGTH = ".class".length(); + static final int JAVA_SUFFIX_LENGTH = ".java".length(); + + private final ClassFilter tester; + private final ClassFinder finder; + + public Processor(ClassFinder finder, ClassFilter tester) { + this.tester = tester; + this.finder = finder; + } + + public Class[] process() { + List> classes = new ArrayList<>(); + for (String fileName : finder.getClasses()) { + String className; + if(isJavaFile(fileName)){ + className = classNameFromJava(fileName); + }else + if(isClassFile(fileName)) { + className = classNameFromFile(fileName); + }else continue; + if (!tester.acceptClassName(className)) { + continue; + } + if (!tester.acceptInnerClass() && isInnerClass(className)) { + continue; + } + if(!className.contains("$")) + try { + Class clazz = Class.forName(className); + if (clazz.isLocalClass() || clazz.isAnonymousClass()) { + continue; + } + if (tester.acceptClass(clazz)) { + classes.add(clazz); + } + } catch (ClassNotFoundException cnfe) { + try { + ClassLoader tmp= Thread.currentThread().getContextClassLoader(); + Class clazz = Class.forName(className,false,tmp); + if (clazz.isLocalClass() || clazz.isAnonymousClass()) { + continue; + } + if (tester.acceptClass(clazz)) { + classes.add(clazz); + } + } catch (ClassNotFoundException cnfe2) { +// cnfe2.printStackTrace(); + } catch (NoClassDefFoundError ncdfe) { + // ignore not instantiable classes + } + } catch (NoClassDefFoundError ncdfe) { + // ignore not instantiable classes + } + } + + Collections.sort(classes, new Comparator>() { + public int compare(Class o1, Class o2) { + return o1.getName().compareTo(o2.getName()); + } + }); + return classes.toArray(new Class[0]); + } + + + private String classNameFromJava(String fileName) { + String s = replaceFileSeparators(cutOffExtension(fileName,JAVA_SUFFIX_LENGTH)); + while (s.startsWith(".")) + s= s.substring(1); + return s; + } + + private boolean isJavaFile(String fileName) { + return fileName.endsWith(".java"); + } + + private boolean isInnerClass(String className) { + return className.contains("$"); + } + + private boolean isClassFile(String classFileName) { + return classFileName.endsWith(".class"); + } + + private String classNameFromFile(String classFileName) { + String s = replaceFileSeparators(cutOffExtension(classFileName,CLASS_SUFFIX_LENGTH)); + while (s.startsWith(".")) + s= s.substring(1); + return s; + } + + private String replaceFileSeparators(String s) { + String result = s.replace(File.separatorChar, '.'); + if (File.separatorChar != '/') { + result = result.replace('/', '.'); + } + return result; + } + + private String cutOffExtension(String classFileName, int length) { + return classFileName.substring(0, classFileName.length() + - length); + } + +} diff --git a/srcs/utils/sacha/impl/AbstractConfigurator.java b/srcs/utils/sacha/impl/AbstractConfigurator.java new file mode 100644 index 0000000..ffa50bd --- /dev/null +++ b/srcs/utils/sacha/impl/AbstractConfigurator.java @@ -0,0 +1,113 @@ +package sacha.impl; + +import java.io.DataInputStream; +import java.io.File; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; + +import org.eclipse.core.internal.localstore.SafeChunkyInputStream; + +import sacha.classloader.enrich.EnrichableClassloader; +import sacha.classloader.factory.ClassloaderFactory; +import sacha.interfaces.IEclipseConfigurable; + +public abstract class AbstractConfigurator implements IEclipseConfigurable { + + private File projectDir = null; + private String projectName = null; + private File metadataFolder = null; + + @Override + public void setEclipseProject(String projectName) { + this.projectName = projectName; + if(projectDir!=null) + refreshProjectDir(); + } + + @Override + public void setEclipseMetadataFolder(String metadataLoc) { + File tmp = new File(metadataLoc); + if (tmp.exists() && tmp.isDirectory() && tmp.canRead()) + this.metadataFolder = tmp; + else + throw new IllegalArgumentException(metadataLoc + " is not a correct absolute path to an eclipse metadata folder"); + if(projectDir!=null) + refreshProjectDir(); + } + + private void refreshProjectDir() { + projectDir=getProjectLocation(); + } + + public File getProjectDir() { + if(projectDir==null) + refreshProjectDir(); + if(projectDir==null) + throw new IllegalArgumentException("you have to use setEclipseProject and setEclipseMetadataFolder before"); + return projectDir; + } + + public File getMetadataFolder() { + if(metadataFolder==null) + throw new IllegalArgumentException("you have to use setEclipseMetadataFolder before"); + return metadataFolder; + } + + /** + * Get the project location for a project in the eclipse metadata. + * + * @param workspaceLocation the location of the workspace + * @param project the project subdirectory in the metadata + * @return the full path to the project. + * @throws IOException failures to read location file + * @throws URISyntaxException failures to read location file + */ + @SuppressWarnings("resource") + private File getProjectLocation(){ + if(projectName==null || metadataFolder==null){ + throw new IllegalArgumentException("you have to use setEclipseProject and setEclipseMetadataFolder before"); + } + String locationPath = metadataFolder.getAbsolutePath()+"/.plugins/org.eclipse.core.resources/.projects/"+projectName+"/.location"; + File location = new File(locationPath); + if (location.exists()) { + SafeChunkyInputStream fileInputStream = null; + try { + fileInputStream = new SafeChunkyInputStream(location); + DataInputStream dataInputStream = new DataInputStream(fileInputStream); + String file = dataInputStream.readUTF().trim(); + + if (file.length() > 0) { + if (!file.startsWith("URI//")) { + throw new IOException(location.getAbsolutePath() + " contains unexpected data: " + file); + } + file = file.substring("URI//".length()); + return new File(new URI(file)); + } + }catch(Throwable t){ + throw new RuntimeException(t); + }finally { + try { + if (fileInputStream != null) + fileInputStream.close(); + } catch (IOException ioe) { + // NOOP + } + } + } + locationPath = metadataFolder.getParentFile().getAbsolutePath()+"/"+projectName; + location = new File(locationPath); + if (location.exists()) { + return location; + } + throw new IllegalArgumentException("cannot find project"); + } + + protected EnrichableClassloader getEnrichableClassloader(){ + EnrichableClassloader eClassloader = ClassloaderFactory.getEnrichableClassloader(); + eClassloader.addEclipseMetadata(getMetadataFolder()); + eClassloader.addEclipseProject(getProjectDir().getAbsolutePath()); + return eClassloader; + } + +} diff --git a/srcs/utils/sacha/impl/DefaultSpooner.java b/srcs/utils/sacha/impl/DefaultSpooner.java new file mode 100644 index 0000000..e053cd8 --- /dev/null +++ b/srcs/utils/sacha/impl/DefaultSpooner.java @@ -0,0 +1,92 @@ +package sacha.impl; + +import java.util.ArrayList; +import java.util.List; + +import sacha.classloader.enrich.EnrichableClassloader; +import sacha.interfaces.ISpooner; +import spoon.Launcher; + +public class DefaultSpooner extends AbstractConfigurator implements ISpooner { + + public static void main(String[] args) throws Exception { + Launcher.main(new String[]{"-h"}); + } + private String outputFolder = null; + private String[] processors = null; + private String[] sources = null; + private boolean graphical = false; + + + @Override + public void setOutputFolder(String folderPath) { + outputFolder=folderPath; + } + + @Override + public void setProcessors(String... processorNames) { + processors=processorNames; + } + + @Override + public void setSourceFolder(String... sources) { + this.sources = sources; + } + + @Override + public void setGraphicalOutput(boolean b) { + graphical = b; + } + + + @Override + public void spoon() { + EnrichableClassloader eClassloader = getEnrichableClassloader(); + + Thread.currentThread().setContextClassLoader(eClassloader); + + List args = new ArrayList<>(); + args.add("-v"); + if(graphical) + args.add("-g"); + args.add("--compliance"); + args.add("7"); + if(sources == null || sources.length==0) + throw new IllegalArgumentException("you have to use setSourceFolder before"); + args.add("-i"); + String tmp = ""; + for (String string : sources) { + if(string==null || string.length()==0) + throw new IllegalArgumentException("setSourceFolder can not be used with empty value"); + tmp+=getProjectDir().getAbsolutePath()+"/"+string+":"; + } + tmp = tmp.substring(0, tmp.length()-1); + args.add(tmp); + if(processors != null && processors.length>0){ + args.add("-p"); + tmp = ""; + for (String string : processors) { + if(string==null || string.length()==0) + throw new IllegalArgumentException("setProcessors can not be used with empty value"); + tmp+=string+":"; + } + tmp = tmp.substring(0, tmp.length()-1); + args.add(tmp); + } + + + if(outputFolder != null){ + args.add("-o"); + if(outputFolder==null || outputFolder.length()==0) + throw new IllegalArgumentException("setOutputFolder can not be used with empty value"); + args.add(outputFolder); + } + + try { + Launcher.main(args.toArray(new String[]{})); + } catch (Exception t) { + throw t instanceof RuntimeException?(RuntimeException)t:new RuntimeException(t); + } + } + +} diff --git a/srcs/utils/sacha/impl/GeneralToJavaCore.java b/srcs/utils/sacha/impl/GeneralToJavaCore.java new file mode 100644 index 0000000..ed8be75 --- /dev/null +++ b/srcs/utils/sacha/impl/GeneralToJavaCore.java @@ -0,0 +1,123 @@ +package sacha.impl; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileWriter; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.InputSource; + +import sacha.interfaces.IGeneralToJava; + +public class GeneralToJavaCore extends AbstractConfigurator implements IGeneralToJava{ + + @Override + public void changeToJava() { + changeNature(); + createPrefs(); + createDefaultClasspath(); + } + + private void changeNature() { + try{ + File project = new File(getProjectDir(),".project"); + if(!project.exists()) + throw new IllegalArgumentException("missing .project file "+project); + FileInputStream cpReader = new FileInputStream(project); + Element cpElement; + try { + DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + cpElement = parser.parse(new InputSource(cpReader)).getDocumentElement(); + } finally { + cpReader.close(); + } + + NodeList list = cpElement.getElementsByTagName("buildSpec"); + if(list.getLength()!=1) + throw new IllegalArgumentException("incorrect .project file "+project); + Node buildSpec = list.item(0); + + if(cpElement.getElementsByTagName("buildCommand").getLength()==0){ + Element buildCommand = buildSpec.getOwnerDocument().createElement("buildCommand"); + buildSpec.appendChild(buildCommand); + Element name = buildSpec.getOwnerDocument().createElement("name"); + name.setTextContent("org.eclipse.jdt.core.javabuilder"); + buildCommand.appendChild(name); + }else{ + throw new IllegalArgumentException("already exist a build command in .project file "+project); + } + + list = cpElement.getElementsByTagName("natures"); + if(list.getLength()!=1) + throw new IllegalArgumentException("incorrect .project file "+project); + Node natures = list.item(0); + + if(cpElement.getElementsByTagName("nature").getLength()==0){ + Element nature = natures.getOwnerDocument().createElement("nature"); + nature.setTextContent("org.eclipse.jdt.core.javanature"); + natures.appendChild(nature); + }else{ + throw new IllegalArgumentException("already exist a nature in .project file "+project); + } + + TransformerFactory tFactory = TransformerFactory.newInstance(); + Transformer transformer = tFactory.newTransformer(); + DOMSource source = new DOMSource(cpElement); + StreamResult result = new StreamResult(new FileWriter(project)); + transformer.transform(source, result); + + }catch(Throwable t){ + throw t instanceof RuntimeException?(RuntimeException)t : new RuntimeException(t); + } + } + + private void createDefaultClasspath() { + try{ + File classpath = new File(getProjectDir(),".classpath"); + BufferedWriter out=null; + try { + FileWriter fstream = new FileWriter(classpath); + out = new BufferedWriter(fstream); + out.write("\n" + + "\n" + + "\t\n" + + "\t\n" + + ""); + } finally { + out.close(); + } + }catch(Throwable t){ + throw t instanceof RuntimeException?(RuntimeException)t : new RuntimeException(t); + } + } + + private void createPrefs() { + try{ + File prefs = new File(getProjectDir().getAbsoluteFile()+"/.settings/org.eclipse.jdt.core.prefs"); + if(!prefs.getParentFile().exists()) + prefs.getParentFile().mkdir(); + BufferedWriter out=null; + try { + FileWriter fstream = new FileWriter(prefs); + out = new BufferedWriter(fstream); + out.write("org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7\neclipse.preferences.version=1" + + "\norg.eclipse.jdt.core.compiler.source=1.7\norg.eclipse.jdt.core.compiler.compliance=1.7"); + } finally { + out.close(); + } + }catch(Throwable t){ + throw t instanceof RuntimeException?(RuntimeException)t : new RuntimeException(t); + } + } + +} diff --git a/srcs/utils/sacha/impl/TestFinderCore.java b/srcs/utils/sacha/impl/TestFinderCore.java new file mode 100644 index 0000000..77febbc --- /dev/null +++ b/srcs/utils/sacha/impl/TestFinderCore.java @@ -0,0 +1,16 @@ +package sacha.impl; + +import sacha.classloader.enrich.EnrichableClassloader; +import sacha.finder.main.TestClassFinder; + +public class TestFinderCore extends AbstractConfigurator { + + public Class[] findTestClasses() { + EnrichableClassloader eClassloader = getEnrichableClassloader(); + + Thread.currentThread().setContextClassLoader(eClassloader); + + return new TestClassFinder(eClassloader).findTestClasses(); + } + +} diff --git a/srcs/utils/sacha/impl/TestRunnerCore.java b/srcs/utils/sacha/impl/TestRunnerCore.java new file mode 100644 index 0000000..8062866 --- /dev/null +++ b/srcs/utils/sacha/impl/TestRunnerCore.java @@ -0,0 +1,33 @@ +package sacha.impl; + +import sacha.classloader.enrich.EnrichableClassloader; +import sacha.finder.main.TestClassFinder; +import sacha.finder.main.TestInFolder; +import sacha.interfaces.IRunner; +import sacha.interfaces.ITestResult; + +public class TestRunnerCore extends AbstractConfigurator implements IRunner { + + @Override + public ITestResult runAllTestsInClasspath() { + EnrichableClassloader eClassloader = getEnrichableClassloader(); + + Thread.currentThread().setContextClassLoader(eClassloader); + + Class[] tests = new TestClassFinder(eClassloader).findTestClasses(); + return new sacha.runner.main.TestRunner(tests).run(); + } + + @Override + public ITestResult runAllTestsInDirectory(String dir) { + + TestInFolder tf = new TestInFolder(dir); + + EnrichableClassloader eClassloader = getEnrichableClassloader(); + + Thread.currentThread().setContextClassLoader(eClassloader); + Class[] tests = new TestClassFinder(eClassloader).findTestClasses(); + + return new sacha.runner.main.TestRunner(tf.find()).run(); + } +} diff --git a/srcs/utils/sacha/impl/TestSuiteCreatorCore.java b/srcs/utils/sacha/impl/TestSuiteCreatorCore.java new file mode 100644 index 0000000..d04ceae --- /dev/null +++ b/srcs/utils/sacha/impl/TestSuiteCreatorCore.java @@ -0,0 +1,48 @@ +package sacha.impl; + +import java.io.PrintStream; + +import sacha.classloader.enrich.EnrichableClassloader; +import sacha.finder.main.TestClassFinder; + +public class TestSuiteCreatorCore extends AbstractConfigurator{ + + public void printJavaTestSuite(PrintStream out, String className){ + EnrichableClassloader eClassloader = getEnrichableClassloader(); + + Thread.currentThread().setContextClassLoader(eClassloader); + + Class[] tests = new TestClassFinder(eClassloader).findTestClasses(); + + if(tests.length==0) + throw new IllegalArgumentException("no tests found in "+getProjectDir().getAbsolutePath()); + + String classes = ""; + for (Class clazz : tests) { + classes+=clazz.getName()+".class"; + classes+=","; + } + classes = classes.substring(0, classes.length()-1); + + out.print("\n" + + "import org.junit.internal.TextListener;\n"+ + "import org.junit.runner.JUnitCore;\n"+ + "import org.junit.runner.Result;\n" + + "\n" + + "public class "+className+"{\n" + + "\tpublic static void main(String[] args){\n" + + "\t\tnew "+className+"().run();\n"+ + "\t}\n" + + "\n" + + "\tpublic Result run(){\n" + + "\t\tJUnitCore runner = new JUnitCore();\n"+ + "\t\trunner.addListener(new TextListener(System.out));\n"+ + "\t\treturn runner.run(getClassesArray());\n"+ + "\t}\n" + + "\n"+ + "\tprivate Class[] getClassesArray(){\n" + + "\t\treturn new Class[]{"+classes+"};\n"+ + "\t}\n" + + "}"); + } +} diff --git a/srcs/utils/sacha/interfaces/IEclipseConfigurable.java b/srcs/utils/sacha/interfaces/IEclipseConfigurable.java new file mode 100644 index 0000000..3406595 --- /dev/null +++ b/srcs/utils/sacha/interfaces/IEclipseConfigurable.java @@ -0,0 +1,9 @@ +package sacha.interfaces; + +public interface IEclipseConfigurable { + + void setEclipseMetadataFolder(String folderName); + + void setEclipseProject(String projectName); + +} diff --git a/srcs/utils/sacha/interfaces/IGeneralToJava.java b/srcs/utils/sacha/interfaces/IGeneralToJava.java new file mode 100644 index 0000000..fb2195a --- /dev/null +++ b/srcs/utils/sacha/interfaces/IGeneralToJava.java @@ -0,0 +1,7 @@ +package sacha.interfaces; + +public interface IGeneralToJava { + + public void changeToJava(); + +} diff --git a/srcs/utils/sacha/interfaces/IRunner.java b/srcs/utils/sacha/interfaces/IRunner.java new file mode 100644 index 0000000..25cc05f --- /dev/null +++ b/srcs/utils/sacha/interfaces/IRunner.java @@ -0,0 +1,11 @@ +package sacha.interfaces; + +public interface IRunner { + + /** setEclipseClassPath must have been called before */ + ITestResult runAllTestsInClasspath(); + + /** dir must be valid source folder */ + ITestResult runAllTestsInDirectory(String dir); + +} diff --git a/srcs/utils/sacha/interfaces/ISpooner.java b/srcs/utils/sacha/interfaces/ISpooner.java new file mode 100644 index 0000000..de25158 --- /dev/null +++ b/srcs/utils/sacha/interfaces/ISpooner.java @@ -0,0 +1,15 @@ +package sacha.interfaces; + +public interface ISpooner extends IEclipseConfigurable { + + void spoon(); + + void setOutputFolder(String folderPath); + + void setProcessors(String... processorNames); + + /** must be set before spooning */ + void setSourceFolder(String... sources); + + void setGraphicalOutput(boolean b); +} diff --git a/srcs/utils/sacha/interfaces/ITestResult.java b/srcs/utils/sacha/interfaces/ITestResult.java new file mode 100644 index 0000000..6139870 --- /dev/null +++ b/srcs/utils/sacha/interfaces/ITestResult.java @@ -0,0 +1,9 @@ +package sacha.interfaces; + +public interface ITestResult { + + int getNbRunTests(); + + int getNbFailedTests(); + +} diff --git a/srcs/utils/sacha/mains/CheckLoopMain.java b/srcs/utils/sacha/mains/CheckLoopMain.java new file mode 100644 index 0000000..7fbe28b --- /dev/null +++ b/srcs/utils/sacha/mains/CheckLoopMain.java @@ -0,0 +1,32 @@ +package sacha.mains; + +/** checks that a Spoon transformation is semantic-preserving */ +public class CheckLoopMain { + + public static void main(String[] args) { + +// +// // sets the source or binary classpath +// // semanticPreservingLoop.setSourceClassPath("foo"); +// // semanticPreservingLoop.dependsOn("foo.jar") +// // or +// setEclipseProject("projectName"); +// +// // runs the test folder +// // ITestResult res = semanticPreservingLoop.testDirectory("/dir/test"); +// // or +// ITestResult res = runAllTestsInClasspath(); +// +// // spoons the main folder +// spoon(new SpoonConfigImpl()); +// +// // re-runs the tests +// ITestResult res2 = runAllTestsInDirectory(""); +// +// // compares both runs, should be the same +// assert res.equals(res2); +// } +// + } + +} diff --git a/srcs/utils/sacha/mains/EclipseGeneralToJavaProject.java b/srcs/utils/sacha/mains/EclipseGeneralToJavaProject.java new file mode 100644 index 0000000..3dc7d41 --- /dev/null +++ b/srcs/utils/sacha/mains/EclipseGeneralToJavaProject.java @@ -0,0 +1,15 @@ +package sacha.mains; + +import sacha.impl.GeneralToJavaCore; + + +/** Manipulates Eclipse projects (nature, classpath, etc. **/ +public class EclipseGeneralToJavaProject { + + public static void main(String[] args) { + GeneralToJavaCore core = new GeneralToJavaCore(); + core.setEclipseMetadataFolder("/home/bcornu/workspace/.metadata"); + core.setEclipseProject("jmeter-maven-plugin"); + core.changeToJava(); + } +} diff --git a/srcs/utils/sacha/mains/MergeMavenProjects.java b/srcs/utils/sacha/mains/MergeMavenProjects.java new file mode 100644 index 0000000..f5a2a93 --- /dev/null +++ b/srcs/utils/sacha/mains/MergeMavenProjects.java @@ -0,0 +1,14 @@ +package sacha.mains; + +import sacha.project.utils.MavenModulesMerger; + +/** Merges Maven projects in one single Eclipse project */ +public class MergeMavenProjects { + + public static void main(String[] args) { + MavenModulesMerger merger = new MavenModulesMerger(); + merger.setEclipseMetadataFolder("/home/bcornu/workspace/.metadata"); + merger.setEclipseProject("find-sec-bugs"); + merger.merge(); + } +} diff --git a/srcs/utils/sacha/mains/RepairLoop1.java b/srcs/utils/sacha/mains/RepairLoop1.java new file mode 100644 index 0000000..997de78 --- /dev/null +++ b/srcs/utils/sacha/mains/RepairLoop1.java @@ -0,0 +1,10 @@ +package sacha.mains; + +/** Is a basic example on how having the repair loop modification -> test suite (TODO Matias) */ +public class RepairLoop1 { + + public static void main(String[] args) { + throw new UnsupportedOperationException(); + } + +} diff --git a/srcs/utils/sacha/mains/RunSpoonWithClasspath.java b/srcs/utils/sacha/mains/RunSpoonWithClasspath.java new file mode 100644 index 0000000..bd92084 --- /dev/null +++ b/srcs/utils/sacha/mains/RunSpoonWithClasspath.java @@ -0,0 +1,25 @@ +package sacha.mains; + +import sacha.impl.DefaultSpooner; +import sacha.interfaces.ISpooner; + +/** Runs spoon in an easy manner */ +public class RunSpoonWithClasspath { + + public static void main(String[] args) { + + ISpooner spooner = new DefaultSpooner(); + //project config + spooner.setEclipseProject("test"); + spooner.setEclipseMetadataFolder("/home/bcornu/workspace/.metadata"); + //spoon config + spooner.setSourceFolder("src"); +// spooner.setProcessors("bcu.transformer.processors.ClassAnnotation","bcu.transformer.processors.TryEncapsulation"); + spooner.setOutputFolder("/home/bcornu/workspace/test-spooned/src"); + + spooner.setGraphicalOutput(true); + + spooner.spoon(); + } + +} diff --git a/srcs/utils/sacha/mains/TestFinderMain.java b/srcs/utils/sacha/mains/TestFinderMain.java new file mode 100644 index 0000000..fa9da30 --- /dev/null +++ b/srcs/utils/sacha/mains/TestFinderMain.java @@ -0,0 +1,20 @@ +package sacha.mains; + +import sacha.impl.TestFinderCore; + +/** Runs all tests of an Eclipse project */ +public class TestFinderMain { + + public static void main(String[] args) { + TestFinderCore finder = new TestFinderCore(); + finder.setEclipseMetadataFolder("/home/bcornu/workspace/.metadata/"); + finder.setEclipseProject("joda-time"); + + Class[] tests = finder.findTestClasses(); + for (Class clazz : tests) { + System.out.println(clazz);; + } + + } + +} diff --git a/srcs/utils/sacha/mains/TestRunnerMain.java b/srcs/utils/sacha/mains/TestRunnerMain.java new file mode 100644 index 0000000..345041d --- /dev/null +++ b/srcs/utils/sacha/mains/TestRunnerMain.java @@ -0,0 +1,20 @@ +package sacha.mains; + +import sacha.impl.TestRunnerCore; +import sacha.interfaces.ITestResult; + +/** Runs all tests of an Eclipse project */ +public class TestRunnerMain { + + public static void main(String[] args) { + TestRunnerCore runner = new TestRunnerCore(); + runner.setEclipseMetadataFolder("/home/bcornu/workspace/.metadata/"); + runner.setEclipseProject("joda-time"); + // runs the test folder + ITestResult res = runner.runAllTestsInClasspath(); + System.out.println(res.getNbRunTests()); + System.out.println(res.getNbFailedTests()); + + } + +} diff --git a/srcs/utils/sacha/mains/TestSuiteGeneratorMain.java b/srcs/utils/sacha/mains/TestSuiteGeneratorMain.java new file mode 100644 index 0000000..2815666 --- /dev/null +++ b/srcs/utils/sacha/mains/TestSuiteGeneratorMain.java @@ -0,0 +1,24 @@ +package sacha.mains; + +import java.io.File; +import java.io.PrintStream; + +import sacha.impl.TestSuiteCreatorCore; + +/** Generates on standard output a JUnit4 test class that runs all the test of a given Eclipse project */ +public class TestSuiteGeneratorMain { + + public static void main(String[] args) { + PrintStream f; + TestSuiteCreatorCore tcsc = new TestSuiteCreatorCore(); + tcsc.setEclipseMetadataFolder("/home/langloisj/workspace/.metadata"); + tcsc.setEclipseProject("jbehave-core"); + try + { + f = new PrintStream(new File("/home/langloisj/eclipse-workspace-projects-with-junit-tests/jbehave-core/src/test/java/AllTests.java")); + }catch(Exception e){throw new RuntimeException(e);} + tcsc.printJavaTestSuite(f,"AllTests"); + } + +} + diff --git a/srcs/utils/sacha/project/utils/IMavenMerger.java b/srcs/utils/sacha/project/utils/IMavenMerger.java new file mode 100644 index 0000000..ab409be --- /dev/null +++ b/srcs/utils/sacha/project/utils/IMavenMerger.java @@ -0,0 +1,7 @@ +package sacha.project.utils; + +public interface IMavenMerger { + + public void merge(); + +} diff --git a/srcs/utils/sacha/project/utils/MavenModulesMerger.java b/srcs/utils/sacha/project/utils/MavenModulesMerger.java new file mode 100644 index 0000000..1e3e8cf --- /dev/null +++ b/srcs/utils/sacha/project/utils/MavenModulesMerger.java @@ -0,0 +1,155 @@ +package sacha.project.utils; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.InputSource; + +import sacha.impl.AbstractConfigurator; + +public class MavenModulesMerger extends AbstractConfigurator implements IMavenMerger{ + + @Override + public void merge() { + try{ + File projectFolder = getProjectDir(); + File maven = new File(projectFolder, "pom.xml"); + if(!maven.exists() || !maven.canRead()) + throw new IllegalArgumentException("cannot access file :"+maven); + File classpath = new File(projectFolder, ".classpath"); + if(!classpath.exists() || !classpath.canRead() || ! classpath.canWrite()) + throw new IllegalArgumentException("cannot access file :"+classpath); + + FileInputStream mvnReader = new FileInputStream(maven); + Element mvnElement; + try { + DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + mvnElement = parser.parse(new InputSource(mvnReader)).getDocumentElement(); + } finally { + mvnReader.close(); + } + NodeList list = mvnElement.getElementsByTagName("module"); + int length = list.getLength(); + List modules = new ArrayList<>(); + Node node; + for (int i = 0; i < length; ++i) { + node = list.item(i); + modules.add(new File(projectFolder,node.getTextContent())); + } + + Set libraries = new HashSet<>(); + Set vars = new HashSet<>(); + Set sourceFolders = new HashSet<>(); + + for (File module : modules) { + File meClasspath = new File(module,".classpath"); + FileInputStream meReader = new FileInputStream(meClasspath); + Element meElement; + try { + DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + meElement = parser.parse(new InputSource(meReader)).getDocumentElement(); + } finally { + meReader.close(); + } + NodeList list1 = meElement.getElementsByTagName("classpathentry"); + int length1 = list1.getLength(); + Node node1; + for (int i1 = 0; i1 < length1; ++i1) { + node1 = list1.item(i1); + if("lib".equalsIgnoreCase(node1.getAttributes().getNamedItem("kind").getNodeValue())){ + String currentPathString = node1.getAttributes().getNamedItem("path").getNodeValue(); + if(!(currentPathString.startsWith("/"))) + currentPathString=module.getAbsolutePath()+File.separator+currentPathString; + libraries.add(currentPathString); + }else if("var".equalsIgnoreCase(node1.getAttributes().getNamedItem("kind").getNodeValue())){ + String currentPathString = node1.getAttributes().getNamedItem("path").getNodeValue(); + vars.add(currentPathString); + }else if("src".equalsIgnoreCase(node1.getAttributes().getNamedItem("kind").getNodeValue())){ + String currentPathString = node1.getAttributes().getNamedItem("path").getNodeValue(); + if(!currentPathString.startsWith("/")){ + sourceFolders.add(module.getName()+File.separator+currentPathString); + } + } + } + } + + FileInputStream cpReader = new FileInputStream(classpath); + Element cpElement; + try { + DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + cpElement = parser.parse(new InputSource(cpReader)).getDocumentElement(); + } finally { + cpReader.close(); + } + + NodeList list1 = cpElement.getElementsByTagName("classpathentry"); + int length1 = list1.getLength(); + Node node1; + List removable = new ArrayList<>(); + for (int i1 = 0; i1 < length1; ++i1) { + node1 = list1.item(i1); + if("lib".equalsIgnoreCase(node1.getAttributes().getNamedItem("kind").getNodeValue())){ + removable.add(node1); + }else if("var".equalsIgnoreCase(node1.getAttributes().getNamedItem("kind").getNodeValue())){ + removable.add(node1); + }else if("src".equalsIgnoreCase(node1.getAttributes().getNamedItem("kind").getNodeValue())){ + removable.add(node1); + } + } + for (Node node2 : removable) { + cpElement.removeChild(node2); + } + + for (String lib : libraries) { + cpElement.appendChild(createLineBreak(cpElement.getOwnerDocument())); + cpElement.appendChild(createNode("lib",lib,cpElement.getOwnerDocument())); + } + for (String var : vars) { + cpElement.appendChild(createLineBreak(cpElement.getOwnerDocument())); + cpElement.appendChild(createNode("var",var,cpElement.getOwnerDocument())); + } + for (String src : sourceFolders) { + cpElement.appendChild(createLineBreak(cpElement.getOwnerDocument())); + cpElement.appendChild(createNode("src",src,cpElement.getOwnerDocument())); + } + cpElement.appendChild(cpElement.getOwnerDocument().createTextNode("\n")); + TransformerFactory tFactory = TransformerFactory.newInstance(); + Transformer transformer = tFactory.newTransformer(); + + DOMSource source = new DOMSource(cpElement); + StreamResult result = new StreamResult(new FileOutputStream(classpath)); + transformer.transform(source, result); + + }catch(Throwable t){ + throw t instanceof RuntimeException?(RuntimeException)t : new RuntimeException(t); + } + } + + private Node createLineBreak(Document document) { + return document.createTextNode("\n\t"); + } + + private Node createNode(String type, String value, Document document) { + Element node = document.createElement("classpathentry"); + node.setAttribute("kind", type); + node.setAttribute("path", value); + return node; + } + +} diff --git a/srcs/utils/sacha/runner/main/TestRunner.java b/srcs/utils/sacha/runner/main/TestRunner.java new file mode 100644 index 0000000..751357a --- /dev/null +++ b/srcs/utils/sacha/runner/main/TestRunner.java @@ -0,0 +1,89 @@ +package sacha.runner.main; + +import java.io.PrintStream; +import java.text.NumberFormat; + +import org.junit.runner.Description; +import org.junit.runner.JUnitCore; +import org.junit.runner.Result; +import org.junit.runner.notification.Failure; +import org.junit.runner.notification.RunListener; + +import sacha.interfaces.ITestResult; +import sacha.runner.utils.TestInfo; + + +public class TestRunner { + + /** + * can be set instead of testFolder + */ + public Class[] classesArray = null; + + public TestRunner(Class[] classesArray) { + this.classesArray = classesArray; + } + + private TestInfo runnedTests = new TestInfo(); + + public ITestResult run() { + JUnitCore runner = new JUnitCore(); +// MyTextListener listener = new MyTextListener(System.out); +// +// runner.addListener(listener); + runner.addListener(new RunListener(){ + public void testStarted(Description description) { + runnedTests.add(description.getClassName(), description.getMethodName()); + } + public void testIgnored(Description description) + throws Exception { + runnedTests.add(description.getClassName(), description.getMethodName()); + } + @Override + public void testFailure(Failure failure) throws Exception { + super.testFailure(failure); + System.err.println(failure.getTestHeader()+" -> "+failure.getTrace()); + } + + public void testRunFinished(Result result) { + runnedTests.setResult(result); + } + }); + Result result = runner.run(classesArray); +// System.out.println("IGNORED ("+result.getIgnoreCount()+" test"+(result.getIgnoreCount()>1?"s":"")+")\n"); +// +// System.out.println("/////////////////////////// results \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"); + + return runnedTests; + } + + private class MyTextListener extends RunListener{ + private final PrintStream fWriter; + + public MyTextListener(PrintStream writer) { + this.fWriter= writer; + } + public void testRunStarted(Description description) throws Exception { + fWriter.println("start tests\n/////////////////////////// tests out \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"); + } + public void testRunFinished(Result result) { + fWriter.println("\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ tests out ///////////////////////////\nend tests"); + fWriter.println("Time: " + NumberFormat.getInstance().format((double) result.getRunTime() / 1000)); + if (result.wasSuccessful()) { + fWriter.println(); + fWriter.print("OK"); + fWriter.println(" (" + result.getRunCount() + " test" + (result.getRunCount() == 1 ? "" : "s") + ")"); + } else { + fWriter.println(); + fWriter.println("FAILURES!!!"); + fWriter.println("Tests run: " + result.getRunCount() + ", Test failed: " + result.getFailureCount()); + } + fWriter.println(); + } + @Override + public void testIgnored(Description description) throws Exception { + fWriter.println("ignored : "+description.getClassName()+"#"+description.getMethodName()); + } + + } +} diff --git a/srcs/utils/sacha/runner/main/TestRunnerMain.java b/srcs/utils/sacha/runner/main/TestRunnerMain.java new file mode 100644 index 0000000..41dbd2b --- /dev/null +++ b/srcs/utils/sacha/runner/main/TestRunnerMain.java @@ -0,0 +1,125 @@ +package sacha.runner.main; + +import java.io.File; +import java.io.PrintStream; +import java.text.NumberFormat; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; + +import org.junit.runner.Description; +import org.junit.runner.JUnitCore; +import org.junit.runner.Result; +import org.junit.runner.notification.RunListener; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import sacha.finder.main.TestMain; +import sacha.runner.utils.TestInfo; + + +public abstract class TestRunnerMain { + /** + * have to be set in static{testFolder = "%path%";} on instances + */ + public static String testFolder = null; + + /** + * can be set instead of testFolder + */ + public static Class[] classesArray = null; + + public static String eclipseTestReport = null; + private static TestInfo runnedTests = new TestInfo(); + private static TestInfo importedTests = new TestInfo(); + + public static void main(String[] args) { + if(classesArray==null){ + if(testFolder==null) + throw new IllegalArgumentException("must set the testFolder in static block"); + classesArray = TestMain.findTest(testFolder); + } + JUnitCore runner = new JUnitCore(); + + MyTextListener listener = new MyTextListener(System.out); + + runner.addListener(listener); + if(eclipseTestReport!=null) + runner.addListener(new RunListener(){ + public void testStarted(Description description) { + runnedTests.add(description.getClassName(), description.getMethodName()); + } + public void testIgnored(Description description) + throws Exception { + runnedTests.add(description.getClassName(), description.getMethodName()); + } + }); + Result result = runner.run(classesArray); + System.out.println("IGNORED ("+result.getIgnoreCount()+" test"+(result.getIgnoreCount()>1?"s":"")+")\n"); + + System.out.println("/////////////////////////// results \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"); + if(eclipseTestReport!=null) + compareTests(eclipseTestReport); + + System.exit(0); + } + + private static void compareTests(String eclipseTestReport) { + try { + File fXmlFile = new File(eclipseTestReport); + if (!fXmlFile.exists() || fXmlFile.isDirectory() || !fXmlFile.canRead()) + throw new IllegalArgumentException("cannot found " + eclipseTestReport + " or is not a file or is not readable"); + DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); + Document doc = dBuilder.parse(fXmlFile); + doc.getDocumentElement().normalize(); + + NodeList nList = doc.getElementsByTagName("testcase"); + for (int temp = 0; temp < nList.getLength(); temp++) { + Node nNode = nList.item(temp); + if (nNode.getNodeType() == Node.ELEMENT_NODE) { + Element eElement = (Element) nNode; + importedTests.add(eElement.getAttribute("classname"),eElement.getAttribute("name")); + } + } + TestInfo.compare(runnedTests,importedTests); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private static class MyTextListener extends RunListener{ + private final PrintStream fWriter; + private int errors=0; + private int failures=0; + + public MyTextListener(PrintStream writer) { + this.fWriter= writer; + } + public void testRunStarted(Description description) throws Exception { + fWriter.println("start tests\n/////////////////////////// tests out \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"); + } + public void testRunFinished(Result result) { + fWriter.println("\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ tests out ///////////////////////////\nend tests"); + fWriter.println("Time: " + NumberFormat.getInstance().format((double) result.getRunTime() / 1000)); + if (result.wasSuccessful()) { + fWriter.println(); + fWriter.print("OK"); + fWriter.println(" (" + result.getRunCount() + " test" + (result.getRunCount() == 1 ? "" : "s") + ")"); + } else { + fWriter.println(); + fWriter.println("FAILURES!!!"); + fWriter.println("Tests run: " + result.getRunCount() + ", Test failed: " + result.getFailureCount()); + fWriter.println("erros: " + errors + ", failures: " + failures); + } + fWriter.println(); + } + @Override + public void testIgnored(Description description) throws Exception { + fWriter.println("ignored : "+description.getClassName()+"#"+description.getMethodName()); + } + + } +} diff --git a/srcs/utils/sacha/runner/utils/TestInfo.java b/srcs/utils/sacha/runner/utils/TestInfo.java new file mode 100644 index 0000000..f82f482 --- /dev/null +++ b/srcs/utils/sacha/runner/utils/TestInfo.java @@ -0,0 +1,72 @@ +package sacha.runner.utils; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Set; + +import org.junit.runner.Result; + +import sacha.interfaces.ITestResult; + +public class TestInfo extends HashMap> implements ITestResult { + + private static final long serialVersionUID = 1L; + + private Result result; + + private String countRun; + + public TestInfo() { + super(); + } + + public void add(String className, String methodName) { + if (!containsKey(className)) + put(className, new ArrayList()); + get(className).add(methodName); + } + + public static void compare(TestInfo runnedTests, TestInfo importedTests) { + System.out.println("runned : "+runnedTests.countRun+" / imported : "+importedTests.countRun); +// int diff = runnedTests.count>importedTests.count?runnedTests.count-importedTests.count:importedTests.count-runnedTests.count; +// if(diff>0) +// System.err.println("number of tests diff : "+diff); + Set runnedClasses = runnedTests.keySet(); + Set importedClasses = importedTests.keySet(); + int total=0; + for (String string : importedClasses) { + if(!runnedClasses.contains(string)){ + System.err.print("imported not runned : "+string); + System.err.println(" number of tests : "+importedTests.get(string).size()); + total+=importedTests.get(string).size(); + } + } + if(total>0) + System.err.println("\ttotal number : "+total); + total = 0; + for (String string : runnedClasses) { + if(!importedClasses.contains(string)){ + System.err.print("runned not imported : "+string); + System.err.println(" number of tests : "+runnedTests.get(string).size()); + total+=runnedTests.get(string).size(); + } + } + if(total>0) + System.err.println("\ttotal number : "+total); + } + + @Override + public int getNbRunTests() { + return result.getRunCount(); + } + + @Override + public int getNbFailedTests() { + return result.getFailureCount(); + } + + public void setResult(Result result) { + this.result = result; + } +} diff --git a/srcs/utils/sacha/utils/SachaDocumentationGenerator.java b/srcs/utils/sacha/utils/SachaDocumentationGenerator.java new file mode 100644 index 0000000..a4801ab --- /dev/null +++ b/srcs/utils/sacha/utils/SachaDocumentationGenerator.java @@ -0,0 +1,38 @@ +package sacha.utils; + +import spoon.Launcher; +import spoon.processing.AbstractManualProcessor; +import spoon.reflect.declaration.CtClass; +import spoon.reflect.declaration.CtPackage; +import spoon.reflect.visitor.filter.TypeFilter; + +/** Generates the documentation of sacha-infrastructure */ +public class SachaDocumentationGenerator extends AbstractManualProcessor { + + @Override + public void process() { + System.out.println("Generated Documentation of sacha-infrastructure\n"+ + "===============================================\n"+ + "(generated with sacha.utils.SachaDocumentationGenerator)\n\n"+ + "Sacha-infrastructure supports the following use cases:\n\n"); + + for (CtPackage pack : getFactory().Package().getAllRoots()) { + + for (CtPackage pack2 : pack.getPackages()) { + if ("sacha.mains".equals(pack2.getQualifiedName())) { + for (CtClass c : pack2.getElements(new TypeFilter(CtClass.class))) { + System.out.println("\n-------------------\n"+c.getSimpleName()+": " + c.getDocComment()); + } + } + } + } + } + + public static void main(String[] _) throws Exception { + String[] args = { + "-p", "sacha.utils.SachaDocumentationGenerator", "-i", "src" + }; +// new Launcher(args).run();; + } + +} diff --git a/targets b/targets new file mode 100644 index 0000000..0431397 --- /dev/null +++ b/targets @@ -0,0 +1,15 @@ +col-331:collections-331 src /home/bcornu/workspace/collections-331-o/src +test:test src/main/java /home/bcornu/workspace/test-spooned/src2 +lang-304:lang-304 src /home/bcornu/workspace/lang-304-o/src +lang-587:lang-587 src /home/bcornu/workspace/lang-587-o/src +lang-703:lang-703 src /home/bcornu/workspace/lang-703-o/src +math-290:math-290 src /home/bcornu/workspace/math-290-o/src +math-305:math-305 src /home/bcornu/workspace/math-305-o/src +math-369:math-369 src /home/bcornu/workspace/math-369-o/src +math988a:math-988a src /home/bcornu/workspace/math-988a-o/src +math988b:math-988b src /home/bcornu/workspace/math-988b-o/src +math-1115:math-1115 src /home/bcornu/workspace/math-1115-o/src +math-1117:math-1117 src2/main/java /home/bcornu/workspace/math-1117-o/src +01-mckoi:01-Mckoi src /home/bcornu/workspace/01-Mckoi-th/src +02-freemarker107:02-freemarker src /home/bcornu/workspace/02-freemarker-o/src +03-jfreechart687:03-jfreechart src /home/bcornu/workspace/03-jfreechart-o/src