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.

There is a newer version: 3.0.2-RELEASE
Show 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.dwrp.ParseUtil;
import org.directwebremoting.dwrp.ProtocolConstants;
import org.directwebremoting.extend.InboundContext;
import org.directwebremoting.extend.InboundVariable;
import org.directwebremoting.extend.MarshallException;
import org.directwebremoting.extend.Property;
import org.directwebremoting.extend.TypeHintContext;
import org.directwebremoting.impl.PropertyDescriptorProperty;
import org.directwebremoting.util.LocalUtil;
import org.directwebremoting.util.Messages;

/**
 * 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 iv, InboundContext inctx) throws MarshallException
    {
        String value = iv.getValue();

        logger.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))
        {
            throw new MarshallException(paramType, Messages.getString("BeanConverter.FormatError", ProtocolConstants.INBOUND_MAP_START));
        }

        if (!value.endsWith(ProtocolConstants.INBOUND_MAP_END))
        {
            throw new MarshallException(paramType, Messages.getString("BeanConverter.FormatError", ProtocolConstants.INBOUND_MAP_START));
        }

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

        try
        {
            if (instanceType != null)
            {
                Class.forName(instanceType.getName());
            }
            else
            {
                Class.forName(paramType.getName());
            }

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

            if (factory == null)
            {
                logger.error("XmlObject.Factory method not found for Class [" + paramType.toString() + "]");
                throw new MarshallException(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)
            {
                inctx.addConverted(iv, instanceType, bean);
            }
            else
            {
                inctx.addConverted(iv, 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();

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

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

                    logger.debug("- The javascript may be refer to a property that does not exist");
                    logger.debug("- You may be missing the correct setter: set" + Character.toTitleCase(key.charAt(0)) + key.substring(1) + "()");
                    logger.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(',');
                        }
                    }
                    logger.debug("Fields exist for (" + all + ").");
                    continue;
                }

                Class propType = property.getPropertyType();

                String[] split = ParseUtil.splitInbound(val);
                String splitValue = split[LocalUtil.INBOUND_INDEX_VALUE];
                String splitType = split[LocalUtil.INBOUND_INDEX_TYPE];

                InboundVariable nested = new InboundVariable(iv.getLookup(), null, splitType, splitValue);
                nested.dereference();

                TypeHintContext incc = createTypeHintContext(inctx, property);

                Object output = converterManager.convertInbound(propType, nested, inctx, incc);
                property.setValue(bean, output);
            }

            return bean;
        }
        catch (MarshallException ex)
        {
            throw ex;
        }
        catch (Exception ex)
        {
            throw new MarshallException(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 MarshallException
    {
        try
        {
            if (!XmlObject.class.isAssignableFrom(paramType))
            {
                throw new MarshallException(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 && descriptor.getWriteMethod() == 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 MarshallException(paramType, ex);
        }

    }

    private static StringEnumAbstractBaseConverter enumConverter = new StringEnumAbstractBaseConverter();

    private static Log logger = LogFactory.getLog(XmlBeanConverter.class);
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy