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

org.broadleafcommerce.common.extensibility.jpa.convert.EntityMarkerClassTransformer Maven / Gradle / Ivy

/*
 * #%L
 * BroadleafCommerce Common Libraries
 * %%
 * Copyright (C) 2009 - 2013 Broadleaf Commerce
 * %%
 * 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.
 * #L%
 */
package org.broadleafcommerce.common.extensibility.jpa.convert;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.broadleafcommerce.common.extensibility.jpa.MergePersistenceUnitManager;
import org.broadleafcommerce.common.extensibility.jpa.copy.AbstractClassTransformer;
import org.broadleafcommerce.common.extensibility.jpa.copy.DirectCopyIgnorePattern;

import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.lang.instrument.IllegalClassFormatException;
import java.security.ProtectionDomain;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;

import javassist.bytecode.AnnotationsAttribute;
import javassist.bytecode.ClassFile;
import javassist.bytecode.annotation.Annotation;

import javax.annotation.Resource;
import javax.persistence.Embeddable;
import javax.persistence.Entity;
import javax.persistence.MappedSuperclass;

/**
 * 

* This class transformer will check to see if there is class that should have been loaded by the {@link MergePersistenceUnitManager} * (meaning, it has an @Entity, @MappedSuperclass or @Embeddable annotation on it and will be inside of a persistence.xml). * If it it should have, it will add the fully qualified classname of that class to the transformedClassNames list. * *

* This is a validation check to ensure that the class transformers are actually working properly * * @author Andre Azzolini (apazzolini) */ public class EntityMarkerClassTransformer extends AbstractClassTransformer implements BroadleafClassTransformer { protected static final Log LOG = LogFactory.getLog(EntityMarkerClassTransformer.class); protected HashSet transformedEntityClassNames = new HashSet(); protected HashSet transformedNonEntityClassNames = new HashSet(); @Resource(name = "blDirectCopyIgnorePatterns") protected List ignorePatterns = new ArrayList(); @Override public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { String convertedClassName = className.replace('/', '.'); if (isIgnored(convertedClassName)) { return null; } try { ClassFile classFile = new ClassFile(new DataInputStream(new ByteArrayInputStream(classfileBuffer))); List attributes = classFile.getAttributes(); Iterator itr = attributes.iterator(); while (itr.hasNext()) { Object object = itr.next(); if (AnnotationsAttribute.class.isAssignableFrom(object.getClass())) { boolean containsTypeLevelAnnotation = containsTypeLevelPersistenceAnnotation(((AnnotationsAttribute) object).getAnnotations()); if (containsTypeLevelAnnotation) { LOG.debug("Marking " + convertedClassName + " as transformed"); transformedEntityClassNames.add(convertedClassName); } else { LOG.debug("Marking " + convertedClassName + " as picked up by the transformer but not detected as an entity"); transformedNonEntityClassNames.add(convertedClassName); } } } } catch (Exception e) { LOG.error(e); throw new IllegalClassFormatException("Unable to mark " + convertedClassName + " as transformed."); } // We don't need to transform anything, so we'll return null return null; } /** * Determines if a given annotation set contains annotations that correspond to ones that someone would expect to appear * in a persistence.xml * * @param annotations * @return */ protected boolean containsTypeLevelPersistenceAnnotation(Annotation[] annotations) { for (Annotation annotation : annotations) { if (annotation.getTypeName().equals(Entity.class.getName()) || annotation.getTypeName().equals(Embeddable.class.getName()) || annotation.getTypeName().equals(MappedSuperclass.class.getName())) { return true; } } return false; } protected boolean isIgnored(String convertedClassName) { boolean isValidPattern = true; List matchedPatterns = new ArrayList(); for (DirectCopyIgnorePattern pattern : ignorePatterns) { boolean isPatternMatch = false; for (String patternString : pattern.getPatterns()) { isPatternMatch = convertedClassName.matches(patternString); if (isPatternMatch) { break; } } if (isPatternMatch) { matchedPatterns.add(pattern); } isValidPattern = !(isPatternMatch && pattern.getTemplateTokenPatterns() == null); if (!isValidPattern) { break; } } return !isValidPattern; } @Override public void compileJPAProperties(Properties props, Object key) throws Exception { // When performing the check that this class transformer does, JPA properties do not need modificiation } /** * @return a list of fully qualified classnames of class that have an @Entity, @MappedSuperclass or @Embeddable * annotation and were picked * up by this class transformer (meaning that other class transformers also would have had a chance to * perform their necessary work on those classes) */ public HashSet getTransformedEntityClassNames() { return transformedEntityClassNames; } /** * @return a list of fully qualified classnames of classes that do not have an @Entity, @MappedSuperclass or @Embeddable * annotation but were picked up by this class transformer. This usually results in a benign misconfiguration as there are * unnecessary classes within the {@link MergePersistenceUnitManager} */ public HashSet getTransformedNonEntityClassNames() { return transformedNonEntityClassNames; } public List getIgnorePatterns() { return ignorePatterns; } public void setIgnorePatterns(List ignorePatterns) { this.ignorePatterns = ignorePatterns; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy