All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.directwebremoting.convert.XmlBeanConverter Maven / Gradle / Ivy

Go to download

DWR is easy Ajax for Java. It makes it simple to call Java code directly from Javascript. It gets rid of almost all the boiler plate code between the web browser and your Java code.

The newest version!
/*
 * Copyright 2005 Joe Walker
 *
 * 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.directwebremoting.convert;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.xmlbeans.XmlObject;
import org.directwebremoting.ConversionException;
import org.directwebremoting.extend.InboundVariable;
import org.directwebremoting.extend.Property;
import org.directwebremoting.extend.PropertyDescriptorProperty;
import org.directwebremoting.extend.ProtocolConstants;
import org.directwebremoting.util.LocalUtil;

/**
 * A Converter for Apache XMLBeans.
 * @author Joe Walker [joe at getahead dot ltd dot uk]
 * @author Matthew Young [matthew dot young at forsakringskassan dot se]
 */
public class XmlBeanConverter extends BeanConverter
{
    /* (non-Javadoc)
     * @see org.directwebremoting.extend.Converter#convertInbound(java.lang.Class, org.directwebremoting.extend.InboundVariable, org.directwebremoting.extend.InboundContext)
     */
    @Override
    public Object convertInbound(Class paramType, InboundVariable data) throws ConversionException
    {
        if (data == null)
        {
            return null;
        }

        String value = data.getValue();

        log.debug("handling variable (" + value + ") for class (" + paramType.getName() + ")");

        // If the text is null then the whole bean is null
        if (value.trim().equals(ProtocolConstants.INBOUND_NULL))
        {
            return null;
        }

        if (!value.startsWith(ProtocolConstants.INBOUND_MAP_START) || !value.endsWith(ProtocolConstants.INBOUND_MAP_END))
        {
            log.warn("Expected object while converting data for " + paramType.getName() + " in " + data.getContext().getCurrentProperty() + ". Passed: " + value);
            throw new ConversionException(paramType, "Data conversion error. See logs for more details.");
        }

        value = value.substring(1, value.length() - 1);

        try
        {
            if (instanceType != null)
            {
               LocalUtil.classForName(instanceType.getName());
            }
            else
            {
                LocalUtil.classForName(paramType.getName());
            }

            Class[] innerClasses = paramType.getClasses();
            Class factory = null;
            for (Class aClass : innerClasses)
            {
                if (aClass.getName().endsWith("Factory"))
                {
                    factory = aClass;
                }
            }

            if (factory == null)
            {
                log.error("XmlObject.Factory method not found for Class [" + paramType.toString() + "]");
                throw new ConversionException(paramType, "XmlObject.Factory method not found");
            }

            Class[] emptyArglist = new Class[0];
            Method newInstance = factory.getMethod("newInstance", emptyArglist);
            Object bean = newInstance.invoke(null, (Object[]) emptyArglist);

            if (instanceType != null)
            {
                data.getContext().addConverted(data, instanceType, bean);
            }
            else
            {
                data.getContext().addConverted(data, paramType, bean);
            }

            Map properties = getPropertyMapFromClass(paramType, false, true);

            // Loop through the properties passed in
            Map tokens = extractInboundTokens(paramType, value);
            for (Entry entry : tokens.entrySet())
            {
                String key = entry.getKey();
                String val = entry.getValue();

                log.debug("token entry (" + key + ") with value (" + val + ")");

                Property property = properties.get(key);
                if (property == null)
                {
                    log.warn("Missing java bean property to match javascript property: " + key + ". For causes see debug level logs:");

                    log.debug("- The javascript may be refer to a property that does not exist");
                    log.debug("- You may be missing the correct setter: set" + Character.toTitleCase(key.charAt(0)) + key.substring(1) + "()");
                    log.debug("- The property may be excluded using include or exclude rules.");

                    StringBuffer all = new StringBuffer();
                    for (Iterator pit = properties.keySet().iterator(); pit.hasNext();)
                    {
                        all.append(pit.next());
                        if (pit.hasNext())
                        {
                            all.append(',');
                        }
                    }
                    log.debug("Fields exist for (" + all + ").");
                    continue;
                }

                Class propType = property.getPropertyType();

                Object output = convert(val, propType, data.getContext(), property);
                property.setValue(bean, output);
            }

            return bean;
        }
        catch (ConversionException ex)
        {
            throw ex;
        }
        catch (Exception ex)
        {
            throw new ConversionException(paramType, ex);
        }
    }

    /* (non-Javadoc)
     * @see org.directwebremoting.convert.BeanConverter#getPropertyMapFromClass(java.lang.Class, boolean, boolean)
     */
    @Override
    public Map getPropertyMapFromClass(Class paramType, boolean readRequired, boolean writeRequired) throws ConversionException
    {
        try
        {
            if (!XmlObject.class.isAssignableFrom(paramType))
            {
                throw new ConversionException(paramType, "class (" + paramType.getName() + ") not assignable from XmlObject");
            }

            Class beanInterface;
            if (paramType.isInterface())
            {
                beanInterface = paramType;
            }
            else
            {
                beanInterface = paramType.getInterfaces()[0];
            }

            Class superInterface = (Class) beanInterface.getGenericInterfaces()[0];

            Map properties = new HashMap();

            while (XmlObject.class.isAssignableFrom(superInterface))
            {
                BeanInfo info = Introspector.getBeanInfo(beanInterface);
                PropertyDescriptor[] descriptors = info.getPropertyDescriptors();

                for (int i = 0; i < descriptors.length; i++)
                {
                    PropertyDescriptor descriptor = descriptors[i];
                    String name = descriptor.getName();
                    String type = descriptor.getPropertyType().getName();

                    // register Enum types
                    if (type.matches(".*\\$Enum"))
                    {
                        getConverterManager().addConverter(type, enumConverter);
                    }

                    // We don't marshall getClass()
                    if ("class".equals(name))
                    {
                        continue;
                    }

                    // Access rules mean we might not want to do this one
                    if (!isAllowedByIncludeExcludeRules(name))
                    {
                        continue;
                    }

                    if (readRequired && descriptor.getReadMethod() == null)
                    {
                        continue;
                    }

                    if (writeRequired && LocalUtil.getWriteMethod(paramType, descriptor) == null)
                    {
                        continue;
                    }

                    properties.put(name, new PropertyDescriptorProperty(descriptor));
                }

                beanInterface = (Class) beanInterface.getGenericInterfaces()[0];
                superInterface = (Class) beanInterface.getGenericInterfaces()[0];
            }

            return properties;
        }
        catch (IntrospectionException ex)
        {
            throw new ConversionException(paramType, ex);
        }

    }

    /**
     * This used to be static, but there's a chance that could fail when there
     * is more than 1 DWR servlet in a given context.
     */
    private final StringEnumAbstractBaseConverter enumConverter = new StringEnumAbstractBaseConverter();

    /**
     * The log stream
     */
    private static Log log = LogFactory.getLog(XmlBeanConverter.class);
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy