blob: 9785aacf793982699332638b05abccc0485b2863 [file] [log] [blame]
/*
* 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.extensions.validator.util;
import org.apache.myfaces.extensions.validator.internal.ToDo;
import org.apache.myfaces.extensions.validator.internal.Priority;
import org.apache.myfaces.extensions.validator.internal.UsageInformation;
import org.apache.myfaces.extensions.validator.internal.UsageCategory;
import javax.faces.component.UIComponent;
import javax.faces.el.ValueBinding;
import java.io.Externalizable;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author Gerhard Petracek
*/
@UsageInformation(UsageCategory.INTERNAL)
public class FaceletsTaglibExpressionUtils
{
public static String tryToCreateValueBindingForFaceletsBinding(
UIComponent uiComponent)
{
String faceletsValueBindingExpression = ELUtils.getValueBindingExpression(uiComponent);
try
{
List<String> foundBindings = extractELTerms(uiComponent.getValueExpression("value"));
return faceletsValueBindingExpression.substring(0, 1) + "{" + createBinding(foundBindings) + "}";
}
catch (Throwable t)
{
return faceletsValueBindingExpression;
}
}
@ToDo(value = Priority.MEDIUM, description = "logging")
private static String createBinding(List<String> expressions)
{
String result = "";
String prevFaceletsAttributeName = null;
String currentBinding;
String partOfBinding;
int indexOfBindingDetails;
String[] foundBindingDetails;
String[] bindingDetails;
for (String entry : expressions)
{
if (entry.startsWith("ValueExpression["))
{
continue;
}
foundBindingDetails = entry.split(" ");
indexOfBindingDetails = findIndexOfBindingDetails(foundBindingDetails);
if (indexOfBindingDetails == -1)
{
return null;
}
bindingDetails = foundBindingDetails[indexOfBindingDetails].split("=");
if (bindingDetails.length < 2)
{
return null;
}
currentBinding = bindingDetails[1];
if (prevFaceletsAttributeName != null)
{
partOfBinding = currentBinding.substring(currentBinding.indexOf(prevFaceletsAttributeName)
+ prevFaceletsAttributeName.length(), currentBinding.indexOf("}"));
result = result + partOfBinding;
}
else
{
result = currentBinding.substring(currentBinding.indexOf("{") + 1, currentBinding.indexOf("}"));
}
prevFaceletsAttributeName = bindingDetails[0];
}
return result;
}
private static int findIndexOfBindingDetails(String[] bindingDetails)
{
int count = 0;
for (String entry : bindingDetails)
{
if (entry.contains("="))
{
return count;
}
count++;
}
return -1;
}
private static List<String> extractELTerms(Object o)
{
List<String> foundELTerms = new ArrayList<String>();
try
{
if (resolveELTerms(o, new HashMap<Object, Object>(), foundELTerms, 0) > 0)
{
return foundELTerms;
}
}
catch (Exception ex)
{
return null;
}
return null;
}
private static int resolveELTerms(Object o, Map<Object, Object> visited,
List<String> foundELTerms, int count) throws Exception
{
if (o == null || visited.containsKey(o) || count > 50)
{
return 0;
}
visited.put(o, null);
int elCount = 0;
Class c = o.getClass();
//inspect maps
if (o instanceof Map)
{
for (Object entry : ((Map) o).values())
{
elCount += resolveELTerms(entry, visited, foundELTerms, count + 1);
}
return elCount;
}
if (isELTerm(o))
{
if (foundELTerms != null)
{
foundELTerms.add(o.toString());
}
return ++elCount;
}
//analyze arrays
if (c.isArray())
{
int length = Array.getLength(o);
//check array [L -> no array of primitive types
if (o.toString().startsWith("[L"))
{
for (int i = 0; i < length; i++)
{
if (o.toString().startsWith("[Ljava.lang.String"))
{
if (isELTerm(Array.get(o, i)))
{
if (foundELTerms != null)
{
foundELTerms.add(o.toString());
}
elCount++;
}
}
else
{
elCount += resolveELTerms(Array.get(o, i), visited, foundELTerms, count + 1);
}
}
}
return elCount;
}
List<Field> attributes = findAllAttributes(c, new ArrayList<Field>());
Field[] fields = (Field[]) attributes.toArray(new Field[attributes.size()]);
AccessibleObject.setAccessible(fields, true);
for (Field currentField : fields)
{
if (currentField.get(o) == null)
{
continue;
}
if (currentField.getType().equals(String.class))
{
if (currentField.get(o) != null && isELTerm(currentField.get(o)))
{
if (foundELTerms != null)
{
foundELTerms.add(o.toString());
}
elCount++;
}
}
else if (!currentField.getType().isPrimitive())
{
elCount += resolveELTerms(currentField.get(o), visited, foundELTerms, count + 1);
}
}
return elCount;
}
private static boolean isELTerm(Object o)
{
if (o instanceof ValueBinding || o instanceof Externalizable)
{
return false;
}
String s = o.toString();
return ((s.contains("#") || s.contains("$")) && s.contains("{") && s.contains("}"));
}
private static List<Field> findAllAttributes(Class c, List<Field> attributes)
{
if (c == null)
{
return attributes;
}
findAllAttributes(c.getSuperclass(), attributes);
Field[] fields = c.getDeclaredFields();
for (Field currentField : fields)
{
if (!Modifier.isStatic(currentField.getModifiers()))
{
attributes.add(currentField);
}
}
return attributes;
}
}