001 /*
002 // $Id: XmlaOlap4jHttpProxy.java 482 2012-01-05 23:27:27Z jhyde $
003 //
004 // Licensed to Julian Hyde under one or more contributor license
005 // agreements. See the NOTICE file distributed with this work for
006 // additional information regarding copyright ownership.
007 //
008 // Julian Hyde licenses this file to you under the Apache License,
009 // Version 2.0 (the "License"); you may not use this file except in
010 // compliance with the License. You may obtain a copy of the License at:
011 //
012 // http://www.apache.org/licenses/LICENSE-2.0
013 //
014 // Unless required by applicable law or agreed to in writing, software
015 // distributed under the License is distributed on an "AS IS" BASIS,
016 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017 // See the License for the specific language governing permissions and
018 // limitations under the License.
019 */
020 package org.olap4j.driver.xmla.proxy;
021
022 import org.olap4j.driver.xmla.XmlaOlap4jDriver;
023 import org.olap4j.driver.xmla.XmlaOlap4jServerInfos;
024 import org.olap4j.impl.Base64;
025
026 import java.io.*;
027 import java.net.*;
028 import java.util.concurrent.Future;
029
030 /**
031 * Extends the AbstractCachedProxy and serves as
032 * a production ready http communication class. Every SOAP request
033 * sends a POST call to the destination XMLA server and returns
034 * the response as a byte array, conforming to the Proxy interface.
035 *
036 * <p>It also takes advantage of the AbstractHttpProxy cookie
037 * managing facilities. All cookies received from the end point
038 * server will be sent back if they are not expired and they also
039 * conform to cookie domain rules.
040 *
041 * @author Luc Boudreau and Julian Hyde
042 * @version $Id: XmlaOlap4jHttpProxy.java 482 2012-01-05 23:27:27Z jhyde $
043 */
044 public class XmlaOlap4jHttpProxy extends XmlaOlap4jAbstractHttpProxy
045 {
046 private final XmlaOlap4jDriver driver;
047
048 /**
049 * Creates a XmlaOlap4jHttpProxy.
050 *
051 * @param driver Driver
052 */
053 public XmlaOlap4jHttpProxy(
054 XmlaOlap4jDriver driver)
055 {
056 this.driver = driver;
057 }
058
059 private static final String DISCOVER =
060 "<Discover xmlns=\"urn:schemas-microsoft-com:xml-analysis\"";
061
062 private static final String EXECUTE =
063 "<Execute xmlns=\"urn:schemas-microsoft-com:xml-analysis\"";
064
065 @Override
066 public byte[] getResponse(XmlaOlap4jServerInfos serverInfos, String request)
067 throws XmlaOlap4jProxyException
068 {
069 URLConnection urlConnection = null;
070 try {
071 URL url = serverInfos.getUrl();
072 // Open connection to manipulate the properties
073 urlConnection = url.openConnection();
074 urlConnection.setDoOutput(true);
075
076 // Set headers
077 urlConnection.setRequestProperty(
078 "content-type",
079 "text/xml");
080 urlConnection.setRequestProperty(
081 "User-Agent",
082 "Olap4j("
083 .concat(driver.getVersion())
084 .concat(")"));
085 urlConnection.setRequestProperty(
086 "Accept",
087 "text/xml;q=1");
088 urlConnection.setRequestProperty(
089 "Accept-Charset",
090 getEncodingCharsetName()
091 .concat(";q=1"));
092
093 // Some servers expect a SOAPAction header.
094 // TODO There is bound to be a better way to do this.
095 if (request.contains(DISCOVER)) {
096 urlConnection.setRequestProperty(
097 "SOAPAction",
098 "\"urn:schemas-microsoft-com:xml-analysis:Discover\"");
099 } else if (request.contains(EXECUTE)) {
100 urlConnection.setRequestProperty(
101 "SOAPAction",
102 "\"urn:schemas-microsoft-com:xml-analysis:Execute\"");
103 }
104
105 // Encode credentials for basic authentication
106 StringBuilder sb = new StringBuilder();
107 if (serverInfos.getUsername() != null
108 && serverInfos.getPassword() != null)
109 {
110 sb.append(serverInfos.getUsername());
111 sb.append(":");
112 sb.append(serverInfos.getPassword());
113 } else if (url.getUserInfo() != null) {
114 sb.append(url.getUserInfo());
115 }
116 if (!sb.toString().equals("")) {
117 String encoding =
118 Base64.encodeBytes(
119 sb.toString().getBytes(), 0);
120 urlConnection.setRequestProperty(
121 "Authorization", "Basic " + encoding);
122 }
123
124 // Set correct cookies
125 this.useCookies(urlConnection);
126
127 // Send data (i.e. POST). Use same encoding as specified in the
128 // header.
129 final String encoding = getEncodingCharsetName();
130 urlConnection.getOutputStream().write(request.getBytes(encoding));
131
132 // Get the response, again assuming default encoding.
133 InputStream is = urlConnection.getInputStream();
134 final ByteArrayOutputStream baos = new ByteArrayOutputStream();
135 byte[] buf = new byte[1024];
136 int count;
137
138 while ((count = is.read(buf)) > 0) {
139 baos.write(buf, 0, count);
140 }
141
142 // Save the returned cookies for later use
143 this.saveCookies(urlConnection);
144
145 return baos.toByteArray();
146 // All exceptions should be trapped here.
147 // The response will only be available here anyways.
148 } catch (Exception e) {
149 // In order to prevent the JDK from keeping this connection
150 // in WAIT mode, we need to empty the error stream cache.
151 try {
152 final int espCode =
153 ((HttpURLConnection)urlConnection).getResponseCode();
154 InputStream errorStream =
155 ((HttpURLConnection)urlConnection).getErrorStream();
156 final ByteArrayOutputStream baos =
157 new ByteArrayOutputStream();
158 final byte[] buf = new byte[1024];
159 int count;
160 if (errorStream != null) {
161 while ((count = errorStream.read(buf)) > 0) {
162 baos.write(buf, 0, count);
163 }
164 errorStream.close();
165 }
166 baos.close();
167 } catch (IOException ex) {
168 // Well, we tried. No point notifying the user here.
169 }
170 throw new XmlaOlap4jProxyException(
171 "This proxy encountered an exception while processing the "
172 + "query.",
173 e);
174 }
175 }
176
177 @Override
178 public Future<byte[]> getResponseViaSubmit(
179 final XmlaOlap4jServerInfos serverInfos,
180 final String request)
181 {
182 return XmlaOlap4jDriver.getFuture(this, serverInfos, request);
183 }
184
185 // implement XmlaOlap4jProxy
186 public String getEncodingCharsetName() {
187 return "UTF-8";
188 }
189 }
190
191 // End XmlaOlap4jHttpProxy.java
192
193
194