/*
// $Id: XmlaOlap4jHttpProxy.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.io.*;
import java.net.*;
import java.util.concurrent.*;
import org.olap4j.driver.olap4ld.Olap4ldDriver;
import org.olap4j.driver.olap4ld.Olap4ldServerInfos;
import org.olap4j.driver.olap4ld.proxy.XmlaOlap4jAbstractHttpProxy;
import org.olap4j.driver.olap4ld.proxy.XmlaOlap4jProxyException;
import org.olap4j.impl.Base64;
/**
* Extends the AbstractCachedProxy and serves as
* a production ready http communication class. Every SOAP request
* sends a POST call to the destination XMLA server and returns
* the response as a byte array, conforming to the Proxy interface.
*
* <p>It also takes advantage of the AbstractHttpProxy cookie
* managing facilities. All cookies received from the end point
* server will be sent back if they are not expired and they also
* conform to cookie domain rules.
*
* @author Luc Boudreau and Julian Hyde
* @version $Id: XmlaOlap4jHttpProxy.java 455 2011-05-24 10:01:26Z jhyde $
*/
public class XmlaOlap4jHttpProxy extends XmlaOlap4jAbstractHttpProxy
{
private final Olap4ldDriver driver;
/**
* Creates a XmlaOlap4jHttpProxy.
*
* @param driver Driver
*/
public XmlaOlap4jHttpProxy(
Olap4ldDriver driver)
{
this.driver = driver;
}
private static final String DISCOVER =
"<Discover xmlns=\"urn:schemas-microsoft-com:xml-analysis\"";
private static final String EXECUTE =
"<Execute xmlns=\"urn:schemas-microsoft-com:xml-analysis\"";
@Override
public byte[] getResponse(Olap4ldServerInfos serverInfos, String request)
throws XmlaOlap4jProxyException
{
URLConnection urlConnection = null;
try {
URL url = serverInfos.getUrl();
// Open connection to manipulate the properties
urlConnection = url.openConnection();
urlConnection.setDoOutput(true);
// Set headers
urlConnection.setRequestProperty(
"content-type",
"text/xml");
urlConnection.setRequestProperty(
"User-Agent",
"Olap4j("
.concat(driver.getVersion())
.concat(")"));
urlConnection.setRequestProperty(
"Accept",
"text/xml;q=1");
urlConnection.setRequestProperty(
"Accept-Charset",
getEncodingCharsetName()
.concat(";q=1"));
// Some servers expect a SOAPAction header.
// TODO There is bound to be a better way to do this.
if (request.contains(DISCOVER)) {
urlConnection.setRequestProperty(
"SOAPAction",
"\"urn:schemas-microsoft-com:xml-analysis:Discover\"");
} else if (request.contains(EXECUTE)) {
urlConnection.setRequestProperty(
"SOAPAction",
"\"urn:schemas-microsoft-com:xml-analysis:Execute\"");
}
// Encode credentials for basic authentication
StringBuilder sb = new StringBuilder();
if (serverInfos.getUsername() != null
&& serverInfos.getPassword() != null)
{
sb.append(serverInfos.getUsername());
sb.append(":");
sb.append(serverInfos.getPassword());
} else if (url.getUserInfo() != null) {
sb.append(url.getUserInfo());
}
if (!sb.toString().equals("")) {
String encoding =
Base64.encodeBytes(
sb.toString().getBytes(), 0);
urlConnection.setRequestProperty(
"Authorization", "Basic " + encoding);
}
// Set correct cookies
this.useCookies(urlConnection);
// Send data (i.e. POST). Use same encoding as specified in the
// header.
final String encoding = getEncodingCharsetName();
urlConnection.getOutputStream().write(request.getBytes(encoding));
// Get the response, again assuming default encoding.
InputStream is = urlConnection.getInputStream();
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
int count;
while ((count = is.read(buf)) > 0) {
baos.write(buf, 0, count);
}
// Save the returned cookies for later use
this.saveCookies(urlConnection);
return baos.toByteArray();
// All exceptions should be trapped here.
// The response will only be available here anyways.
} catch (Exception e) {
// In order to prevent the JDK from keeping this connection
// in WAIT mode, we need to empty the error stream cache.
try {
final int espCode =
((HttpURLConnection)urlConnection).getResponseCode();
InputStream errorStream =
((HttpURLConnection)urlConnection).getErrorStream();
final ByteArrayOutputStream baos =
new ByteArrayOutputStream();
final byte[] buf = new byte[1024];
int count;
if (errorStream != null) {
while ((count = errorStream.read(buf)) > 0) {
baos.write(buf, 0, count);
}
errorStream.close();
}
baos.close();
} catch (IOException ex) {
// Well, we tried. No point notifying the user here.
}
throw new XmlaOlap4jProxyException(
"This proxy encountered an exception while processing the "
+ "query.",
e);
}
}
@Override
public Future<byte[]> getResponseViaSubmit(
final Olap4ldServerInfos serverInfos,
final String request)
{
return Olap4ldDriver.getFuture(this, serverInfos, request);
}
// implement XmlaOlap4jProxy
public String getEncodingCharsetName() {
return "UTF-8";
}
}
// End XmlaOlap4jHttpProxy.java