/*
 * Copyright 2009 Google Inc.
 * 
 * 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 com.google.gwt.rpc.server;

import com.google.gwt.rpc.client.ast.CommandSink;
import com.google.gwt.rpc.client.ast.HasValues;
import com.google.gwt.rpc.client.ast.ReturnCommand;
import com.google.gwt.rpc.client.ast.RpcCommand;
import com.google.gwt.rpc.client.ast.ThrowCommand;
import com.google.gwt.rpc.client.impl.HasValuesCommandSink;
import com.google.gwt.rpc.client.impl.RemoteException;
import com.google.gwt.user.client.rpc.IncompatibleRemoteServiceException;
import com.google.gwt.user.client.rpc.RemoteService;
import com.google.gwt.user.client.rpc.SerializationException;
import com.google.gwt.user.server.rpc.RPCRequest;

import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * EXPERIMENTAL and subject to change. Do not use this in production code.
 * <p>
 * Utility class for integrating with the RPC system.
 */
public class RPC {

  private static final HashMap<String, Class<?>> TYPE_NAMES = new HashMap<String, Class<?>>();

  /**
   * Static map of classes to sets of interfaces (e.g. classes). Optimizes
   * lookup of interfaces for security.
   */
  private static final Map<Class<?>, Set<String>> serviceToImplementedInterfacesMap = new com.google.gwt.dev.util.collect.HashMap<Class<?>, Set<String>>();

