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

org.meruvian.inca.struts2.rest.discoverer.DefaultActionFinder Maven / Gradle / Ivy

/**
 * Copyright 2012 BlueOxygen Technology
 *
 * 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 org.meruvian.inca.struts2.rest.discoverer;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtField;
import javassist.CtMethod;
import javassist.CtNewMethod;
import javassist.NotFoundException;

import org.apache.struts2.StrutsConstants;
import org.meruvian.inca.struts2.rest.annotation.Action;
import org.meruvian.inca.struts2.rest.annotation.Action.HttpMethod;
import org.meruvian.inca.struts2.rest.annotation.ActionParam;
import org.meruvian.inca.struts2.rest.annotation.ExceptionMappings;
import org.meruvian.inca.struts2.rest.annotation.Interceptors;
import org.meruvian.inca.struts2.rest.annotation.Result;
import org.meruvian.inca.struts2.rest.annotation.Results;
import org.meruvian.inca.struts2.rest.commons.ActionUtils;
import org.meruvian.inca.struts2.rest.commons.RestConstants;
import org.meruvian.inca.struts2.rest.commons.StringUtils;

import com.opensymphony.xwork2.inject.Container;
import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.util.PatternMatcher;
import com.opensymphony.xwork2.util.finder.Test;

/**
 * @author Dian Aditya
 * 
 */
public class DefaultActionFinder implements ActionFinder {

	private Test filter;
	private PatternMatcher patternMatcher;

	private Map actionForRequest;
	private Map actionForClassName;
	private ClassPool pool;
	private StrutsAnnotationDiscoverer discoverer;

	private Map> actionClasses = new HashMap>();

	@Inject
	public DefaultActionFinder(Container container) throws Exception {
		this.filter = container.getInstance(Test.class, container.getInstance(
				String.class, RestConstants.INCA_ACTION_FILTER));
		this.patternMatcher = container.getInstance(PatternMatcher.class,
				container.getInstance(String.class,
						StrutsConstants.STRUTS_PATTERNMATCHER));
		this.pool = ClassPool.getDefault();
		this.discoverer = new StrutsAnnotationDiscoverer(filter);

		actionForClassName = new HashMap();
		actionForRequest = new ActionPool(patternMatcher);

		List annotatedClasses = discoverer
				.discoverClassesForAnnotation(Action.class);
		for (String classname : annotatedClasses) {
			buildActionFromMethod(classname);
		}
	}

	protected void buildActionFromMethod(String classname) throws Exception {
		List methods = discoverer.discoverAnnotatedMethods(classname,
				Action.class);

		CtClass actionclass = pool.get(classname);
		// Create proxyObject
		actionclass.setName(classname + "$$$ActionProxy");
		actionclass.setSuperclass(pool.get(classname));

		buildClassProperty(classname, actionclass);

		for (String method : methods) {
			CtMethod actionMethod = actionclass.getDeclaredMethod(method);
			ActionDetails details = buildActionDetails(actionclass,
					actionMethod);

			// actionForRequest.put(details.getRequestUri(), details);
			actionForRequest.put(details, details);
			actionForClassName.put(actionclass.getName(), details);
		}

		{
			ActionDetails details = buildActionDetails(actionclass, null);

			actionForRequest.put(details, details);
			actionForClassName.put(actionclass.getName(), details);
		}
	}

