Java tutorial
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; } }