/*
// $Id: XmlaOlap4jAbstractHttpProxy.java 455 2011-05-24 10:01:26Z jhyde $
// This software is subject to the terms of the Eclipse Public License v1.0
// Agreement, available at the following URL:
// http://www.eclipse.org/legal/epl-v10.html.
// Copyright (C) 2007-2011 Julian Hyde
// All Rights Reserved.
// You must accept the terms of that agreement to use this software.
*/
package org.olap4j.driver.olap4ld.proxy;
import java.net.URL;
import java.net.URLConnection;
import java.util.Map;
import java.util.concurrent.Future;
import org.olap4j.OlapException;
import org.olap4j.driver.olap4ld.Olap4ldDriver;
import org.olap4j.driver.olap4ld.Olap4ldServerInfos;
import org.olap4j.driver.olap4ld.cache.XmlaOlap4jCache;
import org.olap4j.driver.olap4ld.helper.LdHelper;
import org.olap4j.driver.olap4ld.proxy.XmlaOlap4jCachedProxy;
import org.olap4j.driver.olap4ld.proxy.XmlaOlap4jCookieManager;
import org.olap4j.driver.olap4ld.proxy.XmlaOlap4jProxyException;
/**
* <p>Abstract implementation of Proxy which adds a SOAP
* cache layer between the driver and its proxy implementations.
* It can be configured via the setCache() method, as instructed in
* {@link XmlaOlap4jCachedProxy} interface.
*
* <p>It also offers helper methods to keep track of
* the HTTP cookies and sends them back
* to the server along with queries. The useful methods are
* saveCookies(URL) and useCookies(URL).
*
* @author Luc Boudreau
* @version $Id: XmlaOlap4jAbstractHttpProxy.java 455 2011-05-24 10:01:26Z jhyde $
*/
abstract class XmlaOlap4jAbstractHttpProxy
implements XmlaOlap4jCachedProxy
{
private final LdHelper helper = new LdHelper();
/**
* Holds on to the cache implementation.
*/
private XmlaOlap4jCache cache = null;
/**
* Holds on to the connection name which is associated to this proxy.
*/
private String cacheId;
/**
* Keeps a link to the cookie manager instance.
*/
private XmlaOlap4jCookieManager cookieManager = null;
/**
* Creates an XmlaOlap4jAbstractHttpProxy.
*/
protected XmlaOlap4jAbstractHttpProxy() {
}
/**
* Sends a request to a URL and returns the response.
*
* @param url Target URL
* @param request Request string
* @return Response
*/
abstract public byte[] getResponse(
Olap4ldServerInfos serverInfos,
String request)
throws XmlaOlap4jProxyException;
/**
* Submits a request for background execution.
*
* @param url URL
* @param request Request
* @return Future object representing the submitted job
*/
abstract public Future<byte[]> getResponseViaSubmit(
Olap4ldServerInfos serverInfos,
String request);
/**
* Helper method to add cookies to a given connection.
* @param urlConn The url connection to which we want the cookies
* applied to.
*/
protected void useCookies(URLConnection urlConn) {
// Initializes the cookie manager
this.initCookieManager();
// Saves the current cookies
this.cookieManager.setCookies(urlConn);
}
/**
* Helper method to save cookies for later use.
* @param urlConn The url connection for which we want the cookies
* saved for later use.
*/
protected void saveCookies(URLConnection urlConn) {
// Initializes the cookie manager
this.initCookieManager();
// Saves the current cookies
this.cookieManager.storeCookies(urlConn);
}
@SuppressWarnings("unchecked")
public void setCache(
Map<String, String> config,
Map<String, String> properties)
throws OlapException
{
try {
// Loads the cache class
Class clazz = Class.forName(config.get(
Olap4ldDriver.Property.CACHE.name()));
// Instantiates it
this.cache = (XmlaOlap4jCache) clazz.newInstance();
// Configures it
this.cacheId = this.cache.setParameters(config, properties);
} catch (ClassNotFoundException e) {
throw helper.createException(
"The specified cache class name could not be found : "
+ config.get(Olap4ldDriver.Property.CACHE.name()), e);
} catch (InstantiationException e) {
throw helper.createException(
"The specified cache class name could not be instanciated : "
+ config.get(Olap4ldDriver.Property.CACHE.name()), e);
} catch (IllegalAccessException e) {
throw helper.createException(
"An error was encountered while instanciating the cache : "
+ config.get(Olap4ldDriver.Property.CACHE.name()), e);
} catch (IllegalArgumentException e) {
throw helper.createException(
"An error was encountered while instanciating the cache : "
+ config.get(Olap4ldDriver.Property.CACHE.name()), e);
} catch (SecurityException e) {
throw helper.createException(
"An error was encountered while instanciating the cache : "
+ config.get(Olap4ldDriver.Property.CACHE.name()), e);
}
}
// implement XmlaOlap4jProxy
public byte[] get(
Olap4ldServerInfos serverInfos,
String request)
throws XmlaOlap4jProxyException
{
byte[] response = null;
// Tries to fetch from cache
try {
response =
getFromCache(
serverInfos.getUrl(),
request.getBytes(getEncodingCharsetName()));
// Returns the cached value if found
if (response != null) {
return response;
}
} catch (Exception e) {
throw new XmlaOlap4jProxyException(
"An exception was encountered while browsing the proxy cache.",
e);
}
// Executes the query
response = getResponse(serverInfos, request);
try {
// Adds to cache
addToCache(
serverInfos.getUrl(),
request.getBytes(getEncodingCharsetName()),
response);
// Returns result
return response;
} catch (Exception e) {
throw new XmlaOlap4jProxyException(
"An exception was encountered while saving a response in the proxy cache.",
e);
}
}
/**
* Tries to fetch a cached response from the cache implementation.
*
* @param url The url used to send the request
*
* @param request The SOAP request to cache
*
* @return either a response in a byte array or null
* if the response is not in cache
*/
private byte[] getFromCache(final URL url, final byte[] request)
throws OlapException
{
return (this.cache != null)
? this.cache.get(this.cacheId, url, request)
: null;
}
/**
* Caches an entry using the current cache implementation.
* @param url The URL from which originated the request
* @param request The SOAP request to cache
* @param response The SOAP response to cache
*/
private void addToCache(URL url, byte[] request, byte[] response)
throws OlapException
{
if (this.cache != null) {
this.cache.put(this.cacheId, url, request, response);
}
}
// implement XmlaOlap4jProxy
public Future<byte[]> submit(
final Olap4ldServerInfos serverInfos,
final String request)
{
// The submit operation doesn't need to be cached yet, since it will
// call the get operation to fetch the data later on. It will get cached
// then.
//
// I still overridden the submit method in case we need some caching
// done in the end. - Luc
return getResponseViaSubmit(serverInfos, request);
}
/**
* Initializes the cookie manager. It is not initialized
* by default because some proxy implementation might not need this
* functionnality.
*/
private void initCookieManager() {
if (this.cookieManager == null) {
this.cookieManager = new XmlaOlap4jCookieManager();
}
}
}
// End XmlaOlap4jAbstractHttpProxy.java