package com.psddev.cms.image; import com.psddev.cms.view.ViewModel; import com.psddev.dari.util.ClassEnhancer; import com.psddev.dari.util.ObjectUtils; import com.psddev.dari.util.StorageItem; import com.psddev.dari.util.asm.ClassReader; import com.psddev.dari.util.asm.MethodVisitor; import com.psddev.dari.util.asm.Opcodes; import com.psddev.dari.util.asm.Type; import java.lang.reflect.Method; import java.util.Locale; public class ImageSizeEnhancer extends ClassEnhancer { private static final String CLASS_INTERNAL_NAME; private static final String GET_URL_FOR_FIELD_METHOD_NAME; private static final String GET_URL_FOR_FIELD_METHOD_DESC; private static final String GET_URL_METHOD_NAME; private static final String GET_URL_METHOD_DESC; static { Class<?> imageSizeClass = ImageSize.class; Method getUrlMethod; Method getUrlAutomaticallyMethod; try { getUrlMethod = imageSizeClass.getMethod("getUrlForField", StorageItem.class, String.class); getUrlAutomaticallyMethod = imageSizeClass.getMethod("getUrl", StorageItem.class); } catch (NoSuchMethodException error) { throw new IllegalStateException(error); } CLASS_INTERNAL_NAME = Type.getInternalName(imageSizeClass); GET_URL_FOR_FIELD_METHOD_NAME = getUrlMethod.getName(); GET_URL_FOR_FIELD_METHOD_DESC = Type.getMethodDescriptor(getUrlMethod); GET_URL_METHOD_NAME = getUrlAutomaticallyMethod.getName(); GET_URL_METHOD_DESC = Type.getMethodDescriptor(getUrlAutomaticallyMethod); } public static String toField(String methodName) { if (methodName != null && methodName.startsWith("get")) { if (methodName.length() > 3) { methodName = methodName.substring(3); String field = methodName.substring(0, 1).toLowerCase(Locale.ENGLISH); if (methodName.length() > 1) { field += methodName.substring(1); } return field; } } return null; } @Override public boolean canEnhance(ClassReader reader) { Class<?> c = ObjectUtils.getClassByName(reader.getClassName().replace('/', '.')); return c != null && ViewModel.class.isAssignableFrom(c); } @Override public MethodVisitor visitMethod(int access, String viewModelMethodName, String desc, String signature, String[] exceptions) { MethodVisitor visitor = super.visitMethod(access, viewModelMethodName, desc, signature, exceptions); return new MethodVisitor(Opcodes.ASM5, visitor) { @Override public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) { if (opcode == Opcodes.INVOKESTATIC && CLASS_INTERNAL_NAME.equals(owner) && GET_URL_METHOD_NAME.equals(name) && GET_URL_METHOD_DESC.equals(desc)) { String field = toField(viewModelMethodName); if (field != null) { super.visitLdcInsn(field); super.visitMethodInsn(Opcodes.INVOKESTATIC, CLASS_INTERNAL_NAME, GET_URL_FOR_FIELD_METHOD_NAME, GET_URL_FOR_FIELD_METHOD_DESC, false); return; } } super.visitMethodInsn(opcode, owner, name, desc, itf); } }; } }