/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.saiku.reporting.backend.temp.cpf; import java.io.UnsupportedEncodingException; import java.lang.annotation.Annotation; import java.lang.reflect.InvocationTargetException; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.concurrent.Callable; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; import javax.ws.rs.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.pentaho.platform.api.engine.IParameterProvider; import org.pentaho.platform.api.engine.IPentahoSession; import org.pentaho.platform.api.engine.IPluginManager; import org.pentaho.platform.api.engine.PluginBeanException; import org.pentaho.platform.engine.core.solution.SimpleParameterProvider; import org.pentaho.platform.engine.core.system.PentahoSessionHolder; import org.pentaho.platform.engine.core.system.PentahoSystem; import org.pentaho.platform.web.http.request.HttpRequestParameterProvider; import pt.webdetails.cpf.IPluginCall; import pt.webdetails.cpf.plugin.CorePlugin; /** * Call to another pentaho plugin through its content generator. * Not thread safe. */ public class InterPluginCall implements IPluginCall, Runnable, Callable<String> { public final static String SUFIX = ".api"; private final static String DEFAULT_ENCODING = "UTF-8"; public static class Plugin { private String name; private String title; public String getName() { return name; } public String getTitle() { return title; } public Plugin(String name, String title){ this.name = name; this.title = title; } public Plugin(String id){ this.name = id; this.title = id; } } private static final Log logger = LogFactory.getLog(InterPluginCall.class); private Plugin plugin; private String method; private Map<String, Object> requestParameters; private HttpServletResponse response; private HttpServletRequest request; private IPentahoSession session; private IPluginManager pluginManager; private InterPluginCall(){ } /** * Creates a new call. * @param plugin the plugin to call * @param method */ public InterPluginCall(Plugin plugin, String method){ this(); if(plugin == null) throw new IllegalArgumentException("Plugin must be specified"); this.plugin = plugin; this.method = method; this.requestParameters = new HashMap<String, Object>(); } @Override public void init(CorePlugin plug, String method, Map<String, Object> params) { this.plugin = new Plugin(plug.getName(), plug.getTitle()); this.method = method; this.requestParameters = new HashMap<String, Object>(); this.requestParameters.putAll(params!=null?params:new HashMap<String, Object>()); } public InterPluginCall(Plugin plugin, String method, Map<String, Object> params) { this(plugin, method); this.plugin = plugin; this.method = method; this.requestParameters.putAll(params!=null?params:new HashMap<String, Object>()); } public String getMethod() { return method; } public void setMethod(String method) { this.method = method; } protected HttpServletRequest getRequest() { if(request == null){ request = new org.saiku.reporting.backend.temp.cpf.CpfHttpServletRequest(); } return request; } protected void setRequest(HttpServletRequest request) { this.request = request; } public boolean pluginExists(){ return getPluginManager().getClassLoader(plugin.getName()) != null; } /** * Put a request parameter * @param name * @param value * @return this */ public InterPluginCall putParameter(String name, Object value){ requestParameters.put(name, value); return this; } public void run() { String pluginName = plugin.getName(); Class<?> classe = null; Method operation = null; Object o = null; try { classe = getPluginManager().getBean(pluginName+SUFIX).getClass(); Method[] methods = classe.getMethods(); o = classe.newInstance(); for(Method m : methods){ if(m.getName() == method){ operation = m; } } } catch(PluginBeanException ex){ logger.error("Trying to get a plugin not declared on beans", ex); } catch(InstantiationException ex){ logger.error("Error while instanciating class of bean with id "+pluginName, ex); } catch(IllegalAccessException ex){ logger.error("Error while instanciating class of bean with id "+pluginName, ex); } Annotation[][] params = operation.getParameterAnnotations(); Class<?>[] paramTypes = operation.getParameterTypes(); List<Object> parameters = new ArrayList<Object>(); for(int i = 0; i < params.length; i++){ String paramName = ""; String paramDefaultValue = ""; for(Annotation annotation : params[i]){ String annotationClass = annotation.annotationType().getName(); if(annotationClass == "javax.ws.rs.QueryParam"){ QueryParam param = (QueryParam)annotation; paramName = param.value(); } else if(annotationClass == "javax.ws.rs.DefaultValue"){ DefaultValue param = (DefaultValue)annotation; paramDefaultValue = param.value(); } } if(requestParameters.containsKey(paramName)){ if(paramTypes[i] == int.class){ int val = Integer.parseInt((String)requestParameters.get(paramName)); parameters.add(val); } else if(paramTypes[i] == java.lang.Boolean.class){ boolean val = Boolean.parseBoolean((String)requestParameters.get(paramName)); parameters.add(val); } else if(paramTypes[i] == java.util.List.class){ List<String> list = new ArrayList<String>(); String values = (String)requestParameters.get(paramName); String[] splittedValues = values.split(","); for(String s : splittedValues){ list.add(s); } parameters.add(list); } else if(paramTypes[i] == java.lang.String.class){ parameters.add(requestParameters.get(paramName)); } requestParameters.remove(paramName); } else { if(paramTypes[i] == int.class){ int val = Integer.parseInt((String)paramDefaultValue); parameters.add(val); } else if(paramTypes[i] == java.lang.Boolean.class){ boolean val = Boolean.parseBoolean((String)paramDefaultValue); parameters.add(val); } else if(paramTypes[i] == java.util.List.class){ List<String> list = new ArrayList<String>(); String values = paramDefaultValue; String[] splittedValues = values.split(","); for(String s : splittedValues){ list.add(s); } parameters.add(list); } else if(paramTypes[i] == java.lang.String.class){ parameters.add(paramDefaultValue); } } } parameters.add((HttpServletResponse) getParameterProviders().get("path").getParameter("httpresponse")); CpfHttpServletRequest cpfRequest = (CpfHttpServletRequest)getRequest(); for(Map.Entry<String, Object> entry : requestParameters.entrySet()){ String key = entry.getKey(); Object value = entry.getValue(); cpfRequest.setParameter(key, (String)value); } parameters.add(getRequest()); try { operation.invoke(o, parameters.toArray()); } catch (IllegalAccessException ex){ logger.error("",ex); } catch (IllegalArgumentException ex){ logger.error("",ex); } catch (InvocationTargetException ex){ logger.error("",ex); } catch (Exception ex){ logger.error("",ex); } } public String call() { run(); CpfHttpServletResponse cpfResponse = (CpfHttpServletResponse)response; String content = ""; try{ content = cpfResponse.getContentAsString(); } catch(UnsupportedEncodingException ex){ logger.error("Error getting content from CpfHttpServletResponse", ex); } return content; } public void runInPluginClassLoader(){ getClassLoaderCaller().runInClassLoader(this); } public String callInPluginClassLoader() { try { return getClassLoaderCaller().callInClassLoader(this); } catch (Exception e) { logger.error(e); return null; } } public HttpServletResponse getResponse() { if(response == null){ logger.debug("No response passed to method " + this.method + ", adding response."); response = new CpfHttpServletResponse(); } return response; } public void setResponse(HttpServletResponse response) { this.response = response; } public void setSession(IPentahoSession session) { this.session = session; } public void setRequestParameters(Map<String, Object> parameters){ this.requestParameters = parameters; } public void setRequestParameters(IParameterProvider requestParameterProvider){ if(!requestParameters.isEmpty()) requestParameters.clear(); for(@SuppressWarnings("unchecked") Iterator<String> params = requestParameterProvider.getParameterNames(); params.hasNext();){ String parameterName = params.next(); requestParameters.put(parameterName, requestParameterProvider.getParameter(parameterName)); } } protected IPentahoSession getSession(){ if(session == null){ session = PentahoSessionHolder.getSession(); } return session; } protected IParameterProvider getRequestParameterProvider(){ SimpleParameterProvider provider = null; if(request != null){ provider = new HttpRequestParameterProvider(request); provider.setParameters(requestParameters); } else { provider = new SimpleParameterProvider(requestParameters); } return provider; } protected ClassLoaderAwareCaller getClassLoaderCaller(){ return new ClassLoaderAwareCaller(getPluginManager().getClassLoader(plugin.getTitle())); } protected IPluginManager getPluginManager() { if(pluginManager == null){ pluginManager = PentahoSystem.get(IPluginManager.class, getSession()); } return pluginManager; } protected IParameterProvider getPathParameterProvider() { Map<String, Object> pathMap = new HashMap<String, Object>(); pathMap.put("path", "/" + method); // if (response != null) { pathMap.put("httpresponse", getResponse()); // } if(getRequest() != null){ pathMap.put("httprequest", getRequest()); } IParameterProvider pathParams = new SimpleParameterProvider(pathMap); return pathParams; } protected Map<String,IParameterProvider> getParameterProviders(){ IParameterProvider requestParams = getRequestParameterProvider(); IParameterProvider pathParams = getPathParameterProvider(); Map<String, IParameterProvider> paramProvider = new HashMap<String, IParameterProvider>(); paramProvider.put(IParameterProvider.SCOPE_REQUEST, requestParams); paramProvider.put("path", pathParams); return paramProvider; } protected String getEncoding(){ return DEFAULT_ENCODING; } }