Package com.khs.sherpa.servlet.request

Source Code of com.khs.sherpa.servlet.request.DefaultSherpaRequest

package com.khs.sherpa.servlet.request;

/*
* Copyright 2012 the original author or authors.
*
* 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.
*/

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.annotation.security.DenyAll;
import javax.annotation.security.RolesAllowed;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.sf.cglib.proxy.Enhancer;

import org.apache.commons.lang3.StringUtils;
import org.reflections.ReflectionUtils;
import org.reflections.Reflections;

import com.google.common.base.Predicates;
import com.khs.sherpa.annotation.Action;
import com.khs.sherpa.annotation.Endpoint;
import com.khs.sherpa.annotation.Param;
import com.khs.sherpa.context.ApplicationContext;
import com.khs.sherpa.context.ApplicationContextAware;
import com.khs.sherpa.events.RequestEvent;
import com.khs.sherpa.exception.NoSuchManagedBeanExcpetion;
import com.khs.sherpa.exception.SherpaActionNotFoundException;
import com.khs.sherpa.exception.SherpaPermissionExcpetion;
import com.khs.sherpa.exception.SherpaRuntimeException;
import com.khs.sherpa.json.service.Authentication;
import com.khs.sherpa.json.service.JsonProvider;
import com.khs.sherpa.json.service.SessionStatus;
import com.khs.sherpa.json.service.SessionToken;
import com.khs.sherpa.json.service.SessionTokenService;
import com.khs.sherpa.processor.DefaultRequestProcessor;
import com.khs.sherpa.processor.RequestProcessor;
import com.khs.sherpa.processor.RestfulRequestProcessor;
import com.khs.sherpa.servlet.RequestMapper;
import com.khs.sherpa.util.Constants;
import com.khs.sherpa.util.JsonUtil;
import com.khs.sherpa.util.MethodUtil;
import com.khs.sherpa.util.SherpaPredicates;
import com.khs.sherpa.util.Util;

public class DefaultSherpaRequest implements SherpaRequest {

  private static Logger logger = Logger.getLogger(DefaultSherpaRequest.class.getSimpleName());
 
  private Map<String, Object> attributes = new LinkedHashMap<String, Object>();
  private ApplicationContext applicationContext;
  private HttpServletRequest request;
  private HttpServletResponse response;
  private RequestProcessor requestProcessor;
 
  public Object getAttribute(String name) {
    return attributes.get(name);
  }

  public void setAttribute(String name, Object object) {
    attributes.put(name, object);
  }
 
