package test; import java.io.ByteArrayInputStream; import java.io.EOFException; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.nio.CharBuffer; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.Map; import se.lth.control.labcomm.LabCommDecoder; import se.lth.control.labcomm.LabCommDecoderChannel; import se.lth.control.labcomm.LabCommEncoder; import se.lth.control.labcomm.LabCommEncoderChannel; import AST.LabCommParser; import AST.LabCommScanner; import AST.Program; import beaver.Parser.Exception; public class DynamicPart { private static final String TYPE_NAME_FOO = "foo_t"; private static final String SAMPLE_NAME_FOO = "foo"; private static final String SAMPLE_NAME_BAR = "bar"; static final String handlerClassName= "HandlerContainer"; static class HandlerSrc { private String sampleName; private String param; private String body; private final String proto = "public void handle_"; public HandlerSrc(String sampleName, String param, String body) { this.sampleName = sampleName; this.param = param; this.body = body; } public String getSrc() { String res = proto+sampleName+"("+param+")"+body; return res; } } public void doTest(InRAMCompiler irc, String iFile, String oFile) { HandlerContext ctxt = new HandlerContext(); System.out.println("*** reading file "+iFile); decodeTest(irc, ctxt, iFile, SAMPLE_NAME_FOO, SAMPLE_NAME_BAR); System.out.println("*** writing "+oFile); encodeTest(irc, ctxt, oFile); } /** * @param args */ public static void main(String[] args) { /* input data: */ String labcommStr = readLabcommDecl(args[0]); String srcStr = readHandlerDecl(args[1]); /*Map<sample name, handler code>*/ HashMap <String, String> handlers = new HashMap<String, String>(); generateHandlers(srcStr, handlers); // System.out.println("*** Generated handler source:"); handlers.keySet(); // for (String n : handlers.keySet()) { // System.out.println(n+":"); // System.out.println(handlers.get(n)); // } InRAMCompiler irc = generateCode(labcommStr, handlers); if(irc != null) { String iFile = args[2]; String oFile = args[3]; new DynamicPart().doTest(irc, iFile, oFile); } } public static void generateHandlers(String srcStr, HashMap<String,String> handlers) { int pos = 0; while(pos < srcStr.length()) { int nameEnd = srcStr.indexOf(':', pos); if(nameEnd <0) break; String name = srcStr.substring(pos,nameEnd); pos=nameEnd+1; String par = ""; final String handler_decl = "handler("; if(srcStr.startsWith(handler_decl, pos)) { int endPar = srcStr.indexOf(')', pos); par = srcStr.substring(pos+handler_decl.length(), endPar); pos = endPar+1; } else { System.out.println("expeced handler decl:\n"+srcStr.substring(pos)); } int bodyEnd = srcStr.indexOf("}###", pos); // HERE BE DRAGONS! a bit brittle String body = srcStr.substring(pos, bodyEnd+1); pos = bodyEnd+5; HandlerSrc s = new HandlerSrc(name, par, body); final String genSrc = s.getSrc(); handlers.put(name,genSrc); } } public static String readHandlerDecl(String decl) { FileReader fr; int len=0;; CharBuffer buf = CharBuffer.allocate(1024); try { fr = new FileReader(decl); len = fr.read(buf); buf.rewind(); } catch (Throwable e) { e.printStackTrace(); System.exit(1); } String srcStr = buf.toString().substring(0, len); return srcStr; } private static String readLabcommDecl(String lcfile) { FileReader fr; int len=0;; CharBuffer buf = CharBuffer.allocate(1024); try { fr = new FileReader(lcfile); len = fr.read(buf); // buf.append((char) 0x04); buf.rewind(); } catch (Throwable e) { e.printStackTrace(); System.exit(1); } String labcommStr = buf.toString().substring(0, len-1); return labcommStr; } public static InRAMCompiler generateCode(String lcDecl, HashMap<String, String> handlers) { Program ast = null; InputStream in = new ByteArrayInputStream(lcDecl.getBytes()); LabCommScanner scanner = new LabCommScanner(in); LabCommParser parser = new LabCommParser(); Collection errors = new LinkedList(); InRAMCompiler irc = null; try { Program p = (Program)parser.parse(scanner); p.errorCheck(errors); if (errors.isEmpty()) { ast = p; } else { System.out.println("*** Errors:"); for (Iterator iter = errors.iterator(); iter.hasNext(); ) { String s = (String)iter.next(); System.out.println(s); } } } catch (IOException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } if (ast != null) { irc = handleAst(ast, handlers); } else { System.err.println("compilation failed"); } return irc; } /** generate labcomm code and compile handlers * * @param lcAST - the AST of the labcomm declaration * @param handlers - a map <name, source> of handlers for the types in ast * @return an InRAMCompiler object containing the generated clases */ private static InRAMCompiler handleAst(Program lcAST, HashMap<String, String> handlers) { Map<String, String> genCode = new HashMap<String, String>(); try { lcAST.J_gen(genCode, "labcomm.generated"); } catch (IOException e) { e.printStackTrace(); } // System.out.println("Generated labcomm code:"); InRAMCompiler irc = new InRAMCompilerJavax("labcomm.generated", TestLabcommGen.class.getClassLoader()); StringBuilder handlerClass = new StringBuilder(); StringBuilder handlerMethods = new StringBuilder(); handlerClass.append("package labcomm.generated;\n"); handlerClass.append("public class "+handlerClassName+" implements "); String handlerAttributes = "Object context;\n"; String handlerConstr = "public "+handlerClassName+"(){super();}\n"; String handlerConstrCtxt = "public "+handlerClassName+"(Object context){ this.context=context;}\n"; Iterator<String> i = genCode.keySet().iterator(); try { while(i.hasNext()){ final String sampleName = i.next(); final String src = genCode.get(sampleName); String handleM = handlers.get(sampleName); if(handleM != null) { handlerClass.append(sampleName+".Handler"); if(i.hasNext()) { handlerClass.append(", "); } handlerMethods.append(handleM); handlerMethods.append("\n"); } // System.out.println("***"+sampleName+"\n"+src); irc.compile(sampleName, src); // while iterating, compile the labcomm generated code } handlerClass.append("{\n"); handlerClass.append(handlerAttributes); handlerClass.append(handlerConstr); handlerClass.append(handlerConstrCtxt); handlerClass.append(handlerMethods.toString()); handlerClass.append("}\n"); System.out.println("-------------------------------------"); final String handlerSrc = handlerClass.toString(); System.out.println(handlerSrc); irc.compile(handlerClassName, handlerSrc); // compile the generated handler class } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } System.out.println("================================"); return irc; } /** test method */ private void decodeTest(InRAMCompiler irc, HandlerContext ctxt, String tmpFile, String... sampleNames) { try { FileInputStream in = new FileInputStream(tmpFile); LabCommDecoderChannel dec = new LabCommDecoderChannel(in); Class handlerClass = irc.load(handlerClassName); Constructor hcc = handlerClass.getDeclaredConstructor(Object.class); Object handler = hcc.newInstance(ctxt); for (String sampleName : sampleNames) { System.out.println("registering handler for "+sampleName); Class sampleClass = irc.load(sampleName); Class handlerInterface = irc.load(sampleName+"$Handler"); Method reg = sampleClass.getDeclaredMethod("register", LabCommDecoder.class, handlerInterface); reg.invoke(sampleClass, dec, handler); } try{ System.out.println("*** decoding:"); dec.run(); } catch(EOFException e) { System.out.println("*** reached EOF ***"); } in.close(); } catch (Throwable e) { e.printStackTrace(); } } /** test encoding */ private void encodeTest(InRAMCompiler irc, HandlerContext ctxt, String tmpFile) { try { Class ft = irc.load(TYPE_NAME_FOO); Class fc = irc.load(SAMPLE_NAME_FOO); Class bc = irc.load(SAMPLE_NAME_BAR); /* create sample class and instance objects */ Object fv = ft.newInstance(); Field x = ft.getField("x"); Field y = ft.getField("y"); Field z = ft.getField("z"); x.setInt(fv, ctxt.x); y.setInt(fv, ctxt.y); z.setInt(fv, ctxt.z); FileOutputStream out = new FileOutputStream(tmpFile); LabCommEncoderChannel enc = new LabCommEncoderChannel(out); /* register and send foo */ Method regFoo = fc.getDeclaredMethod("register", LabCommEncoder.class); regFoo.invoke(fc, enc); Method doEncodeFoo = fc.getDeclaredMethod("encode", LabCommEncoder.class, ft); doEncodeFoo.invoke(fc, enc, fv); /* register and send bar (NB! uses primitive type int) */ Method regBar = bc.getDeclaredMethod("register", LabCommEncoder.class); regBar.invoke(bc, enc); Method doEncodeBar = bc.getDeclaredMethod("encode", LabCommEncoder.class, Integer.TYPE); doEncodeBar.invoke(bc, enc, ctxt.bar); out.close(); } catch (Throwable e) { e.printStackTrace(); } } /** dummy test creating instances of sample and handler, and calling handle*/ private static void dummyTest(InRAMCompiler irc) { try { Class hc = irc.load(handlerClassName); Constructor hcc = hc.getDeclaredConstructor(Object.class); // Object h = hc.newInstance(); Object h = hcc.newInstance(new HandlerContext()); Class ft = irc.load(TYPE_NAME_FOO); Object f = ft.newInstance(); Field x = ft.getDeclaredField("x"); Field y = ft.getDeclaredField("y"); Field z = ft.getDeclaredField("z"); x.setInt(f, 10); y.setInt(f, 11); z.setInt(f, 12); Method m; try { m = hc.getDeclaredMethod("handle_"+SAMPLE_NAME_FOO, ft); m.invoke(h, f); } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (NoSuchMethodException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (NoSuchFieldException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (NoSuchMethodException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }