Package com.totsp.gwittir.service

Source Code of com.totsp.gwittir.service.StreamServiceUtils

/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.totsp.gwittir.service;

import com.google.gwt.user.client.rpc.IncompatibleRemoteServiceException;
import com.google.gwt.user.client.rpc.SerializationException;
import com.google.gwt.user.server.rpc.RPCRequest;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import com.google.gwt.user.server.rpc.SerializationPolicy;
import com.google.gwt.user.server.rpc.SerializationPolicyProvider;
import com.google.gwt.user.server.rpc.impl.ServerSerializationStreamReader;

import com.google.gwt.user.server.rpc.impl.ServerSerializationStreamWriter;
import java.lang.reflect.Method;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;


/**
*
* @author kebernet
*/
public class StreamServiceUtils {
    private static final HashMap<String, Class<?>> TYPE_NAMES;

    /**
     * Maps primitive wrapper classes to their corresponding primitive class.
     */
    private static final Map<Class<?>, Class<?>> PRIMITIVE_WRAPPER_CLASS_TO_PRIMITIVE_CLASS =
        new HashMap<Class<?>, Class<?>>();

    /**
     * Static map of classes to sets of interfaces (e.g. classes). Optimizes
     * lookup of interfaces for security.
     */
    private static Map<Class<?>, Set<String>> serviceToImplementedInterfacesMap;

    static {
        PRIMITIVE_WRAPPER_CLASS_TO_PRIMITIVE_CLASS.put(Boolean.class,
            Boolean.TYPE);
        PRIMITIVE_WRAPPER_CLASS_TO_PRIMITIVE_CLASS.put(Byte.class, Byte.TYPE);
        PRIMITIVE_WRAPPER_CLASS_TO_PRIMITIVE_CLASS.put(Character.class,
            Character.TYPE);
        PRIMITIVE_WRAPPER_CLASS_TO_PRIMITIVE_CLASS.put(Double.class, Double.TYPE);
        PRIMITIVE_WRAPPER_CLASS_TO_PRIMITIVE_CLASS.put(Float.class, Float.TYPE);
        PRIMITIVE_WRAPPER_CLASS_TO_PRIMITIVE_CLASS.put(Integer.class,
            Integer.TYPE);
        PRIMITIVE_WRAPPER_CLASS_TO_PRIMITIVE_CLASS.put(Long.class, Long.TYPE);
        PRIMITIVE_WRAPPER_CLASS_TO_PRIMITIVE_CLASS.put(Short.class, Short.TYPE);

        TYPE_NAMES = new HashMap<String, Class<?>>();
        TYPE_NAMES.put("Z", boolean.class);
        TYPE_NAMES.put("B", byte.class);
        TYPE_NAMES.put("C", char.class);
        TYPE_NAMES.put("D", double.class);
        TYPE_NAMES.put("F", float.class);
        TYPE_NAMES.put("I", int.class);
        TYPE_NAMES.put("J", long.class);
        TYPE_NAMES.put("S", short.class);

        serviceToImplementedInterfacesMap = new HashMap<Class<?>, Set<String>>();
    }

    public static RPCRequest decodeRequest(String encodedRequest,
        Class<?> type, SerializationPolicyProvider serializationPolicyProvider) {
        if (encodedRequest == null) {
            throw new NullPointerException("encodedRequest cannot be null");
        }

        if (encodedRequest.length() == 0) {
            throw new IllegalArgumentException("encodedRequest cannot be empty");
        }

        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();

        try {
            ServerSerializationStreamReader streamReader = new ServerSerializationStreamReader(classLoader,
                    serializationPolicyProvider);
            streamReader.prepareToRead(encodedRequest);

            // Read the name of the RemoteService interface
            String serviceIntfName = streamReader.readString();

            //            if (type != null) {
            //                if (!implementsInterface(type, serviceIntfName)) {
            //                    // The service does not implement the requested interface
            //                    throw new IncompatibleRemoteServiceException(
            //                        "Blocked attempt to access interface '" +
            //                        serviceIntfName + "', which is not implemented by '" +
            //                        printTypeName(type) +
            //                        "'; this is either misconfiguration or a hack attempt");
            //                }
            //            }
            SerializationPolicy serializationPolicy = streamReader.getSerializationPolicy();

            //            Class<?> serviceIntf;

            //            try {
            //                serviceIntf = getClassFromSerializedName(serviceIntfName,
            //                        classLoader);
            //
            //                if (!RemoteService.class.isAssignableFrom(serviceIntf)) {
            //                    // The requested interface is not a RemoteService interface
            //                    throw new IncompatibleRemoteServiceException(
            //                        "Blocked attempt to access interface '" +
            //                        printTypeName(serviceIntf) +
            //                        "', which doesn't extend RemoteService; this is either misconfiguration or a hack attempt");
            //                }
            //            } catch (ClassNotFoundException e) {
            //                throw new IncompatibleRemoteServiceException(
            //                    "Could not locate requested interface '" + serviceIntfName +
            //                    "' in default classloader", e);
            //            }
            String serviceMethodName = streamReader.readString();

            int paramCount = streamReader.readInt();
            Class<?>[] parameterTypes = new Class[paramCount];

            for (int i = 0; i < parameterTypes.length; i++) {
                String paramClassName = streamReader.readString();

                try {
                    parameterTypes[i] = getClassFromSerializedName(paramClassName,
                            classLoader);
                } catch (ClassNotFoundException e) {
                    throw new IncompatibleRemoteServiceException("Parameter " +
                        i + " of is of an unknown type '" + paramClassName +
                        "'", e);
                }
            }

            try {
                Method method = type.getMethod(serviceMethodName, parameterTypes);

                Object[] parameterValues = new Object[parameterTypes.length];

                for (int i = 0; i < parameterValues.length; i++) {
                    parameterValues[i] = streamReader.deserializeValue(parameterTypes[i]);
                }

                return new RPCRequest(method, parameterValues,
                    serializationPolicy);
            } catch (NoSuchMethodException e) {
                throw new IncompatibleRemoteServiceException(formatMethodNotFoundErrorMessage(
                        type, serviceMethodName, parameterTypes));
            }
        } catch (SerializationException ex) {
            throw new IncompatibleRemoteServiceException(ex.getMessage(), ex);
        }
    }

