/*
* Copyright 2011 cruxframework.org
*
* Licensed 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.cruxframework.crux.core.server.rest.core.dispatch;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Date;
import org.cruxframework.crux.core.server.rest.spi.BadRequestException;
import org.cruxframework.crux.core.utils.ClassUtils;
/**
*
* @author Thiago da Rosa de Bustamante
*
*/
public class StringParameterInjector
{
private static final String CAN_NOT_INVOKE_USING_ARGUMENTS_MSG = "Can not invoke requested service with given arguments";
protected Class<?> rawType;
protected Constructor<?> constructor;
protected Method valueOf;
protected String defaultValue;
protected String paramName;
private boolean isDate;
private boolean isSQLDate;
protected StringParameterInjector()
{
}
protected StringParameterInjector(Class<?> type, String paramName, String defaultValue)
{
initialize(type, paramName, defaultValue);
}
protected void initialize(Class<?> type, String paramName, String defaultValue)
{
this.rawType = type;
this.paramName = paramName;
this.defaultValue = defaultValue;
this.isDate = Date.class.isAssignableFrom(type);
this.isSQLDate = java.sql.Date.class.isAssignableFrom(type);
if (ClassUtils.isSimpleType(rawType))
{
try
{
if(ClassUtils.hasStringConstructor(type))
{
constructor = type.getConstructor(String.class);
} else if(ClassUtils.hasCharacterConstructor(rawType))
{
constructor = type.getConstructor(Character.TYPE);
}
if (constructor != null && !Modifier.isPublic(constructor.getModifiers()))
{
constructor = null;
}
}
catch (NoSuchMethodException ignored)
{
//No error, try valueOf method
}
}
if (constructor == null)
{
valueOf = findValueOfMethod();
}
}
protected Method findValueOfMethod()
{
Method fromString = null;
Method valueOf = null;
try
{
fromString = rawType.getDeclaredMethod("fromString", String.class);
if (Modifier.isStatic(fromString.getModifiers()) == false)
{
fromString = null;
}
}
catch (NoSuchMethodException ignored)
{
//No error, continue searching
}
try
{
valueOf = rawType.getDeclaredMethod("valueOf", String.class);
if (Modifier.isStatic(valueOf.getModifiers()) == false)
{
valueOf = null;
}
}
catch (NoSuchMethodException ignored)
{
//No error, continue searching
}
if (valueOf == null)
{
valueOf = fromString;
}
return valueOf;
}
public String getParamSignature()
{
return rawType.getName() + "(\"" + paramName + "\")";
}
public Object extractValue(String strVal)
{
if (strVal == null || strVal.length() == 0)
{
if (defaultValue == null)
{
if (!rawType.isPrimitive())
{
return null;
}
else
{
return ClassUtils.stringToPrimitiveBoxType(rawType, strVal);
}
}
else
{
strVal = defaultValue;
}
}
else if (isSQLDate && isNumeric(strVal))
{
return new java.sql.Date(Long.parseLong(strVal));
}
else if (isDate && isNumeric(strVal))
{
return new Date(Long.parseLong(strVal));
}
else if (rawType.isPrimitive())
{
return ClassUtils.stringToPrimitiveBoxType(rawType, strVal);
}
else if (constructor != null)
{
try
{
return constructor.newInstance(strVal);
}
catch (Exception e)
{
String errorMsg = "Unable to extract parameter from http request for " + getParamSignature();
if(constructor.getName().equals(Character.class.getCanonicalName()))
{
try
{
return constructor.newInstance(strVal.toCharArray()[0]);
}
catch (Exception f)
{
throw new BadRequestException(errorMsg, CAN_NOT_INVOKE_USING_ARGUMENTS_MSG, e);
}
}
throw new BadRequestException(errorMsg, CAN_NOT_INVOKE_USING_ARGUMENTS_MSG, e);
}
}
else if (valueOf != null)
{
try
{
return valueOf.invoke(null, strVal);
}
catch (Exception e)
{
throw new BadRequestException("Unable to extract parameter from http request: " + getParamSignature(), CAN_NOT_INVOKE_USING_ARGUMENTS_MSG, e);
}
}
return null;
}
private boolean isNumeric(String str)
{
if (str == null)
{
return false;
}
int sz = str.length();
int startPos = 0;
if (sz > 0 && str.charAt(0) == '-')
{
startPos = 1;
}
for (int i = startPos; i < sz; i++)
{
if (!Character.isDigit(str.charAt(i)))
{
return false;
}
}
return true;
}
}