| /******************************************************************************* |
| * 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.model.jsp.analyzer; |
| |
| import java.util.Collections; |
| import java.util.HashSet; |
| import java.util.Set; |
| |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.NullProgressMonitor; |
| import org.eclipse.jdt.core.IJavaProject; |
| import org.eclipse.jdt.core.IType; |
| import org.eclipse.jdt.core.JavaConventions; |
| import org.eclipse.jdt.core.JavaCore; |
| import org.eclipse.jdt.core.JavaModelException; |
| import org.eclipse.jem.internal.proxy.core.IBeanProxy; |
| 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.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.runtime.internal.view.model.common.IJSFTagElement; |
| import org.eclipse.jst.jsf.common.runtime.internal.view.model.common.IHandlerTagElement.TagHandlerType; |
| import org.eclipse.jst.jsf.common.runtime.internal.view.model.common.IJSFTagElement.TagType; |
| import org.eclipse.jst.jsf.core.JSFVersion; |
| 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.designtime.internal.view.DTComponentIntrospector; |
| import org.eclipse.jst.jsf.designtime.internal.view.model.jsp.TLDComponentTagElement; |
| import org.eclipse.jst.jsf.designtime.internal.view.model.jsp.TLDConverterTagElement; |
| import org.eclipse.jst.jsf.designtime.internal.view.model.jsp.TLDTagElement; |
| import org.eclipse.jst.jsf.designtime.internal.view.model.jsp.TLDTagHandlerElement; |
| import org.eclipse.jst.jsf.designtime.internal.view.model.jsp.TLDValidatorTagElement; |
| import org.eclipse.jst.jsf.designtime.internal.view.model.jsp.IAttributeAdvisor.NullAttributeAdvisor; |
| import org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional.TLDElementDeclaration; |
| |
| /** |
| * Utility class supporting methods to derive information from JSP tag |
| * definitions (TLD) |
| * |
| * @author cbateman |
| * |
| */ |
| public final class TagAnalyzer |
| { |
| private static final String JAVAX_FACES_WEBAPP_CONVERTER_TAG = "javax.faces.webapp.ConverterTag"; //$NON-NLS-1$ |
| private static final String JAVAX_FACES_WEBAPP_CONVERTER_ELTAG = "javax.faces.webapp.ConverterELTag"; //$NON-NLS-1$ |
| private static final String JAVAX_FACES_WEBAPP_VALIDATOR_TAG = "javax.faces.webapp.ValidatorTag"; //$NON-NLS-1$ |
| private static final String JAVAX_FACES_WEBAPP_VALIDATOR_ELTAG = "javax.faces.webapp.ValidatorELTag"; //$NON-NLS-1$ |
| private static final String JAVAX_FACES_WEBAPP_FACET_TAG = "javax.faces.webapp.FacetTag"; //$NON-NLS-1$ |
| |
| // private static final String JAVAX_FACES_WEBAPP_ACTIONLISTENER_TAG = |
| // "javax.faces.webapp.ActionListenerTag"; |
| // private static final String JAVAX_FACES_WEBAPP_VALUECHANGELISTENER_TAG = |
| // "javax.faces.webapp.ValueChangeListenerTag"; |
| private static final String JAVAX_FACES_WEBAPP_ATTRIBUTE_TAG = "javax.faces.webapp.AttributeTag"; //$NON-NLS-1$ |
| |
| private final static Set<String> COMPONENT_TAG_HANDLER_TYPES_JSF11; |
| private final static Set<String> COMPONENT_TAG_HANDLER_TYPES_JSF12; |
| |
| private final static Set<String> CONVERTER_TAG_HANDLER_TYPES_JSF11 = Collections |
| .singleton(JAVAX_FACES_WEBAPP_CONVERTER_TAG); |
| private final static Set<String> CONVERTER_TAG_HANDLER_TYPES_JSF12; |
| |
| private final static Set<String> VALIDATOR_TAG_HANDLER_TYPES_JSF11 = Collections |
| .singleton(JAVAX_FACES_WEBAPP_VALIDATOR_TAG); |
| private final static Set<String> VALIDATOR_TAG_HANDLER_TYPES_JSF12; |
| |
| private final static Set<String> FACET_TAG_HANDLER = Collections |
| .singleton(JAVAX_FACES_WEBAPP_FACET_TAG); |
| private final static Set<String> ATTRIBUTE_TAG_HANDLER = Collections |
| .singleton(JAVAX_FACES_WEBAPP_ATTRIBUTE_TAG); |
| // private final static Set<String> ACTIONLISTENER_TAG_HANDLER = Collections |
| // .singleton(JAVAX_FACES_WEBAPP_ACTIONLISTENER_TAG); |
| // private final static Set<String> VALUECHANGELISTENER_TAG_HANDLER = |
| // Collections |
| // .singleton(JAVAX_FACES_WEBAPP_VALUECHANGELISTENER_TAG); |
| |
| private final static Set<String> ALL_HANDLER_TAGS; |
| |
| static |
| { |
| // components |
| // JSF 1.1 |
| Set<String> set = new HashSet<String>(8); |
| set.add("javax.faces.webapp.UIComponentTag"); //$NON-NLS-1$ |
| set.add("javax.faces.webapp.UIComponentBodyTag"); //$NON-NLS-1$ |
| COMPONENT_TAG_HANDLER_TYPES_JSF11 = Collections.unmodifiableSet(set); |
| |
| // JSF 1.2 |
| set = new HashSet<String>(8); |
| set.add("javax.faces.webapp.UIComponentTag"); //$NON-NLS-1$ |
| set.add("javax.faces.webapp.UIComponentBodyTag"); //$NON-NLS-1$ |
| set.add("javax.faces.webapp.UIComponentELTag"); //$NON-NLS-1$ |
| COMPONENT_TAG_HANDLER_TYPES_JSF12 = Collections.unmodifiableSet(set); |
| |
| // converters |
| set = new HashSet<String>(8); |
| set.add(JAVAX_FACES_WEBAPP_CONVERTER_TAG); |
| set.add(JAVAX_FACES_WEBAPP_CONVERTER_ELTAG); |
| CONVERTER_TAG_HANDLER_TYPES_JSF12 = Collections.unmodifiableSet(set); |
| |
| // validators |
| set = new HashSet<String>(8); |
| set.add(JAVAX_FACES_WEBAPP_VALIDATOR_TAG); |
| set.add(JAVAX_FACES_WEBAPP_VALIDATOR_ELTAG); |
| VALIDATOR_TAG_HANDLER_TYPES_JSF12 = Collections.unmodifiableSet(set); |
| |
| // tag handlers |
| ALL_HANDLER_TAGS = new HashSet<String>(); |
| ALL_HANDLER_TAGS.addAll(FACET_TAG_HANDLER); |
| ALL_HANDLER_TAGS.addAll(ATTRIBUTE_TAG_HANDLER); |
| // ALL_HANDLER_TAGS.addAll(VALUECHANGELISTENER_TAG_HANDLER); |
| // ALL_HANDLER_TAGS.addAll(ACTIONLISTENER_TAG_HANDLER); |
| } |
| |
| /** |
| * Tries to determine the component type of the component that corresponds |
| * to the JSP tag defined by tldDecl. |
| * |
| * @param tldDecl |
| * @param project |
| * @return get the component type from the tag definition or null if none. |
| */ |
| public static String findComponentType(final TLDElementDeclaration tldDecl, |
| final IProject project) |
| { |
| final String className = tldDecl.getTagclass(); |
| |
| final IConfigurationContributor[] contributor = new IConfigurationContributor[] |
| { new ServletBeanProxyContributor(project) }; |
| |
| ProxyFactoryRegistry registry = null; |
| try |
| { |
| registry = getProxyFactoryRegistry(contributor, project); |
| |
| if (registry != null) |
| { |
| |
| final IStandardBeanTypeProxyFactory factory = registry |
| .getBeanTypeProxyFactory(); |
| final IBeanTypeProxy classTypeProxy = factory |
| .getBeanTypeProxy(className); |
| final BeanProxyWrapper classTypeWrapper = new BeanProxyWrapper(project, |
| classTypeProxy); |
| |
| try |
| { |
| classTypeWrapper.init(); |
| return classTypeWrapper.callStringMethod("getComponentType"); //$NON-NLS-1$ |
| } |
| catch (final ProxyException tp) |
| { |
| if (JSFCoreTraceOptions.TRACE_JSPTAGINTROSPECTOR) |
| { |
| JSFCoreTraceOptions.log("TagAnalyzer.findComponentType", tp); //$NON-NLS-1$ |
| } |
| } |
| } |
| } |
| finally |
| { |
| if (registry != null) |
| { |
| registry.terminateRegistry(true); |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * Tries to introspect tldDecl's tag class to determine what the identifier |
| * of the underlying Converter that is used to register it in the app config |
| * |
| * @param tldDecl |
| * @param project |
| * @return the converter type identifier for the tldDecl or null if not |
| * found |
| */ |
| public static String findConverterType(final TLDElementDeclaration tldDecl, |
| final IProject project) |
| { |
| // TODO: allow for pluggable resolver? |
| |
| // This one is more hacky and less prone to success than the component |
| // type finder because the ConverterTag doesn't initialize its type |
| // field on construction. Instead, both MyFaces and RI seem to do it |
| // based on the doStartTag method. They also don't provide a standard |
| // interface for acquiring the id so instead we make some guess on |
| // the internal field name. |
| ProxyFactoryRegistry registry = null; |
| try |
| { |
| final String className = tldDecl.getTagclass(); |
| |
| final IConfigurationContributor[] contributor = new IConfigurationContributor[] |
| { new ServletBeanProxyContributor(project) }; |
| registry = getProxyFactoryRegistry( |
| contributor, project); |
| |
| if (registry != null) |
| { |
| final IStandardBeanTypeProxyFactory factory = registry |
| .getBeanTypeProxyFactory(); |
| final IBeanTypeProxy classTypeProxy = factory |
| .getBeanTypeProxy(className); |
| |
| try |
| { |
| final IType type = JavaCore.create(project).findType(className); |
| |
| if (type != null |
| && DTComponentIntrospector |
| .isTypeNameInstanceOfClass( |
| type, |
| Collections |
| .singleton(JAVAX_FACES_WEBAPP_CONVERTER_ELTAG))) |
| { |
| return findConverterType_InELTag(factory, classTypeProxy,project); |
| } |
| // the assumption is that this is a component tag, so we assume |
| // it is one. |
| else if (type != null |
| && DTComponentIntrospector |
| .isTypeNameInstanceOfClass( |
| type, |
| Collections |
| .singleton(JAVAX_FACES_WEBAPP_CONVERTER_TAG))) |
| { |
| return findConverterType_InTag(factory, classTypeProxy, project); |
| } |
| } |
| catch (final JavaModelException jme) |
| { |
| // suppress for now |
| } |
| } |
| } |
| finally |
| { |
| if (registry != null) |
| { |
| registry.terminateRegistry(true); |
| } |
| } |
| return null; |
| } |
| |
| private static String findConverterType_InTag( |
| final IStandardBeanTypeProxyFactory factory, |
| final IBeanTypeProxy classTypeProxy, final IProject project) |
| { |
| final IBeanTypeProxy nullPageContextType = factory |
| .getBeanTypeProxy("javax.servlet.jsp.PageContext"); //$NON-NLS-1$ |
| final BeanProxyWrapper classTypeWrapper = new BeanProxyWrapper(project, |
| classTypeProxy); |
| |
| try |
| { |
| classTypeWrapper.init(); |
| |
| callSuppressExceptions(classTypeWrapper, "setPageContext", //$NON-NLS-1$ |
| new IBeanProxy[] |
| { null }, new IBeanTypeProxy[] |
| { nullPageContextType }); |
| callSuppressExceptions(classTypeWrapper, "doStartTag"); //$NON-NLS-1$ |
| |
| final IBeanTypeProxy converterProxy = factory |
| .getBeanTypeProxy(JAVAX_FACES_WEBAPP_CONVERTER_TAG); |
| |
| // hopefully doStartTag set the converter field before it |
| // failed. |
| // now try to guess what it's called |
| String converterId = getStringField(classTypeWrapper, |
| converterProxy, "converterId"); //$NON-NLS-1$ |
| |
| if (converterId != null) |
| { |
| return converterId; |
| } |
| |
| converterId = getStringField(classTypeWrapper, converterProxy, |
| "_converterId"); //$NON-NLS-1$ |
| |
| if (converterId != null) |
| { |
| return converterId; |
| } |
| |
| // no? look for a CONVERTER_ID |
| converterId = getStringField(classTypeWrapper, classTypeProxy, |
| "CONVERTER_ID"); //$NON-NLS-1$ |
| } |
| catch (final ProxyException tp) |
| { |
| // fall through |
| } |
| return null; |
| } |
| |
| private static String findConverterType_InELTag( |
| final IStandardBeanTypeProxyFactory factory, |
| final IBeanTypeProxy classTypeProxy, final IProject project) |
| { |
| final BeanProxyWrapper classTypeWrapper = new BeanProxyWrapper(project, |
| classTypeProxy); |
| final IBeanTypeProxy elExpressionType = factory |
| .getBeanTypeProxy("javax.el.ValueExpression"); //$NON-NLS-1$ |
| |
| if (elExpressionType == null) |
| { |
| return null; |
| } |
| |
| try |
| { |
| classTypeWrapper.init(); |
| |
| callSuppressExceptions(classTypeWrapper, "doStartTag"); //$NON-NLS-1$ |
| |
| // no? look for a CONVERTER_ID |
| final IBeanProxy converterId = getFieldInParents(classTypeWrapper, |
| classTypeProxy, "CONVERTER_ID_EXPR"); //$NON-NLS-1$ |
| |
| if (converterId != null) |
| { |
| converterId.getTypeProxy().isKindOf(elExpressionType); |
| final BeanProxyWrapper elExprValue = new BeanProxyWrapper(project, |
| converterId.getTypeProxy()); |
| final String value = elExprValue |
| .callStringMethod("getExpressionString"); //$NON-NLS-1$ |
| System.out.println("Expression string:" + value); //$NON-NLS-1$ |
| } |
| |
| // |
| // |
| // final IBeanTypeProxy converterProxy = factory |
| // .getBeanTypeProxy(JAVAX_FACES_WEBAPP_CONVERTER_TAG); |
| |
| } |
| catch (final ProxyException tp) |
| { |
| // fall through |
| } |
| return null; |
| } |
| |
| /** |
| * @param tldDecl |
| * @param project |
| * @return the validator type identifier for the tldDecl or null if not |
| * found |
| */ |
| public static String findValidatorType(final TLDElementDeclaration tldDecl, |
| final IProject project) |
| { |
| // TODO: allow for pluggable resolver? |
| |
| // This one is more hacky and less prone to success than the component |
| // type finder because the Validator doesn't initialize its type |
| // field on construction. Instead, both MyFaces and RI seem to do it |
| // based on the doStartTag method. They also don't provide a standard |
| // interface for acquiring the id so instead we make some guess on |
| // the internal field name. |
| final String className = tldDecl.getTagclass(); |
| |
| final IConfigurationContributor[] contributor = new IConfigurationContributor[] |
| { new ServletBeanProxyContributor(project) }; |
| |
| ProxyFactoryRegistry registry = null; |
| |
| try |
| { |
| registry = getProxyFactoryRegistry(contributor, project); |
| |
| if (registry != null) |
| { |
| final IStandardBeanTypeProxyFactory factory = registry |
| .getBeanTypeProxyFactory(); |
| final IBeanTypeProxy classTypeProxy = factory |
| .getBeanTypeProxy(className); |
| final BeanProxyWrapper classTypeWrapper = new BeanProxyWrapper(project, |
| classTypeProxy); |
| final IBeanTypeProxy converterProxy = factory |
| .getBeanTypeProxy(JAVAX_FACES_WEBAPP_VALIDATOR_TAG); |
| try |
| { |
| classTypeWrapper.init(); |
| |
| callSuppressExceptions(classTypeWrapper, "doStartTag"); //$NON-NLS-1$ |
| callSuppressExceptions(classTypeWrapper, "createValidator"); //$NON-NLS-1$ |
| |
| // hopefully doStartTag set the converter field before it |
| // failed. |
| // now try to guess what it's called |
| String validatorId = getStringField(classTypeWrapper, |
| converterProxy, "validatorId"); //$NON-NLS-1$ |
| |
| if (validatorId != null) |
| { |
| return validatorId; |
| } |
| |
| validatorId = getStringField(classTypeWrapper, converterProxy, |
| "_validatorId"); //$NON-NLS-1$ |
| |
| if (validatorId != null) |
| { |
| return validatorId; |
| } |
| |
| // no? then see if there's a VALIDATOR_ID field *on the tag* |
| validatorId = getStringField(classTypeWrapper, classTypeProxy, |
| "VALIDATOR_ID"); //$NON-NLS-1$ |
| |
| if (validatorId != null) |
| { |
| return validatorId; |
| } |
| } |
| catch (final ProxyException tp) |
| { |
| // fall through |
| } |
| } |
| } |
| finally |
| { |
| if (registry != null) |
| { |
| registry.terminateRegistry(true); |
| } |
| } |
| return null; |
| |
| } |
| |
| private static IBeanProxy getFieldInParents( |
| final BeanProxyWrapper classTypeWrapper, |
| final IBeanTypeProxy typeProxy, final String fieldName) |
| { |
| try |
| { |
| return classTypeWrapper.getFieldValueIncludeParents(fieldName, |
| typeProxy); |
| } |
| catch (final ProxyException e) |
| { |
| // suppress |
| } |
| |
| return null; |
| } |
| |
| private static String getStringField( |
| final BeanProxyWrapper classTypeWrapper, |
| final IBeanTypeProxy typeProxy, final String fieldName) |
| { |
| try |
| { |
| return classTypeWrapper.getStringFieldValue(fieldName, typeProxy); |
| } |
| catch (final ProxyException e) |
| { |
| // suppress |
| } |
| |
| return null; |
| } |
| |
| private static void callSuppressExceptions( |
| final BeanProxyWrapper classTypeWrapper, final String methodName) |
| { |
| try |
| { |
| classTypeWrapper.call(methodName); |
| } |
| catch (final ProxyException tp) |
| { |
| // suppress this since it may well throw an exception |
| // depending on what assumptions the tag class is making |
| // that won't be true because we're not in a servlet |
| } |
| } |
| |
| private static void callSuppressExceptions( |
| final BeanProxyWrapper classTypeWrapper, final String methodName, |
| final IBeanProxy[] args, final IBeanTypeProxy[] argTypes) |
| { |
| try |
| { |
| classTypeWrapper.call(methodName, args, argTypes); |
| } |
| catch (final ProxyException tp) |
| { |
| // suppress this since it may well throw an exception |
| // depending on what assumptions the tag class is making |
| // that won't be true because we're not in a servlet |
| } |
| |
| } |
| |
| /** |
| * @param project |
| * @return a new proxy factory registry or null; |
| * |
| * TODO: caching? |
| */ |
| private static ProxyFactoryRegistry getProxyFactoryRegistry( |
| final IConfigurationContributor[] configuration, |
| final IProject project) |
| { |
| try |
| { |
| return IDERegistration.startAnImplementation(configuration, 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; |
| } |
| |
| /** |
| * @param tldDecl |
| * @param project |
| * @return the tag element for the tldDecl |
| */ |
| public static TLDTagElement createTLDTagElement( |
| final TLDElementDeclaration tldDecl, final IProject project) |
| { |
| if (JSFCoreTraceOptions.TRACE_JSPTAGINTROSPECTOR) |
| { |
| JSFCoreTraceOptions |
| .log(String |
| .format( |
| "TagAnalyzer.createTLDTagElement: Start tld=%s, project=%s", //$NON-NLS-1$ |
| tldDecl.getNodeName(), project.getName())); |
| } |
| long startTime = 0; |
| if (JSFCoreTraceOptions.TRACE_JSPTAGINTROSPECTOR_PERF) |
| { |
| startTime = System.nanoTime(); |
| } |
| |
| try |
| { |
| final IJavaProject javaProject = JavaCore.create(project); |
| final String typeName = tldDecl.getTagclass(); |
| |
| if (typeName == null |
| || JavaConventions.validateJavaTypeName(typeName, |
| JavaCore.VERSION_1_3, |
| JavaCore.VERSION_1_3).getSeverity() == IStatus.ERROR) |
| { |
| JSFCorePlugin.log( |
| "Bad tag class name in " + tldDecl.toString(), //$NON-NLS-1$ |
| new Throwable()); |
| return null; |
| } |
| |
| final IType type = javaProject.findType(typeName); |
| |
| if (type == null) |
| { |
| if (JSFCoreTraceOptions.TRACE_JSPTAGINTROSPECTOR) |
| { |
| JSFCoreTraceOptions.log("Type not found for: "+typeName); //$NON-NLS-1$ |
| } |
| return null; |
| } |
| final TagType tagType = getJSFComponentTagType(type, project); |
| |
| if (JSFCoreTraceOptions.TRACE_JSPTAGINTROSPECTOR) |
| { |
| JSFCoreTraceOptions.log(String.format( |
| "Tag class type=%s\nTag type=%s", type, tagType)); //$NON-NLS-1$ |
| } |
| |
| if (tagType == TagType.COMPONENT) |
| { |
| final TLDTagElement element = createComponentTagElement(tldDecl, project); |
| |
| if (JSFCoreTraceOptions.TRACE_JSPTAGINTROSPECTOR_PERF) |
| { |
| String name = element != null ? element.toString() |
| : "<none>"; //$NON-NLS-1$ |
| System.out.printf( |
| "Time to create component tag element %s was %d\n", //$NON-NLS-1$ |
| name, Long.valueOf(System.nanoTime() - startTime)); |
| } |
| return element; |
| } |
| else if (tagType == TagType.CONVERTER) |
| { |
| final TLDTagElement element = createConverterTagElement(tldDecl, project); |
| if (JSFCoreTraceOptions.TRACE_JSPTAGINTROSPECTOR_PERF) |
| { |
| String name = element != null ? element.toString() |
| : "<none>"; //$NON-NLS-1$ |
| System.out.printf( |
| "Time to create converter tag element %s was %d\n", //$NON-NLS-1$ |
| name, Long.valueOf(System.nanoTime() - startTime)); |
| } |
| return element; |
| } |
| else if (tagType == TagType.VALIDATOR) |
| { |
| final TLDTagElement element = createValidatorTagElement(tldDecl, project); |
| if (JSFCoreTraceOptions.TRACE_JSPTAGINTROSPECTOR_PERF) |
| { |
| String name = element != null ? element.toString() |
| : "<none>"; //$NON-NLS-1$ |
| System.out.printf( |
| "Time to create validator tag element %s was %d\n", //$NON-NLS-1$ |
| name, Long.valueOf(System.nanoTime() - startTime)); |
| } |
| return element; |
| } |
| else if (tagType == TagType.HANDLER) |
| { |
| final TLDTagElement element = createHandlerTagElement(tldDecl, type); |
| if (JSFCoreTraceOptions.TRACE_JSPTAGINTROSPECTOR_PERF) |
| { |
| String name = element != null ? element.toString() |
| : "<none>"; //$NON-NLS-1$ |
| System.out.printf( |
| "Time to create handler tag element %s was %d\n", //$NON-NLS-1$ |
| name, Long.valueOf(System.nanoTime() - startTime)); |
| } |
| return element; |
| } |
| } |
| catch (final JavaModelException jme) |
| { |
| JSFCorePlugin.log(jme, "Trying to get type for TLD"); //$NON-NLS-1$ |
| } |
| |
| return null; |
| } |
| |
| /** |
| * @param tldDecl |
| * @param project |
| * @return a component tag element for tldDecl |
| */ |
| public static TLDTagElement createComponentTagElement( |
| final TLDElementDeclaration tldDecl, final IProject project) |
| { |
| final String componentType = findComponentType(tldDecl, project); |
| |
| if (componentType != null) |
| { |
| final String componentClass = DTComponentIntrospector |
| .findComponentClass(componentType, project); |
| |
| if (componentClass != null && !"".equals(componentClass.trim())) //$NON-NLS-1$ |
| { |
| final ComponentTypeInfo typeInfo = DTComponentIntrospector |
| .getComponent(componentType, componentClass, project, |
| new IConfigurationContributor[] |
| {new ServletBeanProxyContributor(project)}); |
| |
| if (typeInfo != null) |
| { |
| final TLDComponentTagElement tagElement = new TLDComponentTagElement( |
| tldDecl, typeInfo, new NullAttributeAdvisor()); |
| return tagElement; |
| } |
| } |
| } |
| |
| // TODO: really return null? |
| return null; |
| } |
| |
| /** |
| * @param tldDecl |
| * @param project |
| * @return a converter tag element for tldDecl |
| */ |
| public static TLDTagElement createConverterTagElement( |
| final TLDElementDeclaration tldDecl, final IProject project) |
| { |
| final String converterId = findConverterType(tldDecl, project); |
| |
| if (converterId != null) |
| { |
| final String converterClass = DTComponentIntrospector |
| .findConverterClass(converterId, project); |
| |
| if (converterClass != null && !"".equals(converterClass.trim())) //$NON-NLS-1$ |
| { |
| final ConverterTypeInfo typeInfo = DTComponentIntrospector |
| .getConverter(converterId, converterClass); |
| final TLDConverterTagElement tagElement = new TLDConverterTagElement( |
| tldDecl, typeInfo, new NullAttributeAdvisor()); |
| return tagElement; |
| } |
| } |
| |
| // we know (actually we assume by contract) that this a converter |
| // so create an unknown converter tag for it |
| return new TLDConverterTagElement(tldDecl, ConverterTypeInfo.UNKNOWN, new NullAttributeAdvisor()); |
| } |
| |
| /** |
| * @param tldDecl |
| * @param project |
| * @return a validator tag element for the tldDec |
| */ |
| public static TLDTagElement createValidatorTagElement( |
| final TLDElementDeclaration tldDecl, final IProject project) |
| { |
| final String validatorId = findValidatorType(tldDecl, project); |
| |
| if (validatorId != null) |
| { |
| final String validatorClass = DTComponentIntrospector |
| .findValidatorClass(validatorId, project); |
| |
| if (validatorClass != null && !"".equals(validatorClass.trim())) //$NON-NLS-1$ |
| { |
| final ValidatorTypeInfo typeInfo = DTComponentIntrospector |
| .getValidator(validatorId, validatorClass); |
| final TLDValidatorTagElement tagElement = new TLDValidatorTagElement( |
| tldDecl, typeInfo, new NullAttributeAdvisor()); |
| return tagElement; |
| } |
| } |
| // we know (actually we assume by contract) that this a validator |
| // so create an unknown converter tag for it |
| return new TLDValidatorTagElement(tldDecl, ValidatorTypeInfo.UNKNOWN, new NullAttributeAdvisor()); |
| } |
| |
| /** |
| * @param tldDecl |
| * @param type |
| * @return the tag element for a JSF handler |
| */ |
| public static TLDTagElement createHandlerTagElement( |
| final TLDElementDeclaration tldDecl, final IType type) |
| { |
| if (DTComponentIntrospector.isTypeNameInstanceOfClass(type, |
| FACET_TAG_HANDLER)) |
| { |
| return new TLDTagHandlerElement(tldDecl, TagHandlerType.FACET, new NullAttributeAdvisor()); |
| } |
| else if (DTComponentIntrospector.isTypeNameInstanceOfClass(type, |
| ATTRIBUTE_TAG_HANDLER)) |
| { |
| return new TLDTagHandlerElement(tldDecl, TagHandlerType.ATTRIBUTE, new NullAttributeAdvisor()); |
| } |
| // else if (isTypeNameInstanceOfClass(type, ACTIONLISTENER_TAG_HANDLER)) |
| // { |
| // return new TLDTagHandlerElement(tldDecl, |
| // TagHandlerType.ACTIONLISTENER); |
| // } |
| // else if (isTypeNameInstanceOfClass(type, |
| // VALUECHANGELISTENER_TAG_HANDLER)) |
| // { |
| // return new TLDTagHandlerElement(tldDecl, |
| // TagHandlerType.VALUECHANGELISTENER); |
| // } |
| return null; |
| } |
| |
| /** |
| * @param type |
| * @param project |
| * @return true if type represents a JSF component action class (spec 9.2.2) |
| */ |
| public static IJSFTagElement.TagType getJSFComponentTagType( |
| final IType type, final IProject project) |
| { |
| if (JSFCoreTraceOptions.TRACE_JSPTAGINTROSPECTOR) |
| { |
| JSFCoreTraceOptions |
| .log(String |
| .format( |
| "TagAnalyzer.getJSFComponentTagType: Determining Tag Type for type %s on project %s", //$NON-NLS-1$ |
| type.getFullyQualifiedName(), project |
| .toString())); |
| } |
| |
| Set<String> componentTags = null; |
| Set<String> converterTags = null; |
| Set<String> validatorTags = null; |
| |
| final JSFVersion jsfVersion = ServletBeanProxyContributor.getProjectVersion(project); |
| |
| // v1.1(9.2.2): JSF component tags must sub-class one of these |
| if (jsfVersion == JSFVersion.V1_0 || jsfVersion == JSFVersion.V1_1) |
| { |
| componentTags = COMPONENT_TAG_HANDLER_TYPES_JSF11; |
| converterTags = CONVERTER_TAG_HANDLER_TYPES_JSF11; |
| validatorTags = VALIDATOR_TAG_HANDLER_TYPES_JSF11; |
| } |
| // v1.2(9.2.2): JSF component tags must sub-class UIComponentELTag |
| // the original two are included because we must be backward |
| // compatible |
| else if (jsfVersion == JSFVersion.V1_2) |
| { |
| componentTags = COMPONENT_TAG_HANDLER_TYPES_JSF12; |
| converterTags = CONVERTER_TAG_HANDLER_TYPES_JSF12; |
| validatorTags = VALIDATOR_TAG_HANDLER_TYPES_JSF12; |
| } |
| |
| TagType tagType = null; |
| |
| if (DTComponentIntrospector.isTypeNameInstanceOfClass(type, |
| componentTags)) |
| { |
| tagType = TagType.COMPONENT; |
| } |
| else if (DTComponentIntrospector.isTypeNameInstanceOfClass(type, |
| converterTags)) |
| { |
| tagType = TagType.CONVERTER; |
| } |
| else if (DTComponentIntrospector.isTypeNameInstanceOfClass(type, |
| validatorTags)) |
| { |
| tagType = TagType.VALIDATOR; |
| } |
| else if (DTComponentIntrospector.isTypeNameInstanceOfClass(type, |
| ALL_HANDLER_TAGS)) |
| { |
| tagType = TagType.HANDLER; |
| } |
| |
| if (JSFCoreTraceOptions.TRACE_JSPTAGINTROSPECTOR) |
| { |
| JSFCoreTraceOptions.log(String.format( |
| "TagAnalyzer.getJSFComponentTagType: tag type is %s", //$NON-NLS-1$ |
| tagType != null ? tagType.toString() : "null")); //$NON-NLS-1$ |
| } |
| return tagType; |
| } |
| |
| |
| } |