Java tutorial
// Copyright 2008 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package com.google.gwtorm.server; import com.google.gwtorm.schema.ColumnModel; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; import org.objectweb.asm.Type; import java.lang.reflect.Method; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.util.ArrayList; import java.util.List; public class CodeGenSupport implements Opcodes { public final MethodVisitor mv; private ColumnModel col; private int dupOnSet; private int columnIdx; private Type entityType; private int lastLocal = 2; private List<Integer> freeLocals = new ArrayList<Integer>(4); public CodeGenSupport(final MethodVisitor method) { mv = method; } public void push(final int val) { switch (val) { case -1: mv.visitInsn(ICONST_M1); break; case 0: mv.visitInsn(ICONST_0); break; case 1: mv.visitInsn(ICONST_1); break; case 2: mv.visitInsn(ICONST_2); break; case 3: mv.visitInsn(ICONST_3); break; case 4: mv.visitInsn(ICONST_4); break; case 5: mv.visitInsn(ICONST_5); break; default: if (Byte.MIN_VALUE >= val && val < Byte.MAX_VALUE) { mv.visitIntInsn(BIPUSH, val); } else if (Short.MIN_VALUE >= val && val < Short.MAX_VALUE) { mv.visitIntInsn(SIPUSH, val); } else { mv.visitLdcInsn(Integer.valueOf(val)); } break; } } public void loadVar(final Type type, final int index) { mv.visitVarInsn(type.getOpcode(ILOAD), index); } public int newLocal() { if (freeLocals.isEmpty()) { return ++lastLocal; } return freeLocals.remove(freeLocals.size() - 1); } public void freeLocal(final int index) { freeLocals.add(index); } public void setEntityType(final Type et) { entityType = et; } public void setFieldReference(final ColumnModel cm) { col = cm; dupOnSet = -1; columnIdx++; } public void resetColumnIndex(final int s) { columnIdx = s; } public int getColumnIndex() { return columnIdx; } public ColumnModel getFieldReference() { return col; } public void pushSqlHandle() { mv.visitVarInsn(ALOAD, 1); } public void pushEntity() { mv.visitVarInsn(ALOAD, 2); } public void pushColumnIndex() { push(columnIdx); } public void invokePreparedStatementSet(final String sqlTypeName) { final Method m; try { m = PreparedStatement.class.getMethod("set" + sqlTypeName, Integer.TYPE, ResultSet.class.getMethod("get" + sqlTypeName, Integer.TYPE).getReturnType()); } catch (SecurityException e) { throw new RuntimeException("java.sql has no " + sqlTypeName); } catch (NoSuchMethodException e) { throw new RuntimeException("java.sql has no " + sqlTypeName, e); } mv.visitMethodInsn(INVOKEINTERFACE, Type.getInternalName(PreparedStatement.class), m.getName(), Type.getMethodDescriptor(m)); } public void invokeResultSetGet(final String sqlTypeName) { final Method m; try { m = ResultSet.class.getMethod("get" + sqlTypeName, Integer.TYPE); } catch (SecurityException e) { throw new RuntimeException("java.sql has no " + sqlTypeName); } catch (NoSuchMethodException e) { throw new RuntimeException("java.sql has no " + sqlTypeName, e); } mv.visitMethodInsn(INVOKEINTERFACE, Type.getInternalName(ResultSet.class), m.getName(), Type.getMethodDescriptor(m)); } public void fieldSetBegin() { pushEntity(); if (col.getParent() != null) { appendGetField(col.getParent()); } } public void fieldSetEnd() { final Type c = containerClass(col); if (dupOnSet >= 0) { mv.visitInsn(DUP); mv.visitVarInsn(ASTORE, dupOnSet); } mv.visitFieldInsn(PUTFIELD, c.getInternalName(), col.getFieldName(), toType(col).getDescriptor()); } public void setDupOnFieldSetEnd(final int varIdx) { dupOnSet = varIdx; } public void pushFieldValue() { pushEntity(); appendGetField(col); } protected void appendGetField(final ColumnModel c) { if (c.getParent() != null) { appendGetField(c.getParent()); } final Type t = containerClass(c); mv.visitFieldInsn(GETFIELD, t.getInternalName(), c.getFieldName(), toType(c).getDescriptor()); } private Type containerClass(final ColumnModel c) { if (c.getParent() == null) { return entityType; } final String n = c.getParent().getNestedClassName(); return Type.getObjectType(n.replace('.', '/')); } public static Type toType(final ColumnModel c) { if (c.isSqlPrimitive()) { return Type.getType(c.getPrimitiveType()); } return Type.getObjectType(c.getNestedClassName().replace('.', '/')); } }