private static byte[] visitEnd() { ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); cw.visit(Opcodes.V1_1, Opcodes.ACC_PUBLIC, RubyIDClassName, null, "java/lang/Object", null); Method staticBlock = Method.getMethod("void <clinit> ()V"); GeneratorAdapter staticBlockMg = new GeneratorAdapter(Opcodes.ACC_STATIC, staticBlock, null, null, cw); for (Map.Entry<String, String> e : idMap.entrySet()) { cw.visitField( Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC, e.getValue(), Types.RUBY_ID_TYPE.getDescriptor(), null, null); staticBlockMg.push(e.getKey()); staticBlockMg.invokeStatic( Type.getType(RubyID.class), Method.getMethod("com.xruby.runtime.lang.RubyID intern(String)")); staticBlockMg.putStatic( Type.getType("L" + RubyIDClassName + ";"), e.getValue(), Types.RUBY_ID_TYPE); } staticBlockMg.returnValue(); staticBlockMg.endMethod(); cw.visitEnd(); return cw.toByteArray(); }
@Override public Type type(Context ctx) { List<Class<?>> argumentClasses = new ArrayList<>(); List<Type> argumentTypes = new ArrayList<>(); for (Expression argument : arguments) { argumentTypes.add(argument.type(ctx)); if (argument.type(ctx).equals(getType(Object[].class))) { argumentClasses.add(Object[].class); } else { argumentClasses.add(getJavaType(ctx.getClassLoader(), argument.type(ctx))); } } Type returnType; try { if (ctx.getThisType().equals(owner.type(ctx))) { for (org.objectweb.asm.commons.Method method : ctx.getMethods().keySet()) { if (method.getName().equals(methodName)) { if (method.getArgumentTypes().length == arguments.size()) { Type[] methodTypes = method.getArgumentTypes(); boolean isSame = true; for (int i = 0; i < arguments.size(); i++) { if (!methodTypes[i].equals(argumentTypes.get(i))) { isSame = false; break; } } if (isSame) return method.getReturnType(); } } } throw new NoSuchMethodException(); } else { Class<?> ownerJavaType = getJavaType(ctx.getClassLoader(), owner.type(ctx)); Method method = ownerJavaType.getMethod(methodName, argumentClasses.toArray(new Class<?>[] {})); Class<?> returnClass = method.getReturnType(); returnType = getType(returnClass); } } catch (NoSuchMethodException e) { throw new RuntimeException( format( "No method %s.%s(%s). %s", owner.type(ctx).getClassName(), methodName, (!argumentClasses.isEmpty() ? argsToString(argumentClasses) : ""), exceptionInGeneratedClass(ctx))); } return returnType; }
public static void main(final String args[]) throws Exception { // Generates the bytecode corresponding to the following Java class: // // public class Example { // public static void main (String[] args) { // System.out.println("Hello world!"); // } // } // creates a ClassWriter for the Example public class, // which inherits from Object ClassWriter cw = new ClassWriter(0); cw.visit(V1_1, ACC_PUBLIC, "Example", null, "java/lang/Object", null); // creates a MethodWriter for the (implicit) constructor MethodVisitor mw = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null); // pushes the 'this' variable mw.visitVarInsn(ALOAD, 0); // invokes the super class constructor mw.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V"); mw.visitInsn(RETURN); // this code uses a maximum of one stack element and one local variable mw.visitMaxs(1, 1); mw.visitEnd(); // creates a MethodWriter for the 'main' method mw = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "main", "([Ljava/lang/String;)V", null, null); // pushes the 'out' field (of type PrintStream) of the System class mw.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); // pushes the "Hello World!" String constant mw.visitLdcInsn("Hello world!"); // invokes the 'println' method (defined in the PrintStream class) mw.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V"); mw.visitInsn(RETURN); // this code uses a maximum of two stack elements and two local // variables mw.visitMaxs(2, 2); mw.visitEnd(); // gets the bytecode of the Example class, and loads it dynamically byte[] code = cw.toByteArray(); FileOutputStream fos = new FileOutputStream("Example.class"); fos.write(code); fos.close(); Helloworld loader = new Helloworld(); Class<?> exampleClass = loader.defineClass("Example", code, 0, code.length); // uses the dynamically generated class to print 'Helloworld' exampleClass.getMethods()[0].invoke(null, new Object[] {null}); // ------------------------------------------------------------------------ // Same example with a GeneratorAdapter (more convenient but slower) // ------------------------------------------------------------------------ cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); cw.visit(V1_1, ACC_PUBLIC, "Example", null, "java/lang/Object", null); // creates a GeneratorAdapter for the (implicit) constructor Method m = Method.getMethod("void <init> ()"); GeneratorAdapter mg = new GeneratorAdapter(ACC_PUBLIC, m, null, null, cw); mg.loadThis(); mg.invokeConstructor(Type.getType(Object.class), m); mg.returnValue(); mg.endMethod(); // creates a GeneratorAdapter for the 'main' method m = Method.getMethod("void main (String[])"); mg = new GeneratorAdapter(ACC_PUBLIC + ACC_STATIC, m, null, null, cw); mg.getStatic(Type.getType(System.class), "out", Type.getType(PrintStream.class)); mg.push("Hello world!"); mg.invokeVirtual(Type.getType(PrintStream.class), Method.getMethod("void println (String)")); mg.returnValue(); mg.endMethod(); cw.visitEnd(); code = cw.toByteArray(); loader = new Helloworld(); exampleClass = loader.defineClass("Example", code, 0, code.length); // uses the dynamically generated class to print 'Helloworld' exampleClass.getMethods()[0].invoke(null, new Object[] {null}); }
public final class ASMUtil { // private static final int VERSION_2=1; // private static final int VERSION_3=2; public static final short TYPE_ALL = 0; public static final short TYPE_BOOLEAN = 1; public static final short TYPE_NUMERIC = 2; public static final short TYPE_STRING = 4; // private static int version=0; private static final Method CONSTRUCTOR_OBJECT = Method.getMethod("void <init> ()"); private static final Method _SRC_NAME = new Method("_srcName", Types.STRING, new Type[] {}); // private static final String VERSION_MESSAGE = "you use an invalid version of the ASM Jar, // please update your jar files"; private static long id = 0; /** * Gibt zurueck ob das direkt uebergeordnete Tag mit dem uebergebenen Full-Name (Namespace und * Name) existiert. * * @param el Startelement, von wo aus gesucht werden soll. * @param fullName Name des gesuchten Tags. * @return Existiert ein solches Tag oder nicht. */ public static boolean hasAncestorTag(Tag tag, String fullName) { return getAncestorTag(tag, fullName) != null; } /** * Gibt das uebergeordnete CFXD Tag Element zurueck, falls dies nicht existiert wird null * zurueckgegeben. * * @param el Element von dem das parent Element zurueckgegeben werden soll. * @return uebergeordnete CFXD Tag Element */ public static Tag getParentTag(Tag tag) { Statement p = tag.getParent(); if (p == null) return null; p = p.getParent(); if (p instanceof Tag) return (Tag) p; return null; } public static boolean isParentTag(Tag tag, String fullName) { Tag p = getParentTag(tag); if (p == null) return false; return p.getFullname().equalsIgnoreCase(fullName); } public static boolean isParentTag(Tag tag, Class clazz) { Tag p = getParentTag(tag); if (p == null) return false; return p.getClass() == clazz; } public static boolean hasAncestorRetryFCStatement(Statement stat, String label) { return getAncestorRetryFCStatement(stat, null, label) != null; } public static boolean hasAncestorBreakFCStatement(Statement stat, String label) { return getAncestorBreakFCStatement(stat, null, label) != null; } public static boolean hasAncestorContinueFCStatement(Statement stat, String label) { return getAncestorContinueFCStatement(stat, null, label) != null; } public static FlowControlRetry getAncestorRetryFCStatement( Statement stat, List<FlowControlFinal> finallyLabels, String label) { return (FlowControlRetry) getAncestorFCStatement(stat, finallyLabels, FlowControl.RETRY, label); } public static FlowControlBreak getAncestorBreakFCStatement( Statement stat, List<FlowControlFinal> finallyLabels, String label) { return (FlowControlBreak) getAncestorFCStatement(stat, finallyLabels, FlowControl.BREAK, label); } public static FlowControlContinue getAncestorContinueFCStatement( Statement stat, List<FlowControlFinal> finallyLabels, String label) { return (FlowControlContinue) getAncestorFCStatement(stat, finallyLabels, FlowControl.CONTINUE, label); } private static FlowControl getAncestorFCStatement( Statement stat, List<FlowControlFinal> finallyLabels, int flowType, String label) { Statement parent = stat; FlowControlFinal fcf; while (true) { parent = parent.getParent(); if (parent == null) return null; if (((flowType == FlowControl.RETRY && parent instanceof FlowControlRetry) || (flowType == FlowControl.CONTINUE && parent instanceof FlowControlContinue) || (flowType == FlowControl.BREAK && parent instanceof FlowControlBreak)) && labelMatch((FlowControl) parent, label)) { if (parent instanceof ScriptBody) { List<FlowControlFinal> _finallyLabels = finallyLabels == null ? null : new ArrayList<FlowControlFinal>(); FlowControl scriptBodyParent = getAncestorFCStatement(parent, _finallyLabels, flowType, label); if (scriptBodyParent != null) { if (finallyLabels != null) { Iterator<FlowControlFinal> it = _finallyLabels.iterator(); while (it.hasNext()) { finallyLabels.add(it.next()); } } return scriptBodyParent; } return (FlowControl) parent; } return (FlowControl) parent; } // only if not last if (finallyLabels != null) { fcf = parent.getFlowControlFinal(); if (fcf != null) { finallyLabels.add(fcf); } } } } private static boolean labelMatch(FlowControl fc, String label) { if (StringUtil.isEmpty(label, true)) return true; String fcl = fc.getLabel(); if (StringUtil.isEmpty(fcl, true)) return false; return label.trim().equalsIgnoreCase(fcl.trim()); } public static void leadFlow(BytecodeContext bc, Statement stat, int flowType, String label) throws BytecodeException { List<FlowControlFinal> finallyLabels = new ArrayList<FlowControlFinal>(); FlowControl fc; String name; if (FlowControl.BREAK == flowType) { fc = ASMUtil.getAncestorBreakFCStatement(stat, finallyLabels, label); name = "break"; } else if (FlowControl.CONTINUE == flowType) { fc = ASMUtil.getAncestorContinueFCStatement(stat, finallyLabels, label); name = "continue"; } else { fc = ASMUtil.getAncestorRetryFCStatement(stat, finallyLabels, label); name = "retry"; } if (fc == null) throw new BytecodeException( name + " must be inside a loop (for,while,do-while,<cfloop>,<cfwhile> ...)", stat.getStart()); GeneratorAdapter adapter = bc.getAdapter(); Label end; if (FlowControl.BREAK == flowType) end = ((FlowControlBreak) fc).getBreakLabel(); else if (FlowControl.CONTINUE == flowType) end = ((FlowControlContinue) fc).getContinueLabel(); else end = ((FlowControlRetry) fc).getRetryLabel(); // first jump to all final labels FlowControlFinal[] arr = finallyLabels.toArray(new FlowControlFinal[finallyLabels.size()]); if (arr.length > 0) { FlowControlFinal fcf; for (int i = 0; i < arr.length; i++) { fcf = arr[i]; // first if (i == 0) { adapter.visitJumpInsn(Opcodes.GOTO, fcf.getFinalEntryLabel()); } // last if (arr.length == i + 1) fcf.setAfterFinalGOTOLabel(end); else fcf.setAfterFinalGOTOLabel(arr[i + 1].getFinalEntryLabel()); } } else bc.getAdapter().visitJumpInsn(Opcodes.GOTO, end); } public static boolean hasAncestorTryStatement(Statement stat) { return getAncestorTryStatement(stat) != null; } public static Statement getAncestorTryStatement(Statement stat) { Statement parent = stat; while (true) { parent = parent.getParent(); if (parent == null) return null; if (parent instanceof TagTry) { return parent; } else if (parent instanceof TryCatchFinally) { return parent; } } } /** * Gibt ein uebergeordnetes Tag mit dem uebergebenen Full-Name (Namespace und Name) zurueck, falls * ein solches existiert, andernfalls wird null zurueckgegeben. * * @param el Startelement, von wo aus gesucht werden soll. * @param fullName Name des gesuchten Tags. * @return uebergeornetes Element oder null. */ public static Tag getAncestorTag(Tag tag, String fullName) { Statement parent = tag; while (true) { parent = parent.getParent(); if (parent == null) return null; if (parent instanceof Tag) { tag = (Tag) parent; if (tag.getFullname().equalsIgnoreCase(fullName)) return tag; } } } /** * extract the content of a attribut * * @param cfxdTag * @param attrName * @return attribute value * @throws EvaluatorException */ public static Boolean getAttributeBoolean(Tag tag, String attrName) throws EvaluatorException { Boolean b = getAttributeLiteral(tag, attrName).getBoolean(null); if (b == null) throw new EvaluatorException("attribute [" + attrName + "] must be a constant boolean value"); return b; } /** * extract the content of a attribut * * @param cfxdTag * @param attrName * @return attribute value * @throws EvaluatorException */ public static Boolean getAttributeBoolean(Tag tag, String attrName, Boolean defaultValue) { Literal lit = getAttributeLiteral(tag, attrName, null); if (lit == null) return defaultValue; return lit.getBoolean(defaultValue); } /** * extract the content of a attribut * * @param cfxdTag * @param attrName * @return attribute value * @throws EvaluatorException */ public static String getAttributeString(Tag tag, String attrName) throws EvaluatorException { return getAttributeLiteral(tag, attrName).getString(); } /** * extract the content of a attribut * * @param cfxdTag * @param attrName * @return attribute value * @throws EvaluatorException */ public static String getAttributeString(Tag tag, String attrName, String defaultValue) { Literal lit = getAttributeLiteral(tag, attrName, null); if (lit == null) return defaultValue; return lit.getString(); } /** * extract the content of a attribut * * @param cfxdTag * @param attrName * @return attribute value * @throws EvaluatorException */ public static Literal getAttributeLiteral(Tag tag, String attrName) throws EvaluatorException { Attribute attr = tag.getAttribute(attrName); if (attr != null && attr.getValue() instanceof Literal) return ((Literal) attr.getValue()); throw new EvaluatorException("attribute [" + attrName + "] must be a constant value"); } /** * extract the content of a attribut * * @param cfxdTag * @param attrName * @return attribute value * @throws EvaluatorException */ public static Literal getAttributeLiteral(Tag tag, String attrName, Literal defaultValue) { Attribute attr = tag.getAttribute(attrName); if (attr != null && attr.getValue() instanceof Literal) return ((Literal) attr.getValue()); return defaultValue; } /** * Prueft ob das das angegebene Tag in der gleichen Ebene nach dem angegebenen Tag vorkommt. * * @param tag Ausgangspunkt, nach diesem tag darf das angegebene nicht vorkommen. * @param nameToFind Tag Name der nicht vorkommen darf * @return kommt das Tag vor. */ public static boolean hasSisterTagAfter(Tag tag, String nameToFind) { Body body = (Body) tag.getParent(); List<Statement> stats = body.getStatements(); Iterator<Statement> it = stats.iterator(); Statement other; boolean isAfter = false; while (it.hasNext()) { other = it.next(); if (other instanceof Tag) { if (isAfter) { if (((Tag) other).getTagLibTag().getName().equals(nameToFind)) return true; } else if (other == tag) isAfter = true; } } return false; } /** * Prueft ob das angegebene Tag innerhalb seiner Ebene einmalig ist oder nicht. * * @param tag Ausgangspunkt, nach diesem tag darf das angegebene nicht vorkommen. * @return kommt das Tag vor. */ public static boolean hasSisterTagWithSameName(Tag tag) { Body body = (Body) tag.getParent(); List<Statement> stats = body.getStatements(); Iterator<Statement> it = stats.iterator(); Statement other; String name = tag.getTagLibTag().getName(); while (it.hasNext()) { other = it.next(); if (other != tag && other instanceof Tag && ((Tag) other).getTagLibTag().getName().equals(name)) return true; } return false; } /** * remove this tag from his parent body * * @param tag */ public static void remove(Tag tag) { Body body = (Body) tag.getParent(); body.getStatements().remove(tag); } /** * replace src with trg * * @param src * @param trg */ public static void replace(Tag src, Tag trg, boolean moveBody) { trg.setParent(src.getParent()); Body p = (Body) src.getParent(); List<Statement> stats = p.getStatements(); Iterator<Statement> it = stats.iterator(); Statement stat; int count = 0; while (it.hasNext()) { stat = it.next(); if (stat == src) { if (moveBody && src.getBody() != null) src.getBody().setParent(trg); stats.set(count, trg); break; } count++; } } public static Page getAncestorPage(Statement stat) throws BytecodeException { Statement parent = stat; while (true) { parent = parent.getParent(); if (parent == null) { throw new BytecodeException("missing parent Statement of Statement", stat.getStart()); // return null; } if (parent instanceof Page) return (Page) parent; } } public static Page getAncestorPage(Statement stat, Page defaultValue) { Statement parent = stat; while (true) { parent = parent.getParent(); if (parent == null) { return defaultValue; } if (parent instanceof Page) return (Page) parent; } } public static void listAncestor(Statement stat) { Statement parent = stat; aprint.o(stat); while (true) { parent = parent.getParent(); if (parent instanceof Page) aprint.o("page-> " + ((Page) parent).getPageSource().getDisplayPath()); else aprint.o("parent-> " + parent); if (parent == null) break; } } public static Tag getAncestorComponent(Statement stat) throws BytecodeException { // print.ln("getAncestorPage:"+stat); Statement parent = stat; while (true) { parent = parent.getParent(); // print.ln(" - "+parent); if (parent == null) { throw new BytecodeException("missing parent Statement of Statement", stat.getStart()); // return null; } if (parent instanceof TagComponent) // if(parent instanceof Tag && "component".equals(((Tag)parent).getTagLibTag().getName())) return (Tag) parent; } } public static Statement getRoot(Statement stat) { while (true) { if (isRoot(stat)) { return stat; } stat = stat.getParent(); } } public static boolean isRoot(Statement statement) { // return statement instanceof Page || (statement instanceof Tag && // "component".equals(((Tag)statement).getTagLibTag().getName())); return statement instanceof Page || statement instanceof TagComponent; } public static void invokeMethod(GeneratorAdapter adapter, Type type, Method method) { if (type.getClass().isInterface()) adapter.invokeInterface(type, method); else adapter.invokeVirtual(type, method); } public static byte[] createPojo( String className, ASMProperty[] properties, Class parent, Class[] interfaces, String srcName) throws PageException { className = className.replace('.', '/'); className = className.replace('\\', '/'); className = ListUtil.trim(className, "/"); String[] inter = null; if (interfaces != null) { inter = new String[interfaces.length]; for (int i = 0; i < inter.length; i++) { inter[i] = interfaces[i].getName().replace('.', '/'); } } // CREATE CLASS ClassWriter cw = ASMUtil.getClassWriter(); cw.visit( Opcodes.V1_6, Opcodes.ACC_PUBLIC, className, null, parent.getName().replace('.', '/'), inter); String md5; try { md5 = createMD5(properties); } catch (Throwable t) { md5 = ""; t.printStackTrace(); } FieldVisitor fv = cw.visitField( Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL + Opcodes.ACC_STATIC, "_md5_", "Ljava/lang/String;", null, md5); fv.visitEnd(); // Constructor GeneratorAdapter adapter = new GeneratorAdapter(Opcodes.ACC_PUBLIC, CONSTRUCTOR_OBJECT, null, null, cw); adapter.loadThis(); adapter.invokeConstructor(toType(parent, true), CONSTRUCTOR_OBJECT); adapter.returnValue(); adapter.endMethod(); // properties for (int i = 0; i < properties.length; i++) { createProperty(cw, className, properties[i]); } // complexType src if (!StringUtil.isEmpty(srcName)) { GeneratorAdapter _adapter = new GeneratorAdapter( Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL + Opcodes.ACC_STATIC, _SRC_NAME, null, null, cw); _adapter.push(srcName); _adapter.returnValue(); _adapter.endMethod(); } cw.visitEnd(); return cw.toByteArray(); } private static void createProperty(ClassWriter cw, String classType, ASMProperty property) throws PageException { String name = property.getName(); Type type = property.getASMType(); Class clazz = property.getClazz(); cw.visitField(Opcodes.ACC_PRIVATE, name, type.toString(), null, null).visitEnd(); int load = loadFor(type); // int sizeOf=sizeOf(type); // get<PropertyName>():<type> Type[] types = new Type[0]; Method method = new Method( (clazz == boolean.class ? "get" : "get") + StringUtil.ucFirst(name), type, types); GeneratorAdapter adapter = new GeneratorAdapter(Opcodes.ACC_PUBLIC, method, null, null, cw); Label start = new Label(); adapter.visitLabel(start); adapter.visitVarInsn(Opcodes.ALOAD, 0); adapter.visitFieldInsn(Opcodes.GETFIELD, classType, name, type.toString()); adapter.returnValue(); Label end = new Label(); adapter.visitLabel(end); adapter.visitLocalVariable("this", "L" + classType + ";", null, start, end, 0); adapter.visitEnd(); adapter.endMethod(); // set<PropertyName>(object):void types = new Type[] {type}; method = new Method("set" + StringUtil.ucFirst(name), Types.VOID, types); adapter = new GeneratorAdapter(Opcodes.ACC_PUBLIC, method, null, null, cw); start = new Label(); adapter.visitLabel(start); adapter.visitVarInsn(Opcodes.ALOAD, 0); adapter.visitVarInsn(load, 1); adapter.visitFieldInsn(Opcodes.PUTFIELD, classType, name, type.toString()); adapter.visitInsn(Opcodes.RETURN); end = new Label(); adapter.visitLabel(end); adapter.visitLocalVariable("this", "L" + classType + ";", null, start, end, 0); adapter.visitLocalVariable(name, type.toString(), null, start, end, 1); // adapter.visitMaxs(0, 0);//.visitMaxs(sizeOf+1, sizeOf+1);// hansx adapter.visitEnd(); adapter.endMethod(); } public static int loadFor(Type type) { if (type.equals(Types.BOOLEAN_VALUE) || type.equals(Types.INT_VALUE) || type.equals(Types.CHAR) || type.equals(Types.SHORT_VALUE)) return Opcodes.ILOAD; if (type.equals(Types.FLOAT_VALUE)) return Opcodes.FLOAD; if (type.equals(Types.LONG_VALUE)) return Opcodes.LLOAD; if (type.equals(Types.DOUBLE_VALUE)) return Opcodes.DLOAD; return Opcodes.ALOAD; } public static int sizeOf(Type type) { if (type.equals(Types.LONG_VALUE) || type.equals(Types.DOUBLE_VALUE)) return 2; return 1; } /** * translate a string cfml type definition to a Type Object * * @param cfType * @param axistype * @return * @throws PageException */ public static Type toType(String cfType, boolean axistype) throws PageException { return toType(Caster.cfTypeToClass(cfType), axistype); } /** * translate a string cfml type definition to a Type Object * * @param cfType * @param axistype * @return * @throws PageException */ public static Type toType(Class type, boolean axistype) { if (axistype) type = AxisCaster.toAxisTypeClass(type); return Type.getType(type); } public static String createMD5(ASMProperty[] props) { StringBuffer sb = new StringBuffer(); for (int i = 0; i < props.length; i++) { sb.append("name:" + props[i].getName() + ";"); if (props[i] instanceof Property) { sb.append("type:" + ((Property) props[i]).getType() + ";"); } else { try { sb.append("type:" + props[i].getASMType() + ";"); } catch (PageException e) { } } } try { return MD5.getDigestAsString(sb.toString()); } catch (IOException e) { return ""; } } public static void removeLiterlChildren(Tag tag, boolean recursive) { Body body = tag.getBody(); if (body != null) { List<Statement> list = body.getStatements(); Statement[] stats = list.toArray(new Statement[list.size()]); PrintOut po; Tag t; for (int i = 0; i < stats.length; i++) { if (stats[i] instanceof PrintOut) { po = (PrintOut) stats[i]; if (po.getExpr() instanceof Literal) { body.getStatements().remove(po); } } else if (recursive && stats[i] instanceof Tag) { t = (Tag) stats[i]; if (t.getTagLibTag().isAllowRemovingLiteral()) { removeLiterlChildren(t, recursive); } } } } } public static synchronized String getId() { if (id < 0) id = 0; return StringUtil.addZeros(++id, 6); } public static boolean isEmpty(Body body) { return body == null || body.isEmpty(); } /** * @param adapter * @param expr * @param mode */ public static void pop(GeneratorAdapter adapter, Expression expr, int mode) { if (mode == Expression.MODE_VALUE && (expr instanceof ExprDouble)) adapter.pop2(); else adapter.pop(); } public static void pop(GeneratorAdapter adapter, Type type) { if (type.equals(Types.DOUBLE_VALUE)) adapter.pop2(); else if (type.equals(Types.VOID)) ; else adapter.pop(); } public static ClassWriter getClassWriter() { return new ClassWriter(ClassWriter.COMPUTE_MAXS); // |ClassWriter.COMPUTE_FRAMES); } public static String createOverfowMethod( String prefix, int id) { // pattern is used in function callstackget if (StringUtil.isEmpty(prefix)) prefix = "call"; return prefix + "_" + StringUtil.addZeros(id, 6); } public static boolean isOverfowMethod(String name) { return name.length() > 6 && Decision.isNumeric(name.substring(name.length() - 6, name.length())); // return name.startsWith("_call") && name.length()>=11; } public static boolean isDotKey(ExprString expr) { return expr instanceof LitString && !((LitString) expr).fromBracket(); } public static String toString(Expression exp, String defaultValue) { try { return toString(exp); } catch (BytecodeException e) { return defaultValue; } } public static String toString(Expression exp) throws BytecodeException { if (exp instanceof Variable) { return toString(VariableString.toExprString(exp)); } else if (exp instanceof VariableString) { return ((VariableString) exp).castToString(); } else if (exp instanceof Literal) { return ((Literal) exp).toString(); } return null; } public static Boolean toBoolean(Attribute attr, Position start) throws BytecodeException { if (attr == null) throw new BytecodeException("attribute does not exist", start); if (attr.getValue() instanceof Literal) { Boolean b = ((Literal) attr.getValue()).getBoolean(null); if (b != null) return b; } throw new BytecodeException( "attribute [" + attr.getName() + "] must be a constant boolean value", start); } public static Boolean toBoolean(Attribute attr, int line, Boolean defaultValue) { if (attr == null) return defaultValue; if (attr.getValue() instanceof Literal) { Boolean b = ((Literal) attr.getValue()).getBoolean(null); if (b != null) return b; } return defaultValue; } public static boolean isCFC(Statement s) { Statement p; while ((p = s.getParent()) != null) { s = p; } return true; } public static boolean isLiteralAttribute( Tag tag, String attrName, short type, boolean required, boolean throwWhenNot) throws EvaluatorException { return isLiteralAttribute(tag, tag.getAttribute(attrName), type, required, throwWhenNot); } public static boolean isLiteralAttribute( Tag tag, Attribute attr, short type, boolean required, boolean throwWhenNot) throws EvaluatorException { String strType = "/constant"; if (attr != null && !isNull(attr.getValue())) { switch (type) { case TYPE_ALL: if (attr.getValue() instanceof Literal) return true; break; case TYPE_BOOLEAN: if (CastBoolean.toExprBoolean(attr.getValue()) instanceof LitBoolean) return true; strType = " boolean"; break; case TYPE_NUMERIC: if (CastDouble.toExprDouble(attr.getValue()) instanceof LitDouble) return true; strType = " numeric"; break; case TYPE_STRING: if (CastString.toExprString(attr.getValue()) instanceof LitString) return true; strType = " string"; break; } if (!throwWhenNot) return false; throw new EvaluatorException( "Attribute [" + attr.getName() + "] of the Tag [" + tag.getFullname() + "] must be a literal" + strType + " value. " + "attributes java class type " + attr.getValue().getClass().getName()); } if (required) { if (!throwWhenNot) return false; throw new EvaluatorException( "Attribute [" + attr.getName() + "] of the Tag [" + tag.getFullname() + "] is required"); } return false; } public static boolean isNull(Expression expr) { if (expr instanceof NullExpression) return true; if (expr instanceof Cast) { return isNull(((Cast) expr).getExpr()); } return false; } public static boolean isRefType(Type type) { return !(type == Types.BYTE_VALUE || type == Types.BOOLEAN_VALUE || type == Types.CHAR || type == Types.DOUBLE_VALUE || type == Types.FLOAT_VALUE || type == Types.INT_VALUE || type == Types.LONG_VALUE || type == Types.SHORT_VALUE); } public static Type toRefType(Type type) { if (type == Types.BYTE_VALUE) return Types.BYTE; if (type == Types.BOOLEAN_VALUE) return Types.BOOLEAN; if (type == Types.CHAR) return Types.CHARACTER; if (type == Types.DOUBLE_VALUE) return Types.DOUBLE; if (type == Types.FLOAT_VALUE) return Types.FLOAT; if (type == Types.INT_VALUE) return Types.INTEGER; if (type == Types.LONG_VALUE) return Types.LONG; if (type == Types.SHORT_VALUE) return Types.SHORT; return type; } /** * return value type only when there is one * * @param type * @return */ public static Type toValueType(Type type) { if (type == Types.BYTE) return Types.BYTE_VALUE; if (type == Types.BOOLEAN) return Types.BOOLEAN_VALUE; if (type == Types.CHARACTER) return Types.CHAR; if (type == Types.DOUBLE) return Types.DOUBLE_VALUE; if (type == Types.FLOAT) return Types.FLOAT_VALUE; if (type == Types.INTEGER) return Types.INT_VALUE; if (type == Types.LONG) return Types.LONG_VALUE; if (type == Types.SHORT) return Types.SHORT_VALUE; return type; } public static Class getValueTypeClass(Type type, Class defaultValue) { if (type == Types.BYTE_VALUE) return byte.class; if (type == Types.BOOLEAN_VALUE) return boolean.class; if (type == Types.CHAR) return char.class; if (type == Types.DOUBLE_VALUE) return double.class; if (type == Types.FLOAT_VALUE) return float.class; if (type == Types.INT_VALUE) return int.class; if (type == Types.LONG_VALUE) return long.class; if (type == Types.SHORT_VALUE) return short.class; return defaultValue; } public static ASMProperty[] toASMProperties(Property[] properties) { ASMProperty[] asmp = new ASMProperty[properties.length]; for (int i = 0; i < asmp.length; i++) { asmp[i] = (ASMProperty) properties[i]; } return asmp; } public static boolean containsComponent(Body body) { if (body == null) return false; Iterator<Statement> it = body.getStatements().iterator(); while (it.hasNext()) { if (it.next() instanceof TagComponent) return true; } return false; } public static void dummy1(BytecodeContext bc) { bc.getAdapter() .visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/System", "currentTimeMillis", "()J"); bc.getAdapter().visitInsn(Opcodes.POP2); } public static void dummy2(BytecodeContext bc) { bc.getAdapter().visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/System", "nanoTime", "()J"); bc.getAdapter().visitInsn(Opcodes.POP2); } /** * convert a clas array to a type array * * @param classes * @return */ public static Type[] toTypes(Class<?>[] classes) { if (classes == null || classes.length == 0) return new Type[0]; Type[] types = new Type[classes.length]; for (int i = 0; i < classes.length; i++) { types[i] = Type.getType(classes[i]); } return types; } public static String display(ExprString name) { if (name instanceof Literal) { if (name instanceof Identifier) return ((Identifier) name).getRaw(); return ((Literal) name).getString(); } return name.toString(); } public static Literal cachedWithinValue(Expression val) throws EvaluatorException { if (val instanceof Literal) { Literal l = (Literal) val; // double == days Double d = l.getDouble(null); if (d != null) { return new LitLong(TimeSpanImpl.fromDays(d.doubleValue()).getMillis(), null, null); } // request String str = l.getString(); if (str != null && "request".equalsIgnoreCase(str.trim())) return new LitString("request", null, null); throw cacheWithinException(); } // createTimespan else if (val instanceof Variable) { Variable var = (Variable) val; if (var.getMembers().size() == 1) { Member first = var.getFirstMember(); if (first instanceof BIF) { BIF bif = (BIF) first; if ("createTimeSpan".equalsIgnoreCase(bif.getFlf().getName())) { Argument[] args = bif.getArguments(); int len = ArrayUtil.size(args); if (len >= 4 && len <= 5) { double days = toDouble(args[0].getValue()); double hours = toDouble(args[1].getValue()); double minutes = toDouble(args[2].getValue()); double seconds = toDouble(args[3].getValue()); double millis = len == 5 ? toDouble(args[4].getValue()) : 0; return new LitLong( new TimeSpanImpl( (int) days, (int) hours, (int) minutes, (int) seconds, (int) millis) .getMillis(), null, null); } } } } } throw cacheWithinException(); } private static EvaluatorException cacheWithinException() { return new EvaluatorException( "value of cachedWithin must be a literal timespan, like 0.1 or createTimespan(1,2,3,4) or the string \"request\" or the string \"smart\""); } private static double toDouble(Expression e) throws EvaluatorException { if (!(e instanceof Literal)) throw new EvaluatorException( "Paremeters of the function createTimeSpan have to be literal numeric values in this context"); Double d = ((Literal) e).getDouble(null); if (d == null) throw new EvaluatorException( "Paremeters of the function createTimeSpan have to be literal numeric values in this context"); return d.doubleValue(); } public static void visitLabel(GeneratorAdapter ga, Label label) { if (label != null) ga.visitLabel(label); } public static String getClassName(Resource res) throws IOException { byte[] src = IOUtil.toBytes(res); ClassReader cr = new ClassReader(src); return cr.getClassName(); } public static String getClassName(byte[] barr) { return new ClassReader(barr).getClassName(); } public static SourceInfo getSourceInfo(Config config, Class clazz, boolean onlyCFC) throws IOException { return SourceNameClassVisitor.getSourceInfo(config, clazz, onlyCFC); } public static boolean hasOnlyDataMembers(Variable var) { Iterator<Member> it = var.getMembers().iterator(); Member m; while (it.hasNext()) { m = it.next(); if (!(m instanceof DataMember)) return false; } return true; } public static int count(List<Statement> statements, boolean recursive) { if (statements == null) return 0; int count = 0; Iterator<Statement> it = statements.iterator(); while (it.hasNext()) { count += count(it.next(), recursive); } return count; } public static int count(Statement s, boolean recursive) { int count = 1; if (recursive && s instanceof HasBody) { Body b = ((HasBody) s).getBody(); if (b != null) count += count(b.getStatements(), recursive); } return count; } public static void dump(Statement s, int level) { for (int i = 0; i < level; i++) System.err.print("-"); aprint.e(s.getClass().getName()); if (s instanceof HasBody) { Body b = ((HasBody) s).getBody(); if (b != null) { Iterator<Statement> it = b.getStatements().iterator(); while (it.hasNext()) { dump(it.next(), level + 1); } } } } public static void size(ClassWriter cw) { try { MethodVisitor mw = null; Field[] fields = cw.getClass().getDeclaredFields(); Field f; for (int i = 0; i < fields.length; i++) { f = fields[i]; if (f.getType().getName().equals("org.objectweb.asm.MethodWriter")) { f.setAccessible(true); mw = (MethodVisitor) f.get(cw); break; } } } catch (Throwable t) { // TODO Auto-generated catch block t.printStackTrace(); } } public static void createEmptyStruct(GeneratorAdapter adapter) { adapter.newInstance(Types.STRUCT_IMPL); adapter.dup(); adapter.invokeConstructor(Types.STRUCT_IMPL, Page.INIT_STRUCT_IMPL); } public static void createEmptyArray(GeneratorAdapter adapter) { adapter.newInstance(Types.ARRAY_IMPL); adapter.dup(); adapter.invokeConstructor(Types.ARRAY_IMPL, Switch.INIT); } }
@Override public Type load(Context ctx) { GeneratorAdapter g = ctx.getGeneratorAdapter(); owner.load(ctx); List<Class<?>> argumentClasses = new ArrayList<>(); List<Type> argumentTypes = new ArrayList<>(); for (Expression argument : arguments) { argument.load(ctx); argumentTypes.add(argument.type(ctx)); argumentClasses.add(getJavaType(ctx.getClassLoader(), argument.type(ctx))); } Type returnType; try { if (ctx.getThisType().equals(owner.type(ctx))) { org.objectweb.asm.commons.Method method = null; for (org.objectweb.asm.commons.Method m : ctx.getMethods().keySet()) { if (m.getName().equals(methodName)) { if (m.getArgumentTypes().length == arguments.size()) { Type[] methodTypes = m.getArgumentTypes(); boolean isSame = true; for (int i = 0; i < arguments.size(); i++) { if (!methodTypes[i].equals(argumentTypes.get(i))) { isSame = false; break; } } if (isSame) { method = m; break; } } } } if (method == null) throw new NoSuchMethodException(); g.invokeVirtual(owner.type(ctx), method); return method.getReturnType(); } Class<?> ownerJavaType = getJavaType(ctx.getClassLoader(), owner.type(ctx)); Method method = ownerJavaType.getMethod(methodName, argumentClasses.toArray(new Class<?>[] {})); Class<?> returnClass = method.getReturnType(); returnType = getType(returnClass); invokeVirtualOrInterface( g, ownerJavaType, new org.objectweb.asm.commons.Method( methodName, returnType, argumentTypes.toArray(new Type[] {}))); } catch (NoSuchMethodException e) { throw new RuntimeException( format( "No method %s.%s(%s). %s", owner.type(ctx).getClassName(), methodName, (!argumentClasses.isEmpty() ? argsToString(argumentClasses) : ""), exceptionInGeneratedClass(ctx))); } return returnType; }
public static Type invokeScope(GeneratorAdapter adapter, Method m, Type type) { if (type == null) type = Types.PAGE_CONTEXT; adapter.invokeVirtual(type, m); return m.getReturnType(); }