  static {
    // The space is needed to prevent name collisions
    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);
  }

  public static RPCRequest decodeRequest(String encodedRequest, Class<?> type,
      ClientOracle clientOracle) throws RemoteException {
    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 {
      SimplePayloadDecoder decoder;
      try {
        decoder = new SimplePayloadDecoder(clientOracle, encodedRequest);
      } catch (ClassNotFoundException e) {
        throw new IncompatibleRemoteServiceException(
            "Client does not have a type sent by the server", e);
      }
      CommandServerSerializationStreamReader streamReader = new CommandServerSerializationStreamReader();
      if (decoder.getThrownValue() != null) {
        streamReader.prepareToRead(Collections.singletonList(decoder.getThrownValue()));
        try {
          throw new RemoteException((Throwable) streamReader.readObject());
        } catch (ClassCastException e) {
          throw new SerializationException(
              "The remote end threw something other than a Throwable", e);
        } catch (SerializationException e) {
          throw new IncompatibleRemoteServiceException(
              "The remote end threw an exception which could not be deserialized",
              e);
        }
      } else {
        streamReader.prepareToRead(decoder.getValues());
      }

      // 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");
        }
      }

      Class<?> serviceIntf;
      try {
        serviceIntf = getClassFromSerializedName(null, serviceIntfName,
            classLoader);
        if (!RemoteService.class.isAssignableFrom(serviceIntf)) {
          // The requested interface is not a RpcService interface
          throw new IncompatibleRemoteServiceException(
              "Blocked attempt to access interface '"
                  + printTypeName(serviceIntf)
                  + "', which doesn't extend RpcService; "
                  + "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(clientOracle,
              paramClassName, classLoader);
        } catch (ClassNotFoundException e) {
          throw new IncompatibleRemoteServiceException("Parameter " + i
              + " of is of an unknown type '" + paramClassName + "'", e);
        }
      }

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

        Object[] parameterValues = new Object[parameterTypes.length];
        for (int i = 0; i < parameterValues.length; i++) {
          Object o = CommandSerializationUtil.getAccessor(parameterTypes[i]).readNext(
              streamReader);
          parameterValues[i] = o;
        }

        return new RPCRequest(method, parameterValues, null, 0);

      } catch (NoSuchMethodException e) {
        throw new IncompatibleRemoteServiceException(
            formatMethodNotFoundErrorMessage(serviceIntf, serviceMethodName,
                parameterTypes));
      }
    } catch (SerializationException ex) {
      throw new IncompatibleRemoteServiceException(ex.getMessage(), ex);
    }
  }

  public static void invokeAndStreamResponse(Object target,
      Method serviceMethod, Object[] args, ClientOracle clientOracle,
      OutputStream stream) throws SerializationException {
    if (serviceMethod == null) {
      throw new NullPointerException("serviceMethod");
    }

    if (clientOracle == null) {
      throw new NullPointerException("clientOracle");
    }

    CommandSink sink;
    try {
      sink = clientOracle.createCommandSink(stream);
    } catch (IOException e) {
      throw new SerializationException("Unable to initialize output", e);
    }

    try {
      Object result = serviceMethod.invoke(target, args);
      try {
        streamResponse(clientOracle, result, sink, false);
      } catch (SerializationException e) {
        streamResponse(clientOracle, e, sink, true);
      }

    } catch (IllegalAccessException e) {
      SecurityException securityException = new SecurityException(
          formatIllegalAccessErrorMessage(target, serviceMethod));
      securityException.initCause(e);
      throw securityException;
    } catch (IllegalArgumentException e) {
      SecurityException securityException = new SecurityException(
          formatIllegalArgumentErrorMessage(target, serviceMethod, args));
      securityException.initCause(e);
      throw securityException;
    } catch (InvocationTargetException e) {
      // Try to encode the caught exception
      //
      Throwable cause = e.getCause();

      streamResponse(clientOracle, cause, sink, true);
    }
    sink.finish();
  }

  public static void streamResponseForFailure(ClientOracle clientOracle,
      OutputStream out, Throwable payload) throws SerializationException {
    CommandSink sink;
    try {
      sink = clientOracle.createCommandSink(out);
    } catch (IOException e) {
      throw new SerializationException("Unable to initialize output", e);
    }
    streamResponse(clientOracle, payload, sink, true);
    sink.finish();
  }

  public static void streamResponseForSuccess(ClientOracle clientOracle,
      OutputStream out, Object payload) throws SerializationException {
    CommandSink sink;
    try {
      sink = clientOracle.createCommandSink(out);
    } catch (IOException e) {
      throw new SerializationException("Unable to initialize output", e);
    }
    streamResponse(clientOracle, payload, sink, false);
    sink.finish();
  }

  private static String formatIllegalAccessErrorMessage(Object target,
      Method serviceMethod) {
    StringBuffer sb = new StringBuffer();
    sb.append("Blocked attempt to access inaccessible method '");
    sb.append(getSourceRepresentation(serviceMethod));
    sb.append("'");

    if (target != null) {
      sb.append(" on target '");
      sb.append(printTypeName(target.getClass()));
      sb.append("'");
    }

    sb.append("; this is either misconfiguration or a hack attempt");

    return sb.toString();
  }

  private static String formatIllegalArgumentErrorMessage(Object target,
      Method serviceMethod, Object[] args) {
    StringBuffer sb = new StringBuffer();
    sb.append("Blocked attempt to invoke method '");
    sb.append(getSourceRepresentation(serviceMethod));
    sb.append("'");

    if (target != null) {
      sb.append(" on target '");
      sb.append(printTypeName(target.getClass()));
      sb.append("'");
    }

    sb.append(" with invalid arguments");

    if (args != null && args.length > 0) {
      sb.append(Arrays.asList(args));
    }

    return sb.toString();
  }

  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 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(ClientOracle clientOracle,
      String serializedName, ClassLoader classLoader)
      throws ClassNotFoundException {
    Class<?> value = TYPE_NAMES.get(serializedName);
    if (value != null) {
      return value;
    }

    // Interfaces don't exist in the client, so we use unobfuscated names
    if (serializedName.charAt(0) == ' ') {
      serializedName = serializedName.substring(1);
    } else if (clientOracle != null) {
      serializedName = clientOracle.getTypeName(serializedName);
    }
    assert serializedName != null;

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

  /**
   * Returns the source representation for a method signature.
   * 
   * @param method method to get the source signature for
   * @return source representation for a method signature
   */
  private static String getSourceRepresentation(Method method) {
    return method.toString().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) && !RpcServlet.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;
    }
  }

  /**
   * Recursive helper for 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;
  }

  /**
   * 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('$', '.');
  }

  private static void streamResponse(ClientOracle clientOracle, Object payload,
      CommandSink sink, boolean asThrow) throws SerializationException {
    HasValues command;
    if (asThrow) {
      command = new ThrowCommand();
      assert payload instanceof Throwable : "Trying to throw something other than a Throwable";
      // payload = new RemoteException((Throwable) payload);
    } else {
      command = new ReturnCommand();
    }

    CommandServerSerializationStreamWriter out = new CommandServerSerializationStreamWriter(
        clientOracle, new HasValuesCommandSink(command));

    out.writeObject(payload);

    sink.accept((RpcCommand) command);
  }

  private RPC() {
  }
}
