/******************************************************************************* * Copyright (c) 2006-2010 eBay Inc. All Rights Reserved. * 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 *******************************************************************************/ package org.ebayopensource.turmeric.runtime.common.impl.internal.pipeline; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.lang.reflect.Field; import java.net.URLDecoder; import java.nio.ByteBuffer; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; import javax.xml.namespace.QName; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamReader; import org.ebayopensource.turmeric.runtime.binding.impl.parser.objectnode.ObjectNodeBuilder; import org.ebayopensource.turmeric.runtime.binding.impl.parser.objectnode.ObjectNodeStreamReader; import org.ebayopensource.turmeric.runtime.binding.impl.parser.objectnode.SOAPObjectNodeStreamReader; import org.ebayopensource.turmeric.runtime.binding.objectnode.ObjectNode; import org.ebayopensource.turmeric.runtime.binding.objectnode.impl.ObjectNodeImpl; import org.ebayopensource.turmeric.runtime.common.binding.DataBindingDesc; import org.ebayopensource.turmeric.runtime.common.binding.Deserializer; import org.ebayopensource.turmeric.runtime.common.binding.DeserializerFactory; import org.ebayopensource.turmeric.runtime.common.binding.IProtobufDeserializer; import org.ebayopensource.turmeric.runtime.common.exceptions.ErrorDataFactory; import org.ebayopensource.turmeric.runtime.common.exceptions.ServiceException; import org.ebayopensource.turmeric.runtime.common.impl.attachment.BaseMessageAttachments; import org.ebayopensource.turmeric.runtime.common.impl.attachment.InboundMessageAttachments; import org.ebayopensource.turmeric.runtime.common.impl.binding.protobuf.ProtobufDeserializerFactory; import org.ebayopensource.turmeric.runtime.common.impl.internal.monitoring.SystemMetricDefs; import org.ebayopensource.turmeric.runtime.common.impl.internal.utils.PrereadingRawDataRecorder; import org.ebayopensource.turmeric.runtime.common.impl.utils.LogManager; import org.ebayopensource.turmeric.runtime.common.pipeline.InboundMessage; import org.ebayopensource.turmeric.runtime.common.pipeline.ProtocolProcessor; import org.ebayopensource.turmeric.runtime.common.service.ServiceOperationDesc; import org.ebayopensource.turmeric.runtime.common.service.ServiceOperationParamDesc; import org.ebayopensource.turmeric.runtime.common.types.Cookie; import org.ebayopensource.turmeric.runtime.common.types.G11nOptions; import org.ebayopensource.turmeric.runtime.common.types.SOAConstants; import org.ebayopensource.turmeric.runtime.common.types.SOAHeaders; import org.ebayopensource.turmeric.runtime.errorlibrary.ErrorConstants; /** * Internal class representing incoming messages (requests on server side or responses on client side). * */ public final class InboundMessageImpl extends BaseMessageImpl implements InboundMessage { private InputStream m_inputStream; private XMLStreamReader m_xmlReader; private boolean m_deserCompleted; private boolean m_hasParamsByRef; private boolean m_hasErrorHeader; private boolean m_hasErrorHeaderChecked; private boolean m_noStream; private boolean m_messageHeaderCompleted; private int m_maxBytesToRecord; private ObjectNode m_root; private PrereadingRawDataRecorder m_recordingStream; private Collection<Object> m_javaObjectMsgHeaders; private static Logger m_logger = null; private static Logger getLogger() { if (null == m_logger) { m_logger = LogManager.getInstance(InboundMessageImpl.class); } return m_logger; } /** * Internal constructor. Client or service writers should never construct messages directly. * @param isRequestMessage * @param transportProtocol * @param dataBindingDesc * @param g11nOptions * @param transportHeaders * @param cookies * @param attachments * @param operationDesc */ public InboundMessageImpl(boolean isRequestMessage, String transportProtocol, DataBindingDesc dataBindingDesc, G11nOptions g11nOptions, Map<String,String> transportHeaders, Cookie[] cookies, Collection<ObjectNode> messageHeaders, BaseMessageAttachments attachments, ServiceOperationDesc operationDesc) throws ServiceException { this(isRequestMessage, transportProtocol, dataBindingDesc, g11nOptions, transportHeaders, cookies, messageHeaders, attachments, operationDesc, false); } public InboundMessageImpl(boolean isRequestMessage, String transportProtocol, DataBindingDesc dataBindingDesc, G11nOptions g11nOptions, Map<String,String> transportHeaders, Cookie[] cookies, Collection<ObjectNode> messageHeaders, BaseMessageAttachments attachments, ServiceOperationDesc operationDesc, boolean bufferingMode) throws ServiceException { super(isRequestMessage, transportProtocol, dataBindingDesc, g11nOptions, transportHeaders, cookies, messageHeaders, attachments, operationDesc, bufferingMode); } public Collection<Object> getMessageHeadersAsJavaObject() throws ServiceException { if (m_javaObjectMsgHeaders != null) return m_javaObjectMsgHeaders; // java object nodes message headers not created. Create now. Collection<ObjectNode> messageHeaders = getMessageHeaders(); if (messageHeaders != null) { m_javaObjectMsgHeaders = new ArrayList<Object>(); // convert message headres from DOM to java object nodes for (ObjectNode node : messageHeaders) { Object headerObject = getMessageHeaderObject(node); if (headerObject == null) { // If the header object returned is null, don't add it // to the list. continue; } m_javaObjectMsgHeaders.add(headerObject); } } return m_javaObjectMsgHeaders; } /* (non-Javadoc) * @see org.ebayopensource.turmeric.runtime.common.pipeline.Message#getMessageHeader() */ public Collection<ObjectNode> getMessageHeaders() throws ServiceException { if (m_hasParamsByRef) { // This is the skip serialization case. // In this case, there is only the java object as message // body, THe message headers is null. Return null. m_messageHeaderCompleted = true; return null; } if (m_messageHeaderCompleted) { return m_messageHeaders; } ProtocolProcessor pp = getContextImpl().getProtocolProcessor(); if (!pp.supportsHeaders()) { m_messageHeaderCompleted = true; return null; } if (null == m_root) { createRootNode(); } if (m_root == ObjectNodeImpl.EMPTY_ROOT_NODE) { m_messageHeaderCompleted = true; return null; } m_messageHeaders = pp.getMessageHeaders(m_root); m_messageHeaderCompleted = true; return m_messageHeaders; } private Object getMessageHeaderObject(ObjectNode object) throws ServiceException { DeserializerFactory deserFactory = getDataBindingDesc().getDeserializerFactory(); XMLStreamReader reader = deserFactory.getXMLStreamReader(this, object); Deserializer deser = deserFactory.getDeserializer(); QName name = object.getNodeName(); Class javaType = getJavaTypeFromXMLName(getHeaderParamDesc(), name); // If javaType of a given header element is not found, the header element is // unexpected. Return null to ignor it. if (null == javaType) { return null; } Object obj = deser.deserialize(this, javaType, reader); return obj; } /* (non-Javadoc) * @see org.ebayopensource.turmeric.runtime.common.impl.pipeline.BaseMessageImpl#getMessageBody(), * org.ebayopensource.turmeric.runtime.common.pipeline.Message#getMessageBody() */ @Override public ObjectNode getMessageBody() throws ServiceException { if (m_deserCompleted) { return super.getMessageBody(); } if (null == m_root) { createRootNode(); } if (m_root == ObjectNodeImpl.EMPTY_ROOT_NODE) { return null; } ProtocolProcessor pp = getContextImpl().getProtocolProcessor(); return pp.getMessageBody(m_root); } private synchronized void createRootNode() throws ServiceException { try { if (null != m_root) { return; } // make sure streams are OK getXMLStreamReader(); if (!(m_xmlReader instanceof ObjectNodeBuilder)) { m_root = ObjectNodeImpl.createEmptyRootNode(); return; } ObjectNodeBuilder builder = (ObjectNodeBuilder)m_xmlReader; m_root = builder.getObjectNode(); } catch (XMLStreamException e) { throw new ServiceException(ErrorDataFactory.createErrorData(ErrorConstants.SVC_DATA_READ_ERROR, ErrorConstants.ERRORDOMAIN, new Object[] {e.getMessage()}), e); } } public ObjectNode getRootNode() throws ServiceException { if (null == m_root) { try { createRootNode(); } catch (Exception e) { //e.printStackTrace(); // Not a SOAP message } } return m_root; } public final boolean isErrorMessage() throws ServiceException { if (m_errorResponse != null) { return true; } return hasErrorTransportHeader(); } /** * Returns true if SOA X-TURMERIC-ERROR-RESPONSE header is present */ private boolean hasErrorTransportHeader() throws ServiceException { if (!m_hasErrorHeaderChecked) { m_hasErrorHeader = hasTransportHeader(SOAHeaders.ERROR_RESPONSE); m_hasErrorHeaderChecked = true; } return m_hasErrorHeader; } /* (non-Javadoc) * @see org.ebayopensource.turmeric.runtime.common.impl.pipeline.BaseMessageImpl#loadParamsImpl() */ @Override protected void loadParamsImpl() throws ServiceException { if (m_deserCompleted) { return; } // TODO: should we disallow param access in case of errors ? if (m_noStream) { // no data and no error m_deserCompleted = true; return; } try { loadParamsInt(); } finally { // make sure further deserialization is not possible m_deserCompleted = true; m_xmlReader = null; } } private void loadParamsInt() throws ServiceException { BaseMessageContextImpl ctx = getContextImpl(); long startTime = System.nanoTime(); try { DeserializerFactory deserFactory = getDataBindingDesc().getDeserializerFactory(); Deserializer deser = deserFactory.getDeserializer(); if (hasErrorTransportHeader()) { Class javaType = getErrorParamType(); if (deserFactory instanceof ProtobufDeserializerFactory) { IProtobufDeserializer ideser = (IProtobufDeserializer) deser; m_errorResponse = ideser.deserialize(null, javaType, m_inputStream); } else { if (hasExpectedErrorElement()) { // found expected error element. Continue de-serialization m_errorResponse = deser.deserialize(this, javaType); } else { // found unknown error element. Consume the element and // return the root element inside message body as an object node m_errorResponse = consumeMessageBodyRootElement(deser, javaType); } } if (m_errorResponse == null ) { // unable to deserialize the error response throw new ServiceException(ErrorDataFactory.createErrorData(ErrorConstants.SVC_DATA_NULL_ERROR_DESERIALIZE, ErrorConstants.ERRORDOMAIN)); } } else { List<Class> paramTypes = getParamTypes(); if (!paramTypes.isEmpty()) { if (deserFactory instanceof ProtobufDeserializerFactory) { IProtobufDeserializer ideser = (IProtobufDeserializer) deser; m_params = new Object[paramTypes.size()]; for (int i = 0; i < paramTypes.size(); i++) { m_params[i] = ideser.deserialize(null, paramTypes.get(i), m_inputStream); } return; } m_params = new Object[paramTypes.size()]; for (int i = 0; i < paramTypes.size(); i++) { Class paramType = paramTypes.get(i); Object value = deser.deserialize(this, paramType); m_params[i] = value; processQueryParameters(ctx.getRawQueryParams(), ctx.getCharset(), paramType, value); } } // TODO: throw exception if there is more data in the stream past protocol processor // which would indicate too many parameters passed in } ProtocolProcessor pp = ctx.getProtocolProcessor(); pp.postDeserialize(this); } finally { long duration = System.nanoTime() - startTime; ctx.updateSvcAndOpMetric(SystemMetricDefs.OP_TIME_DESERIALIZATION, startTime, duration); } // TODO: get m_body and make sure changes // are synchronized between params and body } // determine whether the reader contains a common.types.ErrorMessage. // This method should be called after calling hasExpectedErrorElement() private boolean isCommonTypesError() throws ServiceException { if (m_xmlReader != null) { if (m_xmlReader.getName().equals(SOAConstants.COMMON_ERROR_MESSAGE_ELEMENT_NAME)) { // found expected error element return true; } } return false; } // determine whether the reader contains an unexpected error element private boolean hasExpectedErrorElement() throws ServiceException { getXMLStreamReader(); if (!(m_xmlReader instanceof ObjectNodeBuilder)) { return false; } // get the expected error element name QName errElementName = getExpectedErrorElementQName(); if (errElementName == null) return false; if (m_xmlReader != null) { if (m_xmlReader.getName().equals(ObjectNodeImpl.ROOT_NODE_QNAME)) { // if it is at root, consumes the root to get the child try { m_xmlReader.next(); } catch (XMLStreamException e) { throw new ServiceException(ErrorDataFactory.createErrorData(ErrorConstants.SVC_DATA_READ_ERROR, ErrorConstants.ERRORDOMAIN)); } } if (m_xmlReader.getName().equals(errElementName)) { // found expected error element return true; } } return false; } /* (non-Javadoc) * @see org.ebayopensource.turmeric.runtime.common.impl.pipeline.BaseMessageImpl#cleanupData() */ @Override protected void cleanupData() { super.cleanupData(); m_inputStream = null; m_xmlReader = null; m_noStream = false; } /* (non-Javadoc) * @see org.ebayopensource.turmeric.runtime.common.pipeline.InboundMessage#setInputStream(java.io.InputStream) */ public void setInputStream(InputStream is) throws ServiceException { setInputStream(is, InboundMessageAttachments.IN_MEMORY_ATTACHMENT_LIMIT); } /* (non-Javadoc) * @see com.ebay.soaframework.common.pipeline.InboundMessage#setInputStream(java.io.InputStream) */ public void setInputStream(InputStream is, Integer inMemoryAttachmentLimit) throws ServiceException { if (is == null) { throw new NullPointerException(); } if (hasContext() && getContext().isOutboundRawMode()) { if (m_byteBuffer == null) { // We are operating in streaming mode ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] buf = new byte[4096]; int n; try { while ((n = is.read(buf)) != -1) { baos.write(buf, 0, n); } m_byteBuffer = ByteBuffer.wrap(baos.toByteArray()); } catch (IOException e) { // add error to the context if we could not read the stream ServiceException e2 = new ServiceException( ErrorDataFactory.createErrorData(ErrorConstants.SVC_RT_CANNOT_READ_FROM_STREAM, ErrorConstants.ERRORDOMAIN, new Object[] {e.toString()}), e); getContext().addError(e2); } if (m_byteBuffer == null) { // At this point we must have a byte buffer throw new IllegalStateException("ByteBuffer in InboundMessageImpl cannot be null when OutboundRawMode is true"); } processInboundHeaders(); return; } } checkNotCleaned(); if (m_inputStream != null) { throw new IllegalStateException("InputStream is already set on InboundMessageImpl"); } if (m_hasParamsByRef) { throw new IllegalStateException("InputStream cannot be set after setting params by reference"); } if (m_noStream) { throw new IllegalStateException("InboundMessageImpl is in no-stream mode"); } InboundMessageAttachments attachments = InboundMessageAttachments.createInboundAttachments(is, this, inMemoryAttachmentLimit); if (null != attachments) { m_attachments = attachments; InputStream rootInputStream = m_attachments.getInputStreamForMasterMessage(); is = rootInputStream; } if(isBufferingMode()) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] temp = new byte[4096]; int n; try { while ((n = is.read(temp)) != -1) { baos.write(temp, 0, n); } m_inputStream = new ByteArrayInputStream(baos.toByteArray()); } catch (IOException e) { ServiceException se = new ServiceException( ErrorDataFactory.createErrorData(ErrorConstants.SVC_RT_CANNOT_READ_FROM_STREAM, ErrorConstants.ERRORDOMAIN, new Object[] {e.toString()}), e); getContext().addError(se); } } else { m_inputStream = is; } startRecording(); if (hasAttachment()) { ((InboundMessageAttachments)m_attachments).setInputStream(m_inputStream); } processInboundHeaders(); } private void processInboundHeaders() throws ServiceException { if (!hasContext()) { return; } Map<String,String> transportHeaders = getTransportHeadersNoCopy(); getContextImpl().processInboundHeaders(transportHeaders); } public void setParamReferences(Object[] params) throws ServiceException { if (params == null) { throw new NullPointerException(); } checkNotCleaned(); if (m_inputStream != null) { throw new IllegalStateException("InputStream is already set on InboundMessageImpl"); } // TODO - deal with errors - getParamTypes does not work for errors if (getParamTypes().size() != params.length) { throw new ServiceException(ErrorDataFactory.createErrorData(ErrorConstants.SVC_RT_MSG_PARAM_COUNT_MISMATCH, ErrorConstants.ERRORDOMAIN, new Object[] {Integer.valueOf(getParamTypes().size()), Integer.valueOf(params.length)})); } if (params.length > 0) { m_params = new Object[params.length]; } for (int i = 0; i < params.length; i++) { setParamInt(i, params[i]); } m_hasParamsByRef = true; m_deserCompleted = true; processInboundHeaders(); } public void setErrorResponseReference(Object errorResponse) throws ServiceException { if (errorResponse == null) { throw new NullPointerException(); } checkNotCleaned(); if (m_inputStream != null) { throw new IllegalStateException("InputStream is already set on InboundMessageImpl"); } Class errorJavaType = getErrorParamType(); if (!errorJavaType.isAssignableFrom(errorResponse.getClass())) { throw new ServiceException(ErrorDataFactory.createErrorData(ErrorConstants.SVC_RT_MSG_INCOMPATIBLE_SET, ErrorConstants.ERRORDOMAIN, new Object[] {errorResponse.getClass().getName(), errorJavaType.getName()})); } m_errorResponse = errorResponse; m_hasParamsByRef = true; m_deserCompleted = true; processInboundHeaders(); } public void setErrorResponse(Object errorResponse) throws ServiceException { if (errorResponse == null) { throw new NullPointerException(); } m_errorResponse = errorResponse; } public Object getErrorResponseInternal() throws ServiceException { return m_errorResponse; } public void recordPayload(int maxBytes) throws ServiceException { checkNotCleaned(); if (maxBytes > m_maxBytesToRecord) { m_maxBytesToRecord = maxBytes; if (m_inputStream != null) { startRecording(); } } } private void startRecording() { if (m_maxBytesToRecord == 0 || m_recordingStream != null) { // already recording or no need to record return; } m_recordingStream = new PrereadingRawDataRecorder(m_inputStream, m_maxBytesToRecord); m_inputStream = m_recordingStream; } public byte[] getRecordedData() throws ServiceException { if (m_recordingStream == null) { return null; } try { return m_recordingStream.getRawByteData(); } catch (IOException e) { // add error to the context as we could not read the stream ServiceException e2 = new ServiceException(ErrorDataFactory.createErrorData(ErrorConstants.SVC_RT_CANNOT_READ_FROM_STREAM, ErrorConstants.ERRORDOMAIN, new Object[] {e.toString()}), e); getContext().addError(e2); return null; } } /* (non-Javadoc) * @see org.ebayopensource.turmeric.runtime.common.pipeline.InboundMessage#unableToProvideStream() */ public void unableToProvideStream() { if (m_noStream || hasCleanedData()) { return; } if (m_inputStream != null && m_hasParamsByRef) { // a failure happened after input stream was set.. // let's not fail and continue with exception processing return; } m_noStream = true; } /* (non-Javadoc) * @see org.ebayopensource.turmeric.runtime.common.pipeline.InboundMessage#getXMLStreamReader() */ public XMLStreamReader getXMLStreamReader() throws ServiceException { if (m_xmlReader != null) { return m_xmlReader; } checkNotCleaned(); if (!isRequestMessage()) { // for client inbound message checkExectedPayload(); } if (m_deserCompleted) { throw new ServiceException(ErrorDataFactory.createErrorData(ErrorConstants.SVC_RT_MSG_DESER_COMPLETE, ErrorConstants.ERRORDOMAIN)); } if (m_hasParamsByRef) { throw new IllegalStateException("Stream Reader cannot be used after setting params by reference"); } if (m_inputStream == null) { throw new IllegalStateException("InputStream is not set on InboundMessageImpl"); } DeserializerFactory deserFactory = getDataBindingDesc().getDeserializerFactory(); List<Class> paramTypes; if (hasErrorTransportHeader()) { paramTypes = getErrorParamTypeList(); } else { paramTypes = getParamTypes(); } XMLStreamReader reader = deserFactory.getXMLStreamReader(this, paramTypes, m_inputStream); String msgProtocol = getContextImpl().getMessageProtocol(); try { if (SOAConstants.MSG_PROTOCOL_SOAP_11.equals(msgProtocol) || SOAConstants.MSG_PROTOCOL_SOAP_12.equals(msgProtocol)) { m_xmlReader = new SOAPObjectNodeStreamReader(reader); } else { m_xmlReader = new ObjectNodeStreamReader(reader); } } catch (Exception e) { throw new ServiceException(ErrorDataFactory.createErrorData( ErrorConstants.SVC_DATA_XML_STREAM_READER_CREATION_ERROR, ErrorConstants.ERRORDOMAIN, new Object[] { getPayloadType() }), e); } return m_xmlReader; } private void checkExectedPayload() throws ServiceException { String actualPayloadTypeName = getTransportHeader(SOAHeaders.RESPONSE_DATA_FORMAT); String expectedPayloadTypeName = getPayloadType(); if (actualPayloadTypeName != null && !actualPayloadTypeName.equalsIgnoreCase(expectedPayloadTypeName)) { throw new ServiceException(ErrorDataFactory.createErrorData(ErrorConstants.SVC_DATA_UNEXPECTED_SERVER_RESPONSE_FORMAT, ErrorConstants.ERRORDOMAIN, new Object[] {actualPayloadTypeName, expectedPayloadTypeName})); } } private QName getExpectedErrorElementQName() throws ServiceException { ServiceOperationDesc opDesc = getOperationDesc(); ServiceOperationParamDesc errParamDesc = opDesc.getErrorType(); QName errElementName = errParamDesc.getXmlNameForJavaType(errParamDesc.getRootJavaTypes().get(0)); return errElementName; } private ObjectNode consumeMessageBodyRootElement(Deserializer deser, Class javaType) throws ServiceException { ObjectNode rootElement = null; List<ObjectNode> childNodesList = null; try { // get the root child of the Message Body childNodesList = getMessageBody().getChildNodes(); if (childNodesList != null && childNodesList.size() > 0) { rootElement = childNodesList.get(0); } // At the end, force deserialization here to advance the reader deser.deserialize(this, javaType); return rootElement; } catch (XMLStreamException e) { throw new ServiceException(ErrorDataFactory.createErrorData(ErrorConstants.SVC_DATA_READ_ERROR, ErrorConstants.ERRORDOMAIN, new Object[] {e.getMessage()}), e); } } /** * This method transforms any aliased headers present per configuration * * @throws ServiceException */ public void doHeaderMapping() throws ServiceException { processInboundHeaders(); } public Class<?> getInputStreamClass() { return m_inputStream == null ? null : m_inputStream.getClass(); } private Object processQueryParameters(Map<String, String> queryParams, Charset charset, Class<?> paramType, Object toReturn) { if(queryParams == null || queryParams.isEmpty()) { return toReturn; } Set<Map.Entry<String, String>> entries = queryParams.entrySet(); String encoding = charset.name(); for(Map.Entry<String, String> e: entries) { try { setValue(URLDecoder.decode(e.getKey(), encoding), URLDecoder.decode(e.getValue(), encoding), toReturn, paramType); } catch (UnsupportedEncodingException e1) { getLogger().log(Level.WARNING, "Specified encoding '" + encoding + "' is not valid"); } } return toReturn; } private void setValue(String key, String value, Object obj, Class<?> type) { Field[] fields = type.getDeclaredFields(); for(Field field: fields) { field.setAccessible(true); } int index = key.indexOf("."); try { if(index > -1) { String fname = key.substring(0, index); Field f = type.getDeclaredField(fname); f.setAccessible(true); setValue(key.substring(index+1), value, f.get(obj), f.getType()); } else { Field f = type.getDeclaredField(key); f.setAccessible(true); setFieldValue(obj, f, value); } } catch (Exception ignored) { // Ignore the exception // Exceptions may occur for arrays and Maps. // Collections are not supported in SOA 2.8 } } private void setFieldValue(Object o, Field f, String v) throws IllegalArgumentException, IllegalAccessException { Object val = adaptType(v, f.getType(), f.getName(), o); if(val != null) { f.set(o, val); } } @SuppressWarnings("unchecked") private static <T> T adaptType(String from, Class<T> to, String field, Object obj) { T returnObject = null; if (to == String.class) { returnObject = (T) from; } else if (to == Integer.class || to == int.class) { returnObject = (T) Integer.valueOf(from); } else if (to == Long.class || to == long.class) { returnObject = (T) Long.valueOf(from); } else if (to == boolean.class || to == Boolean.class) { returnObject = (T) Boolean.valueOf(from); } else if (to == Short.class || to == short.class) { returnObject = (T) Short.valueOf(from); } else if (to == Double.class || to == double.class) { returnObject = (T) Double.valueOf(from); } else if (to == Float.class || to == float.class) { returnObject = (T) Float.valueOf(from); } else if (to == Byte.class || to == byte.class) { returnObject = (T) Byte.valueOf(from); } else if (to == Character.class || to == char.class) { returnObject = (T) Character.valueOf(from.charAt(0)); } return returnObject; } }