001 /*
002 // $Id: XmlaOlap4jHttpProxy.java 278 2009-09-30 13:05:54Z lucboudreau $
003 // This software is subject to the terms of the Eclipse Public License v1.0
004 // Agreement, available at the following URL:
005 // http://www.eclipse.org/legal/epl-v10.html.
006 // Copyright (C) 2007-2008 Julian Hyde
007 // All Rights Reserved.
008 // You must accept the terms of that agreement to use this software.
009 */
010 package org.olap4j.driver.xmla.proxy;
011
012 import java.io.*;
013 import java.net.*;
014 import java.util.concurrent.*;
015
016 import org.olap4j.driver.xmla.XmlaOlap4jDriver;
017 import org.olap4j.impl.Base64;
018
019 /**
020 * Extends the AbstractCachedProxy and serves as
021 * a production ready http communication class. Every SOAP request
022 * sends a POST call to the destination XMLA server and returns
023 * the response as a byte array, conforming to the Proxy interface.
024 *
025 * <p>It also takes advantage of the AbstractHttpProxy cookie
026 * managing facilities. All cookies received from the end point
027 * server will be sent back if they are not expired and they also
028 * conform to cookie domain rules.
029 *
030 * @author Luc Boudreau and Julian Hyde
031 * @version $Id: XmlaOlap4jHttpProxy.java 278 2009-09-30 13:05:54Z lucboudreau $
032 */
033 public class XmlaOlap4jHttpProxy extends XmlaOlap4jAbstractHttpProxy
034 {
035 private final XmlaOlap4jDriver driver;
036
037 /**
038 * Creates a XmlaOlap4jHttpProxy.
039 *
040 * @param driver Driver
041 */
042 public XmlaOlap4jHttpProxy(XmlaOlap4jDriver driver) {
043 this.driver = driver;
044 }
045
046 @Override
047 public byte[] getResponse(URL url, String request)
048 throws XmlaOlap4jProxyException
049 {
050 URLConnection urlConnection = null;
051 try {
052 // Open connection to manipulate the properties
053 urlConnection = url.openConnection();
054 urlConnection.setDoOutput(true);
055
056 // Set headers
057 urlConnection.setRequestProperty(
058 "content-type",
059 "text/xml");
060 urlConnection.setRequestProperty(
061 "User-Agent",
062 "Olap4j("
063 .concat(driver.getVersion())
064 .concat(")"));
065 urlConnection.setRequestProperty(
066 "Accept",
067 "text/xml;q=1");
068 urlConnection.setRequestProperty(
069 "Accept-Charset",
070 getEncodingCharsetName()
071 .concat(";q=1"));
072
073 // Some servers expect a SOAPAction header.
074 // TODO There is bound to be a better way to do this.
075 if (request.contains(
076 "<Discover xmlns=\"urn:schemas-microsoft-com:xml-analysis\""))
077 {
078 urlConnection.setRequestProperty(
079 "SOAPAction",
080 "urn:schemas-microsoft-com:xml-analysis:Discover");
081 } else if (request.contains(
082 "<Execute xmlns=\"urn:schemas-microsoft-com:xml-analysis\""))
083 {
084 urlConnection.setRequestProperty(
085 "SOAPAction",
086 "urn:schemas-microsoft-com:xml-analysis:Execute");
087 }
088
089 // Encode credentials for basic authentication
090 if (url.getUserInfo() != null) {
091 String encoding =
092 Base64.encodeBytes(url.getUserInfo().getBytes(), 0);
093 urlConnection.setRequestProperty(
094 "Authorization", "Basic " + encoding);
095 }
096
097 // Set correct cookies
098 this.useCookies(urlConnection);
099
100 // Send data (i.e. POST). Use same encoding as specified in the
101 // header.
102 final String encoding = getEncodingCharsetName();
103 urlConnection.getOutputStream().write(request.getBytes(encoding));
104
105 // Get the response, again assuming default encoding.
106 InputStream is = urlConnection.getInputStream();
107 final ByteArrayOutputStream baos = new ByteArrayOutputStream();
108 byte[] buf = new byte[1024];
109 int count;
110
111 while ((count = is.read(buf)) > 0) {
112 baos.write(buf, 0, count);
113 }
114
115 // Save the returned cookies for later use
116 this.saveCookies(urlConnection);
117
118 return baos.toByteArray();
119 // All exceptions should be trapped here.
120 // The response will only be available here anyways.
121 } catch (Exception e) {
122 // In order to prevent the JDK from keeping this connection
123 // in WAIT mode, we need to empty the error stream cache.
124 try {
125 final int espCode =
126 ((HttpURLConnection)urlConnection).getResponseCode();
127 InputStream errorStream =
128 ((HttpURLConnection)urlConnection).getErrorStream();
129 final ByteArrayOutputStream baos =
130 new ByteArrayOutputStream();
131 final byte[] buf = new byte[1024];
132 int count;
133 if (errorStream != null) {
134 while ((count = errorStream.read(buf)) > 0) {
135 baos.write(buf, 0, count);
136 }
137 errorStream.close();
138 }
139 baos.close();
140 } catch (IOException ex) {
141 // Well, we tried. No point notifying the user here.
142 }
143 throw new XmlaOlap4jProxyException(
144 "This proxy encountered an exception while processing the "
145 + "query.",
146 e);
147 }
148 }
149
150 @Override
151 public Future<byte[]> getResponseViaSubmit(
152 final URL url,
153 final String request)
154 {
155 return XmlaOlap4jDriver.getFuture(this, url, request);
156 }
157
158 // implement XmlaOlap4jProxy
159 public String getEncodingCharsetName() {
160 return "UTF-8";
161 }
162 }
163
164 // End XmlaOlap4jHttpProxy.java