You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by lu...@apache.org on 2011/11/30 19:04:52 UTC

svn commit: r1208594 - in /myfaces/core/trunk: impl/src/main/java/org/apache/myfaces/renderkit/html/ impl/src/test/java/org/apache/myfaces/renderkit/ shared/src/main/java/org/apache/myfaces/shared/config/ shared/src/main/java/org/apache/myfaces/shared/...

Author: lu4242
Date: Wed Nov 30 18:04:51 2011
New Revision: 1208594

URL: http://svn.apache.org/viewvc?rev=1208594&view=rev
Log:
MYFACES-3412 updated AJAX values sometimes delete other elements

Added:
    myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/renderkit/HtmlRenderKitImplTest.java   (with props)
    myfaces/core/trunk/shared/src/main/java/org/apache/myfaces/shared/renderkit/ContentTypeUtils.java   (with props)
    myfaces/core/trunk/shared/src/test/java/org/apache/myfaces/shared/renderkit/ContentTypeUtilsTest.java   (with props)
Modified:
    myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/renderkit/html/HtmlRenderKitImpl.java
    myfaces/core/trunk/shared/src/main/java/org/apache/myfaces/shared/config/MyfacesConfig.java
    myfaces/core/trunk/shared/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlRendererUtils.java
    myfaces/core/trunk/shared/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlResponseWriterImpl.java

Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/renderkit/html/HtmlRenderKitImpl.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/renderkit/html/HtmlRenderKitImpl.java?rev=1208594&r1=1208593&r2=1208594&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/renderkit/html/HtmlRenderKitImpl.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/renderkit/html/HtmlRenderKitImpl.java Wed Nov 30 18:04:51 2011
@@ -40,6 +40,7 @@ import javax.faces.render.ResponseStateM
 
 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFRenderKit;
 import org.apache.myfaces.shared.config.MyfacesConfig;
+import org.apache.myfaces.shared.renderkit.ContentTypeUtils;
 import org.apache.myfaces.shared.renderkit.html.HtmlRendererUtils;
 import org.apache.myfaces.shared.renderkit.html.HtmlResponseWriterImpl;
 
@@ -223,16 +224,106 @@ public class HtmlRenderKitImpl extends R
     @Override
     public ResponseWriter createResponseWriter(Writer writer, String contentTypeListString, String characterEncoding)
     {
-        String selectedContentType = HtmlRendererUtils.selectContentType(contentTypeListString);
+        FacesContext facesContext = FacesContext.getCurrentInstance();
+        MyfacesConfig myfacesConfig = MyfacesConfig.getCurrentInstance(
+                facesContext.getExternalContext());
+        String selectedContentType = null;
+        String writerContentType = null;
+        boolean isAjaxRequest = facesContext.getPartialViewContext().isAjaxRequest();
+        String contentTypeListStringFromAccept = null;
+
+        // To detect the right contentType, we need to check if the request is an ajax request or not.
+        // If it is an ajax request, HTTP Accept header content type will be set for the ajax itself, which
+        // is application/xml or text/xml. In that case, there are two response writers
+        // (PartialResponseWriterImpl and HtmlResponseWriterImpl),
+        
+        //1. if there is a passed contentTypeListString, it takes precedence over accept header
+        if (contentTypeListString != null)
+        {
+            selectedContentType = ContentTypeUtils.chooseWriterContentType(contentTypeListString, 
+                    ContentTypeUtils.HTML_ALLOWED_CONTENT_TYPES, 
+                    isAjaxRequest ? ContentTypeUtils.AJAX_XHTML_ALLOWED_CONTENT_TYPES :
+                                    ContentTypeUtils.XHTML_ALLOWED_CONTENT_TYPES);
+        }
+
+        //2. If no passed contentTypeListString and no selectedContent
+        //   try to derive it from accept header
+        if (selectedContentType == null && contentTypeListString == null)
+        {
+            contentTypeListStringFromAccept = 
+                ContentTypeUtils.getContentTypeFromAcceptHeader(facesContext);
+            
+            if (contentTypeListStringFromAccept != null)
+            {
+                selectedContentType = ContentTypeUtils.chooseWriterContentType(contentTypeListStringFromAccept,
+                        ContentTypeUtils.HTML_ALLOWED_CONTENT_TYPES, 
+                        isAjaxRequest ? ContentTypeUtils.AJAX_XHTML_ALLOWED_CONTENT_TYPES :
+                                        ContentTypeUtils.XHTML_ALLOWED_CONTENT_TYPES);
+            }
+        }
 
+        //3. if no selectedContentType was derived, set default from the param 
+        if (selectedContentType == null)
+        {
+            if (contentTypeListString == null && contentTypeListStringFromAccept == null)
+            {
+                //If no contentTypeList, return the default
+                selectedContentType = myfacesConfig.getDefaultResponseWriterContentTypeMode();
+            }
+            else
+            {
+                // If a contentTypeList was passed and we don't have direct matches, we still need
+                // to check if */* is found and if that so return the default, otherwise throw
+                // exception.
+                if (contentTypeListString != null)
+                {
+                    String[] contentTypes = ContentTypeUtils.splitContentTypeListString(contentTypeListString);
+                    if (ContentTypeUtils.containsContentType(ContentTypeUtils.ANY_CONTENT_TYPE, contentTypes))
+                    {
+                        selectedContentType = myfacesConfig.getDefaultResponseWriterContentTypeMode();
+                    }
+                }
+                
+                if (contentTypeListStringFromAccept != null)
+                {
+                    String[] contentTypes = ContentTypeUtils.splitContentTypeListString(
+                            contentTypeListStringFromAccept);
+                    if (ContentTypeUtils.containsContentType(ContentTypeUtils.ANY_CONTENT_TYPE, contentTypes))
+                    {
+                        selectedContentType = myfacesConfig.getDefaultResponseWriterContentTypeMode();
+                    }
+                }
+                
+                if (selectedContentType == null)
+                {
+                    throw new IllegalArgumentException(
+                            "ContentTypeList does not contain a supported content type: "
+                                    + contentTypeListString != null ? 
+                                            contentTypeListString : contentTypeListStringFromAccept);
+                }
+            }
+        }
+        if (isAjaxRequest)
+        {
+            // If HTTP Accept header has application/xml or text/xml, that does not means the writer
+            // content type mode should be set to application/xhtml+xml.
+            writerContentType = selectedContentType.indexOf(ContentTypeUtils.XHTML_CONTENT_TYPE) != -1 ?
+                    ContentTypeUtils.XHTML_CONTENT_TYPE : ContentTypeUtils.HTML_CONTENT_TYPE;
+        }
+        else
+        {
+            writerContentType = HtmlRendererUtils.isXHTMLContentType(selectedContentType) ? 
+                    ContentTypeUtils.XHTML_CONTENT_TYPE : ContentTypeUtils.HTML_CONTENT_TYPE;;
+        }
+        
         if (characterEncoding == null)
         {
             characterEncoding = HtmlRendererUtils.DEFAULT_CHAR_ENCODING;
         }
 
         return new HtmlResponseWriterImpl(writer, selectedContentType, characterEncoding, 
-                MyfacesConfig.getCurrentInstance(
-                        FacesContext.getCurrentInstance().getExternalContext()).isWrapScriptContentWithXmlCommentTag());
+                myfacesConfig.isWrapScriptContentWithXmlCommentTag(),
+                        writerContentType);
     }
 
     @Override

