@Override
public ResponseWriter createResponseWriter(Writer writer, String contentTypeListString, String characterEncoding)
{
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 selectedContentType
// try to derive it from accept header
if (selectedContentType == 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 (selectedContentType == null)
{
if (contentTypeListStringFromAccept != null)
{
String[] contentTypes = ContentTypeUtils.splitContentTypeListString(
contentTypeListStringFromAccept);
if (ContentTypeUtils.containsContentType(ContentTypeUtils.ANY_CONTENT_TYPE, contentTypes))
{
selectedContentType = myfacesConfig.getDefaultResponseWriterContentTypeMode();
}
}
else if (isAjaxRequest)
{
// If is an ajax request, contentTypeListStringFromAccept == null and
// contentTypeListString != null, contentTypeListString should not be taken
// into account, because the final content type in this case is for PartialResponseWriter
// implementation. In this case rfc2616-sec14 takes precedence:
//
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
// 14.1 Accept
// If no Accept header field is present, then it is assumed that the client
// accepts all media types.
selectedContentType = myfacesConfig.getDefaultResponseWriterContentTypeMode();
}
if (selectedContentType == null)
{
// Note this case falls when contentTypeListStringFromAccept == null and
// contentTypeListString != null, but since this not an ajax request,
// contentTypeListString should be taken strictly and throw IllegalArgumentException
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.isWrapScriptContentWithXmlCommentTag(),
writerContentType);
}