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