  public void doService(HttpServletRequest request, HttpServletResponse response) {
    this.request = request;
    this.response = response;
   
    Collection<RequestEvent> events = applicationContext.getManagedBeans(RequestEvent.class);
    for(RequestEvent event: events) {
      event.before(applicationContext, request, response);
    }
   
    ServletOutputStream output = null;
    JsonProvider jsonProvider = null;
    try {
      output = response.getOutputStream();
      jsonProvider = applicationContext.getManagedBean(JsonProvider.class);
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
   
    String callback = null;
    if ((Boolean)applicationContext.getAttribute(ApplicationContext.SETTINGS_JSONP)) {
      callback = request.getParameter("callback");
    }
   
    // set the correct Content type
    response.setContentType("application/json");
    if(callback != null) {
      response.setContentType("text/javascript");
    }
   
    try {
      JsonUtil.map(this.proccess(), jsonProvider, output, callback);
    } catch (RuntimeException e) {
      e.printStackTrace();
      JsonUtil.error(e.getMessage(), jsonProvider, output, callback);
      throw e;
    }
   
    for(RequestEvent event: events) {
      event.after(applicationContext, request, response);
    }
  }
 
  @SuppressWarnings("unchecked")
  protected Object proccess() throws SherpaRuntimeException {
    if(!isRestful()) {
      requestProcessor = new DefaultRequestProcessor();
    } else {
      requestProcessor = new RestfulRequestProcessor(applicationContext);
    }
   
    String endpoint = requestProcessor.getEndpoint(request);
    String action = requestProcessor.getAction(request);
    String httpMethod = request.getMethod();
   
    if(StringUtils.isEmpty(endpoint)) {
      if(action.equals(Constants.AUTHENTICATE_ACTION)) {
        return this.processAuthenication();
      } else if(action.equals(Constants.VALID)) {
        return this.processValid();
      }
    }
   
    Object target = null;
    Set<Method> methods = null;
   
    try {
      String userid = request.getHeader("userid");
      if(userid == null) {
        userid = request.getParameter("userid");
      }
      String token = request.getHeader("token");
      if(token == null) {
        token = request.getParameter("token");
      }
     
      this.hasPermission(applicationContext.getType(endpoint), userid, token);
     
      target = applicationContext.getManagedBean(endpoint);
     
      if(ApplicationContextAware.class.isAssignableFrom(target.getClass())) {
        ((ApplicationContextAware)target).setApplicationContext(applicationContext);
      }
     
      methods = Reflections.getAllMethods(applicationContext.getType(endpoint),
            Predicates.and(
                Predicates.not(SherpaPredicates.withAssignableFrom(Object.class)),
                ReflectionUtils.withModifier(Modifier.PUBLIC),
                Predicates.not(ReflectionUtils.withModifier(Modifier.ABSTRACT)),
                Predicates.not(SherpaPredicates.withGeneric()),
                Predicates.and(SherpaPredicates.withAssignableFrom(Enhancer.isEnhanced(target.getClass())? target.getClass().getSuperclass(): target.getClass())),
                Predicates.or(
                    ReflectionUtils.withName(action),
                    Predicates.and(
                        ReflectionUtils.withAnnotation(Action.class),
                        SherpaPredicates.withActionAnnotationValueEqualTo(action)
                      )
                  ))
            );
     
      if(methods.size() == 0) {
        throw new SherpaActionNotFoundException(action);
      }
     
    } catch (NoSuchManagedBeanExcpetion e) {
      throw new SherpaRuntimeException(e);
    }
   
    return this.processEndpoint(target, methods.toArray(new Method[] {}), httpMethod);
  }
 
  protected Object processEndpoint(Object target, Method[] methods, String httpMethod) {
    Method method = MethodUtil.validateHttpMethods(methods, httpMethod);
    String userid = request.getHeader("userid");
    if(userid == null) {
      userid = request.getParameter("userid");
    }
    String token = request.getHeader("token");
    if(token == null) {
      token = request.getParameter("token");
    }
   
    this.hasPermission(method, userid, token);
    Action annotation = method.getAnnotation(Action.class);
    if (annotation == null) {
      throw new SherpaRuntimeException("Error executing"+target+" @Action annotation required for not endpoint methods"  );
    }
    if(annotation.contentType() != null) {
      response.setContentType(method.getAnnotation(Action.class).contentType().type);
    }
    return this.invokeMethod(target, method)
  }
 
  protected void hasPermission(Class<?> target, String userid, String token) {
    SessionTokenService service = null;
    try {
      service = applicationContext.getManagedBean(SessionTokenService.class);
    } catch (NoSuchManagedBeanExcpetion e) {
      throw new SherpaRuntimeException(e);
    }
   
    // make sure Endpoint Authentication is turned on
    if((Boolean)applicationContext.getAttribute(ApplicationContext.SETTINGS_ENDPOINT_AUTH) == false) {
      return;
    }
   
    Endpoint endpoint = null;
    if(Enhancer.isEnhanced(target)) {
      endpoint = target.getSuperclass().getAnnotation(Endpoint.class);
    } else {
      endpoint = target.getAnnotation(Endpoint.class);
    }
   
    // make sure its authenicated
    if(endpoint.authenticated() && !service.isActive(userid, token).equals(SessionStatus.AUTHENTICATED)) {
      throw new SherpaPermissionExcpetion("User status [" + service.isActive(userid, token) + "]", service.isActive(userid, token).toString());
    }
  }
 
  protected void hasPermission(Method method, String userid, String token) {
    SessionTokenService service = null;
    try {
      service = applicationContext.getManagedBean(SessionTokenService.class);
    } catch (NoSuchManagedBeanExcpetion e) {
      throw new SherpaRuntimeException(e);
    }

    if(method.isAnnotationPresent(DenyAll.class)) {
      throw new SherpaPermissionExcpetion("method ["+method.getName()+"] in class ["+method.getDeclaringClass().getCanonicalName()+"] has `@DenyAll` annotation", "DENY_ALL");
    }
   
    if(method.isAnnotationPresent(RolesAllowed.class)) {
      boolean fail = true;
      for(String role: method.getAnnotation(RolesAllowed.class).value()) {
        if(service.hasRole(userid, token, role)) {
          fail = false;
        }
      }
      if(fail) {
        throw new SherpaPermissionExcpetion("method ["+method.getName()+"] in class ["+method.getDeclaringClass().getCanonicalName()+"] has `@RolesAllowed` annotation", "DENY_ROLE" );
      }
    }
  }
 
  protected Object processValid()  throws SherpaRuntimeException {
    String userid = request.getParameter("userid");
    String token = request.getParameter("token");
   
    SessionTokenService service = null;
    Map<String, Object> resp = new HashMap<String, Object>();
    try {
      service = applicationContext.getManagedBean(SessionTokenService.class);
    } catch (NoSuchManagedBeanExcpetion e) {
      throw new SherpaRuntimeException(e);
    }

    resp.put("userid", userid);
    resp.put("token", token);
    resp.put("status", service.isActive(userid, token));
    return resp;
   
  }
 
  protected Object processAuthenication() throws SherpaRuntimeException {
    String userid = request.getParameter("userid");
    String password = request.getParameter("password");
    try {
      Authentication authentication = new Authentication(applicationContext);
      SessionToken token = authentication.authenticate(userid, password, request, response);
     
      boolean hasAdminRole = applicationContext.getManagedBean(SessionTokenService.class)
        .hasRole(token.getUserid(), token.getToken(), (String) applicationContext.getAttribute(ApplicationContext.SETTINGS_ADMIN_USER));
     
      // load the sherpa admin user
      if(hasAdminRole) {
        String[] roles = token.getRoles();
        token.setRoles(Util.append(roles, "SHERPA_ADMIN"));
      }
      return token;
    } catch (NoSuchManagedBeanExcpetion e) {
      throw new SherpaRuntimeException(e);
    }
  }
 
  protected Object invokeMethod(Object target, Method method){
    try {
      Object obj = method.invoke(target, this.getParams(method));
      return obj;
    } catch (Exception e) {
        if(e.getCause() != null && e.getCause().getClass().isAssignableFrom(SherpaRuntimeException.class)) {
          logger.throwing(target.getClass().getName(), method.getName(), e.getCause());
          throw new SherpaRuntimeException(e.getCause().getMessage());
        }
        logger.throwing(target.getClass().getName(), method.getName(), e);
      throw new SherpaRuntimeException("unable to execute method ["+method.getName()+"] in class ["+target.getClass().getCanonicalName()+"]", e);
    } finally {
     
    }
  }
 
  private Object[] getParams(Method method) {
    RequestMapper map = new RequestMapper();
    map.setApplicationContext(applicationContext);
    map.setRequest(request);
    map.setResponse(response);
    map.setRequestProcessor(requestProcessor);
    Class<?>[] types = method.getParameterTypes();
    Object[] params = null;
    // get parameters
    if(types.length > 0) {
      params = new Object[types.length];
    }
   
    Annotation[][] parameters = method.getParameterAnnotations();
    for(int i=0; i<parameters.length; i++) {
      Class<?> type = types[i];
      Annotation annotation = null;
      if(parameters[i].length > 0 ) {
        for(Annotation an: parameters[i]) {
          if(an.annotationType().isAssignableFrom(Param.class)) {
            annotation = an;
            break;
          }
        }
       
      }
      params[i] = map.map(method.getClass().getName(),method.getName(),type, annotation)
    }
    return params;
  }
 
  private boolean isRestful() {
    String path = request.getContextPath();
    if(path.equals("/")) {
      path = request.getServletPath();
    } else {
      path += request.getServletPath();
    }
    return !path.equals(request.getRequestURI());
  }
 
  @Action(disabled = true)
  public void setApplicationContext(ApplicationContext applicationContext) {
    this.applicationContext = applicationContext;
  }
 
}
TOP

Related Classes of com.khs.sherpa.servlet.request.DefaultSherpaRequest

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.