Added: myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/renderkit/HtmlRenderKitImplTest.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/renderkit/HtmlRenderKitImplTest.java?rev=1208594&view=auto
==============================================================================
--- myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/renderkit/HtmlRenderKitImplTest.java (added)
+++ myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/renderkit/HtmlRenderKitImplTest.java Wed Nov 30 18:04:51 2011
@@ -0,0 +1,157 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.renderkit;
+
+import java.io.StringWriter;
+
+import junit.framework.Assert;
+
+import org.apache.myfaces.renderkit.html.HtmlRenderKitImpl;
+import org.apache.myfaces.shared.config.MyfacesConfig;
+import org.apache.myfaces.shared.renderkit.ContentTypeUtils;
+import org.apache.myfaces.shared.renderkit.html.HtmlResponseWriterImpl;
+import org.apache.myfaces.test.base.junit4.AbstractJsfTestCase;
+import org.junit.Test;
+
+public class HtmlRenderKitImplTest extends AbstractJsfTestCase
+{
+
+    @Test
+    public void testCreateResponseWriterContentType1()
+    {
+        MyfacesConfig config = new MyfacesConfig();
+        facesContext.getExternalContext().getApplicationMap().put(MyfacesConfig.class.getName(), config);
+        HtmlRenderKitImpl renderKit = new HtmlRenderKitImpl();
+        StringWriter writer = new StringWriter();
+        HtmlResponseWriterImpl responseWriter = (HtmlResponseWriterImpl) renderKit.createResponseWriter(writer, null, null);
+        Assert.assertEquals(ContentTypeUtils.HTML_CONTENT_TYPE, responseWriter.getContentType());
+        Assert.assertEquals(ContentTypeUtils.HTML_CONTENT_TYPE, responseWriter.getWriterContentTypeMode());
+    }
+    
+    @Test
+    public void testCreateResponseWriterContentType2()
+    {
+        MyfacesConfig config = new MyfacesConfig();
+        config.setDefaultResponseWriterContentTypeMode(ContentTypeUtils.XHTML_CONTENT_TYPE);
+        facesContext.getExternalContext().getApplicationMap().put(MyfacesConfig.class.getName(), config);
+        HtmlRenderKitImpl renderKit = new HtmlRenderKitImpl();
+        StringWriter writer = new StringWriter();
+        HtmlResponseWriterImpl responseWriter = (HtmlResponseWriterImpl) renderKit.createResponseWriter(writer, null, null);
+        Assert.assertEquals(ContentTypeUtils.XHTML_CONTENT_TYPE, responseWriter.getContentType());
+        Assert.assertEquals(ContentTypeUtils.XHTML_CONTENT_TYPE, responseWriter.getWriterContentTypeMode());
+    }
+    
+    @Test
+    public void testCreateResponseWriterContentType3()
+    {
+        MyfacesConfig config = new MyfacesConfig();
+        facesContext.getExternalContext().getApplicationMap().put(MyfacesConfig.class.getName(), config);
+        request.addHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"); //Firefox
+        request.addHeader("Faces-Request", "partial/ajax");
+        HtmlRenderKitImpl renderKit = new HtmlRenderKitImpl();
+        StringWriter writer = new StringWriter();
+        HtmlResponseWriterImpl responseWriter = (HtmlResponseWriterImpl) renderKit.createResponseWriter(writer, null, null);
+        Assert.assertEquals(ContentTypeUtils.HTML_CONTENT_TYPE, responseWriter.getContentType());
+        Assert.assertEquals(ContentTypeUtils.HTML_CONTENT_TYPE, responseWriter.getWriterContentTypeMode());
+    }
+    
+    @Test
+    public void testCreateResponseWriterContentType4()
+    {
+        MyfacesConfig config = new MyfacesConfig();
+        facesContext.getExternalContext().getApplicationMap().put(MyfacesConfig.class.getName(), config);
+        request.addHeader("Accept", "application/xml, text/xml, */*; q=0.01"); //Firefox
+        request.addHeader("Faces-Request", "partial/ajax");
+        HtmlRenderKitImpl renderKit = new HtmlRenderKitImpl();
+        StringWriter writer = new StringWriter();
+        HtmlResponseWriterImpl responseWriter = (HtmlResponseWriterImpl) renderKit.createResponseWriter(writer, null, null);
+        Assert.assertEquals(ContentTypeUtils.HTML_CONTENT_TYPE, responseWriter.getContentType());
+        Assert.assertEquals(ContentTypeUtils.HTML_CONTENT_TYPE, responseWriter.getWriterContentTypeMode());
+    }
+    
+    @Test
+    public void testCreateResponseWriterContentType5()
+    {
+        MyfacesConfig config = new MyfacesConfig();
+        facesContext.getExternalContext().getApplicationMap().put(MyfacesConfig.class.getName(), config);
+        request.addHeader("Accept", "application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5"); //Webkit
+        HtmlRenderKitImpl renderKit = new HtmlRenderKitImpl();
+        StringWriter writer = new StringWriter();
+        HtmlResponseWriterImpl responseWriter = (HtmlResponseWriterImpl) renderKit.createResponseWriter(writer, null, null);
+        Assert.assertEquals(ContentTypeUtils.HTML_CONTENT_TYPE, responseWriter.getContentType());
+        Assert.assertEquals(ContentTypeUtils.HTML_CONTENT_TYPE, responseWriter.getWriterContentTypeMode());
+    }
+    
+    @Test(expected=IllegalArgumentException.class)
+    public void testCreateResponseWriterContentType6()
+    {
+        MyfacesConfig config = new MyfacesConfig();
+        facesContext.getExternalContext().getApplicationMap().put(MyfacesConfig.class.getName(), config);
+        request.addHeader("Accept", "image/png"); //Webkit
+        HtmlRenderKitImpl renderKit = new HtmlRenderKitImpl();
+        StringWriter writer = new StringWriter();
+        HtmlResponseWriterImpl responseWriter = (HtmlResponseWriterImpl) renderKit.createResponseWriter(writer, null, null);
+    }
+    
+    @Test
+    public void testCreateResponseWriterContentType7()
+    {
+        MyfacesConfig config = new MyfacesConfig();
+        facesContext.getExternalContext().getApplicationMap().put(MyfacesConfig.class.getName(), config);
+        request.addHeader("Accept", "image/jpeg, application/x-ms-application, image/gif, application/xaml+xml, " +
+        		"image/pjpeg, application/x-ms-xbap, application/x-shockwave-flash, application/msword, */*"); //IE8
+        HtmlRenderKitImpl renderKit = new HtmlRenderKitImpl();
+        StringWriter writer = new StringWriter();
+        HtmlResponseWriterImpl responseWriter = (HtmlResponseWriterImpl) renderKit.createResponseWriter(writer, null, null);
+        Assert.assertEquals(ContentTypeUtils.HTML_CONTENT_TYPE, responseWriter.getContentType());
+        Assert.assertEquals(ContentTypeUtils.HTML_CONTENT_TYPE, responseWriter.getWriterContentTypeMode());
+    }
+    
+    @Test
+    public void testCreateResponseWriterContentType8()
+    {
+        MyfacesConfig config = new MyfacesConfig();
+        facesContext.getExternalContext().getApplicationMap().put(MyfacesConfig.class.getName(), config);
+        request.addHeader("Accept", "text/html, application/xml;q=0.9, application/xhtml+xml;q=0.9, image/png, " +
+        		"image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1"); //Opera
+        HtmlRenderKitImpl renderKit = new HtmlRenderKitImpl();
+        StringWriter writer = new StringWriter();
+        HtmlResponseWriterImpl responseWriter = (HtmlResponseWriterImpl) renderKit.createResponseWriter(writer, null, null);
+        Assert.assertEquals(ContentTypeUtils.HTML_CONTENT_TYPE, responseWriter.getContentType());
+        Assert.assertEquals(ContentTypeUtils.HTML_CONTENT_TYPE, responseWriter.getWriterContentTypeMode());
+    }
+
+    @Test
+    public void testCreateResponseWriterContentType9()
+    {
+        MyfacesConfig config = new MyfacesConfig();
+        facesContext.getExternalContext().getApplicationMap().put(MyfacesConfig.class.getName(), config);
+        request.addHeader("Accept", "image/gif, image/jpeg, image/pjpeg, application/x-ms-application,"+
+                "application/vnd.ms-xpsdocument, application/xaml+xml,"+
+                "application/x-ms-xbap, application/x-shockwave-flash,"+
+                "application/x-silverlight-2-b2, application/x-silverlight,"+
+                "application/vnd.ms-excel, application/vnd.ms-powerpoint,"+
+                "application/msword, */*"); //IE
+        HtmlRenderKitImpl renderKit = new HtmlRenderKitImpl();
+        StringWriter writer = new StringWriter();
+        HtmlResponseWriterImpl responseWriter = (HtmlResponseWriterImpl) renderKit.createResponseWriter(writer, null, null);
+        Assert.assertEquals(ContentTypeUtils.HTML_CONTENT_TYPE, responseWriter.getContentType());
+        Assert.assertEquals(ContentTypeUtils.HTML_CONTENT_TYPE, responseWriter.getWriterContentTypeMode());
+    }
+}

