blob: 6d6f9910458680959264485f4aa3501902270d8f [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2001, 2005 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
/*
*/
package org.eclipse.jem.internal.java.adapters.jdk;
import java.util.List;
import java.util.logging.Level;
import org.eclipse.emf.common.notify.Notifier;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.xmi.XMIResource;
import org.eclipse.jem.internal.java.adapters.IJavaClassAdaptor;
import org.eclipse.jem.internal.java.adapters.nls.ResourceHandler;
import org.eclipse.jem.java.*;
import org.eclipse.jem.java.internal.impl.JavaClassImpl;
import org.eclipse.jem.util.logger.proxy.Logger;
/**
* Reflect the class using standard java.reflect methods.
* Creation date: (6/6/2000 4:42:50 PM)
* @author: Administrator
*/
public class JavaClassJDKAdaptor extends JDKAdaptor implements IJavaClassAdaptor {
protected Class sourceType = null;
public JavaClassJDKAdaptor(Notifier target, JavaJDKAdapterFactory anAdapterFactory) {
super(target, anAdapterFactory);
}
/**
* addFields - reflect our fields
*/
protected void addFields() {
XMIResource resource = (XMIResource) getJavaClassTarget().eResource();
List targetFields = getJavaClassTarget().getFieldsGen();
targetFields.clear();
java.lang.reflect.Field[] fields = {};
try {
fields = getSourceType().getDeclaredFields();
} catch (NoClassDefFoundError error) {
System.out.println(ResourceHandler.getString(
"Could_Not_Reflect_Fields_ERROR_", new Object[] { getJavaClassTarget().getQualifiedName(), error.getMessage()})); //$NON-NLS-1$
}
for (int i = 0; i < fields.length; i++) {
targetFields.add(createJavaField(fields[i], resource));
}
}
/**
* addMethods - reflect our methods
*/
protected void addMethods() {
// We need to first do methods and then do constructors because the JDK treats them as two
// different objects, which the Java Model treats them as both Method's.
XMIResource resource = (XMIResource) getJavaClassTarget().eResource();
List targetMethods = getJavaClassTarget().getMethodsGen();
targetMethods.clear();
java.lang.reflect.Method[] methods = {};
try {
methods = getSourceType().getDeclaredMethods();
} catch (NoClassDefFoundError error) {
Logger logger = Logger.getLogger();
if (logger.isLoggingLevel(Level.WARNING)) {
logger
.log(
ResourceHandler
.getString(
"Could_Not_Reflect_Methods_ERROR_", new Object[] { getJavaClassTarget().getQualifiedName(), error.toString()}), Level.WARNING); //$NON-NLS-1$
}
}
for (int i = 0; i < methods.length; i++) {
targetMethods.add(createJavaMethod(methods[i], resource));
}
// Now do the constructors
java.lang.reflect.Constructor[] ctors = {};
try {
ctors = getSourceType().getDeclaredConstructors();
} catch (NoClassDefFoundError error) {
Logger logger = Logger.getLogger();
if (logger.isLoggingLevel(Level.WARNING)) {
logger
.log(
ResourceHandler
.getString(
"Could_Not_Reflect_Constructors_ERROR_", new Object[] { getJavaClassTarget().getQualifiedName(), error.getMessage()}), Level.WARNING); //$NON-NLS-1$
}
}
for (int i = 0; i < ctors.length; i++) {
targetMethods.add(createJavaMethod(ctors[i], resource));
}
}
/**
* Clear the reflected fields list.
*/
protected boolean flushFields() {
getJavaClassTarget().getFieldsGen().clear();
return true;
}
/**
* Clear the implements list.
*/
protected boolean flushImplements() {
getJavaClassTarget().getImplementsInterfacesGen().clear();
return true;
}
/**
* Clear the reflected methods list.
*/
protected boolean flushMethods() {
getJavaClassTarget().getMethodsGen().clear();
return true;
}
protected boolean flushInnerClasses() {
getJavaClassTarget().getDeclaredClassesGen().clear();
return true;
}
protected boolean flushModifiers() {
JavaClass javaClassTarget = (JavaClass) getTarget();
javaClassTarget.setAbstract(false);
javaClassTarget.setFinal(false);
javaClassTarget.setPublic(false);
javaClassTarget.setKind(TypeKind.UNDEFINED_LITERAL);
return true;
}
/**
* @see org.eclipse.jem.java.adapters.JavaReflectionAdaptor#flushReflectedValues(boolean)
*/
protected boolean flushReflectedValues(boolean clearCachedModelObject) {
boolean result = flushModifiers();
result &= flushSuper();
result &= flushImplements();
result &= flushMethods();
result &= flushFields();
result &= flushInnerClasses();
return result;
}
/**
* @see org.eclipse.jem.java.adapters.JavaReflectionAdaptor#postFlushReflectedValuesIfNecessary()
*/
protected void postFlushReflectedValuesIfNecessary(boolean isExisting) {
getJavaClassTarget().setReflected(false);
super.postFlushReflectedValuesIfNecessary(isExisting);
}
/**
* Set the supertype to be null.
*/
protected boolean flushSuper() {
List targetSupers = getJavaClassTarget().primGetESuperTypes();
targetSupers.clear();
return true;
}
/**
* Return the target typed to a JavaClass.
*/
protected JavaClassImpl getJavaClassTarget() {
return (JavaClassImpl) getTarget();
}
public Object getReflectionSource() {
return getSourceType();
}
/* (non-Javadoc)
* @see org.eclipse.jem.internal.java.adapters.JavaReflectionAdaptor#hasReflectionSource()
*/
public boolean hasCachedReflectionSource() {
return sourceType != null;
}
/**
* getSourceType - return the java.lang.Class which describes our existing Java class
*/
protected Class getSourceType() {
if (sourceType == null) {
sourceType = getType((JavaClass) getTarget());
}
return sourceType;
}
/**
* getValueIn method comment.
*/
public Object getValueIn(EObject object, EObject attribute) {
// At this point, this adapter does not dynamically compute any values,
// all values are pushed back into the target on the initial call.
return super.getValueIn(object, attribute);
}
/**
* Return true if the sourceType is null or if it is a binary type. Reflection from the JDK is always from binary.
*/
public boolean isSourceTypeFromBinary() {
return true;
}
/**
* reflectValues - template method, subclasses override to pump values into target. on entry: name, containing package (and qualified name), and
* document must be set. Return true if successful JavaClass adaptor: - set modifiers - set name - set reference to super - create methods -
* create fields - add imports
*/
public boolean reflectValues() {
super.reflectValues();
try {
if (getSourceType() != null) {
setModifiers();
setNaming();
try {
setSuper();
} catch (InheritanceCycleException e) {
Logger.getLogger().log(e);
}
setImplements();
addMethods();
addFields();
reflectInnerClasses();
setDeclaringClass();
getAdapterFactory().registerReflection(getSourceType().getName(), this);
// addImports();
return true;
}
return false;
} finally {
//Don't cache the class beyond the operation of reflect values;
//this enables dynamic swapping of the alternate class loader
//for java reflection, as well as avoids potential memory leakage
sourceType = null;
}
}
protected void setDeclaringClass() {
Class declaringType = getSourceType().getDeclaringClass();
if (declaringType != null) {
// Need to get it and reflect it so that the declared type of this target is set correctly. We can just
// set it ourselves directly because ECore would try to add it to the list of inner classes of the declaring type. This
// would cause it to be added twice, once from the reflection caused by the inverse setting, and once from our doing
// the inverse setting itself.
ResourceSet set = getTargetResource().getResourceSet();
JavaClassImpl declaringClass = (JavaClassImpl) JavaRefFactory.eINSTANCE.reflectType(declaringType.getName(), set);
declaringClass.getDeclaredClasses(); // This will cause it to put us into its list and also set our declaring class to this declaring type.
}
}
/**
*
*/
protected void reflectInnerClasses() {
Class[] innerClasses = getSourceType().getClasses();
if (innerClasses.length != 0) {
List declaredClasses = getJavaClassTarget().getDeclaredClassesGen();
JavaClass inner;
ResourceSet set = getTargetResource().getResourceSet();
for (int i = 0; i < innerClasses.length; i++) {
inner = (JavaClass) JavaRefFactory.eINSTANCE.reflectType(innerClasses[i].getName(), set);
declaredClasses.add(inner);
}
}
}
/**
* setImplements - set our implemented/super interfaces here For an interface, these are superclasses. For a class, these are implemented
* interfaces.
*/
protected void setImplements() {
Class[] interfaces = getSourceType().getInterfaces();
// needs work, the names above will be simple names if we are relfecting from a source file
JavaClassImpl javaClassTarget = (JavaClassImpl) getTarget();
JavaClass ref;
List intList = javaClassTarget.getImplementsInterfacesGen();
intList.clear();
for (int i = 0; i < interfaces.length; i++) {
ref = createJavaClassRef(interfaces[i].getName());
intList.add(ref);
}
}
/**
* setModifiers - set the attribute values related to modifiers here
*/
protected void setModifiers() {
JavaClass javaClassTarget = (JavaClass) getTarget();
javaClassTarget.setAbstract(java.lang.reflect.Modifier.isAbstract(getSourceType().getModifiers()));
javaClassTarget.setFinal(java.lang.reflect.Modifier.isFinal(getSourceType().getModifiers()));
javaClassTarget.setPublic(java.lang.reflect.Modifier.isPublic(getSourceType().getModifiers()));
// Set type to class or interface, not yet handling EXCEPTION
if (getSourceType().isInterface())
javaClassTarget.setKind(TypeKind.INTERFACE_LITERAL);
else
javaClassTarget.setKind(TypeKind.CLASS_LITERAL);
}
/**
* setNaming - set the naming values here - qualified name (package name + name) must be set first, that is the path to the real Java class - ID -
* simple name, identity within a package document - NO UUID!!!
*/
protected void setNaming() {
// JavaClass javaClassTarget = (JavaClass) getTarget();
// javaClassTarget.refSetUUID((String) null);
// ((XMIResource)javaClassTarget.eResource()).setID(javaClassTarget,getSimpleName(getSourceType().getName()));
}
/**
* setSuper - set our supertype here, implemented interface are handled separately
*/
protected void setSuper() throws InheritanceCycleException {
Class superClass = null;
superClass = getSourceType().getSuperclass();
if (superClass != null) {
JavaClass javaClassTarget = (JavaClass) getTarget();
javaClassTarget.setSupertype(createJavaClassRef(superClass.getName()));
}
}
/**
* Return true if the sourceType can be found.
*/
public boolean sourceTypeExists() {
return getSourceType() != null;
}
public boolean reflectFieldsIfNecessary() {
return reflectValuesIfNecessary();
}
public boolean reflectMethodsIfNecessary() {
return reflectValuesIfNecessary();
}
}