001/* 002 * (C) Copyright 2007 Nuxeo SAS (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.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 * Nuxeo - initial API and implementation 016 * 017 * $Id: ComponentTagUtils.java 28610 2008-01-09 17:13:52Z sfermigier $ 018 */ 019 020package org.nuxeo.ecm.platform.ui.web.util; 021 022import javax.el.ELContext; 023import javax.el.ELException; 024import javax.el.ExpressionFactory; 025import javax.el.ValueExpression; 026import javax.faces.application.Application; 027import javax.faces.context.FacesContext; 028import javax.faces.view.facelets.FaceletContext; 029 030import org.apache.commons.logging.Log; 031import org.apache.commons.logging.LogFactory; 032 033/** 034 * Component tag utils. 035 * 036 * @author <a href="mailto:at@nuxeo.com">Anahide Tchertchian</a> 037 */ 038public final class ComponentTagUtils { 039 040 private static final Log log = LogFactory.getLog(ComponentTagUtils.class); 041 042 // Utility class. 043 private ComponentTagUtils() { 044 } 045 046 /** 047 * Returns true if the specified value contains a value expression, e.g the start and end of EL markers. 048 * 049 * @param value the value to evaluate, returns false if null 050 */ 051 public static boolean isValueReference(String value) { 052 if (value == null) { 053 return false; 054 } 055 return value.contains("#{") && value.indexOf("#{") < value.indexOf('}') || value.contains("${") 056 && value.indexOf("${") < value.indexOf('}'); 057 } 058 059 /** 060 * Returns true if the specified value is a value expression, e.g starting and ending with EL markers after being 061 * trimmed. 062 * 063 * @param value the value to evaluate, returns false if null 064 * @since 5.6 065 */ 066 public static boolean isStrictValueReference(String value) { 067 if (value == null) { 068 return false; 069 } 070 value = value.trim(); 071 return (value.startsWith("#{") && value.indexOf("#{") < value.indexOf('}') && value.endsWith("}")) 072 || (value.startsWith("${") && value.indexOf("${") < value.indexOf('}') && value.endsWith("}")); 073 } 074 075 /** 076 * Returns a value name for given strict value reference. If reference is #{foo} or ${foo}, will return "foo". 077 * 078 * @since 5.6 079 * @throws IllegalArgumentException if reference is null or {@link #isStrictValueReference(String)} returns false. 080 * @param valueReference 081 */ 082 public static String getBareValueName(String valueReference) { 083 if (!isStrictValueReference(valueReference)) { 084 throw new IllegalArgumentException(String.format("Invalid value reference '%s'", valueReference)); 085 } 086 return valueReference.substring(2, valueReference.length() - 1); 087 } 088 089 /** 090 * Returns true if the specified value conforms to the syntax requirements of a method binding expression. 091 * <p> 092 * The method can have parameters and the expression must use parentheses even if no parameters are needed. 093 * 094 * @param value the value to evaluate (not null) 095 * @deprecated since 5.5: method and value references are now equivalent with jboss EL 096 */ 097 @Deprecated 098 public static boolean isMethodReference(String value) { 099 boolean isValue = isValueReference(value); 100 if (isValue) { 101 if (value.contains("(") && value.indexOf('(') < value.indexOf(')') 102 // make sure it's not a function 103 && (!value.contains(":") || value.indexOf(':') > value.indexOf('('))) { 104 return true; 105 } 106 } 107 return false; 108 } 109 110 /** 111 * Resolves an expression from a given faces context. 112 * <p> 113 * Resolves the expression a second time when first resolution gives a String value using the EL Expression syntax. 114 * <p> 115 * Does not throw any error when resolution fails (only logs an error message). 116 * 117 * @see #resolveElExpression(FaceletContext, String) 118 */ 119 public static Object resolveElExpression(FacesContext context, String elExpression) { 120 if (!isValueReference(elExpression)) { 121 // literal 122 return elExpression; 123 } else { 124 if (context == null) { 125 log.error(String.format("FacesContext is null => cannot resolve el expression '%s'", elExpression)); 126 return null; 127 } 128 // expression => evaluate 129 Application app = context.getApplication(); 130 try { 131 return app.evaluateExpressionGet(context, elExpression, Object.class); 132 } catch (ELException e) { 133 log.error(String.format("Faces context: Error processing expression '%s'", elExpression), e); 134 return null; 135 } 136 } 137 } 138 139 /** 140 * Resolves given value expression as string and sets given value on it. 141 * 142 * @since 6.0 143 */ 144 public static void applyValueExpression(FacesContext context, String elExpression, Object value) { 145 if (!isStrictValueReference(elExpression)) { 146 log.warn(String.format("Cannot set value '%s' for expression '%s'", value, elExpression)); 147 } else { 148 if (context == null) { 149 log.error(String.format("FacesContext is null => cannot resolve el expression '%s'", elExpression)); 150 return; 151 } 152 Application app = context.getApplication(); 153 ExpressionFactory eFactory = app.getExpressionFactory(); 154 ELContext elContext = context.getELContext(); 155 try { 156 ValueExpression vExpression = eFactory.createValueExpression(elContext, elExpression, Object.class); 157 vExpression.setValue(elContext, value); 158 } catch (ELException e) { 159 log.error(String.format("Error setting value '%s' for expression '%s'", value, elExpression), e); 160 } 161 } 162 } 163 164 /** 165 * Resolves an expression from a given facelet context, using its {@link ExpressionFactory} that can hold a wider 166 * context than the faces context behind it. 167 * <p> 168 * Resolves the expression a second time when first resolution gives a String value using the EL Expression syntax. 169 * <p> 170 * Does not throw any error when resolution fails (only logs an error message). 171 */ 172 public static Object resolveElExpression(FaceletContext faceletContext, String elExpression) { 173 if (!isValueReference(elExpression)) { 174 // literal 175 return elExpression; 176 } else { 177 if (faceletContext == null) { 178 log.error(String.format("FaceletContext is null => cannot resolve el expression '%s'", elExpression)); 179 return null; 180 } 181 // expression => evaluate 182 ExpressionFactory eFactory = faceletContext.getExpressionFactory(); 183 ELContext elContext = faceletContext.getFacesContext().getELContext(); 184 ValueExpression expr = eFactory.createValueExpression(faceletContext, elExpression, Object.class); 185 try { 186 return expr.getValue(elContext); 187 } catch (ELException e) { 188 log.error(String.format("Facelet context: Error processing expression '%s'", elExpression), e); 189 return null; 190 } 191 } 192 } 193 194}