Propchange: myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/renderkit/HtmlRenderKitImplTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: myfaces/core/trunk/shared/src/main/java/org/apache/myfaces/shared/config/MyfacesConfig.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/shared/src/main/java/org/apache/myfaces/shared/config/MyfacesConfig.java?rev=1208594&r1=1208593&r2=1208594&view=diff
==============================================================================
--- myfaces/core/trunk/shared/src/main/java/org/apache/myfaces/shared/config/MyfacesConfig.java (original)
+++ myfaces/core/trunk/shared/src/main/java/org/apache/myfaces/shared/config/MyfacesConfig.java Wed Nov 30 18:04:51 2011
@@ -340,6 +340,16 @@ public class MyfacesConfig
     public final static String INIT_PARAM_STRICT_JSF_2_CC_EL_RESOLVER = "org.apache.myfaces.STRICT_JSF_2_CC_EL_RESOLVER";
     public final static boolean INIT_PARAM_STRICT_JSF_2_CC_EL_RESOLVER_DEFAULT = false;
     
+    /**
+     * Define the default content type that the default ResponseWriter generates, when no match can be derived from
+     * HTTP Accept Header.
+     */
+    @JSFWebConfigParam(since="2.0.11,2.1.5", expectedValues="text/html, application/xhtml+xml", 
+            defaultValue="text/html", group="render")
+    public final static String INIT_PARAM_DEFAULT_RESPONSE_WRITER_CONTENT_TYPE_MODE = 
+        "org.apache.myfaces.DEFAULT_RESPONSE_WRITER_CONTENT_TYPE_MODE";
+    public final static String INIT_PARAM_DEFAULT_RESPONSE_WRITER_CONTENT_TYPE_MODE_DEFAULT = "text/html";
+    
     private boolean _prettyHtml;
     private boolean _detectJavascript;
     private boolean _allowJavascript;
@@ -365,6 +375,7 @@ public class MyfacesConfig
     private boolean _debugPhaseListenerEnabled;
     private boolean _strictJsf2RefreshTargetAjax;
     private boolean _strictJsf2CCELResolver;
+    private String _defaultResponseWriterContentTypeMode;
 
     private static final boolean TOMAHAWK_AVAILABLE;
     private static final boolean MYFACES_IMPL_AVAILABLE;
@@ -459,6 +470,7 @@ public class MyfacesConfig
         setDebugPhaseListenerEnabled(INIT_PARAM_DEBUG_PHASE_LISTENER_DEFAULT);
         setStrictJsf2RefreshTargetAjax(INIT_PARAM_STRICT_JSF_2_REFRESH_TARGET_AJAX_DEFAULT);
         setStrictJsf2CCELResolver(INIT_PARAM_STRICT_JSF_2_CC_EL_RESOLVER_DEFAULT);
+        setDefaultResponseWriterContentTypeMode(INIT_PARAM_DEFAULT_RESPONSE_WRITER_CONTENT_TYPE_MODE_DEFAULT);
     }
 
     private static MyfacesConfig createAndInitializeMyFacesConfig(ExternalContext extCtx)
@@ -547,6 +559,10 @@ public class MyfacesConfig
         
         myfacesConfig.setStrictJsf2CCELResolver(WebConfigParamUtils.getBooleanInitParameter(extCtx, 
                 INIT_PARAM_STRICT_JSF_2_CC_EL_RESOLVER, INIT_PARAM_STRICT_JSF_2_CC_EL_RESOLVER_DEFAULT));
+        
+        myfacesConfig.setDefaultResponseWriterContentTypeMode(WebConfigParamUtils.getStringInitParameter(
+                extCtx, INIT_PARAM_DEFAULT_RESPONSE_WRITER_CONTENT_TYPE_MODE,
+                INIT_PARAM_DEFAULT_RESPONSE_WRITER_CONTENT_TYPE_MODE_DEFAULT));
 
         if (TOMAHAWK_AVAILABLE)
         {
@@ -1003,4 +1019,15 @@ public class MyfacesConfig
     {
         this._strictJsf2CCELResolver = strictJsf2CCELResolver;
     }
+
+    public String getDefaultResponseWriterContentTypeMode()
+    {
+        return _defaultResponseWriterContentTypeMode;
+    }
+
+    public void setDefaultResponseWriterContentTypeMode(
+            String defaultResponseWriterContentTypeMode)
+    {
+        this._defaultResponseWriterContentTypeMode = defaultResponseWriterContentTypeMode;
+    }
 }

Added: myfaces/core/trunk/shared/src/main/java/org/apache/myfaces/shared/renderkit/ContentTypeUtils.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/shared/src/main/java/org/apache/myfaces/shared/renderkit/ContentTypeUtils.java?rev=1208594&view=auto
==============================================================================
--- myfaces/core/trunk/shared/src/main/java/org/apache/myfaces/shared/renderkit/ContentTypeUtils.java (added)
+++ myfaces/core/trunk/shared/src/main/java/org/apache/myfaces/shared/renderkit/ContentTypeUtils.java Wed Nov 30 18:04:51 2011
@@ -0,0 +1,133 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.shared.renderkit;
+
+import javax.faces.context.FacesContext;
+
+import org.apache.myfaces.shared.renderkit.html.HtmlRendererUtils;
+import org.apache.myfaces.shared.util.StringUtils;
+
+/**
+ * 
+ * @author Leonardo Uribe
+ *
+ */
+public class ContentTypeUtils
+{
+    public static final String HTML_CONTENT_TYPE = "text/html";
+    public static final String TEXT_ANY_CONTENT_TYPE = "text/*";
+    public static final String ANY_CONTENT_TYPE = "*/*";
+
+    public static final String[] HTML_ALLOWED_CONTENT_TYPES = {HTML_CONTENT_TYPE, ANY_CONTENT_TYPE, TEXT_ANY_CONTENT_TYPE};
+    
+    public static final String XHTML_CONTENT_TYPE = "application/xhtml+xml";
+    public static final String APPLICATION_XML_CONTENT_TYPE = "application/xml";
+    public static final String TEXT_XML_CONTENT_TYPE = "text/xml";
+    
+    public static final String[] XHTML_ALLOWED_CONTENT_TYPES = {XHTML_CONTENT_TYPE, APPLICATION_XML_CONTENT_TYPE, TEXT_XML_CONTENT_TYPE};
+    
+    public static final String[] AJAX_XHTML_ALLOWED_CONTENT_TYPES = {XHTML_CONTENT_TYPE};
+
+
+    /**
+     * Indicate if the passes content type match one of the options passed. 
+     */
+    public static boolean containsContentType(String contentType, String[] allowedContentTypes)
+    {
+        if (allowedContentTypes == null)
+        {
+            return false;
+        }
+        for (int i = 0; i < allowedContentTypes.length; i++)
+        {
+            if (allowedContentTypes[i].indexOf(contentType) != -1)
+            {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public static String chooseWriterContentType(String contentTypeListString, String[] htmlContentTypes, String[] xhtmlContentTypes)
+    {
+        String[] contentTypeList = splitContentTypeListString(contentTypeListString);
+        String[] supportedContentTypeArray = HtmlRendererUtils.getSupportedContentTypes();
+        String selectedContentType = null;
+        for (int i = 0; i < supportedContentTypeArray.length; i++)
+        {
+            String supportedContentType = supportedContentTypeArray[i].trim();
+
+            for (int j = 0; j < contentTypeList.length; j++)
+            {
+                String contentType = (String) contentTypeList[j];
+
+                if (contentType.indexOf(supportedContentType) != -1)
+                {
+                    if (containsContentType(contentType, htmlContentTypes))
+                    {
+                        selectedContentType = HTML_CONTENT_TYPE;
+                    }
+                    else if (containsContentType(contentType, xhtmlContentTypes))
+                    {
+                        selectedContentType = XHTML_CONTENT_TYPE;
+                    }
+                    break;
+                }
+            }
+            if (selectedContentType != null)
+            {
+                break;
+            }
+        }
+        return selectedContentType;
+    }
+    
+    public static String[] splitContentTypeListString(String contentTypeListString)
+    {
+        String[] splittedArray = StringUtils.splitShortString(contentTypeListString, ',');
+        for (int i = 0; i < splittedArray.length; i++)
+        {
+            int semicolonIndex = splittedArray[i].indexOf(";");
+            if (semicolonIndex != -1)
+            {
+                splittedArray[i] = splittedArray[i].substring(0,semicolonIndex);
+            }
+        }
+        return splittedArray;
+    }
+    
+    public static String getContentTypeFromAcceptHeader(FacesContext context)
+    {
+        String contentTypeListString = (String) context.getExternalContext()
+            .getRequestHeaderMap().get("Accept");
+        // There is a windows mobile IE client (6.12) sending
+        // "application/vnd.wap.mms-message;*/*"
+        // Note that the Accept header should be written as 
+        // "application/vnd.wap.mms-message,*/*" ,
+        // so this is bug of the client. Anyway, this is a workaround ...
+        if (contentTypeListString != null
+                && contentTypeListString
+                        .startsWith("application/vnd.wap.mms-message;*/*"))
+        {
+            contentTypeListString = "*/*";
+        }
+        return contentTypeListString;
+    }
+
+}

Propchange: myfaces/core/trunk/shared/src/main/java/org/apache/myfaces/shared/renderkit/ContentTypeUtils.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: myfaces/core/trunk/shared/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlRendererUtils.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/shared/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlRendererUtils.java?rev=1208594&r1=1208593&r2=1208594&view=diff
==============================================================================
--- myfaces/core/trunk/shared/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlRendererUtils.java (original)
+++ myfaces/core/trunk/shared/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlRendererUtils.java Wed Nov 30 18:04:51 2011
@@ -1652,6 +1652,10 @@ public final class HtmlRendererUtils
             XHTML_CONTENT_TYPE, APPLICATION_XML_CONTENT_TYPE,
             TEXT_XML_CONTENT_TYPE, TEXT_ANY_CONTENT_TYPE, ANY_CONTENT_TYPE };
 
+    /**
+     * @deprecated use ContentTypeUtils instead
+     */
+    @Deprecated
     public static String selectContentType(String contentTypeListString)
     {
         if (contentTypeListString == null)

Modified: myfaces/core/trunk/shared/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlResponseWriterImpl.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/shared/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlResponseWriterImpl.java?rev=1208594&r1=1208593&r2=1208594&view=diff
==============================================================================
--- myfaces/core/trunk/shared/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlResponseWriterImpl.java (original)
+++ myfaces/core/trunk/shared/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlResponseWriterImpl.java Wed Nov 30 18:04:51 2011
@@ -30,6 +30,7 @@ import javax.faces.FacesException;
 import javax.faces.component.UIComponent;
 import javax.faces.context.ResponseWriter;
 
+import org.apache.myfaces.shared.renderkit.ContentTypeUtils;
 import org.apache.myfaces.shared.renderkit.RendererUtils;
 import org.apache.myfaces.shared.renderkit.html.util.UnicodeEncoder;
 import org.apache.myfaces.shared.util.CommentUtils;
@@ -73,6 +74,8 @@ public class HtmlResponseWriterImpl
     
     private String _contentType;
     
+    private String _writerContentTypeMode;
+    
     /**
      * This var prevents check if the contentType is for xhtml multiple times.
      */
@@ -131,7 +134,15 @@ public class HtmlResponseWriterImpl
     }
 
     public HtmlResponseWriterImpl(Writer writer, String contentType, String characterEncoding,
-             boolean wrapScriptContentWithXmlCommentTag)
+            boolean wrapScriptContentWithXmlCommentTag)
+    {
+        this(writer,contentType, characterEncoding, wrapScriptContentWithXmlCommentTag, 
+                contentType != null && HtmlRendererUtils.isXHTMLContentType(contentType) ? 
+                    ContentTypeUtils.XHTML_CONTENT_TYPE : ContentTypeUtils.HTML_CONTENT_TYPE);
+    }
+    
+    public HtmlResponseWriterImpl(Writer writer, String contentType, String characterEncoding,
+             boolean wrapScriptContentWithXmlCommentTag, String writerContentTypeMode)
     throws FacesException
     {
         _outputWriter = writer;
@@ -149,10 +160,11 @@ public class HtmlResponseWriterImpl
             }
             _contentType = DEFAULT_CONTENT_TYPE;
         }
