001/* 002 * (C) Copyright 2013 Nuxeo SA (http://nuxeo.com/) and contributors. 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 * Guillaume Renard 016 */ 017package org.nuxeo.ecm.platformui.web.form; 018 019import java.io.IOException; 020 021import javax.faces.component.UIComponent; 022import javax.faces.component.html.HtmlForm; 023import javax.faces.context.FacesContext; 024 025import org.apache.commons.lang.StringUtils; 026import org.nuxeo.runtime.api.Framework; 027import org.nuxeo.runtime.services.config.ConfigurationService; 028 029import com.sun.faces.renderkit.html_basic.FormRenderer; 030 031/** 032 * Nuxeo h:form tag renderer override, to include javascript code preventing multiple submissions of the form. 033 * 034 * @since 5.7.3 035 */ 036public class NxFormRenderer extends FormRenderer { 037 038 public static final String ENABLE_DOUBLE_CLICK_SHIELD = "nuxeo.jsf.enableDoubleClickShield"; 039 040 public static final String ENABLE_DOUBLE_CLICK_ON_ELEMENT = "disableDoubleClickShield"; 041 042 public static final String DOUBLE_CLICK_SHIELD_CSS_CLASS_FLAG = "doubleClickShielded"; 043 044 protected static boolean isDoubleShieldEnabled() { 045 ConfigurationService configurationService = Framework.getService(ConfigurationService.class); 046 return !configurationService.isBooleanPropertyFalse(ENABLE_DOUBLE_CLICK_SHIELD); 047 } 048 049 protected static boolean dcDisabledOnElement(UIComponent component) { 050 if (component != null) { 051 Object dcDisabledOnElement = component.getAttributes().get(ENABLE_DOUBLE_CLICK_ON_ELEMENT); 052 if (dcDisabledOnElement != null) { 053 if (dcDisabledOnElement instanceof String) { 054 return Boolean.TRUE.equals(Boolean.valueOf((String) dcDisabledOnElement)); 055 } else if (dcDisabledOnElement instanceof Boolean) { 056 return Boolean.TRUE.equals(dcDisabledOnElement); 057 } 058 } 059 } else { 060 return true; 061 } 062 return false; 063 } 064 065 protected static boolean containsDoubleClickShieldClass(final String styleClass) { 066 if (styleClass != null) { 067 String[] split = styleClass.split(" "); 068 for (String s : split) { 069 if (s.equals(DOUBLE_CLICK_SHIELD_CSS_CLASS_FLAG)) { 070 return true; 071 } 072 } 073 } 074 return false; 075 } 076 077 @Override 078 public void encodeBegin(FacesContext context, UIComponent component) throws IOException { 079 080 if (component.isRendered() && isDoubleShieldEnabled()) { 081 if (!dcDisabledOnElement(component)) { 082 String styleClass = (String) ((HtmlForm) component).getAttributes().get("styleClass"); 083 if (StringUtils.isBlank(styleClass)) { 084 ((HtmlForm) component).setStyleClass(DOUBLE_CLICK_SHIELD_CSS_CLASS_FLAG); 085 } else { 086 if (!containsDoubleClickShieldClass(styleClass)) { 087 ((HtmlForm) component).setStyleClass(styleClass + " " + DOUBLE_CLICK_SHIELD_CSS_CLASS_FLAG); 088 } 089 } 090 } 091 } 092 093 super.encodeBegin(context, component); 094 095 } 096 097}