dev@javaserverfaces.java.net

Seeking Review: 10-extensionMetadata: no more context-param

From: Ed Burns <Ed.Burns_at_Sun.COM>
Date: Tue, 27 Jan 2009 13:04:16 -0800

AS> 3. 10-ExtensionMetadata - context parameter usage.

AS> It seems that the content within the <composite:extension> element is
AS> not automatically ignored - ie. you must set the
AS> javax.faces.FACELETS_IGNORE_URI_LIST to include the URIs of any
AS> namespaces of elements that are embedded within <composite:extension>.
AS>
AS> From a design perspective a cleaner solution would be to spec that all
AS> contents within <composite:extension> are automatically ignored, and not
AS> require the use of the context parameter.
AS>
AS> Were there implementation problems that prevented us from doing this?
AS> (Or is there some design issue here that I am missing?)

Yes, it was a bit of a pain to implement, but here's what I've got. We
will drop the silly context-parameter.

Here's the change-bundle. After this, I'll get to Jeff's comments.

Issue: 10-extensionMetadata

r=retroactive review, automated tests still run successfully.

Drop the FACELETS_IGNORE_URI_LIST context-param and instead take Andy
Schwartz's suggestion to add a <composite:extension> element that can be
used to wrap any old XML in the composite page.

SECTION: Modified Files
----------------------------
M jsf-ri/conf/share/composite.tld

- Document <composite:extension> element

M jsf-ri/src/com/sun/faces/facelets/compiler/CompilationManager.java

- adhere to new signature for Compiler.createTagLibrary(), the one that
  takes a CompilationMessageHolder instance.

- add a method that gets a CompilationMessageHolder instance.

- adhere to the new contract for TagLibrary.containsNamespace(), the one
  that optionally takes a Tag instance.

M jsf-ri/src/com/sun/faces/facelets/compiler/Compiler.java

- modify signature of createTagLibrary to take a
  CompilationMessageHolder instance, which is passed on to the
  CompositeTagLibrary ctor.

M jsf-ri/src/com/sun/faces/facelets/compiler/EncodingHandler.java

- Use this to make the current compilation unit's CompilationMessageHolder
  instance available to tag handlers during page execution.

M jsf-ri/src/com/sun/faces/facelets/compiler/SAXCompiler.java

- Adhere to the new ctor signature for EncodingHandler that takes a
  CompilationMessageHolder instance

M jsf-ri/src/com/sun/faces/facelets/tag/TagLibrary.java

- modify containsNamespace() to take a Tag as an additional argument.

M jsf-ri/src/com/sun/faces/facelets/tag/composite/DeclareFacetHandler.java
M jsf-ri/src/com/sun/faces/facelets/tag/composite/AttributeHandler.java
M jsf-ri/src/com/sun/faces/facelets/tag/composite/AttachedObjectTargetHandler.java

- Make sure the nextHandler is applied. Without this the
  <composite:extension> handler will not be called.

M jsf-ri/src/com/sun/faces/facelets/tag/composite/CompositeLibrary.java

- add extension tag handler

M jsf-ri/src/com/sun/faces/facelets/tag/CompositeTagLibrary.java

- Add ctor that takes CompilationMessageHolder

- Modify code that looks at XML namespaces when compiling. Previously,
  this code would queue a FacesMessage immediately if it encountered an
  unknown namespace. This is now modified to use the
  CompilationMessageHolder.

- remove the getNamespaceMessageMap(), moved to CompilationMessageHolder

M jsf-ri/src/com/sun/faces/facelets/tag/AbstractTagLibrary.java
M jsf-ri/src/com/sun/faces/facelets/tag/jstl/fn/JstlFnLibrary.java

- Adhere to new containsNamespace() signature.

M jsf-ri/src/com/sun/faces/util/Util.java

- Somewhat unrelated bug fix to correctly handle prefix and extension mappings
  correctly.

M jsf-ri/systest/web/WEB-INF/web.xml

- add an entry to facelets.VIEW_MAPPINGS, tested in automated test.

A jsf-ri/src/com/sun/faces/facelets/compiler/CompilationMessageHolderImpl.java
A jsf-ri/src/com/sun/faces/facelets/compiler/CompilationMessageHolder.java

+ * The CompilationManager vends one of these
+ * to store compilation messages for later use. During page compilation,
+ * if any messages need to be shown to the user, they will be
+ * added using this interface. If, during page execution,
+ * the messages turn out not to be needed, as is the case with
+ * a foreign xml element nested within a <composite:extension> element,
+ * this interface can be used to remove the messages.
+ *
+ * Currently the messages are keyed by namespace prefix.
+ *
+ * The EncodingHandler class is always the outermost FaceletHandler in any
+ * Facelet compilation unit. Therefore, this handler is used
+ * to anchor the implementation of the CompilationMessageHolder so
+ * other tags can access it. See EncodingHandler for how to do it.

A jsf-ri/src/com/sun/faces/facelets/tag/composite/ExtensionHandler.java

- Tag handler that removes a compilation message if the prefix of the
  child content was present in the compilation messages.

A jsf-ri/systest/src/com/sun/faces/component/CompositeMetaDataTestCase.java
A jsf-ri/systest/web/composite/jsr276-using.xhtml
A jsf-ri/systest/web/resources/composite/jsr276Incorrect01.xhtml
A jsf-ri/systest/web/resources/composite/jsr276Correct01.xhtml

- automated testcase

SECTION: Diffs
----------------------------
Index: jsf-ri/conf/share/composite.tld
===================================================================
--- jsf-ri/conf/share/composite.tld (revision 6279)
+++ jsf-ri/conf/share/composite.tld (working copy)
@@ -1378,6 +1378,27 @@
         </attribute>
   </tag>
 
+<tag>
+ <description>
 
+ <![CDATA[
+<div class="changed_added_2_0">
+<p>Used within a <code>&lt;composite:interface&gt;</code> section,
+within any sub-element of that section, to include XML content not
+defined by this specification. This element can be used to incorporate
+<a target="_" href="http://jcp.org/en/jsr/detail?id=276">JSR-276</a>
+metadata into a composite component.</p>
 
+</div>]]>
+ </description>
+ <name>
+ extension
+ </name>
+ <body-content>
+ JSP
+ </body-content>
+ </tag>
+
+
+
 </taglib>
Index: jsf-ri/src/com/sun/faces/facelets/compiler/CompilationMessageHolderImpl.java
===================================================================
--- jsf-ri/src/com/sun/faces/facelets/compiler/CompilationMessageHolderImpl.java (revision 0)
+++ jsf-ri/src/com/sun/faces/facelets/compiler/CompilationMessageHolderImpl.java (revision 0)
@@ -0,0 +1,92 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common Development
+ * and Distribution License("CDDL") (collectively, the "License"). You
+ * may not use this file except in compliance with the License. You can obtain
+ * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
+ * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
+ * language governing permissions and limitations under the License.
+ *
+ * When distributing the software, include this License Header Notice in each
+ * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
+ * Sun designates this particular file as subject to the "Classpath" exception
+ * as provided by Sun in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the License
+ * Header, with the fields enclosed by brackets [] replaced by your own
+ * identifying information: "Portions Copyrighted [year]
+ * [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by only the CDDL or
+ * only the GPL Version 2, indicate your decision by adding "[Contributor]
+ * elects to include this software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice of license, a
+ * recipient has the option to distribute your version of this file under
+ * either the CDDL, the GPL Version 2 or to extend the choice of license to
+ * its licensees as provided above. However, if you add GPL Version 2 code
+ * and therefore, elected the GPL Version 2 license, then the option applies
+ * only if the new code is made subject to such option by the copyright
+ * holder.
+ */
+
+package com.sun.faces.facelets.compiler;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.faces.application.FacesMessage;
+import javax.faces.context.FacesContext;
+
+/**
+ *
+ * @author edburns
+ */
+public class CompilationMessageHolderImpl implements CompilationMessageHolder {
+
+ private Map<String, List<FacesMessage>> messageListMap;
+
+
+ private Map<String, List<FacesMessage>> getMessageListMap() {
+ if (null == messageListMap) {
+ messageListMap = new HashMap<String, List<FacesMessage>>();
+ }
+ return messageListMap;
+ }
+
+ public List<FacesMessage> getNamespacePrefixMessages(FacesContext context,
+ String prefix) {
+ List<FacesMessage> result = null;
+ Map<String, List<FacesMessage>> map = getMessageListMap();
+ if (null == (result = map.get(prefix))) {
+ result = new ArrayList<FacesMessage>();
+ map.put(prefix, result);
+ }
+
+ return result;
+ }
+
+ public void processCompilationMessages(FacesContext context) {
+ Map<String, List<FacesMessage>> map = getMessageListMap();
+ Collection<List<FacesMessage>> values = map.values();
+ for (List<FacesMessage> curList : values) {
+ for (FacesMessage curMessage : curList) {
+ context.addMessage(null, curMessage);
+ }
+ }
+ }
+
+ public void removeNamespacePrefixMessages(String prefix) {
+ Map<String, List<FacesMessage>> map = getMessageListMap();
+ map.remove(prefix);
+ }
+
+
+
+}
Index: jsf-ri/src/com/sun/faces/facelets/compiler/CompilationManager.java
===================================================================
--- jsf-ri/src/com/sun/faces/facelets/compiler/CompilationManager.java (revision 6279)
+++ jsf-ri/src/com/sun/faces/facelets/compiler/CompilationManager.java (working copy)
@@ -53,10 +53,13 @@
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
 import java.util.Stack;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
+import javax.faces.application.FacesMessage;
+import javax.faces.context.FacesContext;
 import javax.faces.webapp.pdl.facelets.FaceletHandler;
 import javax.faces.webapp.pdl.facelets.tag.Tag;
 import javax.faces.webapp.pdl.facelets.tag.TagAttribute;
@@ -101,6 +104,8 @@
     
     private final String alias;
     
+ private CompilationMessageHolder messageHolder = null;
+
     public CompilationManager(String alias, Compiler compiler) {
         
         // this is our alias
@@ -109,7 +114,7 @@
         // grab compiler state
         this.compiler = compiler;
         this.tagDecorator = compiler.createTagDecorator();
- this.tagLibrary = compiler.createTagLibrary();
+ this.tagLibrary = compiler.createTagLibrary(this.getCompilationMessageHolder());
 
         // namespace management
         this.namespaceManager = new NamespaceManager();
@@ -130,6 +135,18 @@
     private InterfaceUnit getInterfaceUnit() {
         return interfaceUnit;
     }
+
+ public CompilationMessageHolder getCompilationMessageHolder() {
+ if (null == messageHolder) {
+ messageHolder = new CompilationMessageHolderImpl();
+ }
+ return messageHolder;
+ }
+
+ public void setCompilationMessageHolder(CompilationMessageHolder messageHolder) {
+ this.messageHolder = messageHolder;
+ }
+
     private void setInterfaceUnit(InterfaceUnit interfaceUnit) {
         this.interfaceUnit = interfaceUnit;
     }
@@ -263,7 +280,7 @@
             } else {
                 this.startUnit(new TagUnit(this.tagLibrary, qname[0], qname[1], t, this.nextTagId()));
             }
- } else if (this.tagLibrary.containsNamespace(qname[0])) {
+ } else if (this.tagLibrary.containsNamespace(qname[0], t)) {
             throw new TagException(orig, "Tag Library supports namespace: "+qname[0]+", but no tag was defined for name: "+qname[1]);
         } else {
             TextUnit unit;
@@ -314,6 +331,7 @@
         }
     }
 