    /**
    * Returns the {@link Class} instance for the named class or primitive type.
    *
    * @param serializedName the serialized name of a class or primitive type
    * @param classLoader the classLoader used to load {@link Class}es
    * @return Class instance for the given type name
    * @throws ClassNotFoundException if the named type was not found
    */
    private static Class<?> getClassFromSerializedName(String serializedName,
        ClassLoader classLoader) throws ClassNotFoundException {
        Class<?> value = TYPE_NAMES.get(serializedName);

        if (value != null) {
            return value;
        }

        return Class.forName(serializedName, false, classLoader);
    }

    /**
     * Straight copy from
     * {@link com.google.gwt.dev.util.TypeInfo#getSourceRepresentation(Class)} to
     * avoid runtime dependency on gwt-dev.
     */
    private static String printTypeName(Class<?> type) {
        // Primitives
        //
        if (type.equals(Integer.TYPE)) {
            return "int";
        } else if (type.equals(Long.TYPE)) {
            return "long";
        } else if (type.equals(Short.TYPE)) {
            return "short";
        } else if (type.equals(Byte.TYPE)) {
            return "byte";
        } else if (type.equals(Character.TYPE)) {
            return "char";
        } else if (type.equals(Boolean.TYPE)) {
            return "boolean";
        } else if (type.equals(Float.TYPE)) {
            return "float";
        } else if (type.equals(Double.TYPE)) {
            return "double";
        }

        // Arrays
        //
        if (type.isArray()) {
            Class<?> componentType = type.getComponentType();

            return printTypeName(componentType) + "[]";
        }

        // Everything else
        //
        return type.getName().replace('$', '.');
    }

    /**
    * Used to determine whether the specified interface name is implemented by
    * the service class. This is done without loading the class (for security).
    */
    private static boolean implementsInterface(Class<?> service, String intfName) {
        synchronized (serviceToImplementedInterfacesMap) {
            // See if it's cached.
            //
            Set<String> interfaceSet = serviceToImplementedInterfacesMap.get(service);

            if (interfaceSet != null) {
                if (interfaceSet.contains(intfName)) {
                    return true;
                }
            } else {
                interfaceSet = new HashSet<String>();
                serviceToImplementedInterfacesMap.put(service, interfaceSet);
            }

            if (!service.isInterface()) {
                while ((service != null) &&
                        !RemoteServiceServlet.class.equals(service)) {
                    Class<?>[] intfs = service.getInterfaces();

                    for (Class<?> intf : intfs) {
                        if (implementsInterfaceRecursive(intf, intfName)) {
                            interfaceSet.add(intfName);

                            return true;
                        }
                    }

                    // did not find the interface in this class so we look in the
                    // superclass
                    //
                    service = service.getSuperclass();
                }
            } else {
                if (implementsInterfaceRecursive(service, intfName)) {
                    interfaceSet.add(intfName);

                    return true;
                }
            }

            return false;
        }
    }

    /**
     * Only called from implementsInterface().
     */
    private static boolean implementsInterfaceRecursive(Class<?> clazz,
        String intfName) {
        assert (clazz.isInterface());

        if (clazz.getName().equals(intfName)) {
            return true;
        }

        // search implemented interfaces
        Class<?>[] intfs = clazz.getInterfaces();

        for (Class<?> intf : intfs) {
            if (implementsInterfaceRecursive(intf, intfName)) {
                return true;
            }
        }

        return false;
    }

    private static String formatMethodNotFoundErrorMessage(
        Class<?> serviceIntf, String serviceMethodName,
        Class<?>[] parameterTypes) {
        StringBuffer sb = new StringBuffer();

        sb.append("Could not locate requested method '");
        sb.append(serviceMethodName);
        sb.append("(");

        for (int i = 0; i < parameterTypes.length; ++i) {
            if (i > 0) {
                sb.append(", ");
            }

            sb.append(printTypeName(parameterTypes[i]));
        }

        sb.append(")'");

        sb.append(" in interface '");
        sb.append(printTypeName(serviceIntf));
        sb.append("'");

        return sb.toString();
    }

    //
    /**
   * Returns a string that encodes the results of an RPC call. Private overload
   * that takes a flag signaling the preamble of the response payload.
   *
   * @param object the object that we wish to send back to the client
   * @param wasThrown if true, the object being returned was an exception thrown
   *          by the service method; if false, it was the result of the service
   *          method's invocation
   * @return a string that encodes the response from a service method
   * @throws SerializationException if the object cannot be serialized
   */
  public static String encodeResponse(Class<?> responseClass, Object object,
      boolean wasThrown, SerializationPolicy serializationPolicy)
      throws SerializationException {

    ServerSerializationStreamWriter stream = new ServerSerializationStreamWriter(
        serializationPolicy);

    stream.prepareToWrite();
    if (responseClass != void.class) {
      stream.serializeValue(object, responseClass);
    }

    String bufferStr = (wasThrown ? "//EX" : "//OK") + stream.toString();
    return bufferStr;
  }
}
TOP

Related Classes of com.totsp.gwittir.service.StreamServiceUtils

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.