You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by lu...@apache.org on 2017/03/10 00:20:34 UTC
svn commit: r1786263 - in /myfaces/core/branches/2.3.x:
api/src/main/java/javax/faces/component/ api/src/main/java/javax/faces/view/
impl/src/main/java/org/apache/myfaces/el/unified/
impl/src/main/java/org/apache/myfaces/el/unified/resolver/ impl/src/m...
Author: lu4242
Date: Fri Mar 10 00:20:34 2017
New Revision: 1786263
URL: http://svn.apache.org/viewvc?rev=1786263&view=rev
Log:
MYFACES-4101 Implement f:importConstants
Added:
myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/component/UIImportConstants.java
myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/el/unified/resolver/ImportConstantsELResolver.java
Modified:
myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/view/ViewMetadata.java
myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/el/unified/ResolverBuilderForFaces.java
myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/view/facelets/tag/jsf/core/CoreLibrary.java
Added: myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/component/UIImportConstants.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/component/UIImportConstants.java?rev=1786263&view=auto
==============================================================================
--- myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/component/UIImportConstants.java (added)
+++ myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/component/UIImportConstants.java Fri Mar 10 00:20:34 2017
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+package javax.faces.component;
+
+import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFComponent;
+import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFProperty;
+
+/**
+ *
+ */
+@JSFComponent
+(clazz = "javax.faces.component.UIImportConstants",
+ name = "f:importConstants", bodyContent = "empty")
+public class UIImportConstants extends UIComponentBase
+{
+
+ static public final String COMPONENT_FAMILY = "javax.faces.ImportConstants";
+ static public final String COMPONENT_TYPE = "javax.faces.ImportConstants";
+
+
+ public UIImportConstants()
+ {
+ setRendererType(null);
+ }
+
+ @Override
+ public String getFamily()
+ {
+ return COMPONENT_FAMILY;
+ }
+
+ @JSFProperty
+ public String getType()
+ {
+ return (String) getStateHelper().eval(PropertyKeys.type);
+ }
+
+ public void setType(String type)
+ {
+ getStateHelper().put(PropertyKeys.type, type );
+ }
+
+ @JSFProperty
+ public String getVar()
+ {
+ return (String) getStateHelper().eval(PropertyKeys.var);
+ }
+
+ public void setVar(String var)
+ {
+ getStateHelper().put(PropertyKeys.var, var );
+ }
+
+ enum PropertyKeys
+ {
+ type
+ , var
+ }
+}
Modified: myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/view/ViewMetadata.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/view/ViewMetadata.java?rev=1786263&r1=1786262&r2=1786263&view=diff
==============================================================================
--- myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/view/ViewMetadata.java (original)
+++ myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/view/ViewMetadata.java Fri Mar 10 00:20:34 2017
@@ -24,6 +24,7 @@ import java.util.Iterator;
import java.util.LinkedList;
import javax.faces.component.UIComponent;
+import javax.faces.component.UIImportConstants;
import javax.faces.component.UIViewAction;
import javax.faces.component.UIViewParameter;
import javax.faces.component.UIViewRoot;
@@ -147,4 +148,57 @@ public abstract class ViewMetadata
UIComponent metadataFacet = root.getFacet(UIViewRoot.METADATA_FACET_NAME);
return metadataFacet != null ? metadataFacet.getChildCount() > 0 : false;
}
+
+ /**
+ * @since 2.3
+ * @param root
+ * @return
+ */
+ public static Collection<UIImportConstants> getImportConstants(UIViewRoot root)
+ {
+ LinkedList<UIImportConstants> result = null;
+ UIComponent metadataFacet = root.getFacet (UIViewRoot.METADATA_FACET_NAME);
+ Iterator<UIComponent> children;
+
+ if (metadataFacet == null)
+ {
+ // No metadata, so return an empty collection.
+
+ return Collections.emptyList();
+ }
+
+ // Iterate over all the children, keep only the view parameters.
+
+ if (metadataFacet.getChildCount() > 0)
+ {
+ children = metadataFacet.getChildren().iterator();
+
+ while (children.hasNext())
+ {
+ UIComponent component = children.next();
+
+ if (result == null)
+ {
+ result = new LinkedList<UIImportConstants>();
+ }
+
+ if (component instanceof UIImportConstants)
+ {
+ result.add ((UIImportConstants) component);
+ }
+ }
+ }
+
+ // TODO: does this need to be immutable? Spec does not indicate either
+ // way.
+ if (result == null)
+ {
+ return Collections.emptyList();
+ }
+ else
+ {
+ return Collections.unmodifiableCollection (result);
+ }
+ }
+
}
Modified: myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/el/unified/ResolverBuilderForFaces.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/el/unified/ResolverBuilderForFaces.java?rev=1786263&r1=1786262&r2=1786263&view=diff
==============================================================================
--- myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/el/unified/ResolverBuilderForFaces.java (original)
+++ myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/el/unified/ResolverBuilderForFaces.java Fri Mar 10 00:20:34 2017
@@ -37,6 +37,7 @@ import org.apache.myfaces.config.Runtime
import org.apache.myfaces.el.FlashELResolver;
import org.apache.myfaces.el.unified.resolver.CompositeComponentELResolver;
import org.apache.myfaces.el.unified.resolver.FacesCompositeELResolver.Scope;
+import org.apache.myfaces.el.unified.resolver.ImportConstantsELResolver;
import org.apache.myfaces.el.unified.resolver.ImportHandlerResolver;
import org.apache.myfaces.el.unified.resolver.ManagedBeanResolver;
import org.apache.myfaces.el.unified.resolver.ResourceBundleResolver;
@@ -104,6 +105,7 @@ public class ResolverBuilderForFaces ext
list.add(new ResourceResolver());
list.add(new ResourceBundleELResolver());
list.add(new ResourceBundleResolver());
+ list.add(new ImportConstantsELResolver());
if (STATIC_FIELD_EL_RESOLVER_CLASS != null &&
GET_STREAM_EL_RESOLVER_METHOD != null)
Added: myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/el/unified/resolver/ImportConstantsELResolver.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/el/unified/resolver/ImportConstantsELResolver.java?rev=1786263&view=auto
==============================================================================
--- myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/el/unified/resolver/ImportConstantsELResolver.java (added)
+++ myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/el/unified/resolver/ImportConstantsELResolver.java Fri Mar 10 00:20:34 2017
@@ -0,0 +1,251 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+package org.apache.myfaces.el.unified.resolver;
+
+import java.beans.FeatureDescriptor;
+import static java.lang.String.format;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import static java.util.logging.Level.FINE;
+import java.util.logging.Logger;
+import javax.el.ELContext;
+import javax.el.ELException;
+import javax.el.ELResolver;
+import javax.el.PropertyNotFoundException;
+import javax.el.PropertyNotWritableException;
+import javax.faces.component.UIImportConstants;
+import javax.faces.component.UIViewRoot;
+import javax.faces.context.FacesContext;
+import javax.faces.view.ViewMetadata;
+import org.apache.myfaces.shared.util.ClassUtils;
+import org.apache.myfaces.view.facelets.FaceletViewDeclarationLanguage;
+
+/**
+ *
+ */
+public final class ImportConstantsELResolver extends ELResolver
+{
+ private static final String ERROR_MISSING_CLASS = "Cannot find type '%s' in classpath.";
+ private static final String ERROR_FIELD_ACCESS = "Cannot access constant field '%s' of type '%s'.";
+
+ private static final String IMPORT_CONSTANTS = "oam.importConstants";
+
+ @Override
+ public Object getValue(final ELContext context, final Object base,
+ final Object property)
+ throws NullPointerException, PropertyNotFoundException, ELException
+ {
+ if (base != null)
+ {
+ return null;
+ }
+ if (property == null)
+ {
+ throw new PropertyNotFoundException();
+ }
+ if (!(property instanceof String))
+ {
+ return null;
+ }
+
+ final FacesContext facesContext = facesContext(context);
+ if (facesContext == null)
+ {
+ return null;
+ }
+
+ UIViewRoot viewRoot = facesContext.getViewRoot();
+ if (viewRoot == null)
+ {
+ return null;
+ }
+
+ Map<String, String> importConstantsMap = (Map<String, String>)
+ viewRoot.getTransientStateHelper().getTransient(IMPORT_CONSTANTS);
+ if (importConstantsMap == null)
+ {
+ Collection<UIImportConstants> constants = ViewMetadata.getImportConstants(viewRoot);
+ if (constants != null && !constants.isEmpty())
+ {
+ importConstantsMap = new HashMap<String, String>();
+ for (UIImportConstants c : constants)
+ {
+ String var = c.getVar();
+ String type = c.getType();
+ if (var == null)
+ {
+ int innerClass = type.lastIndexOf('$');
+ int outerClass = type.lastIndexOf('.');
+ var = type.substring(Math.max(innerClass, outerClass) + 1);
+ }
+ importConstantsMap.put(var, type);
+ }
+ }
+ else
+ {
+ importConstantsMap = Collections.emptyMap();
+ }
+ if (!FaceletViewDeclarationLanguage.isBuildingViewMetadata(facesContext))
+ {
+ viewRoot.getTransientStateHelper().putTransient(IMPORT_CONSTANTS, importConstantsMap);
+ }
+ }
+
+ if (importConstantsMap != null && !importConstantsMap.isEmpty())
+ {
+ String type = importConstantsMap.get((String)property);
+ if (type != null)
+ {
+ Map<String, Object> constantsMap = collectConstants(type);
+ if (constantsMap != null && !constantsMap.isEmpty())
+ {
+ context.setPropertyResolved(true);
+ return constantsMap;
+ }
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public Class<?> getType(final ELContext context, final Object base,
+ final Object property)
+ throws NullPointerException, PropertyNotFoundException, ELException
+ {
+ return null;
+ }
+
+ @Override
+ public void setValue(ELContext elc, Object o, Object o1, Object o2)
+ throws NullPointerException, PropertyNotFoundException, PropertyNotWritableException, ELException
+ {
+ //No op
+ }
+
+ @Override
+ public boolean isReadOnly(final ELContext context, final Object base,
+ final Object property)
+ throws NullPointerException, PropertyNotFoundException, ELException
+ {
+ return false;
+ }
+
+ @Override
+ public Iterator<FeatureDescriptor> getFeatureDescriptors(final ELContext context, final Object base)
+ {
+ return null;
+ }
+
+ @Override
+ public Class<?> getCommonPropertyType(final ELContext context, final Object base)
+ {
+ return base == null ? Object.class : null;
+ }
+
+ // get the FacesContext from the ELContext
+ private static FacesContext facesContext(final ELContext context)
+ {
+ return (FacesContext) context.getContext(FacesContext.class);
+ }
+
+ // Helpers --------------------------------------------------------------------------------------------------------
+ /**
+ * Collect constants of the given type. That are, all public static final fields of the given type.
+ *
+ * @param type The fully qualified name of the type to collect constants for.
+ * @return Constants of the given type.
+ */
+ private static Map<String, Object> collectConstants(final String type)
+ {
+ Map<String, Object> constants = new HashMap<String, Object>();
+
+ for (Field field : toClass(type).getFields())
+ {
+ if (isPublicStaticFinal(field))
+ {
+ try
+ {
+ constants.put(field.getName(), field.get(null));
+ }
+ catch (Exception e)
+ {
+ throw new IllegalArgumentException(format(ERROR_FIELD_ACCESS, type, field.getName()), e);
+ }
+ }
+ }
+
+ return constants;
+ }
+
+ /**
+ * Convert the given type, which should represent a fully qualified name, to a concrete {@link Class} instance.
+ *
+ * @param type The fully qualified name of the class.
+ * @return The concrete {@link Class} instance.
+ * @throws IllegalArgumentException When it is missing in the classpath.
+ */
+ static Class<?> toClass(String type)
+ {
+ // Package-private so that ImportFunctions can also use it.
+ try
+ {
+ return ClassUtils.classForName(type);
+ }
+ catch (ClassNotFoundException e)
+ {
+ // Perhaps it's an inner enum which is specified as com.example.SomeClass.SomeEnum.
+ // Let's be lenient on that although the proper type notation should be com.example.SomeClass$SomeEnum.
+ int i = type.lastIndexOf('.');
+
+ if (i > 0)
+ {
+ try
+ {
+ return toClass(new StringBuilder(type).replace(i, i + 1, "$").toString());
+ }
+ catch (Exception ignore)
+ {
+ Logger.getLogger(ImportConstantsELResolver.class.getName()).log(
+ FINE, "Ignoring thrown exception; previous exception will be rethrown instead.", ignore);
+ // Just continue to IllegalArgumentException on original ClassNotFoundException.
+ }
+ }
+
+ throw new IllegalArgumentException(format(ERROR_MISSING_CLASS, type), e);
+ }
+ }
+
+ /**
+ * Returns whether the given field is a constant field, that is when it is public, static and final.
+ *
+ * @param field The field to be checked.
+ * @return <code>true</code> if the given field is a constant field, otherwise <code>false</code>.
+ */
+ private static boolean isPublicStaticFinal(Field field)
+ {
+ int modifiers = field.getModifiers();
+ return Modifier.isPublic(modifiers) && Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers);
+ }
+
+}
Modified: myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/view/facelets/tag/jsf/core/CoreLibrary.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/view/facelets/tag/jsf/core/CoreLibrary.java?rev=1786263&r1=1786262&r2=1786263&view=diff
==============================================================================
--- myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/view/facelets/tag/jsf/core/CoreLibrary.java (original)
+++ myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/view/facelets/tag/jsf/core/CoreLibrary.java Fri Mar 10 00:20:34 2017
@@ -18,6 +18,7 @@
*/
package org.apache.myfaces.view.facelets.tag.jsf.core;
+import javax.faces.component.UIImportConstants;
import javax.faces.component.UIParameter;
import javax.faces.component.UISelectItem;
import javax.faces.component.UISelectItems;
@@ -114,6 +115,8 @@ public final class CoreLibrary extends A
this.addComponent("viewAction", UIViewAction.COMPONENT_TYPE, null);
this.addComponent("viewParam", UIViewParameter.COMPONENT_TYPE, null);
+
+ this.addComponent("importConstants", UIImportConstants.COMPONENT_TYPE, null);
this.addComponent("verbatim", "javax.faces.HtmlOutputText", "javax.faces.Text", VerbatimHandler.class);