+
     public void pushNamespace(String prefix, String uri) {
 
         if (log.isLoggable(Level.FINE)) {
@@ -452,7 +470,7 @@
         int remove = 0;
         for (int i = 0; i < attr.length; i++) {
             if (attr[i].getQName().startsWith("xmlns")
- && this.tagLibrary.containsNamespace(attr[i].getValue())) {
+ && this.tagLibrary.containsNamespace(attr[i].getValue(), null)) {
                 remove |= 1 << i;
                 if (log.isLoggable(Level.FINE)) {
                     log.fine(attr[i] + " Namespace Bound to TagLibrary");
Index: jsf-ri/src/com/sun/faces/facelets/compiler/CompilationMessageHolder.java
===================================================================
--- jsf-ri/src/com/sun/faces/facelets/compiler/CompilationMessageHolder.java (revision 0)
+++ jsf-ri/src/com/sun/faces/facelets/compiler/CompilationMessageHolder.java (revision 0)
@@ -0,0 +1,68 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common Development
+ * and Distribution License("CDDL") (collectively, the "License"). You
+ * may not use this file except in compliance with the License. You can obtain
+ * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
+ * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
+ * language governing permissions and limitations under the License.
+ *
+ * When distributing the software, include this License Header Notice in each
+ * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
+ * Sun designates this particular file as subject to the "Classpath" exception
+ * as provided by Sun in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the License
+ * Header, with the fields enclosed by brackets [] replaced by your own
+ * identifying information: "Portions Copyrighted [year]
+ * [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by only the CDDL or
+ * only the GPL Version 2, indicate your decision by adding "[Contributor]
+ * elects to include this software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice of license, a
+ * recipient has the option to distribute your version of this file under
+ * either the CDDL, the GPL Version 2 or to extend the choice of license to
+ * its licensees as provided above. However, if you add GPL Version 2 code
+ * and therefore, elected the GPL Version 2 license, then the option applies
+ * only if the new code is made subject to such option by the copyright
+ * holder.
+ */
+
+package com.sun.faces.facelets.compiler;
+
+import java.util.List;
+import javax.faces.application.FacesMessage;
+import javax.faces.context.FacesContext;
+
+/*
+ * The CompilationManager vends one of these
+ * to store compilation messages for later use. During page compilation,
+ * if any messages need to be shown to the user, they will be
+ * added using this interface. If, during page execution,
+ * the messages turn out not to be needed, as is the case with
+ * a foreign xml element nested within a <composite:extension> element,
+ * this interface can be used to remove the messages.
+ *
+ * Currently the messages are keyed by namespace prefix.
+ *
+ * The EncodingHandler class is always the outermost FaceletHandler in any
+ * Facelet compilation unit. Therefore, this handler is used
+ * to anchor the implementation of the CompilationMessageHolder so
+ * other tags can access it. See EncodingHandler for how to do it.
+ *
+ */
+public interface CompilationMessageHolder {
+
+ public List<FacesMessage> getNamespacePrefixMessages(FacesContext context, String prefix);
+
+ public void removeNamespacePrefixMessages(String prefix);
+
+ public void processCompilationMessages(FacesContext context);
+
+}
Index: jsf-ri/src/com/sun/faces/facelets/compiler/Compiler.java
===================================================================
--- jsf-ri/src/com/sun/faces/facelets/compiler/Compiler.java (revision 6279)
+++ jsf-ri/src/com/sun/faces/facelets/compiler/Compiler.java (working copy)
@@ -171,10 +171,10 @@
         return null;
     }
 
- public final TagLibrary createTagLibrary() {
+ public final TagLibrary createTagLibrary(CompilationMessageHolder unit) {
         if (this.libraries.size() > 0) {
             return new CompositeTagLibrary((TagLibrary[]) this.libraries
- .toArray(new TagLibrary[this.libraries.size()]));
+ .toArray(new TagLibrary[this.libraries.size()]), unit);
         }
         return EMPTY_LIBRARY;
     }
Index: jsf-ri/src/com/sun/faces/facelets/compiler/EncodingHandler.java
===================================================================
--- jsf-ri/src/com/sun/faces/facelets/compiler/EncodingHandler.java (revision 6279)
+++ jsf-ri/src/com/sun/faces/facelets/compiler/EncodingHandler.java (working copy)
@@ -65,16 +65,30 @@
 
     private final FaceletHandler next;
     private final String encoding;
+ private final CompilationMessageHolder messageHolder;
     
- public EncodingHandler(FaceletHandler next, String encoding) {
+ public EncodingHandler(FaceletHandler next, String encoding,
+ CompilationMessageHolder messageHolder) {
         this.next = next;
         this.encoding = encoding;
+ this.messageHolder = messageHolder;
     }
 
     public void apply(FaceletContext ctx, UIComponent parent)
             throws IOException, FacesException, FaceletException, ELException {
+ ctx.getFacesContext().getAttributes().put("facelets.compilationMessages", this.messageHolder);
         this.next.apply(ctx, parent);
+ ctx.getFacesContext().getAttributes().remove("facelets.compilationMessages");
+ this.messageHolder.processCompilationMessages(ctx.getFacesContext());
         ctx.getFacesContext().getAttributes().put("facelets.Encoding", this.encoding);
     }
+
+ public static CompilationMessageHolder getCompilationMessageHolder(FaceletContext ctx) {
+ CompilationMessageHolder result = null;
+
+ result = (CompilationMessageHolder) ctx.getFacesContext().getAttributes().get("facelets.compilationMessages");
 
+ return result;
+ }
+
 }
Index: jsf-ri/src/com/sun/faces/facelets/compiler/SAXCompiler.java
===================================================================
--- jsf-ri/src/com/sun/faces/facelets/compiler/SAXCompiler.java (revision 6279)
+++ jsf-ri/src/com/sun/faces/facelets/compiler/SAXCompiler.java (working copy)
@@ -280,7 +280,11 @@
                 is.close();
             }
         }
- return new EncodingHandler(mngr.createFaceletHandler(), encoding);
+ FaceletHandler result = new EncodingHandler(mngr.createFaceletHandler(), encoding,
+ mngr.getCompilationMessageHolder());
+ mngr.setCompilationMessageHolder(null);
+
+ return result;
     }
 
     protected static final String writeXmlDecl(InputStream is, CompilationManager mngr)
Index: jsf-ri/src/com/sun/faces/facelets/tag/TagLibrary.java
===================================================================
--- jsf-ri/src/com/sun/faces/facelets/tag/TagLibrary.java (revision 6279)
+++ jsf-ri/src/com/sun/faces/facelets/tag/TagLibrary.java (working copy)
@@ -56,6 +56,7 @@
 import java.lang.reflect.Method;
 
 import javax.faces.FacesException;
+import javax.faces.webapp.pdl.facelets.tag.Tag;
 
 /**
  * A library of Tags associated with one or more namespaces.
@@ -66,22 +67,24 @@
 public interface TagLibrary {
 
     /**
- * If this library contains the passed namespace
+ * true if the namespace is used in this library
      *
      * @param ns
      * namespace
- * @return true if the namespace is used in this library
+ * @param t the tag instance currently active at the time
+ * this method is called. May be null
+
      */
- public boolean containsNamespace(String ns);
+ public boolean containsNamespace(String ns, Tag t);
 
     /**
- * If this library contains a TagHandler for the namespace and local name
+ * If this library contains a TagHandler for the namespace and local name true if handled by this library
      *
      * @param ns
      * namespace
      * @param localName
      * local name
- * @return true if handled by this library
+ * @return
      */
     public boolean containsTagHandler(String ns, String localName);
 
Index: jsf-ri/src/com/sun/faces/facelets/tag/composite/DeclareFacetHandler.java
===================================================================
--- jsf-ri/src/com/sun/faces/facelets/tag/composite/DeclareFacetHandler.java (revision 6279)
+++ jsf-ri/src/com/sun/faces/facelets/tag/composite/DeclareFacetHandler.java (working copy)
@@ -161,6 +161,7 @@
             propertyDescriptor.setValue("default", ve);
         }
         
+ this.nextHandler.apply(ctx, parent);
         
     }
 
Index: jsf-ri/src/com/sun/faces/facelets/tag/composite/AttributeHandler.java
===================================================================
--- jsf-ri/src/com/sun/faces/facelets/tag/composite/AttributeHandler.java (revision 6279)
+++ jsf-ri/src/com/sun/faces/facelets/tag/composite/AttributeHandler.java (working copy)
@@ -168,7 +168,7 @@
             propertyDescriptor.setValue("targets", ve);
         }
         
-
+ this.nextHandler.apply(ctx, parent);
         
     }
 
Index: jsf-ri/src/com/sun/faces/facelets/tag/composite/AttachedObjectTargetHandler.java
===================================================================
--- jsf-ri/src/com/sun/faces/facelets/tag/composite/AttachedObjectTargetHandler.java (revision 6279)
+++ jsf-ri/src/com/sun/faces/facelets/tag/composite/AttachedObjectTargetHandler.java (working copy)
@@ -121,6 +121,8 @@
             target.setTargetsList(ve);
         }
         
+ this.nextHandler.apply(ctx, parent);
+
     }
 
 }
Index: jsf-ri/src/com/sun/faces/facelets/tag/composite/ExtensionHandler.java
===================================================================
--- jsf-ri/src/com/sun/faces/facelets/tag/composite/ExtensionHandler.java (revision 0)
+++ jsf-ri/src/com/sun/faces/facelets/tag/composite/ExtensionHandler.java (revision 0)
@@ -0,0 +1,82 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common Development
+ * and Distribution License("CDDL") (collectively, the "License"). You
+ * may not use this file except in compliance with the License. You can obtain
+ * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
+ * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
+ * language governing permissions and limitations under the License.
+ *
+ * When distributing the software, include this License Header Notice in each
+ * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
+ * Sun designates this particular file as subject to the "Classpath" exception
+ * as provided by Sun in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the License
+ * Header, with the fields enclosed by brackets [] replaced by your own
+ * identifying information: "Portions Copyrighted [year]
+ * [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by only the CDDL or
+ * only the GPL Version 2, indicate your decision by adding "[Contributor]
+ * elects to include this software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice of license, a
+ * recipient has the option to distribute your version of this file under
+ * either the CDDL, the GPL Version 2 or to extend the choice of license to
+ * its licensees as provided above. However, if you add GPL Version 2 code
+ * and therefore, elected the GPL Version 2 license, then the option applies
+ * only if the new code is made subject to such option by the copyright
+ * holder.
+ */
+
+package com.sun.faces.facelets.tag.composite;
+
+import com.sun.faces.facelets.compiler.CompilationMessageHolder;
+import com.sun.faces.facelets.compiler.EncodingHandler;
+import java.io.IOException;
+import javax.el.ELException;
+import javax.faces.FacesException;
+import javax.faces.component.UIComponent;
+import javax.faces.webapp.pdl.facelets.FaceletContext;
+import javax.faces.webapp.pdl.facelets.FaceletException;
+import javax.faces.webapp.pdl.facelets.tag.TagConfig;
+import javax.faces.webapp.pdl.facelets.tag.TagHandler;
+
+/**
+ *
+ * @author edburns
+ */
+public class ExtensionHandler extends TagHandler {
+
+ public ExtensionHandler(TagConfig arg0) {
+ super(arg0);
+ }
+
+ public void apply(FaceletContext ctx, UIComponent arg1) throws IOException, FacesException, FaceletException, ELException {
+ // extract a prefix from the child content
+ if (null != nextHandler) {
+ String content = this.nextHandler.toString().trim();
+ if (content.startsWith("<")) {
+ int i;
+ if (-1 != (i = content.indexOf(":"))) {
+ content = content.substring(1, i);
+ CompilationMessageHolder messageHolder = EncodingHandler.getCompilationMessageHolder(ctx);
+ // remove any compilation messages pertaining to this prefix
+ if (null != messageHolder) {
+ messageHolder.removeNamespacePrefixMessages(content);
+ }
+ }
+ }
+ }
+
+ }
+
+
+
+
+}
Index: jsf-ri/src/com/sun/faces/facelets/tag/composite/CompositeLibrary.java
===================================================================
--- jsf-ri/src/com/sun/faces/facelets/tag/composite/CompositeLibrary.java (revision 6279)
+++ jsf-ri/src/com/sun/faces/facelets/tag/composite/CompositeLibrary.java (working copy)
@@ -72,6 +72,7 @@
         // Things that go insead of the interface section
         this.addTagHandler("attribute", AttributeHandler.class);
         this.addTagHandler("deferred-value", DeferredValueHandler.class);
+ this.addTagHandler("extension", ExtensionHandler.class);
         this.addTagHandler("type", TypeHandler.class);
         this.addTagHandler("deferred-method", DeferredMethodHandler.class);
         this.addTagHandler("method-signature", MethodSignatureHandler.class);
Index: jsf-ri/src/com/sun/faces/facelets/tag/CompositeTagLibrary.java
===================================================================
--- jsf-ri/src/com/sun/faces/facelets/tag/CompositeTagLibrary.java (revision 6279)
+++ jsf-ri/src/com/sun/faces/facelets/tag/CompositeTagLibrary.java (working copy)
@@ -51,6 +51,7 @@
 
 package com.sun.faces.facelets.tag;
 
+import com.sun.faces.facelets.compiler.CompilationMessageHolder;
 import javax.faces.webapp.pdl.facelets.tag.TagHandler;
 import javax.faces.webapp.pdl.facelets.tag.TagConfig;
 import com.sun.faces.facelets.tag.jsf.CompositeComponentTagLibrary;
@@ -60,11 +61,13 @@
 
 import com.sun.faces.util.Util;
 
-import java.util.HashMap;
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Map;
 import javax.faces.application.FacesMessage;
 import javax.faces.application.ProjectStage;
 import javax.faces.context.FacesContext;
+import javax.faces.webapp.pdl.facelets.tag.Tag;
 
 /**
  * A TagLibrary that is composed of 1 or more TagLibrary children. Uses the
@@ -77,21 +80,27 @@
 public final class CompositeTagLibrary implements TagLibrary {
 
     private TagLibrary[] libraries;
+ private CompilationMessageHolder messageHolder;
 
- public CompositeTagLibrary(TagLibrary[] libraries) {
+ public CompositeTagLibrary(TagLibrary[] libraries, CompilationMessageHolder unit) {
         Util.notNull("libraries", libraries);
         this.libraries = libraries;
+ this.messageHolder = unit;
     }
 
+ public CompositeTagLibrary(TagLibrary[] libraries) {
+ this(libraries, null);
+ }
+
     /*
      * (non-Javadoc)
      *
      * @see com.sun.facelets.tag.TagLibrary#containsNamespace(java.lang.String)
      */
- public boolean containsNamespace(String ns) {
+ public boolean containsNamespace(String ns, Tag t) {
         boolean result = true;
         for (int i = 0; i < this.libraries.length; i++) {
- if (this.libraries[i].containsNamespace(ns)) {
+ if (this.libraries[i].containsNamespace(ns, null)) {
                 return true;
             }
         }
@@ -112,12 +121,20 @@
         else {
             FacesContext context = FacesContext.getCurrentInstance();
             if (ProjectStage.Development == context.getApplication().getProjectStage()) {
- if (!ns.equals("http://www.w3.org/1999/xhtml")) {
- if (!getNamespaceMessageMap(context).containsKey(ns)) {
- context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN,
+ if (null != t &&
+ !ns.equals("http://www.w3.org/1999/xhtml")) {
+ // messageHolder will only be null in the case of the private
+ // EMPTY_LIBRARY class variable of the Compiler class.
+ // This code will never be called on that CompositeTagLibrary
+ // instance.
+ assert(null != this.messageHolder);
+ String prefix = getPrefixFromTag(t);
+ if (null != prefix) {
+ List<FacesMessage> prefixMessages = this.messageHolder.getNamespacePrefixMessages(context, prefix);
+ prefixMessages.add(new FacesMessage(FacesMessage.SEVERITY_WARN,
                                 "Warning: This page calls for XML namespace " + ns +
+ " declared with prefix " + prefix +
                                 " but no taglibrary exists for that namespace.", ""));
- getNamespaceMessageMap(context).put(ns, Boolean.TRUE);
                     }
                 }
             }
@@ -125,18 +142,17 @@
         return false;
     }
     
- private Map<String,Boolean> getNamespaceMessageMap(FacesContext context) {
- Map<String, Boolean> result = null;
-
- if (null == (result = (Map<String,Boolean>)
- context.getAttributes().get("facelets.namespaceMessageMap"))) {
- result = new HashMap<String,Boolean>();
- context.getAttributes().put("facelets.namespaceMessageMap", result);
+ private String getPrefixFromTag(Tag t) {
+ String result = t.getQName();
+ if (null != result) {
+ int i;
+ if (-1 != (i = result.indexOf(":"))) {
+ result = result.substring(0, i);
+ }
         }
-
         return result;
     }
-
+
     /*
      * (non-Javadoc)
      *
Index: jsf-ri/src/com/sun/faces/facelets/tag/AbstractTagLibrary.java
===================================================================
--- jsf-ri/src/com/sun/faces/facelets/tag/AbstractTagLibrary.java (revision 6279)
+++ jsf-ri/src/com/sun/faces/facelets/tag/AbstractTagLibrary.java (working copy)
@@ -530,7 +530,7 @@
      *
      * @see com.sun.facelets.tag.TagLibrary#containsNamespace(java.lang.String)
      */
- public boolean containsNamespace(String ns) {
+ public boolean containsNamespace(String ns, Tag t) {
         return this.namespace.equals(ns);
     }
 
Index: jsf-ri/src/com/sun/faces/facelets/tag/jstl/fn/JstlFnLibrary.java
===================================================================
--- jsf-ri/src/com/sun/faces/facelets/tag/jstl/fn/JstlFnLibrary.java (revision 6279)
+++ jsf-ri/src/com/sun/faces/facelets/tag/jstl/fn/JstlFnLibrary.java (working copy)
@@ -61,6 +61,7 @@
 import javax.faces.webapp.pdl.facelets.tag.TagConfig;
 import javax.faces.webapp.pdl.facelets.tag.TagHandler;
 import com.sun.faces.facelets.tag.TagLibrary;
+import javax.faces.webapp.pdl.facelets.tag.Tag;
 
 /**
  * Library for JSTL Functions
@@ -88,7 +89,7 @@
         }
     }
 
- public boolean containsNamespace(String ns) {
+ public boolean containsNamespace(String ns, Tag t) {
         return Namespace.equals(ns);
     }
 
Index: jsf-ri/src/com/sun/faces/util/Util.java
===================================================================
--- jsf-ri/src/com/sun/faces/util/Util.java (revision 6279)
+++ jsf-ri/src/com/sun/faces/util/Util.java (working copy)
@@ -437,20 +437,55 @@
             // and search for a match in the faceletsViewMappings
             for (j = 0; j < faceletsViewMappings.length; j++) {
                 if (null != faceletsViewMappings[j]) {
+ // If this is a prefix mapping, it would have been
+ // handled before getting this far. Therefore, we
+ // can skip prefix mapped entries.
+ if (faceletsViewMappings[j].startsWith("/")) {
+ continue;
+ }
+ // Look for an exact match
                     if (true == (foundMatch =
                             faceletsViewMappings[j].equals(candidateViewId))) {
                         break;
                     } else {
- // If we didn't find a match in the faceletsViewMappings
- // look for a physical resource with that name
- try {
- if (extContext.getResource(candidateViewId) != null) {
- // RELEASE_PENDING (rlubke,driscoll) cache the lookup
- requestViewId = candidateViewId;
- foundMatch = true;
- break;
+ // We don't have an exact match.
+ // PENDING(rlubke): do a more robust wild card
+ // matching thing here.
+ if (faceletsViewMappings[j].startsWith("*.")) {
+ String
+ faceletsViewCopy = faceletsViewMappings[j],
+ candidateCopy = candidateViewId;
+ if (-1 == (i = candidateCopy.lastIndexOf(".")) || 0 == i) {
+ assert(false);
                             }
- } catch (MalformedURLException e) {
+ candidateCopy = candidateCopy.substring(0, i);
+ if (-1 == (i = faceletsViewCopy.lastIndexOf(".")) || 0 == i) {
+ assert(false);
+ }
+ faceletsViewCopy = faceletsViewCopy.substring(i);
+ candidateCopy = candidateCopy + faceletsViewCopy;
+ // If we didn't find a match in the faceletsViewMappings
+ // look for a physical resource with that name
+ try {
+ if (extContext.getResource(candidateCopy) != null) {
+ requestViewId = candidateCopy;
+ foundMatch = true;
+ break;
+ }
+ } catch (MalformedURLException e) {
+ }
+ } else {
+ // If we didn't find a match in the faceletsViewMappings
+ // look for a physical resource with that name
+ try {
+ if (extContext.getResource(candidateViewId) != null) {
+ // RELEASE_PENDING (rlubke,driscoll) cache the lookup
+ requestViewId = candidateViewId;
+ foundMatch = true;
+ break;
+ }
+ } catch (MalformedURLException e) {
+ }
                         }
                     }
                 }
Index: jsf-ri/systest/src/com/sun/faces/component/CompositeMetaDataTestCase.java
===================================================================
--- jsf-ri/systest/src/com/sun/faces/component/CompositeMetaDataTestCase.java (revision 0)
+++ jsf-ri/systest/src/com/sun/faces/component/CompositeMetaDataTestCase.java (revision 0)
@@ -0,0 +1,99 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common Development
+ * and Distribution License("CDDL") (collectively, the "License"). You
+ * may not use this file except in compliance with the License. You can obtain
+ * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
+ * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
+ * language governing permissions and limitations under the License.
+ *
+ * When distributing the software, include this License Header Notice in each
+ * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
+ * Sun designates this particular file as subject to the "Classpath" exception
+ * as provided by Sun in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the License
+ * Header, with the fields enclosed by brackets [] replaced by your own
+ * identifying information: "Portions Copyrighted [year]
+ * [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by only the CDDL or
+ * only the GPL Version 2, indicate your decision by adding "[Contributor]
+ * elects to include this software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice of license, a
+ * recipient has the option to distribute your version of this file under
+ * either the CDDL, the GPL Version 2 or to extend the choice of license to
+ * its licensees as provided above. However, if you add GPL Version 2 code
+ * and therefore, elected the GPL Version 2 license, then the option applies
+ * only if the new code is made subject to such option by the copyright
+ * holder.
+ */
+
+package com.sun.faces.component;
+
+import com.sun.faces.htmlunit.AbstractTestCase;
+import com.gargoylesoftware.htmlunit.html.HtmlPage;
+import com.gargoylesoftware.htmlunit.html.HtmlSubmitInput;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class CompositeMetaDataTestCase extends AbstractTestCase {
+
+ public CompositeMetaDataTestCase(String name) {
+ super(name);
+ }
+
+
+ /**
+ * Set up instance variables required by this test case.
+ */
+ public void setUp() throws Exception {
+ super.setUp();
+ }
+
+
+ /**
+ * Return the tests included in this test suite.
+ */
+ public static Test suite() {
+ return (new TestSuite(CompositeMetaDataTestCase.class));
+ }
+
+
+ /**
+ * Tear down instance variables required by this test case.
+ */
+ public void tearDown() {
+ super.tearDown();
+ }
+
+
+ /**
+ * Added for issue 10
+ *
+ * @throws Exception
+ */
+ public void testPrefixMappedFaceletPage() throws Exception {
+
+ HtmlPage page = getPage("/faces/resources/composite/jsr276Correct01.xhtml");
+ String text = page.asText();
+ assertTrue(-1 != text.indexOf("composite component with correctly specified jsr276 metadata"));
+ }
+
+ public void testExtensionMappedFaceletPage() throws Exception {
+
+ HtmlPage page = getPage("/composite/jsr276-using.faces");
+ String text = page.asText();
+ assertTrue(-1 != text.indexOf("composite component with correctly specified jsr276 metadata"));
+ assertTrue(-1 != text.indexOf("composite component with incorrectly specified jsr276 metadata"));
+ assertTrue(-1 == text.indexOf("prefix fmd"));
+ assertTrue(-1 != text.indexOf("prefix metaData"));
+ }
+
+
+} // end of class PathTestCase
Index: jsf-ri/systest/web/composite/jsr276-using.xhtml
===================================================================
--- jsf-ri/systest/web/composite/jsr276-using.xhtml (revision 0)
+++ jsf-ri/systest/web/composite/jsr276-using.xhtml (revision 0)
@@ -0,0 +1,71 @@
+<!--
+
+ DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+
+ Copyright 1997-2008 Sun Microsystems, Inc. All rights reserved.
+
+ The contents of this file are subject to the terms of either the GNU
+ General Public License Version 2 only ("GPL") or the Common Development
+ and Distribution License("CDDL") (collectively, the "License"). You
+ may not use this file except in compliance with the License. You can obtain
+ a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
+ or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
+ language governing permissions and limitations under the License.
+
+ When distributing the software, include this License Header Notice in each
+ file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
+ Sun designates this particular file as subject to the "Classpath" exception
+ as provided by Sun in the GPL Version 2 section of the License file that
+ accompanied this code. If applicable, add the following below the License
+ Header, with the fields enclosed by brackets [] replaced by your own
+ identifying information: "Portions Copyrighted [year]
+ [name of copyright owner]"
+
+ Contributor(s):
+
+ If you wish your version of this file to be governed by only the CDDL or
+ only the GPL Version 2, indicate your decision by adding "[Contributor]
+ elects to include this software in this distribution under the [CDDL or GPL
+ Version 2] license." If you don't indicate a single choice of license, a
+ recipient has the option to distribute your version of this file under
+ either the CDDL, the GPL Version 2 or to extend the choice of license to
+ its licensees as provided above. However, if you add GPL Version 2 code
+ and therefore, elected the GPL Version 2 license, then the option applies
+ only if the new code is made subject to such option by the copyright
+ holder.
+
+-->
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:h="http://java.sun.com/jsf/html"
+ xmlns:f="http://java.sun.com/jsf/core"
+ xmlns:ui="http://java.sun.com/jsf/facelets"
+ xmlns:ez="http://java.sun.com/jsf/composite/composite">
+<h:head>
+<title>Using jsr276 in a composite component</title>
+<style type="text/css">
+.grayBox { padding: 8px; margin: 10px 0; border: 1px solid #CCC; background-color: #f9f9f9; }
+</style>
+</h:head>
+
+<h:body>
+
+ <ui:debug hotkey="p" rendered="true"/>
+
+<h:form>
+
+<h1>Correct usage</h1>
+
+ <p><ez:jsr276Correct01 /></p>
+
+<h1>Incorrect usage</h1>
+
+ <p><ez:jsr276Incorrect01 /></p>
+
+
+
+</h:form>
+
+</h:body>
+
+</html>
Index: jsf-ri/systest/web/WEB-INF/web.xml
===================================================================
--- jsf-ri/systest/web/WEB-INF/web.xml (revision 6279)
+++ jsf-ri/systest/web/WEB-INF/web.xml (working copy)
@@ -80,7 +80,7 @@
 
     <context-param>
         <param-name>facelets.VIEW_MAPPINGS</param-name>
- <param-value>*.xhtml</param-value>
+ <param-value>/resources/composite/*;*.xhtml</param-value>
     </context-param>
 
     <context-param>
@@ -89,6 +89,11 @@
     </context-param>
 
     <context-param>
+ <param-name>javax.faces.PROJECT_STAGE</param-name>
+ <param-value>Development</param-value>
+ </context-param>
+
+ <context-param>
         <param-name>javax.faces.FACELETS_LIBRARIES</param-name>
         <param-value>/WEB-INF/source1.taglib.xml</param-value>
     </context-param>
@@ -114,6 +119,12 @@
         <url-pattern>/faces/*</url-pattern>
     </servlet-mapping>
 
+ <servlet-mapping>
+ <servlet-name>Faces Servlet</servlet-name>
+ <url-pattern>*.faces</url-pattern>
+ </servlet-mapping>
+
+
     <env-entry>
         <env-entry-name>welcomeMessage</env-entry-name>
         <env-entry-type>java.lang.String</env-entry-type>
Index: jsf-ri/systest/web/resources/composite/jsr276Incorrect01.xhtml
===================================================================
--- jsf-ri/systest/web/resources/composite/jsr276Incorrect01.xhtml (revision 0)
+++ jsf-ri/systest/web/resources/composite/jsr276Incorrect01.xhtml (revision 0)
@@ -0,0 +1,70 @@
+<!--
+
+ DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+
+ Copyright 1997-2008 Sun Microsystems, Inc. All rights reserved.
+
+ The contents of this file are subject to the terms of either the GNU
+ General Public License Version 2 only ("GPL") or the Common Development
+ and Distribution License("CDDL") (collectively, the "License"). You
+ may not use this file except in compliance with the License. You can obtain
+ a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
+ or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
+ language governing permissions and limitations under the License.
+
+ When distributing the software, include this License Header Notice in each
+ file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
+ Sun designates this particular file as subject to the "Classpath" exception
+ as provided by Sun in the GPL Version 2 section of the License file that
+ accompanied this code. If applicable, add the following below the License
+ Header, with the fields enclosed by brackets [] replaced by your own
+ identifying information: "Portions Copyrighted [year]
+ [name of copyright owner]"
+
+ Contributor(s):
+
+ If you wish your version of this file to be governed by only the CDDL or
+ only the GPL Version 2, indicate your decision by adding "[Contributor]
+ elects to include this software in this distribution under the [CDDL or GPL
+ Version 2] license." If you don't indicate a single choice of license, a
+ recipient has the option to distribute your version of this file under
+ either the CDDL, the GPL Version 2 or to extend the choice of license to
+ its licensees as provided above. However, if you add GPL Version 2 code
+ and therefore, elected the GPL Version 2 license, then the option applies
+ only if the new code is made subject to such option by the copyright
+ holder.
+
+-->
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:h="http://java.sun.com/jsf/html"
+ xmlns:f="http://java.sun.com/jsf/core"
+ xmlns:ui="http://java.sun.com/jsf/facelets"
+ xmlns:metaData="http://java.sun.com/xml/ns/javaee/faces/design-time-metadata"
+ xmlns:composite="http://java.sun.com/jsf/composite">
+<head>
+
+<title>Not present in rendered output</title>
+
+</head>
+
+<body>
+
+<composite:interface name="jsr276">
+
+ <composite:attribute name="pinLabel" default="PIN">
+ <metaData:expert>true</metaData:expert>
+ </composite:attribute>
+
+</composite:interface>
+
+<composite:implementation>
+
+ <p class="grayBox">composite component with incorrectly specified jsr276
+ metadata</p>
+
+</composite:implementation>
+
+</body>
+
+</html>
Index: jsf-ri/systest/web/resources/composite/jsr276Correct01.xhtml
===================================================================
--- jsf-ri/systest/web/resources/composite/jsr276Correct01.xhtml (revision 0)
+++ jsf-ri/systest/web/resources/composite/jsr276Correct01.xhtml (revision 0)
@@ -0,0 +1,72 @@
+<!--
+
+ DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+
+ Copyright 1997-2008 Sun Microsystems, Inc. All rights reserved.
+
+ The contents of this file are subject to the terms of either the GNU
+ General Public License Version 2 only ("GPL") or the Common Development
+ and Distribution License("CDDL") (collectively, the "License"). You
+ may not use this file except in compliance with the License. You can obtain
+ a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
+ or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
+ language governing permissions and limitations under the License.
+
+ When distributing the software, include this License Header Notice in each
+ file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
+ Sun designates this particular file as subject to the "Classpath" exception
+ as provided by Sun in the GPL Version 2 section of the License file that
+ accompanied this code. If applicable, add the following below the License
+ Header, with the fields enclosed by brackets [] replaced by your own
+ identifying information: "Portions Copyrighted [year]
+ [name of copyright owner]"
+
+ Contributor(s):
+
+ If you wish your version of this file to be governed by only the CDDL or
+ only the GPL Version 2, indicate your decision by adding "[Contributor]
+ elects to include this software in this distribution under the [CDDL or GPL
+ Version 2] license." If you don't indicate a single choice of license, a
+ recipient has the option to distribute your version of this file under
+ either the CDDL, the GPL Version 2 or to extend the choice of license to
+ its licensees as provided above. However, if you add GPL Version 2 code
+ and therefore, elected the GPL Version 2 license, then the option applies
+ only if the new code is made subject to such option by the copyright
+ holder.
+
+-->
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:h="http://java.sun.com/jsf/html"
+ xmlns:f="http://java.sun.com/jsf/core"
+ xmlns:ui="http://java.sun.com/jsf/facelets"
+ xmlns:fmd="http://java.sun.com/xml/ns/javaee/faces/design-time-metadata"
+ xmlns:composite="http://java.sun.com/jsf/composite">
+<head>
+
+<title>Not present in rendered output</title>
+
+</head>
+
+<body>
+
+<composite:interface name="jsr276">
+
+ <composite:attribute name="pinLabel" default="PIN">
+ <composite:extension>
+ <fmd:expert>true</fmd:expert>
+ </composite:extension>
+ </composite:attribute>
+
+</composite:interface>
+
+<composite:implementation>
+
+ <p class="grayBox">composite component with correctly specified jsr276
+ metadata</p>
+
+</composite:implementation>
+
+</body>
+
+</html>
Index: jsf-demo/ezcomp02/src/main/webapp/resources/ezcomp/loginPanel.xhtml
===================================================================
--- jsf-demo/ezcomp02/src/main/webapp/resources/ezcomp/loginPanel.xhtml (revision 6279)
+++ jsf-demo/ezcomp02/src/main/webapp/resources/ezcomp/loginPanel.xhtml (working copy)
@@ -40,6 +40,7 @@
       xmlns:h="http://java.sun.com/jsf/html"
       xmlns:f="http://java.sun.com/jsf/core"
       xmlns:ui="http://java.sun.com/jsf/facelets"
+ xmlns:fmd="http://java.sun.com/xml/ns/javaee/faces/design-time-metadata"
       xmlns:composite="http://java.sun.com/jsf/composite">
 <head>
 
@@ -56,7 +57,11 @@
                      shortDescription="An illustration of the composite component feature">
 
   <composite:attribute name="usernameLabel" default="Username" />
- <composite:attribute name="pinLabel" default="PIN" />
+ <composite:attribute name="pinLabel" default="PIN">
+ <composite:extension>
+ <fmd:expert>true</fmd:expert>
+ </composite:extension>
+ </composite:attribute>
   <composite:attribute name="loginLabel" default="Login" />
   <composite:attribute name="model" required="true"/>
   <composite:attribute name="action" method-signature="java.lang.Object action()" targets="loginEvent"/>
@@ -67,6 +72,7 @@
   <composite:editableValueHolder name="allInputs" targets="usernameInput pinInput" />
   <composite:actionSource name="loginEvent" />
 
+
 </composite:interface>
 
 <composite:implementation>



-- 
| ed.burns_at_sun.com  | office: 408 884 9519 OR x31640
| homepage:         | http://ridingthecrest.com/