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

io.ingenieux.lambada.invoker.UserHandlerFactory Maven / Gradle / Ivy

/*
 * Copyright (c) 2016 ingenieux Labs
 *
 * 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 io.ingenieux.lambada.invoker;

import com.amazonaws.services.lambda.runtime.Context;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.lang.reflect.Type;

public abstract class UserHandlerFactory {

  public abstract UserHandler getUserHandler(Object o, Method m);

  public static class NoOpUserHandlerFactory extends UserHandlerFactory {

    public UserHandler getUserHandler(Object o, Method m) {
      if (0 == m.getParameterCount() && hasReturnType(m, Void.TYPE)) {
        return new UserHandler(o, m) {
          @Override
          public void invoke(InputStream is, OutputStream os, Context c) throws Exception {
            m.invoke(o);
          }
        };
      }

      if (hasReturnType(m, Void.TYPE) && hasParameterTypes(m, Context.class)) {
        return new UserHandler(o, m) {
          public void invoke(InputStream is, OutputStream os, Context c) throws Exception {
            m.invoke(o, c);
          }
        };
      }

      return null;
    }
  }

  public static class RawUserHandlerFactory extends UserHandlerFactory {

    public UserHandler getUserHandler(Object o, Method m) {
      if (1 == m.getParameterCount() && hasReturnType(m, Void.TYPE) && hasParameterTypes(m, InputStream.class)) {
        return new UserHandler(o, m) {
          @Override
          public void invoke(InputStream is, OutputStream os, Context c) throws Exception {
            m.invoke(o, is);
          }
        };
      }

      if (2 == m.getParameterCount() && hasReturnType(m, Void.TYPE) && hasParameterTypes(m, InputStream.class, Context.class)) {
        return new UserHandler(o, m) {
          @Override
          public void invoke(InputStream is, OutputStream os, Context c) throws Exception {
            m.invoke(o, is, c);
          }
        };
      }

      if (1 == m.getParameterCount() && hasReturnType(m, Void.TYPE) && hasParameterTypes(m, OutputStream.class)) {
        return new UserHandler(o, m) {
          @Override
          public void invoke(InputStream is, OutputStream os, Context c) throws Exception {
            m.invoke(o, os);
          }
        };
      }

      if (2 == m.getParameterCount() && hasReturnType(m, Void.TYPE) && hasParameterTypes(m, OutputStream.class, Context.class)) {
        return new UserHandler(o, m) {
          @Override
          public void invoke(InputStream is, OutputStream os, Context c) throws Exception {
            m.invoke(o, os, c);
          }
        };
      }

      if (2 == m.getParameterCount() &&
          hasReturnType(m, Void.TYPE) &&
          hasParameterTypes(m, InputStream.class, OutputStream.class)) {
        return new UserHandler(o, m) {
          @Override
          public void invoke(InputStream is, OutputStream os, Context c) throws Exception {
            m.invoke(o, is, os);
          }
        };
      }

      if (3 == m.getParameterCount() &&
                 hasReturnType(m, Void.TYPE) &&
                 hasParameterTypes(m, InputStream.class, OutputStream.class, Context.class)) {
        return new UserHandler(o, m) {
          public void invoke(InputStream is, OutputStream os, Context c) throws Exception {
            m.invoke(o, is, os, c);
          }
        };
      }

      return null;
    }
  }

  public static class JacksonAbleUserHandlerFactory extends UserHandlerFactory {

    final ObjectMapper OBJECT_MAPPER = new ObjectMapper();

    public UserHandler getUserHandler(Object o, final Method m) {
      if (1 == m.getParameterCount() &&
          hasJacksonAbleParameters(m, m.getParameterTypes()[0]) && Void.TYPE.equals(m.getReturnType())) {
        return new UserHandler(o, m) {
          @Override
          public void invoke(InputStream is, OutputStream os, Context ctx) throws Exception {
            Object inputArgument = OBJECT_MAPPER.readValue(is, m.getParameterTypes()[0]);

            m.invoke(o, inputArgument);
          }
        };
      }

      if (1 == m.getParameterCount() && hasJacksonAbleParameters(m, m.getParameterTypes()[0],
                                                                 m.getReturnType())) {
        return new UserHandler(o, m) {
          @Override
          public void invoke(InputStream is, OutputStream os, Context ctx) throws Exception {
            Object inputArgument = OBJECT_MAPPER.readValue(is, m.getParameterTypes()[0]);

            Object result = m.invoke(o, inputArgument);

            OBJECT_MAPPER.writeValue(os, result);
          }
        };
      }

      if (2 == m.getParameterCount() &&
                 m.getParameterTypes()[1] == Context.class &&
                 hasJacksonAbleParameters(m, m.getParameterTypes()[0], m.getReturnType())) {
        return new UserHandler(o, m) {
          @Override
          public void invoke(InputStream is, OutputStream os, Context ctx) throws Exception {
            Object inputArgument = OBJECT_MAPPER.readValue(is, m.getParameterTypes()[0]);

            Object result = m.invoke(o, inputArgument, ctx);

            OBJECT_MAPPER.writeValue(os, result);
          }
        };
      }

      return null;
    }

    protected boolean hasJacksonAbleParameters(Method m, Type... types) {
      for (Type t : types) {
        try {
          JavaType javaType = (JavaType) OBJECT_MAPPER.getTypeFactory().constructType(t);

          boolean serializeP = OBJECT_MAPPER.canSerialize((Class) t);
          boolean deserializeP = OBJECT_MAPPER.canDeserialize(javaType);

          if (! (serializeP && deserializeP))
            return false;
        } catch (IllegalArgumentException e) {
          return false;
        }
      }

      return true;
    }
  }

  protected boolean hasReturnType(Method m, Class t) {
    return m.getReturnType().equals(t);
  }

  protected boolean hasParameterTypes(Method m, Class... types) {
    int i = 0;

    for (Class t : types) {
      if (!t.equals(m.getParameterTypes()[i])) {
        return false;
      }

      i++;
    }
    return true;
  }

  private static final UserHandlerFactory[] factories = new UserHandlerFactory[] {
      new NoOpUserHandlerFactory(),
      new RawUserHandlerFactory(),
      new JacksonAbleUserHandlerFactory(),
      };


  public static UserHandler findUserFactory(Object o, Method m) {
    UserHandler h = null;

    for (UserHandlerFactory f : factories) {
      h = f.getUserHandler(o, m);

      if (null != h) {
        break;
      }
    }

    return h;
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy