<commit_before>/*
    Weave (Web-based Analysis and Visualization Environment)
    Copyright (C) 2008-2011 University of Massachusetts Lowell

    This file is a part of Weave.

    Weave is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License, Version 3,
    as published by the Free Software Foundation.

    Weave is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Weave.  If not, see <http://www.gnu.org/licenses/>.
*/

package weave.servlets;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.rmi.RemoteException;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import java.util.zip.DeflaterOutputStream;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.IOUtils;
import org.postgresql.util.Base64;

import weave.beans.JsonRpcErrorModel;
import weave.beans.JsonRpcRequestModel;
import weave.beans.JsonRpcResponseModel;
import weave.utils.CSVParser;
import weave.utils.ListUtils;
import weave.utils.MapUtils;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonNull;
import com.google.gson.JsonParseException;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import com.heatonresearch.httprecipes.html.PeekableInputStream;
import com.thoughtworks.paranamer.BytecodeReadingParanamer;
import com.thoughtworks.paranamer.Paranamer;

import flex.messaging.MessageException;
import flex.messaging.io.SerializationContext;
import flex.messaging.io.amf.ASObject;
import flex.messaging.io.amf.Amf3Input;
import flex.messaging.io.amf.Amf3Output;
import flex.messaging.messages.ErrorMessage;

/**
 * This class provides a servlet interface to a set of functions.
 * The functions may be invoked using URL parameters via HTTP GET using url parameters
 * or via HTTP POST using JSON RPC 2.0 or AMF3-serialized objects.
 * If using URL variables or JSON RPC 2.0, the return value will be provided as a JSON RPC 2.0 response object.
 * If using AMF3, the return value will be provided as compressed AMF3.
 * 
 * @author skota
 * @author adufilie
 * @author skolman
 */

public class WeaveServlet extends HttpServlet
{
	private static final long serialVersionUID = 1L;
	public static long debugThreshold = 1000;
	
	/**
	 * The name of the property which contains the remote method name.
	 */
	protected final String METHOD = "method";
	/**
	 * The name of the property which contains method parameters.
	 */
	protected final String PARAMS = "params";
	/**
	 * The name of the property which specifies the index in the params Array that corresponds to an InputStream.
	 */
	protected final String STREAM_PARAMETER_INDEX = "streamParameterIndex";
	
	private Map<String, ExposedMethod> methodMap = new HashMap<String, ExposedMethod>(); //Key: methodName
	private Paranamer paranamer = new BytecodeReadingParanamer(); // this gets parameter names from Methods
	
	/**
	 * This class contains a Method with its parameter names and class instance.
	 */
	private class ExposedMethod
	{
		public ExposedMethod(Object instance, Method method, String[] paramNames)
		{
			this.instance = instance;
			this.method = method;
			this.paramNames = paramNames;
		}
		public Object instance;
		public Method method;
		public String[] paramNames;
	}
	
	/**
	 * Default constructor.
	 * This initializes all public methods defined in a class extending WeaveServlet.
	 */
	protected WeaveServlet()
	{
		super();
		initLocalMethods();
	}
	
	/**
	 * @param serviceObjects The objects to invoke methods on.
	 */
	protected WeaveServlet(Object ...serviceObjects)
	{
	    super();
	    initLocalMethods();
	    for (Object serviceObject : serviceObjects)
	    	initAllMethods(serviceObject);
	}
	
	/**
	 * This function will expose all the public methods of this object as servlet methods.
	 */
	protected void initLocalMethods()
	{
		initAllMethods(this);
		try
		{
			initMethod(this, WeaveServlet.class.getMethod(GET_CAPABILITIES));
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
	}
	
	/**
	 * This function will expose all the declared public methods of a class as servlet methods,
	 * except methods that match those declared by WeaveServlet or a superclass of WeaveServlet.
	 * @param serviceObject The object containing public methods to be exposed by the servlet.
	 */
	protected void initAllMethods(Object serviceObject)
	{
		Method[] weaveServletMethods = WeaveServlet.class.getMethods();
		Method[] declaredMethods = serviceObject.getClass().getDeclaredMethods();
		for (int i = declaredMethods.length; i-- > 0;)
		{
			Method declaredMethod = declaredMethods[i];
			boolean shouldIgnore = false;
			for (Method weaveServletMethod : weaveServletMethods)
			{
				if (declaredMethod.getName().equals(weaveServletMethod.getName()) &&
					Arrays.equals(declaredMethod.getParameterTypes(), weaveServletMethod.getParameterTypes()) )
				{
					shouldIgnore = true;
					break;
				}
			}
			if (!shouldIgnore)
				initMethod(serviceObject, declaredMethod);
		}
	}
	
	/**
	 * @param serviceObject The instance of an object to use in the servlet.
	 * @param method The method to expose on serviceObject.
	 */
	synchronized protected void initMethod(Object serviceObject, Method method)
	{
		// only expose public methods
		if (!Modifier.isPublic(method.getModifiers()))
			return;
		String methodName = method.getName();
		if (methodMap.containsKey(methodName))
		{
			methodMap.put(methodName, null);
	
			System.err.println(String.format(
					"Method %s.%s will not be supported because there are multiple definitions.",
					this.getClass().getName(), methodName
				));<commit_msg>simplified code<commit_after>/*
    Weave (Web-based Analysis and Visualization Environment)
    Copyright (C) 2008-2011 University of Massachusetts Lowell

    This file is a part of Weave.

    Weave is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License, Version 3,
    as published by the Free Software Foundation.

    Weave is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Weave.  If not, see <http://www.gnu.org/licenses/>.
*/

package weave.servlets;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.rmi.RemoteException;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import java.util.zip.DeflaterOutputStream;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.IOUtils;
import org.postgresql.util.Base64;

import weave.beans.JsonRpcErrorModel;
import weave.beans.JsonRpcRequestModel;
import weave.beans.JsonRpcResponseModel;
import weave.utils.CSVParser;
import weave.utils.ListUtils;
import weave.utils.MapUtils;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonNull;
import com.google.gson.JsonParseException;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import com.heatonresearch.httprecipes.html.PeekableInputStream;
import com.thoughtworks.paranamer.BytecodeReadingParanamer;
import com.thoughtworks.paranamer.Paranamer;

import flex.messaging.MessageException;
import flex.messaging.io.SerializationContext;
import flex.messaging.io.amf.ASObject;
import flex.messaging.io.amf.Amf3Input;
import flex.messaging.io.amf.Amf3Output;
import flex.messaging.messages.ErrorMessage;

/**
 * This class provides a servlet interface to a set of functions.
 * The functions may be invoked using URL parameters via HTTP GET using url parameters
 * or via HTTP POST using JSON RPC 2.0 or AMF3-serialized objects.
 * If using URL variables or JSON RPC 2.0, the return value will be provided as a JSON RPC 2.0 response object.
 * If using AMF3, the return value will be provided as compressed AMF3.
 * 
 * @author skota
 * @author adufilie
 * @author skolman
 */

public class WeaveServlet extends HttpServlet
{
	private static final long serialVersionUID = 1L;
	public static long debugThreshold = 1000;
	
	/**
	 * The name of the property which contains the remote method name.
	 */
	protected final String METHOD = "method";
	/**
	 * The name of the property which contains method parameters.
	 */
	protected final String PARAMS = "params";
	/**
	 * The name of the property which specifies the index in the params Array that corresponds to an InputStream.
	 */
	protected final String STREAM_PARAMETER_INDEX = "streamParameterIndex";
	
	private Map<String, ExposedMethod> methodMap = new HashMap<String, ExposedMethod>(); //Key: methodName
	private Paranamer paranamer = new BytecodeReadingParanamer(); // this gets parameter names from Methods
	
	/**
	 * This class contains a Method with its parameter names and class instance.
	 */
	private class ExposedMethod
	{
		public ExposedMethod(Object instance, Method method, String[] paramNames)
		{
			this.instance = instance;
			this.method = method;
			this.paramNames = paramNames;
		}
		public Object instance;
		public Method method;
		public String[] paramNames;
	}
	
	/**
	 * @param serviceObjects The objects to invoke methods on.
	 */
	protected WeaveServlet(Object ...serviceObjects)
	{
	    super();
	    
	    try
	    {
	    	// explicitly initialize this method
	    	initMethod(this, WeaveServlet.class.getMethod(GET_CAPABILITIES));
	    }
	    catch (NoSuchMethodException e)
	    {
	    	e.printStackTrace();
	    }
	    
	    // automatically initialize methods of this object
	    initAllMethods(this);
	    
	    for (Object serviceObject : serviceObjects)
	    	initAllMethods(serviceObject);
	}
	
	/**
	 * This function will expose all the declared public methods of a class as servlet methods,
	 * except methods that match those declared by WeaveServlet or a superclass of WeaveServlet.
	 * @param serviceObject The object containing public methods to be exposed by the servlet.
	 */
	protected void initAllMethods(Object serviceObject)
	{
		for (Method method : serviceObject.getClass().getDeclaredMethods())
		{
			try
			{
				// if this succeeds, we don't want to initialize the method automatically
				WeaveServlet.class.getMethod(method.getName(), method.getParameterTypes());
			}
			catch (NoSuchMethodException e)
			{
				// no matching method found in WeaveServlet, so initialize the method
				initMethod(serviceObject, method);
			}
		}
	}
	
	/**
	 * @param serviceObject The instance of an object to use in the servlet.
	 * @param method The method to expose on serviceObject.
	 */
	synchronized protected void initMethod(Object serviceObject, Method method)
	{
		// only expose public methods
		if (!Modifier.isPublic(method.getModifiers()))
			return;
		String methodName = method.getName();
		if (methodMap.containsKey(methodName))
		{
			methodMap.put(methodName, null);
	
			System.err.println(String.format(
					"Method %s.%s will not be supported because there are multiple definitions.",
					this.getClass().getName(), methodName
				));
{'fraction_non_alphanumeric': 0.0841959972394755, 'fraction_numerical': 0.004217467985583928, 'mean_word_length': 4.227254509018036, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 10, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3745416', 'n_tokens_mistral': 3924, 'n_tokens_neox': 3627, 'n_words': 1192}