All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.broadleafcommerce.common.cache.engine.HydrationScanner Maven / Gradle / Ivy

/*
 * Copyright 2008-2009 the original author or authors.
 *
 * 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 org.broadleafcommerce.common.cache.engine;

import javax.persistence.Id;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

import org.broadleafcommerce.common.cache.Hydrated;
import org.hibernate.annotations.Cache;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.Attribute;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.EmptyVisitor;

/**
 * 
 * @author jfischer
 *
 */
public class HydrationScanner implements ClassVisitor, FieldVisitor, AnnotationVisitor {
	
	private static final int CLASSSTAGE = 0;
	private static final int FIELDSTAGE = 1;
	
	@SuppressWarnings("unchecked")
	public HydrationScanner(Class topEntityClass, Class entityClass) {
		this.topEntityClass = topEntityClass;
		this.entityClass = entityClass;
	}
	
	private String cacheRegion;
	private Map idMutators = new HashMap();
	private Map cacheMutators = new HashMap();
	@SuppressWarnings("unchecked")
	private final Class entityClass;
	@SuppressWarnings("unchecked")
	private final Class topEntityClass;
	
	private int stage = CLASSSTAGE;
	@SuppressWarnings("unchecked")
	private Class clazz;
	private String annotation;
	private String fieldName;
	@SuppressWarnings("unchecked")
	private Class fieldClass;
	
	public void init() {
		try {
			InputStream in = HydrationScanner.class.getClassLoader().getResourceAsStream(topEntityClass.getName().replace('.', '/') + ".class");
			new ClassReader(in).accept(this, ClassReader.SKIP_DEBUG);
			in = HydrationScanner.class.getClassLoader().getResourceAsStream(entityClass.getName().replace('.', '/') + ".class");
			new ClassReader(in).accept(this, ClassReader.SKIP_DEBUG);
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
	}
	
	public String getCacheRegion() {
		return cacheRegion;
	}

	public Map getIdMutators() {
		return idMutators;
	}

	public Map getCacheMutators() {
		return cacheMutators;
	}

	//Common
	public AnnotationVisitor visitAnnotation(String arg0, boolean arg1) {
		Type annotationType = Type.getType(arg0);
		switch(stage) {
		case CLASSSTAGE: {
			if (annotationType.getClassName().equals(Cache.class.getName())){
				annotation = Cache.class.getName();
			}
			break;
		}
		case FIELDSTAGE: {
			if (annotationType.getClassName().equals(Id.class.getName())){
				idMutators.put(fieldName, retrieveMutators());
			}
			if (annotationType.getClassName().equals(Hydrated.class.getName())){
				annotation = Hydrated.class.getName();
			}
			break;
		}
		default : {
			annotation = null;
			fieldName = null;
			break;
		}
		}
		return this;
	}
	
	private Method[] retrieveMutators() {
		String mutatorName = fieldName.substring(0,1).toUpperCase() + fieldName.substring(1, fieldName.length());
		Method getMethod = null;
		try {
			getMethod = clazz.getMethod("get"+mutatorName, new Class[]{});
		} catch (Exception e) {
			//do nothing
		}
		if (getMethod == null) {
			try {
				getMethod = clazz.getMethod("is"+mutatorName, new Class[]{});
			} catch (Exception e) {
				//do nothing
			}
		}
		if (getMethod == null) {
			try {
				getMethod = clazz.getMethod(fieldName, new Class[]{});
			} catch (Exception e) {
				//do nothing
			}
		}
		Method setMethod = null;
		try {
			setMethod = clazz.getMethod("set"+mutatorName, new Class[]{fieldClass});
		} catch (Exception e) {
			//do nothing
		}
		if (getMethod == null || setMethod == null) {
			throw new RuntimeException("Unable to find a getter and setter method for the AdminPresentation field: " + fieldName + ". Make sure you have a getter method entitled: get" + mutatorName + "(), or is" + mutatorName + "(), or " + fieldName + "(). Make sure you have a setter method entitled: set" + mutatorName + "(..).");
		}
		return new Method[]{getMethod, setMethod};
	}

	//FieldVisitor
	public void visitAttribute(Attribute arg0) {
		//do nothing
	}

	public void visitEnd() {
		//do nothing
	}

	//ClassVisitor
	public void visit(int arg0, int arg1, String arg2, String arg3, String arg4, String[] arg5) {
		try {
			clazz = Class.forName(arg2.replaceAll("/", "."));
		} catch (ClassNotFoundException e) {
			throw new RuntimeException(e);
		}
		stage = CLASSSTAGE;
	}

	public FieldVisitor visitField(int arg0, String arg1, String arg2, String arg3, Object arg4) {
		stage = FIELDSTAGE;
		fieldName = arg1;
		Type fieldType = Type.getType(arg2);
		switch(fieldType.getSort()){
		case Type.BOOLEAN:
			fieldClass = boolean.class;
			break;
		case Type.BYTE:
			fieldClass = byte.class;
			break;
		case Type.CHAR:
			fieldClass = char.class;
			break;
		case Type.DOUBLE:
			fieldClass = double.class;
			break;
		case Type.FLOAT:
			fieldClass = float.class;
			break;
		case Type.INT:
			fieldClass = int.class;
			break;
		case Type.LONG:
			fieldClass = long.class;
			break;
		case Type.SHORT:
			fieldClass = short.class;
			break;
		case Type.OBJECT:
			try {
				fieldClass = Class.forName(Type.getType(arg2).getClassName());
			} catch (ClassNotFoundException e) {
				throw new RuntimeException(e);
			}
			break;
		}
		return this;
	}

	public void visitInnerClass(String arg0, String arg1, String arg2, int arg3) {
		//do nothing
	}

	public MethodVisitor visitMethod(int arg0, String arg1, String arg2, String arg3, String[] arg4) {
		return new EmptyVisitor();
	}

	public void visitOuterClass(String arg0, String arg1, String arg2) {
		//do nothing
	}

	public void visitSource(String arg0, String arg1) {
		//do nothing
	}

	//AnnotationVisitor
	public void visit(String arg0, Object arg1) {
		if (Cache.class.getName().equals(annotation) && "region".equals(arg0)) {
			cacheRegion = (String) arg1;
		}
		if (Hydrated.class.getName().equals(annotation) && "factoryMethod".equals(arg0)) {
			HydrationItemDescriptor itemDescriptor = new HydrationItemDescriptor();
			itemDescriptor.setFactoryMethod((String) arg1);
			itemDescriptor.setMutators(retrieveMutators());
			cacheMutators.put(fieldName, itemDescriptor);
		}
	}

	public AnnotationVisitor visitAnnotation(String arg0, String arg1) {
		return this;
	}

	public AnnotationVisitor visitArray(String arg0) {
		return this;
	}

	public void visitEnum(String arg0, String arg1, String arg2) {
		//do nothing
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy