001/* 002 * (C) Copyright 2013 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the GNU Lesser General Public License 006 * (LGPL) version 2.1 which accompanies this distribution, and is available at 007 * http://www.gnu.org/licenses/lgpl-2.1.html 008 * 009 * This library is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 012 * Lesser General Public License for more details. 013 * 014 * Contributors: 015 * Thomas Roger 016 */ 017 018package org.nuxeo.ecm.platform.ui.web.component.message; 019 020import java.io.IOException; 021import java.util.Iterator; 022 023import javax.faces.application.FacesMessage; 024import javax.faces.component.UIComponent; 025import javax.faces.component.UIMessages; 026import javax.faces.context.FacesContext; 027import javax.faces.context.ResponseWriter; 028 029import org.apache.commons.lang.StringEscapeUtils; 030import org.nuxeo.runtime.api.Framework; 031 032import com.sun.faces.renderkit.html_basic.MessagesRenderer; 033 034/** 035 * Handles rendering of {@link javax.faces.application.FacesMessage} through jQuery Ambiance plugin. 036 * 037 * @since 5.7.3 038 */ 039public class NXMessagesRenderer extends MessagesRenderer { 040 041 public static final String RENDERER_TYPE = "javax.faces.NXMessages"; 042 043 @Override 044 public void encodeEnd(FacesContext context, UIComponent component) throws IOException { 045 rendererParamsNotNull(context, component); 046 047 if (!shouldEncode(component)) { 048 return; 049 } 050 051 // If id is user specified, we must render 052 boolean mustRender = shouldWriteIdAttribute(component); 053 054 UIMessages messages = (UIMessages) component; 055 ResponseWriter writer = context.getResponseWriter(); 056 assert (writer != null); 057 058 String clientId = ((UIMessages) component).getFor(); 059 // if no clientId was included 060 if (clientId == null) { 061 // and the author explicitly only wants global messages 062 if (messages.isGlobalOnly()) { 063 // make it so only global messages get displayed. 064 clientId = ""; 065 } 066 } 067 068 // "for" attribute optional for Messages 069 Iterator messageIter = getMessageIter(context, clientId, component); 070 071 assert (messageIter != null); 072 073 if (!messageIter.hasNext()) { 074 if (mustRender) { 075 // no message to render, but must render anyway 076 // but if we're writing the dev stage messages, 077 // only write it if messages exist 078 if ("javax_faces_developmentstage_messages".equals(component.getId())) { 079 return; 080 } 081 writer.startElement("div", component); 082 writeIdAttributeIfNecessary(context, writer, component); 083 writer.endElement("div"); 084 } // otherwise, return without rendering 085 return; 086 } 087 088 boolean showDetail = messages.isShowDetail(); 089 090 while (messageIter.hasNext()) { 091 FacesMessage curMessage = (FacesMessage) messageIter.next(); 092 if (curMessage.isRendered() && !messages.isRedisplay()) { 093 continue; 094 } 095 curMessage.rendered(); 096 097 // make sure we have a non-null value for summary and 098 // detail. 099 String summary = (null != (summary = curMessage.getSummary())) ? summary : ""; 100 // Default to summary if we have no detail 101 String detail = (null != (detail = curMessage.getDetail())) ? detail : summary; 102 103 String severityStyleClass = null; 104 String errorType = "default"; 105 long timeout = 5; 106 if (curMessage.getSeverity() == FacesMessage.SEVERITY_INFO) { 107 severityStyleClass = (String) component.getAttributes().get("infoClass"); 108 errorType = "info"; 109 } else if (curMessage.getSeverity() == FacesMessage.SEVERITY_WARN) { 110 severityStyleClass = (String) component.getAttributes().get("warnClass"); 111 errorType = "warn"; 112 } else if (curMessage.getSeverity() == FacesMessage.SEVERITY_ERROR) { 113 severityStyleClass = (String) component.getAttributes().get("errorClass"); 114 errorType = "error"; 115 timeout = 0; 116 } else if (curMessage.getSeverity() == FacesMessage.SEVERITY_FATAL) { 117 severityStyleClass = (String) component.getAttributes().get("fatalClass"); 118 errorType = "fatal"; 119 timeout = 0; 120 } 121 122 // ensure message stays visible when running tests 123 if (Framework.getProperty("org.nuxeo.ecm.tester.name") != null) { 124 timeout = 0; 125 } 126 127 writer.startElement("script", messages); 128 writer.writeAttribute("type", "text/javascript", null); 129 130 String scriptContent = "jQuery(document).ready(function() {\n" + " jQuery.ambiance({\n" + " " 131 + "message: \"%s\",\n" + " title: \"%s\",\n" + " type: \"%s\",\n" 132 + " className: \"%s\",\n" + " timeout: \"%d\"" + " })\n" + "});\n"; 133 String formattedScriptContent; 134 if (showDetail) { 135 formattedScriptContent = String.format(scriptContent, StringEscapeUtils.escapeJavaScript(detail), 136 StringEscapeUtils.escapeJavaScript(summary), errorType, severityStyleClass, timeout); 137 } else { 138 formattedScriptContent = String.format(scriptContent, "", StringEscapeUtils.escapeJavaScript(summary), 139 errorType, severityStyleClass, timeout); 140 } 141 writer.writeText(formattedScriptContent, null); 142 writer.endElement("script"); 143 144 } 145 } 146}