Package org.pentaho.reporting.engine.classic.extensions.datasources.cda

Source Code of org.pentaho.reporting.engine.classic.extensions.datasources.cda.CdaDataFactory

package org.pentaho.reporting.engine.classic.extensions.datasources.cda;

import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Array;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import javax.swing.table.TableModel;

import org.apache.commons.httpclient.Credentials;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.NTCredentials;
import org.apache.commons.httpclient.UsernamePasswordCredentials;
import org.apache.commons.httpclient.auth.AuthScope;
import org.apache.commons.httpclient.cookie.CookiePolicy;
import org.apache.commons.httpclient.methods.GetMethod;
import org.pentaho.reporting.engine.classic.core.DataFactory;
import org.pentaho.reporting.engine.classic.core.DataRow;
import org.pentaho.reporting.engine.classic.core.ReportDataFactoryException;
import org.pentaho.reporting.engine.classic.core.ResourceBundleFactory;
import org.pentaho.reporting.engine.classic.core.util.TypedTableModel;
import org.pentaho.reporting.libraries.base.config.Configuration;
import org.pentaho.reporting.libraries.base.util.CSVQuoter;
import org.pentaho.reporting.libraries.base.util.StringUtils;
import org.pentaho.reporting.libraries.formula.util.URLEncoder;
import org.pentaho.reporting.libraries.resourceloader.ResourceKey;
import org.pentaho.reporting.libraries.resourceloader.ResourceManager;

/**
* Todo: Document me!
* <p/>
* Date: 16.12.10
* Time: 18:25
*
* @author Thomas Morgner.
*/
public class CdaDataFactory implements DataFactory, Cloneable
{
  private static final char DOMAIN_SEPARATOR = '\\';

  private String username;
  private String password;

  private String baseUrl;
  private String baseUrlField;

  private String solution;
  private String path;
  private String file;

  private HashMap<String, String> querymappings;
  private transient Configuration configuration;
  private transient ResourceBundleFactory resourceBundleFactory;
  private transient HttpClient client;
  private transient volatile GetMethod httpCall;

  public CdaDataFactory()
  {
    querymappings = new HashMap<String, String>();
  }

  public void initialize(final Configuration configuration,
                         final ResourceManager resourceManager,
                         final ResourceKey contextKey,
                         final ResourceBundleFactory resourceBundleFactory)
  {

    this.configuration = configuration;
    this.resourceBundleFactory = resourceBundleFactory;
  }


  /**
   * Checks whether the query would be executable by this datafactory. This performs a rough check, not a full query.
   *
   * @param query
   * @param parameters
   * @return
   */
  public boolean isQueryExecutable(final String query, final DataRow parameters)
  {
    return querymappings.containsKey(query);
  }

  public void setQuery(final String name, final String queryString)
  {
    if (queryString == null)
    {
      querymappings.remove(name);
    }
    else
    {
      querymappings.put(name, queryString);
    }
  }


  /**
   * Queries a datasource. The string 'query' defines the name of the query. The Parameterset given here may contain
   * more data than actually needed.
   * <p/>
   * The dataset may change between two calls, do not assume anything!
   *
   * @param query
   * @param parameters
   * @return
   */
  public synchronized TableModel queryData(final String query, final DataRow parameters)
      throws ReportDataFactoryException
  {
    if (query == null)
    {
      throw new NullPointerException("Query is null."); //$NON-NLS-1$
    }
    final String realQuery = getQuery(query);
    if (realQuery == null)
    {
      throw new ReportDataFactoryException("Query '" + query + "' is not recognized."); //$NON-NLS-1$ //$NON-NLS-2$
    }

    final TypedTableModel parameterModel = fetchParameter(parameters, realQuery);
    // name = 0
    // type = 1
    // defaultValue = 2
    // pattern = 3
    final HashMap<String, String> extraParams = new HashMap<String, String>();
    extraParams.put("dataAccessId", realQuery);
   
    final int nameIdx = parameterModel.findColumn("name");
    final int typeIdx = parameterModel.findColumn("type");
    final int defaultValueIdx = parameterModel.findColumn("defaultValue");
    final int patternIdx = parameterModel.findColumn("pattern");
    for (int p = 0; p < parameterModel.getRowCount(); p++)
    {
      final String name = (String) parameterModel.getValueAt(p, nameIdx);
      final String type = (String) parameterModel.getValueAt(p, typeIdx);
      final String pattern = (String) parameterModel.getValueAt(p, patternIdx);

      // if parameter is null, use default value from cda
      final Object value = parameters.get(name)==null?parameterModel.getValueAt(p, defaultValueIdx):parameters.get(name);
 
      final String param = parameterToString(name, type, pattern, value);
      extraParams.put(name, param);
    }

    return fetchData(parameters, "doQuery", extraParams);
  }

  private String parameterToString(final String name,
                                   final String type,
                                   final String pattern,
                                   final Object raw) throws ReportDataFactoryException
  {
    if (raw == null)
    {
      return "";
    }
    if ("Date".equals(type))
    {
      if (raw instanceof Date == false && raw instanceof Number == false)
      {
        throw new ReportDataFactoryException("For parameter " + name + " Expected date, but got " + raw);
      }
      final SimpleDateFormat dateFormat = new SimpleDateFormat(pattern, resourceBundleFactory.getLocale());
      dateFormat.setTimeZone(resourceBundleFactory.getTimeZone());
      return dateFormat.format(raw);
    }
    if ("Integer".equals(type) || "Numeric".equals(type))
    {
      if (raw instanceof Number == false)
      {
        throw new ReportDataFactoryException("For parameter " + name + " Expected number, but got " + raw);
      }
      return String.valueOf(raw);
    }
    if ("String".equals(type))
    {
      return String.valueOf(raw);
    }
    if (type.endsWith("Array"))
    {
      if (raw.getClass().isArray() == false)
      {
        throw new ReportDataFactoryException("For parameter " + name + " Expected array, but got " + raw);
      }

      final CSVQuoter quoter = new CSVQuoter(';');
      final String arrayType = type.substring(0, type.length() - 5);
      final StringBuffer b = new StringBuffer();
      final int length = Array.getLength(raw);
      for (int i = 0; i < length; i++)
      {
        final Object o = Array.get(raw, i);
        if (i > 0)
        {
          b.append(";");
        }
        final String str = parameterToString(name + "[" + i + "]", arrayType, pattern, o);
        b.append(quoter.doQuoting(str));
      }
    }
    throw new ReportDataFactoryException("Unknown type " + type + " for parameter " + name);
  }

  public String getQuery(final String name)
  {
    return querymappings.get(name);
  }

  public String[] getQueryNames()
  {
    return querymappings.keySet().toArray(new String[querymappings.size()]);
  }

  private String computeBaseUrl(final DataRow dataRow)
  {
    if (baseUrlField != null)
    {
      final Object baseUrlRaw = dataRow.get(baseUrlField);
      if (baseUrlRaw != null)
      {
        return String.valueOf(baseUrlRaw);
      }
    }
    return baseUrl;
  }

  private TypedTableModel fetchData(final DataRow dataRow,
                                    final String method,
                                    final Map<String, String> extraParameter) throws ReportDataFactoryException
  {
    final String baseURL = computeBaseUrl(dataRow);
    if (StringUtils.isEmpty(baseURL, true))
    {
      throw new ReportDataFactoryException("Base URL is null");
    }
    try
    {
      final StringBuilder url = new StringBuilder();
      url.append(baseURL);
      url.append("/content/cda/");
      url.append(method);
      url.append("?");
      url.append("outputType=xml");
      url.append("&solution=");
      url.append(encodeParameter(solution));
      url.append("&path=");
      url.append(encodeParameter(path));
      url.append("&file=");
      url.append(encodeParameter(file));
      for (final Map.Entry<String, String> entry : extraParameter.entrySet())
      {
        final String key = encodeParameter(entry.getKey());
        if (StringUtils.isEmpty(key))
        {
          continue;
        }
       
        // For custom parameters, we prepend 'param'. Exception is dataAccessId
        if(key.equals("dataAccessId")){
          url.append("&");       
        }
        else{
          url.append("&param");
        }
        url.append(key);
        url.append("=");
        url.append(encodeParameter(entry.getValue()));
      }

      httpCall = new GetMethod(url.toString());
      final HttpClient client = getHttpClient();
      final int status = client.executeMethod(httpCall);
      if (status != 200)
      {
        throw new ReportDataFactoryException("Failed to retrieve data: " + httpCall.getStatusLine());
      }

      final InputStream responseBody = httpCall.getResponseBodyAsStream();
      return CdaResponseParser.performParse(responseBody);
    }
    catch (UnsupportedEncodingException use)
    {
      throw new ReportDataFactoryException("Failed to encode parameter", use);
    }
    catch (Exception e)
    {
      throw new ReportDataFactoryException("Failed to send request", e);
    }
    finally
    {
      httpCall = null;
    }
  }

