| /******************************************************************************* |
| * Copyright (c) 2001, 2008 Oracle 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: |
| * Oracle Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.jst.jsf.designtime.internal.view; |
| |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.NullProgressMonitor; |
| import org.eclipse.jdt.core.IJavaProject; |
| import org.eclipse.jdt.core.IType; |
| import org.eclipse.jdt.core.JavaCore; |
| import org.eclipse.jdt.core.JavaModelException; |
| import org.eclipse.jem.internal.proxy.core.IBeanTypeProxy; |
| import org.eclipse.jem.internal.proxy.core.IConfigurationContributor; |
| import org.eclipse.jem.internal.proxy.core.IStandardBeanTypeProxyFactory; |
| import org.eclipse.jem.internal.proxy.core.ProxyFactoryRegistry; |
| import org.eclipse.jem.internal.proxy.ide.IDERegistration; |
| import org.eclipse.jst.jsf.common.internal.types.TypeInfoCache; |
| import org.eclipse.jst.jsf.common.runtime.internal.model.component.ComponentTypeInfo; |
| import org.eclipse.jst.jsf.common.runtime.internal.model.decorator.ConverterTypeInfo; |
| import org.eclipse.jst.jsf.common.runtime.internal.model.decorator.ValidatorTypeInfo; |
| import org.eclipse.jst.jsf.common.util.JDTBeanIntrospector; |
| import org.eclipse.jst.jsf.common.util.JDTBeanProperty; |
| import org.eclipse.jst.jsf.core.internal.JSFCorePlugin; |
| import org.eclipse.jst.jsf.core.internal.JSFCoreTraceOptions; |
| import org.eclipse.jst.jsf.core.internal.jem.BeanProxyUtil.BeanProxyWrapper; |
| import org.eclipse.jst.jsf.core.internal.jem.BeanProxyUtil.ProxyException; |
| import org.eclipse.jst.jsf.core.jsfappconfig.internal.IJSFAppConfigManager; |
| import org.eclipse.jst.jsf.core.jsfappconfig.internal.JSFAppConfigManagerFactory; |
| import org.eclipse.jst.jsf.facesconfig.emf.ComponentType; |
| import org.eclipse.jst.jsf.facesconfig.emf.ConverterType; |
| import org.eclipse.jst.jsf.facesconfig.emf.ValidatorType; |
| |
| /** |
| * Utility class for finding and bean introspecting component and related |
| * classes. |
| * |
| * @author cbateman |
| * |
| */ |
| public final class DTComponentIntrospector |
| { |
| /** |
| * A shared type cache for doing tag class introspection. The cache stores |
| * type hierarchies and updates them on detected changes to reduce the |
| * overhead of doing such lookups |
| */ |
| private static TypeInfoCache TYPE_CACHE; // lazily created, don't access |
| |
| // directly |
| |
| /** |
| * @return the type cache used by all DTComponentIntrospector internally. |
| */ |
| public static TypeInfoCache getSharedTypeCache() |
| { |
| if (TYPE_CACHE == null) |
| { |
| TYPE_CACHE = TypeInfoCache.createNewInstance(); |
| } |
| return TYPE_CACHE; |
| } |
| |
| /** |
| * @param classType |
| * @param className |
| * @param project |
| * @param contributors may be null |
| * @return the component type info for the class type or null if none. Adds |
| * contributors to the class path |
| */ |
| public static ComponentTypeInfo getComponent(final String classType, |
| final String className, final IProject project, |
| final IConfigurationContributor[] contributors) |
| { |
| ProxyFactoryRegistry registry = null; |
| try |
| { |
| registry = getProxyFactoryRegistry(project, |
| contributors); |
| |
| if (registry != null) |
| { |
| final IStandardBeanTypeProxyFactory factory = registry |
| .getBeanTypeProxyFactory(); |
| final IBeanTypeProxy classTypeProxy = factory |
| .getBeanTypeProxy(className); |
| final BeanProxyWrapper classTypeWrapper = new BeanProxyWrapper(project, |
| classTypeProxy); |
| |
| String family = null; |
| String renderer = null; |
| try |
| { |
| classTypeWrapper.init(); |
| family = classTypeWrapper.callStringMethod("getFamily"); //$NON-NLS-1$ |
| renderer = classTypeWrapper.callStringMethod("getRendererType"); //$NON-NLS-1$ |
| } |
| catch (ProxyException e1) |
| { |
| // fall through |
| if (JSFCoreTraceOptions.TRACE_JSPTAGINTROSPECTOR) |
| { |
| JSFCoreTraceOptions.log("DTComponentIntrospector.getComponent:", e1); //$NON-NLS-1$ |
| } |
| } |
| |
| IType type = null; |
| |
| try |
| { |
| type = JavaCore.create(project).findType(className); |
| } |
| catch (JavaModelException e) |
| { |
| // fall through; |
| } |
| |
| List<String> interfaces = new ArrayList<String>(); |
| List<String> superClasses = new ArrayList<String>(); |
| |
| if (type != null) |
| { |
| TypeInfoCache typeCache = getSharedTypeCache(); |
| |
| IType[] interfaceTypes = typeCache.cacheInterfaceTypesFor(type); |
| for (IType interfaze : interfaceTypes) |
| { |
| interfaces.add(interfaze.getFullyQualifiedName()); |
| } |
| |
| IType[] superClassTypes = typeCache.cacheSupertypesFor(type); |
| |
| for (IType superClass : superClassTypes) |
| { |
| superClasses.add(superClass.getFullyQualifiedName()); |
| } |
| } |
| |
| return new ComponentTypeInfo(classType, className, superClasses |
| .toArray(new String[0]), interfaces.toArray(new String[0]), |
| family, renderer); |
| } |
| } |
| finally |
| { |
| if (registry != null) |
| { |
| registry.terminateRegistry(true); |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * @param classType |
| * @param className |
| * @param project |
| * @return the component type info with no additional classpath |
| * contributions. May return null; |
| */ |
| public static ComponentTypeInfo getComponent(final String classType, |
| final String className, final IProject project) |
| { |
| return getComponent(classType, className, project, null); |
| } |
| |
| /** |
| * @param converterId |
| * @param converterClass |
| * @return a new converter type info for the converter id. |
| */ |
| public static ConverterTypeInfo getConverter(final String converterId, |
| final String converterClass) |
| { |
| return new ConverterTypeInfo(converterClass, converterId); |
| } |
| |
| /** |
| * @param validatorId |
| * @param validatorClass |
| * @return a new validator type info for the validator id |
| */ |
| public static ValidatorTypeInfo getValidator(final String validatorId, |
| final String validatorClass) |
| { |
| return new ValidatorTypeInfo(validatorClass, validatorId); |
| } |
| |
| /** |
| * @param componentType |
| * @param project |
| * @return the configured class name for the JSF component type id or null |
| * if not found. |
| */ |
| public static String findComponentClass(final String componentType, |
| final IProject project) |
| { |
| final IJSFAppConfigManager manager = JSFAppConfigManagerFactory |
| .getJSFAppConfigManagerInstance(project); |
| final List<ComponentType> components = manager.getComponents(); |
| |
| for (final ComponentType component : components) |
| { |
| final String type = component.getComponentType().getTextContent() |
| .trim(); |
| |
| if (componentType.equals(type) && component.getComponentClass() != null && component.getComponentClass().getTextContent() != null) |
| { |
| return component.getComponentClass().getTextContent().trim(); |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * @param converterId |
| * @param project |
| * @return a fully qualified class name corresponding to converterId or null |
| * if none. |
| */ |
| public static String findConverterClass(final String converterId, |
| final IProject project) |
| { |
| final IJSFAppConfigManager manager = JSFAppConfigManagerFactory |
| .getJSFAppConfigManagerInstance(project); |
| final List<ConverterType> converters = manager.getConverters(); |
| |
| for (final ConverterType converter : converters) |
| { |
| if (converter != null && converter.getConverterId() != null |
| && converter.getConverterId().getTextContent() != null) |
| { |
| final String type = converter.getConverterId().getTextContent() |
| .trim(); |
| |
| if (converterId.equals(type)) |
| { |
| if (converter.getConverterClass() != null && converter.getConverterClass().getTextContent()!=null) |
| { |
| return converter.getConverterClass().getTextContent() |
| .trim(); |
| } |
| return null; |
| } |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * @param validatorId |
| * @param project |
| * @return a fully qualified class name corresponding to the validatorId or |
| * null if none. |
| */ |
| public static String findValidatorClass(final String validatorId, |
| final IProject project) |
| { |
| final IJSFAppConfigManager manager = JSFAppConfigManagerFactory |
| .getJSFAppConfigManagerInstance(project); |
| final List<ValidatorType> validators = manager.getValidators(); |
| |
| for (final ValidatorType validatorType : validators) |
| { |
| if (validatorType != null && validatorType.getValidatorId() != null && |
| validatorType.getValidatorId().getTextContent() != null) |
| { |
| final String type = validatorType.getValidatorId().getTextContent() |
| .trim(); |
| |
| if (validatorId.equals(type)) |
| { |
| return validatorType.getValidatorClass().getTextContent() |
| .trim(); |
| } |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * @param type |
| * @param checkInstanceOf |
| * @return true if type resolves to a type that is an instance of one of the |
| * types in checkInstanceOf. |
| */ |
| public static boolean isTypeNameInstanceOfClass(final IType type, |
| final Set<String> checkInstanceOf) |
| { |
| if (checkInstanceOf == null) |
| { |
| throw new AssertionError(); |
| } |
| if (type != null) |
| { |
| // first and foremost, are these exactly droids you're |
| // looking for and not just their predecessors? |
| if (checkInstanceOf.contains(type.getFullyQualifiedName())) |
| { |
| return true; |
| } |
| |
| for (final IType supertype : getSharedTypeCache() |
| .cacheSupertypesFor(type)) |
| { |
| if (checkInstanceOf.contains(supertype.getFullyQualifiedName())) |
| { |
| return true; |
| } |
| } |
| |
| for (final IType interfaces : getSharedTypeCache() |
| .cacheInterfaceTypesFor(type)) |
| { |
| if (checkInstanceOf |
| .contains(interfaces.getFullyQualifiedName())) |
| { |
| return true; |
| } |
| } |
| } |
| |
| return false; |
| } |
| |
| /** |
| * @param typeInfo |
| * @param project |
| * @return a list of all bean properties (using the POJO method) on |
| * typeInfo. List may be empty, never null. |
| */ |
| public static Map<String, JDTBeanProperty> getBeanProperties( |
| final ComponentTypeInfo typeInfo, final IProject project) |
| { |
| Map<String, JDTBeanProperty> properties = new HashMap<String, JDTBeanProperty>(); |
| |
| IJavaProject javaProject = JavaCore.create(project); |
| try |
| { |
| IType type = javaProject.findType(typeInfo.getClassName()); |
| |
| if (type != null) |
| { |
| // TODO: should be able to use type cache for this |
| final JDTBeanIntrospector introspector = new JDTBeanIntrospector( |
| type); |
| properties = introspector.getProperties(); |
| } |
| } |
| catch (JavaModelException e) |
| { |
| JSFCorePlugin.log("Error finding component type", e); //$NON-NLS-1$ |
| } |
| |
| return properties; |
| } |
| |
| /** |
| * @param project |
| * @return a new proxy factory registry or null; |
| * |
| * TODO: caching? |
| */ |
| private static ProxyFactoryRegistry getProxyFactoryRegistry( |
| final IProject project, final IConfigurationContributor[] contributors) |
| { |
| try |
| { |
| return IDERegistration.startAnImplementation(contributors, false, project, |
| project.getName(), JSFCorePlugin.PLUGIN_ID, |
| new NullProgressMonitor()); |
| } |
| catch (final CoreException e) |
| { |
| JSFCorePlugin.log("Error starting vm for project: " //$NON-NLS-1$ |
| + project.getName(), e); |
| } |
| |
| return null; |
| } |
| |
| private DTComponentIntrospector() |
| { |
| // no external instantiation |
| } |
| |
| // private static class |
| } |