public final static String SHERPA_NOT_INITIALIZED = "SHERPA_SERVER_NOT_INITIALIZED->"; public static String msg(String msg) {
	return SHERPA_SERVER+msg;	
} 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(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(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 {

		}
	}

	protected boolean isEnhanced(Class clazz) {
		return Enhancer.isEnhanced(clazz);
	}

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

} public class Encode {
	
	public static final String XML = "XML";
	public static final String HTML = "HTML";
	public static final String CSV = "CSV";

} public class DefaultActivityService implements ActivityService {
	
	private static final Logger LOGGER = LoggerFactory.getLogger(DefaultActivityService.class);

	public void logActivity(String userid, String activity) {
		LOGGER.info(msg(userid+":"+activity));
	}

} public class DefaultTokenService implements SessionTokenService {

	public Map<String, SessionToken> tokens = new LinkedHashMap<String, SessionToken>();

	private SecureRandom random = new SecureRandom();
	
	public String newToken(String userid) {
		return new BigInteger(130, random).toString(32);
	}

	public SessionStatus isActive(String userid, String tokenId) {

		SessionToken token = tokens.get(tokenId);
		if (token == null) {
			return SessionStatus.NOT_AUTHENTICATED;
		}

		if (token.getToken().equals(tokenId) && token.getUserid().equals(userid)) {

			// validate timeout
			long current = System.currentTimeMillis();
			if (token.getTimeout() > 0 && current - token.getLastActive() > token.getTimeout()) {
				return SessionStatus.TIMED_OUT;
			}			
		} else {
			return SessionStatus.INVALID_TOKEN;
		}

		return SessionStatus.AUTHENTICATED;
	}

	public void activate(String userid, SessionToken token) {
		tokens.put(token.getToken(), token);
	}

	private void deactivate(String token) {
		tokens.remove(token);
	}
	
	public void deactivateUser(String userid) {
		
		 List<String> users = new ArrayList<String>();	
		 for (SessionToken session : tokens.values()) {
			 if (session.getUserid().equals(userid)) {
				 users.add(session.getToken()); 
			 }
		  }		 
		 // deactivate tokens
		 for (String token : users) {
			 deactivate(token);
		 }
		
	}
	
    public List<SessionToken> sessions() {
	   
	   List<SessionToken> results = new ArrayList<SessionToken>();
	   for (SessionToken token : tokens.values()) {
		   results.add(token);
	   }
	  	   
	   return results;
	   
   }

	public boolean hasRole(String userid, String tokenId, String role) {
		SessionToken token = tokens.get(tokenId);
		if (token == null) {
			return false;
		}
		if(token.getRoles() != null) {
			for(String r: token.getRoles()) {
				if(r.equals(role) == true) {
					return true;
				}
			}
		}
		
		return false;
	}
	
	
	

} public class DefaultUserService implements UserService {

	public String[] authenticate(String username, String password, HttpServletRequest request, HttpServletResponse response) {
		// Default always fails authentication
		throw new SherpaInvalidUsernamePassword("Authentication Error Invalid Credentials");	
	}
} public class GsonJsonProvider implements JsonProvider {

	public String toJson(Object object) {
		Gson gson = new Gson();
		return gson.toJson(object);
	}

	public <T> T toObject(String json, Class<T> type) {
		Gson gson = new Gson();
		return gson.fromJson(json, type);
	}
	
} public class SherpaServlet extends HttpServlet {

	private static final long serialVersionUID = 4345668988238038540L;	
	
	private static final Logger LOGGER = LoggerFactory.getLogger(SherpaServlet.class);

	@Override
	public void init() throws ServletException {
		super.init();
	}

	private void doService(HttpServletRequest request, HttpServletResponse response) throws RuntimeException, IOException {
		try {

			ApplicationContext applicationContext = GenericApplicationContext.getApplicationContext(getServletContext());

			SherpaRequest sherpaRequest = applicationContext.getManagedBean(DefaultSherpaRequest.class);
			sherpaRequest.setApplicationContext(applicationContext);

			sherpaRequest.doService(request, response);
			
		} catch (SherpaInvalidUsernamePassword e) {
			response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
			response.setContentType("application/json");
			LOGGER.info(msg("INFO "+e.getMessage() ));			
		} catch (SherpaRuntimeException e) {
			response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
			response.setContentType("application/json");
			LOGGER.error(msg("ERROR "+e.getMessage() ));
		} catch (Exception e) {
			response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
			response.setContentType("application/json");
		} finally {
			// do nothing right now
		}
	}
	
	@Override
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doService(request, response);
	}

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doService(request, response);
	}

	@Override
	protected void doPut(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doService(request, response);
	}

	@Override
	protected void doDelete(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doService(request, response);
	}

	@Override
	protected long getLastModified(HttpServletRequest req) {
		return super.getLastModified(req);
	}

	@Override
	protected void doHead(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		super.doHead(req, resp);
	}
	
	@Override
	protected void doOptions(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		super.doOptions(req, resp);
	}

	@Override
	protected void doTrace(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		super.doTrace(req, resp);
	}
	
}
 public class Defaults {
	
	public final static String DATE_FORMAT = "MM/dd/yyyy";
	public final static String DATE_TIME_FORMAT = "MM/dd/yyyy hh:mm:ss a";
	public final static long SESSION_TIMEOUT = 0;
	public final static boolean ENDPOINT_AUTHENTICATION = false;
	public final static String BOOLEAN_FORMAT = "0";
	public final static boolean ACTIVITY_LOG = true;
	public final static String ENCODE = null;
	public final static String SHERPA_ADMIN = "ROLE_ADMIN";
	public final static boolean JSONP_SUPPORT = false;
	public final static Class<? extends JsonProvider> JSON_PROVIDER = GsonJsonProvider.class;

	public final static Class<?> BOOLEAN_PARAM_PARSER = BooleanParamParser.class;
	public final static Class<?> CALENDAR_PARAM_PARSER = CalendarParamParser.class;
	public final static Class<?> DATE_PARAM_PARSER = DateParamParser.class;
	public final static Class<?> DOULBE_PARAM_PARSER = DoubleParamPaser.class;
	public final static Class<?> FLOAT_PARAM_PARSER = FloatParamParser.class;
	public final static Class<?> INTEGER_PARAM_PARSER = IntegerParamParser.class;
	public final static Class<?> JSON_PARAM_PARSER = JsonParamParser.class;
	public final static Class<?> STRING_PARAM_PARSER = StringParamParser.class;
	
}
import com.khs.sherpa.json.service.DefaultActivityService;
import com.khs.sherpa.json.service.DefaultTokenService;
import com.khs.sherpa.json.service.DefaultUserService;
import com.khs.sherpa.json.service.GsonJsonProvider;
import com.khs.sherpa.servlet.SherpaServlet;
import com.khs.sherpa.util.Defaults;
import static com.khs.sherpa.util.Constants.SHERPA_NOT_INITIALIZED;
import static com.khs.sherpa.util.Util.msg;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import com.khs.sherpa.servlet.request.DefaultSherpaRequest;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.khs.sherpa.annotation.Encode;
package com.khs.sherpa;

/*
 * 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.
 */





public class SherpaSettings {

	private static Logger LOGGER = LoggerFactory.getLogger(SherpaSettings.class);
	
	public static final String SETTINGS_SHERPA_CONTEXT = "com.khs.sherpa.SETTINGS_SHERPA_CONTEXT";
	public static final String SETTINGS_SERVER_URL = "com.khs.sherpa.SETTINGS_SERVER_URL";
	public static final String SETTINGS_SERVER_TOKEN = "com.khs.sherpa.SETTINGS_SERVER_TOKEN";
	
	protected Properties properties;
	
	public SherpaSettings(String configFile) {
		
		try {
			
			InputStream in = null;
			if(configFile.startsWith("classpath:")) {
				in = SherpaServlet.class.getClassLoader().getResourceAsStream(configFile.substring("classpath:".length()));
			} else {
				in = new FileInputStream(configFile);
			}
		    if (in != null) {
		    	properties = new Properties();
		    	properties.load(in);
		    	LOGGER.info(msg("sherpa properties loaded"));