-        _isXhtmlContentType = HtmlRendererUtils.isXHTMLContentType(_contentType);
+        _writerContentTypeMode = writerContentTypeMode;
+        _isXhtmlContentType = writerContentTypeMode.indexOf(ContentTypeUtils.XHTML_CONTENT_TYPE) != -1;
         
-        _useStraightXml = _contentType.indexOf(APPLICATION_XML_CONTENT_TYPE) != -1 ||
-                          _contentType.indexOf(TEXT_XML_CONTENT_TYPE) != -1;
+        _useStraightXml = _isXhtmlContentType && (_contentType.indexOf(APPLICATION_XML_CONTENT_TYPE) != -1 ||
+                          _contentType.indexOf(TEXT_XML_CONTENT_TYPE) != -1);
 
         if (characterEncoding == null)
         {
@@ -200,6 +212,11 @@ public class HtmlResponseWriterImpl
     {
         return _contentType;
     }
+    
+    public String getWriterContentTypeMode()
+    {
+        return _writerContentTypeMode;
+    }
 
     public String getCharacterEncoding()
     {
@@ -861,7 +878,7 @@ public class HtmlResponseWriterImpl
     {
         HtmlResponseWriterImpl newWriter
                 = new HtmlResponseWriterImpl(writer, getContentType(), getCharacterEncoding(), 
-                        _wrapScriptContentWithXmlCommentTag);
+                        _wrapScriptContentWithXmlCommentTag, _writerContentTypeMode);
         //newWriter._writeDummyForm = _writeDummyForm;
         //newWriter._dummyFormParams = _dummyFormParams;
         return newWriter;

Added: myfaces/core/trunk/shared/src/test/java/org/apache/myfaces/shared/renderkit/ContentTypeUtilsTest.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/shared/src/test/java/org/apache/myfaces/shared/renderkit/ContentTypeUtilsTest.java?rev=1208594&view=auto
==============================================================================
--- myfaces/core/trunk/shared/src/test/java/org/apache/myfaces/shared/renderkit/ContentTypeUtilsTest.java (added)
+++ myfaces/core/trunk/shared/src/test/java/org/apache/myfaces/shared/renderkit/ContentTypeUtilsTest.java Wed Nov 30 18:04:51 2011
@@ -0,0 +1,83 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ * 
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.myfaces.shared.renderkit;
+
+import org.apache.myfaces.test.base.junit4.AbstractJsfTestCase;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class ContentTypeUtilsTest extends AbstractJsfTestCase
+{
+
+    @Test
+    public void testContainsContentType() throws Exception
+    {
+        Assert.assertTrue(ContentTypeUtils.containsContentType(
+                ContentTypeUtils.HTML_CONTENT_TYPE, ContentTypeUtils.HTML_ALLOWED_CONTENT_TYPES));
+        Assert.assertTrue(ContentTypeUtils.containsContentType(
+                ContentTypeUtils.ANY_CONTENT_TYPE, ContentTypeUtils.HTML_ALLOWED_CONTENT_TYPES));
+        Assert.assertTrue(ContentTypeUtils.containsContentType(
+                ContentTypeUtils.TEXT_ANY_CONTENT_TYPE, ContentTypeUtils.HTML_ALLOWED_CONTENT_TYPES));
+        
+        Assert.assertTrue(ContentTypeUtils.containsContentType(
+                ContentTypeUtils.XHTML_CONTENT_TYPE, ContentTypeUtils.XHTML_ALLOWED_CONTENT_TYPES));
+        Assert.assertTrue(ContentTypeUtils.containsContentType(
+                ContentTypeUtils.APPLICATION_XML_CONTENT_TYPE, ContentTypeUtils.XHTML_ALLOWED_CONTENT_TYPES));
+        Assert.assertTrue(ContentTypeUtils.containsContentType(
+                ContentTypeUtils.TEXT_XML_CONTENT_TYPE, ContentTypeUtils.XHTML_ALLOWED_CONTENT_TYPES));
+    }
+    
+    @Test
+    public void testSplitContentTypeListString() throws Exception
+    {
+        String [] splittedArray = ContentTypeUtils.splitContentTypeListString("text/*, text/html ");
+        
+        Assert.assertTrue(ContentTypeUtils.containsContentType(
+                ContentTypeUtils.HTML_CONTENT_TYPE, splittedArray));
+        Assert.assertTrue(ContentTypeUtils.containsContentType(
+                ContentTypeUtils.TEXT_ANY_CONTENT_TYPE, splittedArray));
+        
+        splittedArray = ContentTypeUtils.splitContentTypeListString(" text/x-dvi; q=.8; mxb=100000; mxt=5.0, text/x-c");
+        Assert.assertTrue(ContentTypeUtils.containsContentType(
+                "text/x-dvi", splittedArray));
+        Assert.assertTrue(ContentTypeUtils.containsContentType(
+                "text/x-c", splittedArray));
+    }
+    
+    public void testChooseWriterContentType() throws Exception
+    {
+        Assert.assertEquals(ContentTypeUtils.HTML_CONTENT_TYPE, 
+                ContentTypeUtils.chooseWriterContentType(
+                        "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", 
+                        ContentTypeUtils.HTML_ALLOWED_CONTENT_TYPES,
+                        ContentTypeUtils.XHTML_ALLOWED_CONTENT_TYPES));
+
+        Assert.assertEquals(ContentTypeUtils.XHTML_CONTENT_TYPE, 
+                ContentTypeUtils.chooseWriterContentType(
+                        "application/xml, text/xml , */*; q=0.01", 
+                        ContentTypeUtils.HTML_ALLOWED_CONTENT_TYPES,
+                        ContentTypeUtils.XHTML_ALLOWED_CONTENT_TYPES));
+
+        //In ajax request application/xml and text/xml does not match.
+        Assert.assertNull(ContentTypeUtils.chooseWriterContentType(
+                        "application/xml, text/xml, */*; q=0.01", 
+                        ContentTypeUtils.HTML_ALLOWED_CONTENT_TYPES,
+                        ContentTypeUtils.AJAX_XHTML_ALLOWED_CONTENT_TYPES));
+    }
+}

Propchange: myfaces/core/trunk/shared/src/test/java/org/apache/myfaces/shared/renderkit/ContentTypeUtilsTest.java
------------------------------------------------------------------------------
    svn:eol-style = native