  private HttpClient getHttpClient()
  {
    if (client == null)
    {
      client = new HttpClient();
      client.getParams().setCookiePolicy(CookiePolicy.BROWSER_COMPATIBILITY);
      client.getParams().setAuthenticationPreemptive(true);
      client.getState().setCredentials(AuthScope.ANY, getCredentials(username, password));
    }
    return client;
  }

  public static Credentials getCredentials(final String user,
                                           final String password)
  {
    if (StringUtils.isEmpty(user))
    {
      return null;
    }

    final int domainIdx = user.indexOf(DOMAIN_SEPARATOR);
    if (domainIdx == -1)
    {
      return new UsernamePasswordCredentials(user, password);
    }
    try
    {
      final String domain = user.substring(0, domainIdx);
      final String username = user.substring(domainIdx + 1);
      final String host = InetAddress.getLocalHost().getHostName();
      return new NTCredentials(username, password, host, domain);
    }
    catch (UnknownHostException uhe)
    {
      return new UsernamePasswordCredentials(user, password);
    }
  }


  private String getURLEncoding()
  {
    return configuration.getConfigProperty("org.pentaho.reporting.engine.classic.core.URLEncoding");
  }

  private String encodeParameter(final String value) throws UnsupportedEncodingException
  {
    if (StringUtils.isEmpty(value))
    {
      return "";
    }
    return URLEncoder.encode(value, getURLEncoding());
  }

  private TypedTableModel fetchParameter(final DataRow dataRow, final String queryId)
      throws ReportDataFactoryException
  {
    final HashMap<String, String> extras = new HashMap<String, String>();
    extras.put("dataAccessId", queryId);
    return fetchData(dataRow, "listParameters", extras);
  }

  public DataFactory derive()
  {
    final CdaDataFactory clone = (CdaDataFactory) clone();
    clone.client = null;
    clone.httpCall = null;
    return clone;
  }

  public String getUsername()
  {
    return username;
  }

  public void setUsername(final String username)
  {
    this.username = username;
  }

  public String getPassword()
  {
    return password;
  }

  public void setPassword(final String password)
  {
    this.password = password;
  }

  public String getBaseUrl()
  {
    return baseUrl;
  }

  public void setBaseUrl(final String baseUrl)
  {
    this.baseUrl = baseUrl;
  }

  public String getBaseUrlField()
  {
    return baseUrlField;
  }

  public void setBaseUrlField(final String baseUrlField)
  {
    this.baseUrlField = baseUrlField;
  }

  public String getSolution()
  {
    return solution;
  }

  public void setSolution(final String solution)
  {
    this.solution = solution;
  }

  public String getPath()
  {
    return path;
  }

  public void setPath(final String path)
  {
    this.path = path;
  }

  public String getFile()
  {
    return file;
  }

  public void setFile(final String file)
  {
    this.file = file;
  }

  public void open() throws ReportDataFactoryException
  {

  }

  public void close()
  {
    client = null;
  }

  public Object clone()
  {
    try
    {
      final CdaDataFactory dataFactory = (CdaDataFactory) super.clone();
      dataFactory.querymappings = (HashMap<String, String>) querymappings.clone();
      dataFactory.httpCall = null;
      return dataFactory;
    }
    catch (CloneNotSupportedException cne)
    {
      throw new IllegalStateException(cne);
    }
  }

  public void cancelRunningQuery()
  {
    final GetMethod call = httpCall;
    if (call != null)
    {
      call.abort();
    }
  }
}
TOP

Related Classes of org.pentaho.reporting.engine.classic.extensions.datasources.cda.CdaDataFactory

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.