[jsr-314-open-mirror] [jsr-314-open] 490-XmlViews Processing JSPX files as Facelets

Kito Mann kito.mann at virtua.com
Wed Oct 6 11:35:24 EDT 2010


This sounds fine, but I'm worried about introducing configuration in
faces-config.xml that might ordinarily be in web.xml without a plan for how
we handle existing parameters. Consistency is really important, especially
for frameworks, and adding the configuration for this feature to
faces-config.xml opens the door to having half of the configuration in
faces-config.xml and half in web.xml with no obvious justification other
than "these parameters are newer".

So I think we should implement this as a standard web.xml context parameter,
_or_ provide faces-config.xml support for all existing context parameters.

---
Kito D. Mann | twitter: kito99 | Author, JSF in Action
Virtua, Inc. | http://www.virtua.com | JSF/Java EE training and consulting
http://www.JSFCentral.com - JavaServer Faces FAQ, news, and info | twitter:
jsfcentral
+1 203-404-4848 x3

Sign up for the JSFCentral newsletter: http://oi.vresp.com/?fid=ac048d0e17



On Thu, Sep 30, 2010 at 11:22 PM, Edward Burns <edward.burns at oracle.com>wrote:

>
> https://javaserverfaces-spec-public.dev.java.net/issues/show_bug.cgi?id=490
>
> As a first step towards making JSPX files runable as Facelets, this
> commit introduces a new configuration syntax.
>
> Andy Schwartz requested this feature.
>
> For the first time ever, we are using the faces-config to specify
> context-param like configuration options.  In this case, we're
> leveraging the faces-config-extension facility.  Andy also suggested
> this config concept.
>
> The automated test for this feature has the following faces-config.
>
> <?xml version='1.0' encoding='UTF-8'?>
> <faces-config
>  xmlns="http://java.sun.com/xml/ns/javaee"
>  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
>  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
> http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd"
>  version="2.0">
>
>  <faces-config-extension>
>    <facelets-processing>
>      <file-extension>.jspx</file-extension>
>      <process-as>jspx</process-as>
>    </facelets-processing>
>    <facelets-processing>
>      <file-extension>.view.xml</file-extension>
>      <process-as>xml</process-as>
>    </facelets-processing>
>  </faces-config-extension>
>
> </faces-config>
>
> The <facelets-processing> elements are new.
>
> The sample app also has these context params:
>
>    <context-param>
>        <param-name>javax.faces.FACELETS_VIEW_MAPPINGS</param-name>
>        <param-value>*.xhtml;*.view.xml;*.jspx</param-value>
>    </context-param>
>
>    <context-param>
>        <param-name>javax.faces.DEFAULT_SUFFIX</param-name>
>        <param-value>.xhtml .view.xml .jsp .jspx</param-value>
>    </context-param>
>
> PENDING(edburns): Currently this feature relies on the existing
> <xsd:any> declaration for the children of faces-config-extension.  I
> would like to tighten this up to allow validaiton but will do it after
> the 30 Sept deadline.
>
> The preceding faces-config and web.xml example must cause the
> implementation to behave as follows.
>
>  The web.xml says that jspx should be considered as one of the default
>  suffixes for JSF.  It also says that files with a .jspx extension must
>  be treated as facelets, not JSPs.
>
>  The faces-config.xml says that files with the .jspx extension should be
>  treated as if they are running in Facelets for JSPX mode, as specified
>  in the following table.  It also says that files ending in .view.xml
>  must be handled as if they are running in Facelets for XML mode, also
>  specified in the table.
>
>
>  XML construct               process-as mode
>  -------------               ---------------
>
>                         xhtml           xml        jspx
> XML Declaration          passed through  consumed   consumed
> Processing Instructions  passed through  consumed   consumed
> CDATA                    passed through  consumed   consumed
> Inline text escaping     escaped         escaped    not escaped
> Comments                 passed through  consumed   consumed
>
> PENDING(edburns): should the table specified above be the default, even
> if no facelets-processing elements appear?  Right now, the
> facelets-processing elements must appear, otherwise the legacy facelets
> format is used in all facelet cases.  I think that's correct, but I am
> open to suggestions.
>
> SECTION: Modified Files
> ----------------------------
> M       jsf-ri/src/main/java/com/sun/faces/config/WebConfiguration.java
>
> - enhance this class, which previously only handled web.xml style
>  configuration, to also handle faces-config.xml style
>  configuration. The first manifestation of this is the new pair of
>  getFacesConfigOptionValue() methods, one with a boolean create
>  parameter.
>
> - To make the intent of the feature more clear, a define a read-only
>  singleton helper class, FaceletsConfiguration, which is owned by the
>  WebConfiguration.
>
> A
> jsf-ri/src/main/java/com/sun/faces/config/FaceletsConfiguration.java
>
> - A place to hang methods that allow the runtime to query the facelets
>  configuration.  Currently this only includes config options conveyed
>  via the new faces-config-extension/facelets-processing elements.
>
> M
> jsf-ri/src/main/java/com/sun/faces/facelets/compiler/LiteralTextInstruction.java
>
> - When writing inline text, use the new config facility to determine if
>  the text should be escaped or not.
>
> M
> jsf-ri/src/main/java/com/sun/faces/facelets/compiler/CompilationManager.java
>
> - add some ivars and getters.
>
> M       jsf-ri/src/main/java/com/sun/faces/facelets/compiler/TextUnit.java
>
> - To ease migration from JSPX to facelets, allow the new <faces-view>
>  markup element to exist in XHTML or XML pages, but make sure it gets
>  swallowed and does not appear in the output.  The startTag() and
>  endTag() methods were hit.
>
> M jsf-ri/src/main/java/com/sun/faces/facelets/compiler/SAXCompiler.java
>
> - Take the correct action regarding CDATA, comments,
>  processingInstructions, and the XML declaration.
>
> M       jsf-ri/src/main/java/com/sun/faces/facelets/tag/xml/XmlLibrary.java
>
> - Clean imports
>
> M       jsf-ri/src/main/java/com/sun/faces/config/ConfigManager.java
>
> - Add a new config processor for the faces-config-extension content.
>
> M       jsf-ri/src/main/java/com/sun/faces/config/ConfigureListener.java
> M       jsf-ri/systest-per-webapp/build.xml
> M       jsf-ri/systest-per-webapp/build-tests.xml
>
> - new automated test
>
> A
> jsf-ri/src/main/java/com/sun/faces/config/processor/FacesConfigExtensionProcessor.java
>
> - expose xml config to runtime.
>
> A       jsf-ri/systest-per-webapp/process-as-jspx
> A       jsf-ri/systest-per-webapp/process-as-jspx/src
> A       jsf-ri/systest-per-webapp/process-as-jspx/src/java
> A       jsf-ri/systest-per-webapp/process-as-jspx/src/java/com
> A       jsf-ri/systest-per-webapp/process-as-jspx/src/java/com/sun
> A       jsf-ri/systest-per-webapp/process-as-jspx/src/java/com/sun/faces
> A jsf-ri/systest-per-webapp/process-as-jspx/src/java/com/sun/faces/systest
> A
> jsf-ri/systest-per-webapp/process-as-jspx/src/java/com/sun/faces/systest/ProcessAsJspxTestCase.java
> A
> jsf-ri/systest-per-webapp/process-as-jspx/src/java/com/sun/faces/systest/ProcessAsJspxBean.java
> A       jsf-ri/systest-per-webapp/process-as-jspx/web
> A       jsf-ri/systest-per-webapp/process-as-jspx/web/jspxview.jspx
> A       jsf-ri/systest-per-webapp/process-as-jspx/web/xhtmlview.xhtml
> A       jsf-ri/systest-per-webapp/process-as-jspx/web/jspview.jsp
> A       jsf-ri/systest-per-webapp/process-as-jspx/web/xmlview.view.xml
> A       jsf-ri/systest-per-webapp/process-as-jspx/web/WEB-INF
> A jsf-ri/systest-per-webapp/process-as-jspx/web/WEB-INF/faces-config.xml
> A       jsf-ri/systest-per-webapp/process-as-jspx/web/WEB-INF/web.xml
> A       jsf-ri/systest-per-webapp/process-as-jspx/web/index.html
>
> - Automated test.
>
>
> SECTION: Diffs
> ----------------------------
> Index:
> jsf-ri/src/main/java/com/sun/faces/facelets/compiler/LiteralTextInstruction.java
> ===================================================================
> ---
> jsf-ri/src/main/java/com/sun/faces/facelets/compiler/LiteralTextInstruction.java
> (revision 8624)
> +++
> jsf-ri/src/main/java/com/sun/faces/facelets/compiler/LiteralTextInstruction.java
> (working copy)
> @@ -55,10 +55,11 @@
>
>  package com.sun.faces.facelets.compiler;
>
> +import com.sun.faces.config.FaceletsConfiguration;
> +import javax.faces.context.FacesContext;
> +import java.io.IOException;
>  import javax.el.ELContext;
>  import javax.el.ExpressionFactory;
> -import javax.faces.context.FacesContext;
> -import java.io.IOException;
>
>  final class LiteralTextInstruction implements Instruction {
>     private final String text;
> @@ -68,7 +69,11 @@
>     }
>
>     public void write(FacesContext context) throws IOException {
> -        context.getResponseWriter().writeText(this.text, null);
> +        if
> (FaceletsConfiguration.getInstance(context).isEscapeInlineText(context)) {
> +            context.getResponseWriter().writeText(this.text, null);
> +        } else {
> +            context.getResponseWriter().write(this.text);
> +        }
>     }
>
>     public Instruction apply(ExpressionFactory factory, ELContext ctx) {
> Index:
> jsf-ri/src/main/java/com/sun/faces/facelets/compiler/CompilationManager.java
> ===================================================================
> ---
> jsf-ri/src/main/java/com/sun/faces/facelets/compiler/CompilationManager.java
> (revision 8624)
> +++
> jsf-ri/src/main/java/com/sun/faces/facelets/compiler/CompilationManager.java
> (working copy)
> @@ -56,6 +56,7 @@
>
>  package com.sun.faces.facelets.compiler;
>
> +import com.sun.faces.config.WebConfiguration;
>  import com.sun.faces.facelets.tag.TagAttributesImpl;
>  import com.sun.faces.facelets.tag.TagLibrary;
>  import com.sun.faces.facelets.tag.composite.CompositeLibrary;
> @@ -102,6 +103,8 @@
>     private final String alias;
>
>     private CompilationMessageHolder messageHolder = null;
> +
> +    private WebConfiguration config;
>
>     public CompilationManager(String alias, Compiler compiler) {
>
> @@ -125,6 +128,8 @@
>         // our compilationunit stack
>         this.units = new Stack<CompilationUnit>();
>         this.units.push(new CompilationUnit());
> +
> +        config = WebConfiguration.getInstance();
>
>     }
>
> @@ -139,6 +144,14 @@
>         }
>         return messageHolder;
>     }
> +
> +    public String getAlias() {
> +        return alias;
> +    }
> +
> +    public WebConfiguration getWebConfiguration() {
> +        return config;
> +    }
>
>     public void setCompilationMessageHolder(CompilationMessageHolder
> messageHolder) {
>         this.messageHolder = messageHolder;
> Index: jsf-ri/src/main/java/com/sun/faces/facelets/compiler/TextUnit.java
> ===================================================================
> --- jsf-ri/src/main/java/com/sun/faces/facelets/compiler/TextUnit.java
> (revision 8624)
> +++ jsf-ri/src/main/java/com/sun/faces/facelets/compiler/TextUnit.java
> (working copy)
> @@ -54,13 +54,16 @@
>
>  package com.sun.faces.facelets.compiler;
>
> +import com.sun.faces.config.FaceletsConfiguration;
>  import com.sun.faces.facelets.el.ELText;
>
>  import javax.el.ELException;
>  import javax.faces.view.facelets.*;
>  import java.util.ArrayList;
>  import java.util.List;
> +import java.util.Map;
>  import java.util.Stack;
> +import java.util.concurrent.ConcurrentHashMap;
>
>  /**
>  *
> @@ -85,6 +88,14 @@
>
>     private final String id;
>
> +    private final static Map<String, Boolean> qNamesToSwallow;
> +
> +
> +    static {
> +        qNamesToSwallow = new ConcurrentHashMap<String, Boolean>(1);
> +        qNamesToSwallow.put("faces-view", Boolean.TRUE);
> +    }
> +
>     public TextUnit(String alias, String id) {
>         this.alias = alias;
>         this.id = id;
> @@ -168,16 +179,16 @@
>     public void writeComment(String text) {
>         this.finishStartTag();
>
> -        ELText el = ELText.parse(text);
> -        if (el.isLiteral()) {
> -            this.addInstruction(new LiteralCommentInstruction(text));
> -        } else {
> -            this.addInstruction(new CommentInstruction(el));
> +            ELText el = ELText.parse(text);
> +            if (el.isLiteral()) {
> +                this.addInstruction(new LiteralCommentInstruction(text));
> +            } else {
> +                this.addInstruction(new CommentInstruction(el));
> +            }
> +
> +            this.buffer.append("<!--" + text + "-->");
>         }
>
> -        this.buffer.append("<!--" + text + "-->");
> -    }
> -
>     public void startTag(Tag tag) {
>
>         // finish any previously written tags
> @@ -185,36 +196,39 @@
>
>         // push this tag onto the stack
>         this.tags.push(tag);
> +        String qName = tag.getQName();
>
> -        // write it out
> -        this.buffer.append('<');
> -        this.buffer.append(tag.getQName());
> +        if (!qNamesToSwallow.containsKey(qName)) {
> +            // write it out
> +            this.buffer.append('<');
> +            this.buffer.append(qName);
>
> -        this.addInstruction(new StartElementInstruction(tag.getQName()));
> +            this.addInstruction(new
> StartElementInstruction(tag.getQName()));
>
> -        TagAttribute[] attrs = tag.getAttributes().getAll();
> -        if (attrs.length > 0) {
> -            for (int i = 0; i < attrs.length; i++) {
> -                String qname = attrs[i].getQName();
> -                String value = attrs[i].getValue();
> -                this.buffer.append('
> ').append(qname).append("=\"").append(
> +            TagAttribute[] attrs = tag.getAttributes().getAll();
> +            if (attrs.length > 0) {
> +                for (int i = 0; i < attrs.length; i++) {
> +                    String qname = attrs[i].getQName();
> +                    String value = attrs[i].getValue();
> +                    this.buffer.append('
> ').append(qname).append("=\"").append(
>                         value).append("\"");
>
> -                ELText txt = ELText.parse(value);
> -                if (txt != null) {
> -                    if (txt.isLiteral()) {
> -                        this.addInstruction(new
> LiteralAttributeInstruction(
> -                                qname, txt.toString()));
> -                    } else {
> -                        this.addInstruction(new AttributeInstruction(
> -                                this.alias, qname, txt));
> +                    ELText txt = ELText.parse(value);
> +                    if (txt != null) {
> +                        if (txt.isLiteral()) {
> +                            this.addInstruction(new
> LiteralAttributeInstruction(
> +                                    qname, txt.toString()));
> +                        } else {
> +                            this.addInstruction(new AttributeInstruction(
> +                                    this.alias, qname, txt));
> +                        }
>                     }
>                 }
>             }
> +            // notify that we have an open tag
> +            this.startTagOpen = true;
>         }
>
> -        // notify that we have an open tag
> -        this.startTagOpen = true;
>     }
>
>     private void finishStartTag() {
> @@ -227,13 +241,17 @@
>     public void endTag() {
>         Tag tag = (Tag) this.tags.pop();
>
> -        this.addInstruction(new EndElementInstruction(tag.getQName()));
> +        String qName = tag.getQName();
>
> -        if (this.startTagOpen) {
> -            this.buffer.append("/>");
> -            this.startTagOpen = false;
> -        } else {
> -            this.buffer.append("</").append(tag.getQName()).append('>');
> +        if (!qNamesToSwallow.containsKey(qName)) {
> +            this.addInstruction(new EndElementInstruction(qName));
> +
> +            if (this.startTagOpen) {
> +                this.buffer.append("/>");
> +                this.startTagOpen = false;
> +            } else {
> + this.buffer.append("</").append(tag.getQName()).append('>');
> +            }
>         }
>     }
>
> Index:
> jsf-ri/src/main/java/com/sun/faces/facelets/compiler/SAXCompiler.java
> ===================================================================
> --- jsf-ri/src/main/java/com/sun/faces/facelets/compiler/SAXCompiler.java
> (revision 8624)
> +++ jsf-ri/src/main/java/com/sun/faces/facelets/compiler/SAXCompiler.java
> (working copy)
> @@ -55,6 +55,7 @@
>  package com.sun.faces.facelets.compiler;
>
>  import com.sun.faces.RIConstants;
> +import com.sun.faces.config.FaceletsConfiguration;
>  import com.sun.faces.config.WebConfiguration;
>  import com.sun.faces.facelets.tag.TagAttributeImpl;
>  import com.sun.faces.facelets.tag.TagAttributesImpl;
> @@ -71,6 +72,7 @@
>  import java.io.IOException;
>  import java.io.InputStream;
>  import java.net.URL;
> +import java.util.Map;
>  import java.util.regex.Matcher;
>  import java.util.regex.Pattern;
>
> @@ -96,6 +98,8 @@
>         protected Locator locator;
>
>         protected final CompilationManager unit;
> +
> +        private boolean inSuppressedCDATA;
>
>         public CompilationHandler(CompilationManager unit, String alias) {
>             this.unit = unit;
> @@ -105,14 +109,18 @@
>         public void characters(char[] ch, int start, int length)
>                 throws SAXException {
>             if (this.inDocument) {
> -                this.unit.writeText(new String(ch, start, length));
> +                if (!inSuppressedCDATA) {
> +                    this.unit.writeText(new String(ch, start, length));
> +                }
>             }
>         }
>
>         public void comment(char[] ch, int start, int length)
>                 throws SAXException {
>             if (this.inDocument) {
> -                this.unit.writeComment(new String(ch, start, length));
> +                if
> (!unit.getWebConfiguration().getFaceletsConfiguration().isConsumeComments(alias))
> {
> +                    this.unit.writeComment(new String(ch, start, length));
> +                }
>             }
>         }
>
> @@ -134,7 +142,10 @@
>
>         public void endCDATA() throws SAXException {
>             if (this.inDocument) {
> -                this.unit.writeInstruction("]]>");
> +                if
> (!unit.getWebConfiguration().getFaceletsConfiguration().isConsumeCDATA(alias))
> {
> +                    this.unit.writeInstruction("]]>");
> +                }
> +                this.inSuppressedCDATA = false;
>             }
>         }
>
> @@ -192,7 +203,12 @@
>
>         public void startCDATA() throws SAXException {
>             if (this.inDocument) {
> -                this.unit.writeInstruction("<![CDATA[");
> +                if
> (!unit.getWebConfiguration().getFaceletsConfiguration().isConsumeCDATA(alias))
> {
> +                    inSuppressedCDATA = false;
> +                    this.unit.writeInstruction("<![CDATA[");
> +                } else {
> +                    inSuppressedCDATA = true;
> +                }
>             }
>         }
>
> @@ -241,10 +257,18 @@
>         public void processingInstruction(String target, String data)
>                 throws SAXException {
>             if (this.inDocument) {
> -                StringBuffer sb = new StringBuffer(64);
> -                sb.append("<?").append(target).append('
> ').append(data).append(
> -                        "?>\n");
> -                this.unit.writeInstruction(sb.toString());
> +
> +                // If there is a process-as value for the extension, only
> allow
> +                // the PI to be written if its value is xhtml
> +                boolean processAsXhtml =
> +
> this.unit.getWebConfiguration().getFaceletsConfiguration().isProcessCurrentDocumentAsFaceletsXhtml(alias);
> +
> +                if (processAsXhtml) {
> +                    StringBuffer sb = new StringBuffer(64);
> +                    sb.append("<?").append(target).append('
> ').append(data).append(
> +                            "?>\n");
> +                    this.unit.writeInstruction(sb.toString());
> +                }
>             }
>         }
>     }
> @@ -418,8 +442,16 @@
>                 String r = new String(b);
>                 Matcher m = XmlDeclaration.matcher(r);
>                 if (m.find()) {
> -                    WebConfiguration config =
> WebConfiguration.getInstance();
> -                    if
> (!config.isOptionEnabled(WebConfiguration.BooleanWebContextInitParameter.SuppressXmlDeclaration))
> {
> +                    WebConfiguration config = mngr.getWebConfiguration();
> +                    FaceletsConfiguration faceletsConfig =
> config.getFaceletsConfiguration();
> +                    boolean suppressXmlDeclIsEnabled =
> config.isOptionEnabled(WebConfiguration.BooleanWebContextInitParameter.SuppressXmlDeclaration);
> +                    boolean currentModeIsXhtml =
> faceletsConfig.isProcessCurrentDocumentAsFaceletsXhtml(mngr.getAlias());
> +
> +                    // We want to write the XML declaration if and only if
> +                    // The SuppressXmlDeclaration context-param is NOT
> enabled
> +                    // and the file extension for the current file has a
> mapping
> +                    // with the value of XHTML
> +                    if (!suppressXmlDeclIsEnabled && currentModeIsXhtml) {
>                         mngr.writeInstruction(m.group(0) + "\n");
>                         if (m.group(3) != null) {
>                             encoding = m.group(3);
> Index: jsf-ri/src/main/java/com/sun/faces/facelets/tag/xml/XmlLibrary.java
> ===================================================================
> --- jsf-ri/src/main/java/com/sun/faces/facelets/tag/xml/XmlLibrary.java
> (revision 8624)
> +++ jsf-ri/src/main/java/com/sun/faces/facelets/tag/xml/XmlLibrary.java
> (working copy)
> @@ -54,7 +54,6 @@
>
>  package com.sun.faces.facelets.tag.xml;
>
> -import com.sun.faces.facelets.tag.composite.*;
>  import com.sun.faces.facelets.tag.AbstractTagLibrary;
>
>  /**
> Index:
> jsf-ri/src/main/java/com/sun/faces/config/processor/FacesConfigExtensionProcessor.java
> ===================================================================
> ---
> jsf-ri/src/main/java/com/sun/faces/config/processor/FacesConfigExtensionProcessor.java
> (revision 0)
> +++
> jsf-ri/src/main/java/com/sun/faces/config/processor/FacesConfigExtensionProcessor.java
> (revision 0)
> @@ -0,0 +1,183 @@
> +/*
> + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
> + *
> + * Copyright 1997-2010 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.config.processor;
> +
> +import com.sun.faces.config.DocumentInfo;
> +import com.sun.faces.config.WebConfiguration;
> +import com.sun.faces.util.FacesLogger;
> +import org.w3c.dom.Element;
> +import org.w3c.dom.Node;
> +import org.w3c.dom.NodeList;
> +import org.w3c.dom.Document;
> +
> +import javax.servlet.ServletContext;
> +
> +import java.text.MessageFormat;
> +import java.util.Map;
> +import java.util.logging.Level;
> +import java.util.logging.Logger;
> +
> +
> +/**
> + * <p>
> + *  This <code>ConfigProcessor</code> handles all elements defined under
> + *  <code>/faces-config/factory</code>.
> + * </p>
> + */
> +public class FacesConfigExtensionProcessor extends AbstractConfigProcessor
> {
> +
> +    private static final Logger LOGGER = FacesLogger.CONFIG.getLogger();
> +
> +    /**
> +     * <code>/faces-config/faces-config-extension</code>
> +     */
> +    private static final String FACES_CONFIG_EXTENSION =
> "faces-config-extension";
> +
> +    /**
> +     *
> <code>/faces-config/faces-config-extension/facelets-processing</code>
> +     */
> +    private static final String FACELETS_PROCESSING =
> "facelets-processing";
> +
> +    /**
> +     *
> <code>/faces-config/faces-config-extension/facelets-processing/file-extension</code>
> +     */
> +    private static final String FILE_EXTENSION = "file-extension";
> +
> +    /**
> +     *
> <code>/faces-config/faces-config-extension/facelets-processing/process-as</code>
> +     */
> +    private static final String PROCESS_AS = "process-as";
> +
> +    // ------------------------------------------------------------
> Constructors
> +
> +
> +    public FacesConfigExtensionProcessor() { }
> +
> +
> +    // -------------------------------------------- Methods from
> ConfigProcessor
> +
> +
> +    /**
> +     * @see
> ConfigProcessor#process(javax.servlet.ServletContext,com.sun.faces.config.DocumentInfo[])
> +     */
> +    public void process(ServletContext sc, DocumentInfo[] documentInfos)
> +    throws Exception {
> +
> +        for (int i = 0; i < documentInfos.length; i++) {
> +            if (LOGGER.isLoggable(Level.FINE)) {
> +                LOGGER.log(Level.FINE,
> +                           MessageFormat.format(
> +                                "Processing faces-config-extension
> elements for document: ''{0}''",
> +                                documentInfos[i].getSourceURL()));
> +            }
> +            Document document = documentInfos[i].getDocument();
> +            String namespace = document.getDocumentElement()
> +                 .getNamespaceURI();
> +            NodeList facesConfigExtensions = document.getDocumentElement()
> +                 .getElementsByTagNameNS(namespace,
> FACES_CONFIG_EXTENSION);
> +            if (facesConfigExtensions != null &&
> facesConfigExtensions.getLength() > 0) {
> +                processFacesConfigExtensions(facesConfigExtensions,
> +                                 namespace, documentInfos[i]);
> +            }
> +        }
> +
> +        // invoke the next config processor
> +        invokeNext(sc, documentInfos);
> +
> +    }
> +
> +    // --------------------------------------------------------- Private
> Methods
> +
> +
> +    private void processFacesConfigExtensions(NodeList
> facesConfigExtensions,
> +                                  String namespace, DocumentInfo info) {
> +        WebConfiguration config = null;
> +
> +        for (int i = 0, size = facesConfigExtensions.getLength(); i <
> size; i++) {
> +            Node facesConfigExtension = facesConfigExtensions.item(i);
> +            NodeList children = ((Element) facesConfigExtension)
> +                 .getElementsByTagNameNS(namespace, "*");
> +            for (int c = 0, csize = children.getLength(); c < csize; c++)
> {
> +                Node n = children.item(c);
> +                if (FACELETS_PROCESSING.equals(n.getLocalName())) {
> +                    Node faceletsProcessing = n;
> +                    NodeList faceletsProcessingChildren = ((Element)
> faceletsProcessing)
> +                           .getElementsByTagNameNS(namespace, "*");
> +                    String fileExtension = null, processAs = null;
> +                    for (int fp = 0, fpsize =
> faceletsProcessingChildren.getLength(); fp < fpsize; fp++) {
> +                        Node childOfInterset =
> faceletsProcessingChildren.item(fp);
> +                        if (null == fileExtension &&
> + FILE_EXTENSION.equals(childOfInterset.getLocalName())) {
> +                            fileExtension = getNodeText(childOfInterset);
> +                        } else if (null == processAs &&
> + PROCESS_AS.equals(childOfInterset.getLocalName())) {
> +                            processAs = getNodeText(childOfInterset);
> +                        } else {
> +                            if (LOGGER.isLoggable(Level.WARNING)) {
> +                                LOGGER.log(Level.WARNING,
> +                                        MessageFormat.format(
> +                                        "Processing faces-config-extension
> elements for document: ''{0}'', encountered unexpected configuration
> ''{1}'', ignoring and continuing",
> +                                        info.getSourceURL(),
> getNodeText(childOfInterset)));
> +                            }
> +                        }
> +
> +                    }
> +
> +                    if (null != fileExtension && null != processAs) {
> +                        if (null == config) {
> +                            config = WebConfiguration.getInstance();
> +                        }
> +                        Map<String, String> faceletsProcessingMappings =
> +
> config.getFacesConfigOptionValue(WebConfiguration.WebContextInitParameter.FaceletsProcessingFileExtensionProcessAs,
> true);
> +                        faceletsProcessingMappings.put(fileExtension,
> processAs);
> +
> +                    } else {
> +                        if (LOGGER.isLoggable(Level.WARNING)) {
> +                            LOGGER.log(Level.WARNING,
> +                                    MessageFormat.format(
> +                                    "Processing faces-config-extension
> elements for document: ''{0}'', encountered <facelets-processing> elemnet
> without expected children",
> +                                    info.getSourceURL()));
> +                        }
> +                    }
> +                }
> +            }
> +        }
> +
> +    }
> +
> +
> +}
> Index: jsf-ri/src/main/java/com/sun/faces/config/ConfigManager.java
> ===================================================================
> --- jsf-ri/src/main/java/com/sun/faces/config/ConfigManager.java (revision
> 8624)
> +++ jsf-ri/src/main/java/com/sun/faces/config/ConfigManager.java (working
> copy)
> @@ -62,6 +62,7 @@
>  import com.sun.faces.config.processor.RenderKitConfigProcessor;
>  import com.sun.faces.config.processor.ValidatorConfigProcessor;
>  import com.sun.faces.config.processor.FaceletTaglibConfigProcessor;
> +import com.sun.faces.config.processor.FacesConfigExtensionProcessor;
>  import com.sun.faces.util.FacesLogger;
>  import com.sun.faces.util.Timer;
>  import org.xml.sax.InputSource;
> @@ -252,6 +253,7 @@
>              new RenderKitConfigProcessor(),
>              new NavigationConfigProcessor(),
>              new BehaviorConfigProcessor(),
> +             new FacesConfigExtensionProcessor()
>         };
>         for (int i = 0; i < configProcessors.length; i++) {
>             ConfigProcessor p = configProcessors[i];
> Index: jsf-ri/src/main/java/com/sun/faces/config/WebConfiguration.java
> ===================================================================
> --- jsf-ri/src/main/java/com/sun/faces/config/WebConfiguration.java
> (revision 8624)
> +++ jsf-ri/src/main/java/com/sun/faces/config/WebConfiguration.java
> (working copy)
> @@ -40,7 +40,6 @@
>  import java.util.EnumMap;
>  import java.util.Enumeration;
>  import java.util.HashSet;
> -import java.util.List;
>  import java.util.Map;
>  import java.util.Set;
>  import java.util.logging.Level;
> @@ -59,8 +58,10 @@
>
>  import com.sun.faces.util.FacesLogger;
>  import com.sun.faces.util.Util;
> +import java.util.Collections;
>
>  import java.util.HashMap;
> +import java.util.concurrent.ConcurrentHashMap;
>  import javax.faces.component.UIInput;
>  import javax.faces.validator.BeanValidator;
>  import javax.faces.view.facelets.ResourceResolver;
> @@ -90,6 +91,9 @@
>     private Map<WebContextInitParameter, String> contextParameters =
>           new EnumMap<WebContextInitParameter,
> String>(WebContextInitParameter.class);
>
> +    private Map<WebContextInitParameter, Map<String, String>>
> facesConfigParameters =
> +            new EnumMap<WebContextInitParameter, Map<String,
> String>>(WebContextInitParameter.class);
> +
>     private Map<WebEnvironmentEntry, String> envEntries =
>           new EnumMap<WebEnvironmentEntry,
> String>(WebEnvironmentEntry.class);
>
> @@ -101,7 +105,9 @@
>
>     private ArrayList<DeferredLoggingAction> deferredLoggingActions;
>
> +    private FaceletsConfiguration faceletsConfig;
>
> +
>     // ------------------------------------------------------------
> Constructors
>
>
> @@ -228,6 +234,39 @@
>         return result;
>
>     }
> +
> +    public FaceletsConfiguration getFaceletsConfiguration() {
> +
> +        if (null == faceletsConfig) {
> +            faceletsConfig = new FaceletsConfiguration(this);
> +        }
> +        return faceletsConfig;
> +
> +    }
> +
> +    public Map<String, String>
> getFacesConfigOptionValue(WebContextInitParameter param, boolean create) {
> +        Map<String, String> result = null;
> +
> +        assert(null != facesConfigParameters);
> +
> +        result = facesConfigParameters.get(param);
> +        if (null == result) {
> +            if (create) {
> +                result = new ConcurrentHashMap<String, String>(3);
> +                facesConfigParameters.put(param, result);
> +            } else {
> +                result = Collections.emptyMap();
> +            }
> +        }
> +
> +        return result;
> +
> +    }
> +
> +    public Map<String, String>
> getFacesConfigOptionValue(WebContextInitParameter param) {
> +        return getFacesConfigOptionValue(param, false);
> +    }
> +
>
>     public String[] getOptionValue(WebContextInitParameter param, String
> sep) {
>         String [] result;
> @@ -335,7 +374,7 @@
>     }
>
>
> -    public void doLoggingActions() {
> +    public void doPostBringupActions() {
>
>         if (deferredLoggingActions != null) {
>             for (DeferredLoggingAction loggingAction :
> deferredLoggingActions) {
> @@ -892,6 +931,10 @@
>         FaceletCache(
>             "com.sun.faces.faceletCache",
>             ""
> +        ),
> +        FaceletsProcessingFileExtensionProcessAs(
> +                "",
> +                ""
>         );
>
>
> Index: jsf-ri/src/main/java/com/sun/faces/config/FaceletsConfiguration.java
> ===================================================================
> --- jsf-ri/src/main/java/com/sun/faces/config/FaceletsConfiguration.java
> (revision 0)
> +++ jsf-ri/src/main/java/com/sun/faces/config/FaceletsConfiguration.java
> (revision 0)
> @@ -0,0 +1,191 @@
> +
> +/*
> + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
> + *
> + * Copyright 1997-2010 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.config;
> +
> +import java.util.Map;
> +import javax.faces.context.FacesContext;
> +
> +
> +/*
> + * This read-only singleton class is vended by the WebConfiguration.
> + * It is queried from any point in the program that needs to take action
> based
> + * on configuration options pertaining to facelets.
> + *
> + */
> +public class FaceletsConfiguration {
> +
> +    public static final String FACELETS_CONFIGURATION_ATTRIBUTE_NAME =
> "com.sun.faces.config.FaceletsConfiguration";
> +
> +    private static final String ESCAPE_INLINE_TEXT_ATTRIBUTE_NAME =
> "com.sun.faces.config.EscapeInlineText";
> +
> +    private static final String CONSUME_COMMENTS_ATTRIBUTE_NAME =
> "com.sun.faces.config.ConsumeComments";
> +
> +    private WebConfiguration config;
> +
> +    private  Map<String, String> faceletsProcessingMappings;
> +
> +
> +    public FaceletsConfiguration(WebConfiguration config) {
> +        this.config = config;
> +
> +        faceletsProcessingMappings =
> +
> config.getFacesConfigOptionValue(WebConfiguration.WebContextInitParameter.FaceletsProcessingFileExtensionProcessAs);
> +
> +    }
> +
> +    public boolean isProcessCurrentDocumentAsFaceletsXhtml(String alias) {
> +        // We want to write the XML declaration if and only if
> +        // The SuppressXmlDeclaration context-param is NOT enabled
> +        // and the file extension for the current file has a mapping
> +        // with the value of XHTML
> +        boolean currentModeIsXhtml = true;
> +        String extension = alias;
> +        if (null == extension) {
> +            extension = ".xhtml";
> +        }
> +        int i = extension.indexOf(".");
> +        if (-1 != i && 1 < extension.length()) {
> +            extension = extension.substring(i);
> +        } else {
> +            extension = ".xhtml";
> +        }
> +
> +        assert (null != faceletsProcessingMappings);
> +        if (faceletsProcessingMappings.containsKey(extension)) {
> +            String value = faceletsProcessingMappings.get(extension);
> +            currentModeIsXhtml = value.equals("xhtml");
> +        }
> +
> +        return currentModeIsXhtml;
> +    }
> +
> +    public boolean isConsumeComments(String alias) {
> +        boolean consumeComments = false;
> +        String extension = alias;
> +        if (null == extension) {
> +            extension = ".xhtml";
> +        }
> +        int i = extension.indexOf(".");
> +        if (-1 != i && 1 < extension.length()) {
> +            extension = extension.substring(i);
> +        } else {
> +            extension = ".xhtml";
> +        }
> +
> +        assert (null != faceletsProcessingMappings);
> +        if (faceletsProcessingMappings.containsKey(extension)) {
> +            String value = faceletsProcessingMappings.get(extension);
> +            consumeComments = value.equals("xml") || value.equals("jspx");
> +        }
> +
> +        return consumeComments;
> +
> +    }
> +
> +    public boolean isConsumeCDATA(String alias) {
> +        boolean consumeCDATA = false;
> +        String extension = alias;
> +        if (null == extension) {
> +            extension = ".xhtml";
> +        }
> +        int i = extension.indexOf(".");
> +        if (-1 != i && 1 < extension.length()) {
> +            extension = extension.substring(i);
> +        } else {
> +            extension = ".xhtml";
> +        }
> +
> +        assert (null != faceletsProcessingMappings);
> +        if (faceletsProcessingMappings.containsKey(extension)) {
> +            String value = faceletsProcessingMappings.get(extension);
> +            consumeCDATA = value.equals("jspx") || value.equals("xml");
> +        }
> +
> +        return consumeCDATA;
> +
> +    }
> +
> +    public boolean isEscapeInlineText(FacesContext context) {
> +        Boolean result = Boolean.TRUE;
> +
> +        result = (Boolean)
> context.getAttributes().get(ESCAPE_INLINE_TEXT_ATTRIBUTE_NAME);
> +        if (null == result) {
> +            String extension = context.getViewRoot().getViewId();
> +            if (null == extension) {
> +                extension = ".xhtml";
> +            }
> +            int i = extension.indexOf(".");
> +            if (-1 != i && 1 < extension.length()) {
> +                extension = extension.substring(i);
> +            } else {
> +                extension = ".xhtml";
> +            }
> +
> +            assert (null != faceletsProcessingMappings);
> +            if (faceletsProcessingMappings.containsKey(extension)) {
> +                String value = faceletsProcessingMappings.get(extension);
> +                result = value.equals("xml") || value.equals("xhtml");
> +            } else {
> +                result = Boolean.TRUE;
> +            }
> +            context.getAttributes().put(ESCAPE_INLINE_TEXT_ATTRIBUTE_NAME,
> +                    result);
> +        }
> +
> +        return result;
> +    }
> +
> +    public static FaceletsConfiguration getInstance(FacesContext context)
> {
> +        FaceletsConfiguration result = null;
> +        Map<Object, Object> attrs = context.getAttributes();
> +        result = (FaceletsConfiguration)
> attrs.get(FaceletsConfiguration.FACELETS_CONFIGURATION_ATTRIBUTE_NAME);
> +        if (null == result) {
> +            WebConfiguration config =
> WebConfiguration.getInstance(context.getExternalContext());
> +            result = config.getFaceletsConfiguration();
> + attrs.put(FaceletsConfiguration.FACELETS_CONFIGURATION_ATTRIBUTE_NAME,
> result);
> +        }
> +        return result;
> +    }
> +
> +    public static FaceletsConfiguration getInstance() {
> +        FacesContext context = FacesContext.getCurrentInstance();
> +        return FaceletsConfiguration.getInstance(context);
> +    }
> +
> +
> +}
> Index: jsf-ri/src/main/java/com/sun/faces/config/ConfigureListener.java
> ===================================================================
> --- jsf-ri/src/main/java/com/sun/faces/config/ConfigureListener.java
> (revision 8624)
> +++ jsf-ri/src/main/java/com/sun/faces/config/ConfigureListener.java
> (working copy)
> @@ -266,7 +266,7 @@
>                     UIViewRoot.class,
>                     webAppListener);
>
> -            webConfig.doLoggingActions();
> +            webConfig.doPostBringupActions();
>
>         } catch (Throwable t) {
>             if (LOGGER.isLoggable(Level.SEVERE)) {
> Index: jsf-ri/systest-per-webapp/build.xml
> ===================================================================
> --- jsf-ri/systest-per-webapp/build.xml (revision 8624)
> +++ jsf-ri/systest-per-webapp/build.xml (working copy)
> @@ -106,7 +106,8 @@
>                    flash,
>                    jsp-flash,
>                    suppress-xml-decl,
> -                   replace-vdl"/>
> +                   replace-vdl,
> +                   process-as-jspx"/>
>     <!--
>
>        EXCLUDED APPLICATIONS:
> Index: jsf-ri/systest-per-webapp/build-tests.xml
> ===================================================================
> --- jsf-ri/systest-per-webapp/build-tests.xml   (revision 8624)
> +++ jsf-ri/systest-per-webapp/build-tests.xml   (working copy)
> @@ -123,6 +123,8 @@
>
> value="com/sun/faces/systest/replacevdl/ReplaceViewDeclarationLanguageTestCase.class"
> />
>     <property  name="myfaces-uidata-component-state-test"
>
> value="com/sun/faces/systest/myfaces_uidata_component_state_test/MyFacesUIDataTestCase.class"
> />
> +    <property  name="process-as-jspx"
> +               value="com/sun/faces/systest/ProcessAsJspxTestCase.class"
> />
>
>     <!--
>         EXCLUDED APPLICATIONS:
> Index:
> jsf-ri/systest-per-webapp/process-as-jspx/src/java/com/sun/faces/systest/ProcessAsJspxTestCase.java
> ===================================================================
> ---
> jsf-ri/systest-per-webapp/process-as-jspx/src/java/com/sun/faces/systest/ProcessAsJspxTestCase.java
> (revision 0)
> +++
> jsf-ri/systest-per-webapp/process-as-jspx/src/java/com/sun/faces/systest/ProcessAsJspxTestCase.java
> (revision 0)
> @@ -0,0 +1,132 @@
> +/*
> + * 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.systest;
> +
> +
> +import com.gargoylesoftware.htmlunit.html.HtmlPage;
> +import com.sun.faces.htmlunit.AbstractTestCase;
> +import java.io.BufferedReader;
> +import java.io.InputStreamReader;
> +import java.net.URL;
> +import java.util.regex.Pattern;
> +import junit.framework.Test;
> +import junit.framework.TestSuite;
> +
> +
> +public class ProcessAsJspxTestCase extends AbstractTestCase {
> +
> +    private final static Pattern XmlDeclaration =
> Pattern.compile("(?s)^<\\?xml(\\s)*version=.*\\?>.*");
> +    private final static Pattern XmlPI =
> Pattern.compile("(?s).*<\\?xml-stylesheet.*\\?>.*");
> +    private final static Pattern CDATASection =
> Pattern.compile("(?s).*<!\\[CDATA\\[ .*\\]\\]>.*");
> +    private final static Pattern Comment =
> Pattern.compile("(?s).*<!--.*-->.*");
> +    private final static Pattern EscapedText =
> Pattern.compile("(?s).*&amp;lt;context-param&amp;gt;.*");
> +    private final static Pattern NotEscapedText =
> Pattern.compile("(?s).*&lt;context-param&gt;.*");
> +
> +
> +    public ProcessAsJspxTestCase(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(ProcessAsJspxTestCase.class));
> +    }
> +
> +
> +    /**
> +     * Tear down instance variables required by this test case.
> +     */
> +    public void tearDown() {
> +        super.tearDown();
> +    }
> +
> +    private String getRawMarkup(String path) throws Exception {
> +        URL url = getURL(path);
> +        BufferedReader reader = new BufferedReader(new
> InputStreamReader(url.openStream()));
> +        StringBuilder builder = new StringBuilder();
> +        String cur;
> +        while (null != (cur = reader.readLine())) {
> +            builder.append(cur);
> +        }
> +
> +        String xml = builder.toString();
> +        return xml;
> +    }
> +
> +    // ------------------------------------------------------------ Test
> Methods
> +
> +    public void testProcessAsXhtml() throws Exception {
> +
> +        String xml = getRawMarkup("/faces/xhtmlview.xhtml");
> +        assertTrue(XmlDeclaration.matcher(xml).matches());
> +        assertTrue(XmlPI.matcher(xml).matches());
> +        assertTrue(CDATASection.matcher(xml).matches());
> +        assertTrue(EscapedText.matcher(xml).matches());
> +        assertTrue(Comment.matcher(xml).matches());
> +    }
> +
> +    public void testProcessAsXml() throws Exception {
> +
> +        String xml = getRawMarkup("/faces/xmlview.view.xml");
> +        assertFalse(XmlDeclaration.matcher(xml).matches());
> +        assertFalse(XmlPI.matcher(xml).matches());
> +        assertFalse(CDATASection.matcher(xml).matches());
> +        assertTrue(EscapedText.matcher(xml).matches());
> +        assertFalse(Comment.matcher(xml).matches());
> +    }
> +
> +    public void testProcessAsJspx() throws Exception {
> +
> +        String xml = getRawMarkup("/faces/jspxview.jspx");
> +        assertFalse(XmlDeclaration.matcher(xml).matches());
> +        assertFalse(XmlPI.matcher(xml).matches());
> +        assertFalse(CDATASection.matcher(xml).matches());
> +        assertTrue(NotEscapedText.matcher(xml).matches());
> +        assertFalse(Comment.matcher(xml).matches());
> +    }
> +
> +}
> Index:
> jsf-ri/systest-per-webapp/process-as-jspx/src/java/com/sun/faces/systest/ProcessAsJspxBean.java
> ===================================================================
> ---
> jsf-ri/systest-per-webapp/process-as-jspx/src/java/com/sun/faces/systest/ProcessAsJspxBean.java
> (revision 0)
> +++
> jsf-ri/systest-per-webapp/process-as-jspx/src/java/com/sun/faces/systest/ProcessAsJspxBean.java
> (revision 0)
> @@ -0,0 +1,14 @@
> +package com.sun.faces.systest;
> +
> +import javax.faces.bean.ManagedBean;
> +import javax.faces.bean.RequestScoped;
> +
> + at ManagedBean
> + at RequestScoped
> +public class ProcessAsJspxBean {
> +
> +    public String getProp() {
> +       return "Hello < World";
> +    }
> +
> +}
> Index: jsf-ri/systest-per-webapp/process-as-jspx/web/jspxview.jspx
> ===================================================================
> --- jsf-ri/systest-per-webapp/process-as-jspx/web/jspxview.jspx (revision
> 0)
> +++ jsf-ri/systest-per-webapp/process-as-jspx/web/jspxview.jspx (revision
> 0)
> @@ -0,0 +1,67 @@
> +<?xml version='1.0' encoding='utf-8'?>
> +<!-- Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights
> reserved. -->
> +<jsp:root xmlns="http://www.w3.org/1999/xhtml"
> +          xmlns:jsp="http://java.sun.com/JSP/Page"
> +          xmlns:f="http://java.sun.com/jsf/core"
> +          xmlns:h="http://java.sun.com/jsf/html"
> +          version="1.2">
> +  <jsp:directive.page contentType="text/html;charset=utf-8"/>
> +  <f:view>
> +
> +
> +        <f:attribute name="mode" value="index"/>
> +
> +<h2>XML declaration: consumed</h2>
> +
> +<h2>Processing instruction: consumed</h2>
> +
> +<?xml-stylesheet href="funky.xsl" type="text/xml" alternate="yes"?>
> +
> +<h2>CDATA section: consumed</h2>
> +
> +<![CDATA[ <p>This is CDATA</p> ]]>
> +
> +<h2>Inline text escaping: not escaped</h2>
> +
> +
> +                  <code>
> +                    <br/>
> +                    &amp;lt;context-param&amp;gt;
> +                    <br/>
> +
> +&amp;nbsp;&amp;nbsp;&amp;lt;param-name&amp;gt;javax.faces.PARTIAL_STATE_SAVING
>
> +
> +&amp;lt;/param-name&amp;gt;
> +                    <br/>
> +
> +&amp;nbsp;&amp;nbsp;&amp;lt;param-value&amp;gt;true&amp;lt;/param-value&amp;gt
>
> +
> +;
> +                    <br/>
> +                    &amp;lt;/context-param&amp;gt;
> +                  </code>
> +
> +<h2>Comments: consumed</h2>
> +
> +
> +<p>HTML Template Text</p>
> +
> +
> +
> +<p><h:outputText value="#{processAsJspxBean.prop}" /></p>
> +
> +<h:form prependId="false">
> +
> +<h:commandButton value="reload" />
> +
> +</h:form>
> +
> +
> +<!-- comments consumed -->
> +
> +
> +
> +
> +
> +  </f:view>
> +</jsp:root>
> Index: jsf-ri/systest-per-webapp/process-as-jspx/web/xhtmlview.xhtml
> ===================================================================
> --- jsf-ri/systest-per-webapp/process-as-jspx/web/xhtmlview.xhtml (revision
> 0)
> +++ jsf-ri/systest-per-webapp/process-as-jspx/web/xhtmlview.xhtml (revision
> 0)
> @@ -0,0 +1,103 @@
> +<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
> +<!--
> + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
> +
> + Copyright 2009 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">
> +<h:head>
> +    <title>Process JSPX as Facelets for JSPX mode</title>
> +</h:head>
> +<h:body bgcolor="white">
> +
> +<h2>XML declaration: passed through</h2>
> +
> +<h2>Processing instruction: passed through</h2>
> +
> +<?xml-stylesheet href="funky.xsl" type="text/xml" alternate="yes"?>
> +
> +<h2>CDATA section: passed through</h2>
> +
> +<![CDATA[ <h2>This is CDATA</h2> ]]>
> +
> +<h2>Inline text escaping: escaped</h2>
> +
> +                  <code>
> +                    <br/>
> +                    &amp;lt;context-param&amp;gt;
> +                    <br/>
> +
> +&amp;nbsp;&amp;nbsp;&amp;lt;param-name&amp;gt;javax.faces.PARTIAL_STATE_SAVING
>
> +
> +&amp;lt;/param-name&amp;gt;
> +                    <br/>
> +
> +&amp;nbsp;&amp;nbsp;&amp;lt;param-value&amp;gt;true&amp;lt;/param-value&amp;gt
>
> +
> +;
> +                    <br/>
> +                    &amp;lt;/context-param&amp;gt;
> +                  </code>
> +
> +<h2>Comments: passed through</h2>
> +
> +<!-- comments pass through -->
> +
> +<hr />
> +
> +  <h:form prependId="false" id="form1">
> +
> +   <h:panelGrid columns="2" border="1" width="600">
> +
> +     <h:outputText value="column1" />
> +
> +     <h:outputText value="column2" />
> +
> +   </h:panelGrid>
> +
> +   <h2><h:messages id="messages"/></h2>
> +
> +
> +
> +   #{processAsJspxBean.prop}
> +
> +
> +
> +
> +  </h:form>
> +
> +</h:body>
> +</html>
> Index: jsf-ri/systest-per-webapp/process-as-jspx/web/jspview.jsp
> ===================================================================
> --- jsf-ri/systest-per-webapp/process-as-jspx/web/jspview.jsp   (revision
> 0)
> +++ jsf-ri/systest-per-webapp/process-as-jspx/web/jspview.jsp   (revision
> 0)
> @@ -0,0 +1,86 @@
> +<%--
> + 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.
> +--%>
> +
> +<!--
> + Copyright 2004 Sun Microsystems, Inc. All rights reserved.
> + SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
> +-->
> +
> +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
> +<html>
> +  <head>
> +    <title>JSP view</title>
> +    <%@ taglib uri="http://java.sun.com/jsf/core"  prefix="f" %>
> +    <%@ taglib uri="http://java.sun.com/jsf/html"  prefix="h" %>
> +  </head>
> +
> +  <body>
> +<f:view>
> +
> +<p>HTML Template Text</p>
> +
> +<p><h:outputText value="#{processAsJspxBean.prop}" /></p>
> +
> +<h:form prependId="false">
> +
> +<h:commandButton value="reload" />
> +
> +</h:form>
> +
> +                  <code>
> +                    <br/>
> +                    &amp;lt;context-param&amp;gt;
> +                    <br/>
> +
> +&amp;nbsp;&amp;nbsp;&amp;lt;param-name&amp;gt;javax.faces.PARTIAL_STATE_SAVING
>
> +
> +&amp;lt;/param-name&amp;gt;
> +                    <br/>
> +
> +&amp;nbsp;&amp;nbsp;&amp;lt;param-value&amp;gt;true&amp;lt;/param-value&amp;gt
>
> +
> +;
> +                    <br/>
> +                    &amp;lt;/context-param&amp;gt;
> +                  </code>
> +
> +
> +
> +</f:view>
> +
> +    <hr>
> +  </body>
> +</html>
> Index: jsf-ri/systest-per-webapp/process-as-jspx/web/xmlview.view.xml
> ===================================================================
> --- jsf-ri/systest-per-webapp/process-as-jspx/web/xmlview.view.xml
> (revision 0)
> +++ jsf-ri/systest-per-webapp/process-as-jspx/web/xmlview.view.xml
> (revision 0)
> @@ -0,0 +1,103 @@
> +<?xml version="1.0" encoding="UTF-8"?>
> +<!--
> + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
> +
> + Copyright 2010 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.
> +-->
> +<faces-view xmlns="http://www.w3.org/1999/xhtml"
> +            xmlns:h="http://java.sun.com/jsf/html">
> +
> +    <h:html>
> +
> +        <h:head><h:title>Raw XML View</h:title></h:head>
> +
> +        <h:body>
> +
> +<h2>XML declaration: consumed</h2>
> +
> +<h2>Processing instruction: consumed</h2>
> +
> +<?xml-stylesheet href="funky.xsl" type="text/xml" alternate="yes"?>
> +
> +<h2>CDATA section: consumed</h2>
> +
> +<![CDATA[ <p>This is CDATA</p> ]]>
> +
> +<h2>Inline text escaping: escaped</h2>
> +
> +                  <code>
> +                    <br/>
> +                    &amp;lt;context-param&amp;gt;
> +                    <br/>
> +
> +&amp;nbsp;&amp;nbsp;&amp;lt;param-name&amp;gt;javax.faces.PARTIAL_STATE_SAVING
>
> +
> +&amp;lt;/param-name&amp;gt;
> +                    <br/>
> +
> +&amp;nbsp;&amp;nbsp;&amp;lt;param-value&amp;gt;true&amp;lt;/param-value&amp;gt
>
> +
> +;
> +                    <br/>
> +                    &amp;lt;/context-param&amp;gt;
> +                  </code>
> +
> +<h2>Comments: consumed</h2>
> +
> +<!-- comments consumed -->
> +
> +            <h:form prependId="false" id="form">
> +
> +                <h:panelGrid id="grid" column="2">
> +
> +                    <h:outputText id="text" value="hello"></h:outputText>
> +
> +                    <h:commandButton id="button"
> value="reload"></h:commandButton>
> +
> +
> +                </h:panelGrid>
> +
> +   #{processAsJspxBean.prop}
> +
> +<p>html template text</p>
> +
> +
> +            </h:form>
> +
> +        </h:body>
> +
> +    </h:html>
> +
> +</faces-view>
> +
> +
> Index:
> jsf-ri/systest-per-webapp/process-as-jspx/web/WEB-INF/faces-config.xml
> ===================================================================
> --- jsf-ri/systest-per-webapp/process-as-jspx/web/WEB-INF/faces-config.xml
> (revision 0)
> +++ jsf-ri/systest-per-webapp/process-as-jspx/web/WEB-INF/faces-config.xml
> (revision 0)
> @@ -0,0 +1,19 @@
> +<?xml version='1.0' encoding='UTF-8'?>
> +<faces-config
> +  xmlns="http://java.sun.com/xml/ns/javaee"
> +  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
> +  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
> http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd"
> +  version="2.0">
> +
> +  <faces-config-extension>
> +    <facelets-processing>
> +      <file-extension>.jspx</file-extension>
> +      <process-as>jspx</process-as>
> +    </facelets-processing>
> +    <facelets-processing>
> +      <file-extension>.view.xml</file-extension>
> +      <process-as>xml</process-as>
> +    </facelets-processing>
> +  </faces-config-extension>
> +
> +</faces-config>
> Index: jsf-ri/systest-per-webapp/process-as-jspx/web/WEB-INF/web.xml
> ===================================================================
> --- jsf-ri/systest-per-webapp/process-as-jspx/web/WEB-INF/web.xml (revision
> 0)
> +++ jsf-ri/systest-per-webapp/process-as-jspx/web/WEB-INF/web.xml (revision
> 0)
> @@ -0,0 +1,72 @@
> +<?xml version="1.0" encoding="ISO-8859-1"?>
> +
> +<!--
> + 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.
> +-->
> +
> +<web-app version="2.5"
> +         xmlns="http://java.sun.com/xml/ns/javaee"
> +         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
> +         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
> http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
> +
> +    <description>
> +       JSPX Compatibility
> +    </description>
> +    <display-name>JSPX Compatibility</display-name>
> +
> +    <context-param>
> +        <param-name>javax.faces.FACELETS_VIEW_MAPPINGS</param-name>
> +        <param-value>*.xhtml;*.view.xml;*.jspx</param-value>
> +    </context-param>
> +
> +    <context-param>
> +        <param-name>javax.faces.DEFAULT_SUFFIX</param-name>
> +        <param-value>.xhtml .view.xml .jsp .jspx</param-value>
> +    </context-param>
> +
> +    <!-- Faces Servlet -->
> +    <servlet>
> +        <servlet-name>Faces Servlet</servlet-name>
> +        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
> +        <load-on-startup> 1 </load-on-startup>
> +    </servlet>
> +
> +    <!-- Faces Servlet Mapping -->
> +    <servlet-mapping>
> +        <servlet-name>Faces Servlet</servlet-name>
> +        <url-pattern>/faces/*</url-pattern>
> +    </servlet-mapping>
> +
> +</web-app>
> Index: jsf-ri/systest-per-webapp/process-as-jspx/web/index.html
> ===================================================================
> --- jsf-ri/systest-per-webapp/process-as-jspx/web/index.html    (revision
> 0)
> +++ jsf-ri/systest-per-webapp/process-as-jspx/web/index.html    (revision
> 0)
> @@ -0,0 +1,124 @@
> +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
> +<html>
> +  <head>
> +    <title>Test all permutations of facelets processing modes</title>
> +  </head>
> +
> +  <body>
> +    <h1>Test all permutations of facelets processing modes</h1>
> +
> +<table border="1">
> +
> +<tr>
> +
> +<td>&nbsp;
> +</td>
> +
> +<th>xhtml
> +</th>
> +
> +<th>xml
> +</th>
> +
> +<th>jspx
> +</th>
> +
> +</tr>
> +
> +<tr>
> +
> +<th>XML Declaration
> +</th>
> +
> +<td>passed through
> +</td>
> +
> +<td>consumed
> +</td>
> +
> +<td>consumed
> +</td>
> +
> +</tr>
> +
> +<tr>
> +
> +<th>Processing Instructions
> +</th>
> +
> +<td>passed through
> +</td>
> +
> +<td>consumed
> +</td>
> +
> +<td>consumed
> +</td>
> +
> +</tr>
> +
> +<tr>
> +
> +<th>CDATA
> +</th>
> +
> +<td>passed through
> +</td>
> +
> +<td>consumed
> +</td>
> +
> +<td>consumed
> +</td>
> +
> +</tr>
> +
> +<tr>
> +
> +<th>Inline text escaping
> +</th>
> +
> +<td>escaped
> +</td>
> +
> +<td>escaped
> +</td>
> +
> +<td>not escaped
> +</td>
> +
> +</tr>
> +
> +<tr>
> +
> +<th>Comments
> +</th>
> +
> +<td>passed through
> +</td>
> +
> +<td>consumed
> +</td>
> +
> +<td>consumed
> +</td>
> +
> +</tr>
> +
> +
> +</table>
> +
> +
> +
> +<p><a href="/jsf-process-as-jspx/faces/xhtmlview.xhtml">Classic Facelets
> processed as Facelets in XHTML mode</a></p>
> +<p><a href="/jsf-process-as-jspx/faces/xmlview.view.xml">XML processed as
> Facelets in XML mode</a></p>
> +<p><a href="/jsf-process-as-jspx/faces/jspxview.jspx">JSPX processed as
> Facelets in JSPX mode</a></p>
> +<p><a href="/jsf-process-as-jspx/faces/jspview.jsp">JSP processed as
> JSP</a></p>
> +
> +    <hr>
> +<!-- Created: Wed Sep 29 12:17:11 EDT 2010 -->
> +<!-- hhmts start -->
> +Last modified: Thu Sep 30 17:01:18 EDT 2010
> +<!-- hhmts end -->
> +  </body>
> +</html>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.jboss.org/pipermail/jsr-314-open-mirror/attachments/20101006/babe0d86/attachment-0002.html 


More information about the jsr-314-open-mirror mailing list