	private ActionDetails buildActionDetails(CtClass actionClass,
			CtMethod actionMethod) throws Exception {

		if (actionMethod == null) {
			try {
				actionMethod = actionClass.getDeclaredMethod("execute");
			} catch (NotFoundException e) {
			}
		}

		Action classAnnotation = ActionUtils.findActionAnnotation(actionClass);
		Action methodAnnotation = ActionUtils.findAnnotation(actionMethod,
				Action.class);
		Interceptors interceptors = ActionUtils.findAnnotation(actionMethod,
				Interceptors.class);
		ExceptionMappings exceptionMappings = ActionUtils.findAnnotation(
				actionMethod, ExceptionMappings.class);

		Results actionResults = ActionUtils.findAnnotation(actionClass,
				Results.class);
		Results methodResults = ActionUtils.findAnnotation(actionMethod,
				Results.class);

		ActionDetails details = new ActionDetails();

		if (methodAnnotation == null) {
			details.setActionMethod("execute");
			details.setActionAnnotation(classAnnotation);
		} else {
			details.setActionMethod(actionMethod.getName());
			details.setActionAnnotation(methodAnnotation);
		}

		Class generatedActionclass = actionClasses
				.get(actionClass.getName());

		if (generatedActionclass == null) {
			generatedActionclass = actionClass.toClass();
			actionClasses.put(actionClass.getName(), generatedActionclass);
		}

		details.setActionClass(generatedActionclass);
		details.setNamespace(ActionUtils.getUriFromAnnotation(classAnnotation));
		details.setAction(ActionUtils.getUriFromAnnotation(methodAnnotation));
		details.setHttpMethod(details.getActionAnnotation().method());
		details.setInterceptors(interceptors);
		details.setExceptionMappings(exceptionMappings);

		if (actionResults != null) {
			for (Result result : actionResults.value()) {
				details.getActionResults().put(result.name(), result);
			}
		}

		if (methodResults != null) {
			for (Result result : methodResults.value()) {
				details.getActionResults().put(result.name(), result);
			}
		}

		return details;
	}

	public void buildClassProperty(String classname, CtClass actionClass)
			throws Exception {
		List fields = discoverer.discoverAnnotatedFields(classname,
				ActionParam.class);

		for (String fieldName : fields) {
			CtField field = actionClass.getDeclaredField(fieldName);
			ActionParam param = (ActionParam) field
					.getAnnotation(ActionParam.class);

			String fieldValue = param.value();

			CtMethod getter = CtNewMethod.getter(
					"get" + StringUtils.toCamelCase(fieldValue), field);
			CtMethod setter = CtNewMethod.setter(
					"set" + StringUtils.toCamelCase(fieldValue), field);

			actionClass.addMethod(getter);
			actionClass.addMethod(setter);
		}
	}

	@Override
	public ActionDetails findAction(String namespace, String action,
			String httpMethod) {
		ActionDetails details = new ActionDetails(namespace, action,
				HttpMethod.fromString(httpMethod));

		return actionForRequest.get(details);

	}

	@Override
	public ActionDetails findActionClass(String className) {
		return actionForClassName.get(className);
	}

	protected static class ActionPool extends
			LinkedHashMap {

		private PatternMatcher patternMatcher;

		public ActionPool(PatternMatcher patternMatcher) {
			this.patternMatcher = patternMatcher;
		}

		private boolean httpMethodMatch(ActionDetails details,
				ActionDetails request) {
			return (HttpMethod.ALL.equals(details.getHttpMethod()) || request
					.getHttpMethod().equals(details.getHttpMethod()));
		}

		@Override
		public ActionDetails get(Object key) {
			if (key == null || !(key instanceof ActionDetails))
				return null;

			ActionDetails detailsKey = (ActionDetails) key;
			for (java.util.Map.Entry e : entrySet()) {
				ActionDetails details = e.getKey();

				Object o = patternMatcher.compilePattern(details
						.getRequestUri());

				Map map = new HashMap();
				if (details.getRequestUri().equals(detailsKey.getRequestUri())) {
					if (httpMethodMatch(details, detailsKey))
						return e.getValue();
				} else if (patternMatcher.match(map,
						detailsKey.getRequestUri(), o)) {
					if (httpMethodMatch(details, detailsKey)) {
						details = e.getValue();
						details.setParameter(map);

						return details;
					}
				}
			}

			return null;
		}

		// @Override
		// public ActionDetails get(Object key) {
		// if (key == null)
		// return null;
		//
		// for (String k : keySet()) {
		// Object o = patternMatcher.compilePattern(k);
		// Map map = new HashMap();
		// if (patternMatcher.match(map, (String) key, o)) {
		// ActionDetails details = super.get(k);
		// details.setParameter(map);
		// return details;
		// }
		// }
		//
		// ActionDetails action = super.get(key);
		// if (action != null)
		// return action;
		//
		// return null;
		// }
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy