org.datanucleus.enhancer.EnhancerClassChecker Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of datanucleus-core Show documentation
Show all versions of datanucleus-core Show documentation
DataNucleus Core provides the primary components of a heterogenous Java persistence solution.
It supports persistence API's being layered on top of the core functionality.
/**********************************************************************
Copyright (c) 2007 Andy Jefferson and others. All rights reserved.
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.
Contributors:
...
**********************************************************************/
package org.datanucleus.enhancer;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import org.datanucleus.enhancer.asm.AnnotationVisitor;
import org.datanucleus.enhancer.asm.Attribute;
import org.datanucleus.enhancer.asm.ClassVisitor;
import org.datanucleus.enhancer.asm.FieldVisitor;
import org.datanucleus.enhancer.asm.MethodVisitor;
import org.datanucleus.enhancer.asm.Type;
import org.datanucleus.metadata.ClassPersistenceModifier;
import org.datanucleus.util.Localiser;
/**
* Visitor used to check the enhancement state of a class.
* Checks the methods/fields present against what is required for enhancement.
*/
public class EnhancerClassChecker extends ClassVisitor
{
/** Enhancer for the class. */
protected ClassEnhancer enhancer;
/** Set of fields required to be present. */
protected Set fieldsRequired = new HashSet();
/** Set of methods required to be present. */
protected Set methodsRequired = new HashSet();
/** Flag for whether the class is enhanced. Set in the visit process. */
protected boolean enhanced = false;
/** Whether to log any errors at error level. */
protected boolean logErrors = true;
/**
* Constructor.
* @param enhancer The class enhancer
* @param logErrors Whether to log any errors at error level
*/
public EnhancerClassChecker(ClassEnhancer enhancer, boolean logErrors)
{
super(ClassEnhancer.ASM_API_VERSION);
this.enhancer = enhancer;
this.logErrors = logErrors;
if (enhancer.getClassMetaData().getPersistenceModifier() == ClassPersistenceModifier.PERSISTENCE_CAPABLE)
{
fieldsRequired.addAll(enhancer.getFieldsList());
methodsRequired.addAll(enhancer.getMethodsList());
}
}
/**
* Accessor for whether the class is considered enhanced.
* Should only be run after passing this class to the reader as a visitor.
* @return Whether the class is enhanced.
*/
public boolean isEnhanced()
{
return enhanced;
}
/**
* Convenience method to report an error in the enhancement of this class.
* @param msg The message
*/
protected void reportError(String msg)
{
if (logErrors)
{
DataNucleusEnhancer.LOGGER.error(msg);
}
else
{
if (DataNucleusEnhancer.LOGGER.isDebugEnabled())
{
DataNucleusEnhancer.LOGGER.debug(msg);
}
}
enhanced = false;
}
/**
* Method to visit the header of the class
* @param version Version of the class file
* @param access Access type
* @param name name of the class
* @param signature signature of the class
* @param supername superclass name
* @param interfaces interface(s)
*/
public void visit(int version, int access, String name, String signature, String supername, String[] interfaces)
{
enhanced = true; // Default to true unless we find a problem
if (enhancer.getClassMetaData().getPersistenceModifier() == ClassPersistenceModifier.PERSISTENCE_CAPABLE)
{
if (interfaces == null)
{
enhanced = false;
return;
}
if (!hasInterface(interfaces, enhancer.getNamer().getPersistableAsmClassName()))
{
reportError(Localiser.msg("005027", enhancer.getClassName(), enhancer.getNamer().getPersistableClass().getName()));
}
if (enhancer.getClassMetaData().isDetachable())
{
if (!hasInterface(interfaces, enhancer.getNamer().getDetachableAsmClassName()))
{
reportError(Localiser.msg("005027", enhancer.getClassName(), enhancer.getNamer().getDetachableClass().getName()));
}
}
}
}
/**
* Convenience method to check if a particular interface is present in the list.
* @param interfaces The list of interfaces implemented
* @param intf The interface we are looking for
* @return Whether it is present
*/
protected boolean hasInterface(String[] interfaces, String intf)
{
if (interfaces == null || interfaces.length <= 0)
{
return false;
}
for (int i=0;i iter = methodsRequired.iterator();
while (iter.hasNext())
{
ClassMethod method = iter.next();
if (method.getName().equals(name) && method.getDescriptor().equals(desc))
{
if (method.getAccess() != access)
{
reportError(Localiser.msg("005032", enhancer.getClassName(), name));
}
else
{
// Remove the method since it is present
iter.remove();
break;
}
}
}
// TODO Check enhancement of all fields to use dnGetXXX, dnSetXXX
return null;
}
/**
* Visit an outer class.
* @param owner owner for the outer class
* @param name name of the outer class
* @param desc Descriptor of the outer class
*/
public void visitOuterClass(String owner, String name, String desc)
{
}
/**
* Visit the source of the class
* @param source name of source file
* @param debug debug info
*/
public void visitSource(String source, String debug)
{
}
}