diff --git a/src/org/olap4j/OlapExceptionHelper.java b/src/org/olap4j/OlapExceptionHelper.java index 4bfe803..258e80e 100644 --- a/src/org/olap4j/OlapExceptionHelper.java +++ b/src/org/olap4j/OlapExceptionHelper.java @@ -21,6 +21,10 @@ public static OlapException createException(String msg) { return new OlapException(msg); } + public static OlapException createException(Throwable cause) { + return new OlapException(cause.getMessage(), cause); + } + public static OlapException createException(String msg, Throwable cause) { return new OlapException(msg, cause); } diff --git a/src/org/olap4j/driver/xmla/XmlaOlap4jCellSet.java b/src/org/olap4j/driver/xmla/XmlaOlap4jCellSet.java index 6f60e1e..158f3cc 100644 --- a/src/org/olap4j/driver/xmla/XmlaOlap4jCellSet.java +++ b/src/org/olap4j/driver/xmla/XmlaOlap4jCellSet.java @@ -13,8 +13,8 @@ import org.olap4j.impl.Olap4jUtil; import static org.olap4j.driver.xmla.XmlaOlap4jUtil.*; import org.olap4j.metadata.*; -import org.w3c.dom.Document; -import org.w3c.dom.Element; +import org.w3c.dom.*; +import org.w3c.dom.ls.*; import org.xml.sax.SAXException; import java.io.*; @@ -107,8 +107,6 @@ void populate() throws OlapException { findChild(body, SOAP_NS, "Fault"); if (fault != null) { /* - Example: - SOAP-ENV:Client.00HSBC01 XMLA connection datasource not found @@ -123,10 +121,15 @@ void populate() throws OlapException { */ // TODO: log doc to logfile - final Element faultstring = findChild(fault, null, "faultstring"); - String message = faultstring.getTextContent(); + // A message must include the fault XML content. This is the right + // and efficient way to do it, according to + // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6181019 + // They changed the node.getString() in java... .... + DOMImplementation impl = fault.getOwnerDocument().getImplementation(); + DOMImplementationLS factory = (DOMImplementationLS) impl.getFeature("LS", "3.0"); + LSSerializer serializer = factory.createLSSerializer(); throw OlapExceptionHelper.createException( - "XMLA provider gave exception: " + message); + "XMLA provider gave exception: " + serializer.writeToString(fault)); } Element executeResponse = findChild(body, XMLA_NS, "ExecuteResponse"); diff --git a/src/org/olap4j/driver/xmla/XmlaOlap4jConnection.java b/src/org/olap4j/driver/xmla/XmlaOlap4jConnection.java index 05a37a7..b76baec 100644 --- a/src/org/olap4j/driver/xmla/XmlaOlap4jConnection.java +++ b/src/org/olap4j/driver/xmla/XmlaOlap4jConnection.java @@ -597,7 +597,18 @@ Element xxx(String request) throws OlapException { try { bytes = proxy.get(serverUrl, request); } catch (IOException e) { - throw OlapExceptionHelper.createException(null, e); + /* + * FIXME This type of exception should not reach this point. + * It was maintained because some other proxy implementations + * exists out there that still throw an IOException arround. + * This was a bad design which we will fix at some point but not + * before the 1.0 release. + */ + throw OlapExceptionHelper.createException(e); + } catch (XmlaOlap4jProxyException e) { + throw OlapExceptionHelper.createException( + "This connection encountered an exception while executing a query.", + e); } Document doc; try { diff --git a/src/org/olap4j/driver/xmla/proxy/XmlaOlap4jAbstractHttpProxy.java b/src/org/olap4j/driver/xmla/proxy/XmlaOlap4jAbstractHttpProxy.java index 37dcaad..0f8b778 100644 --- a/src/org/olap4j/driver/xmla/proxy/XmlaOlap4jAbstractHttpProxy.java +++ b/src/org/olap4j/driver/xmla/proxy/XmlaOlap4jAbstractHttpProxy.java @@ -63,7 +63,7 @@ public abstract class XmlaOlap4jAbstractHttpProxy * @throws IOException */ abstract public byte[] getResponse(URL url, String request) - throws IOException; + throws XmlaOlap4jProxyException; /** @@ -84,7 +84,7 @@ abstract public Future getResponseViaSubmit( * @throws IOException An io exception gets thrown if the given url * connection has not been opened yet. */ - protected void useCookies(URLConnection urlConn) throws IOException { + protected void useCookies(URLConnection urlConn){ // Initializes the cookie manager this.initCookieManager(); @@ -100,7 +100,7 @@ protected void useCookies(URLConnection urlConn) throws IOException { * @throws IOException An io exception gets thrown if the given url * connection has already been opened. */ - protected void saveCookies(URLConnection urlConn) throws IOException { + protected void saveCookies(URLConnection urlConn){ // Initializes the cookie manager this.initCookieManager(); @@ -151,29 +151,40 @@ public void setCache(Map config, Map properties) } // implement XmlaOlap4jProxy - public byte[] get(URL url, String request) throws IOException { + public byte[] get(URL url, String request) throws XmlaOlap4jProxyException { + byte[] response = null; // Tries to fetch from cache - byte[] response = - getFromCache( - url, - request.getBytes(getEncodingCharsetName())); - - // Returns the cached value if found - if (response != null) { - return response; + try { + response = + getFromCache( + url, + request.getBytes(getEncodingCharsetName())); + // Returns the cached value if found + if (response != null) { + return response; + } + } catch (IOException e) { + throw new XmlaOlap4jProxyException( + "An exception was encountered while browsing the proxy cache.", + e); } // Executes the query response = getResponse(url, request); - // Adds to cache - addToCache( - url, - request.getBytes(getEncodingCharsetName()), - response); - - // Returns result - return response; + try { + // Adds to cache + addToCache( + url, + request.getBytes(getEncodingCharsetName()), + response); + // Returns result + return response; + } catch (IOException e) { + throw new XmlaOlap4jProxyException( + "An exception was encountered while saving a response in the proxy cache.", + e); + } } diff --git a/src/org/olap4j/driver/xmla/proxy/XmlaOlap4jCookieManager.java b/src/org/olap4j/driver/xmla/proxy/XmlaOlap4jCookieManager.java index 1340c22..14f5498 100644 --- a/src/org/olap4j/driver/xmla/proxy/XmlaOlap4jCookieManager.java +++ b/src/org/olap4j/driver/xmla/proxy/XmlaOlap4jCookieManager.java @@ -9,16 +9,10 @@ */ package org.olap4j.driver.xmla.proxy; -import java.io.IOException; -import java.net.URL; -import java.net.URLConnection; -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.Iterator; -import java.util.Map; -import java.util.StringTokenizer; -import java.util.concurrent.ConcurrentHashMap; +import java.net.*; +import java.text.*; +import java.util.*; +import java.util.concurrent.*; /** *

CookieManager is a simple utility for handling cookies when working @@ -88,7 +82,7 @@ public XmlaOlap4jCookieManager() { * or IOException will be thrown * @throws java.io.IOException Thrown if conn is not open. */ - public void storeCookies(URLConnection conn) throws IOException { + public void storeCookies(URLConnection conn){ // Determines the domain from where these cookies are being sent String domain = getDomainFromHost(conn.getURL().getHost()); @@ -164,7 +158,7 @@ public void storeCookies(URLConnection conn) throws IOException { * @param conn a java.net.URLConnection - must NOT be open, or IOException will be thrown * @throws java.io.IOException Thrown if conn has already been opened. */ - public void setCookies(URLConnection conn) throws IOException { + public void setCookies(URLConnection conn){ // Determines the domain and path to retrieve the appropriate cookies URL url = conn.getURL(); @@ -200,9 +194,8 @@ && isNotExpired((String) cookie.get(EXPIRES))) { } conn.setRequestProperty(COOKIE, cookieStringBuffer.toString()); } catch (java.lang.IllegalStateException ise) { - IOException ioe = new IOException( + throw new RuntimeException( "Illegal State! Cookies cannot be set on a URLConnection that is already connected. Only call setCookies(java.net.URLConnection) AFTER calling java.net.URLConnection.connect()."); - throw ioe; } } diff --git a/src/org/olap4j/driver/xmla/proxy/XmlaOlap4jHttpProxy.java b/src/org/olap4j/driver/xmla/proxy/XmlaOlap4jHttpProxy.java index 9c5f98c..c9ef89b 100644 --- a/src/org/olap4j/driver/xmla/proxy/XmlaOlap4jHttpProxy.java +++ b/src/org/olap4j/driver/xmla/proxy/XmlaOlap4jHttpProxy.java @@ -34,59 +34,66 @@ public class XmlaOlap4jHttpProxy extends XmlaOlap4jAbstractHttpProxy { @Override public byte[] getResponse(URL url, String request) - throws IOException + throws XmlaOlap4jProxyException { - // Open connection to manipulate the properties - URLConnection urlConnection = url.openConnection(); - urlConnection.setDoOutput(true); + try { + // Open connection to manipulate the properties + URLConnection urlConnection = url.openConnection(); + urlConnection.setDoOutput(true); - // Set headers - urlConnection.setRequestProperty( - "content-type", - "text/xml"); - urlConnection.setRequestProperty( - "User-Agent", - "Olap4j(" - .concat(XmlaOlap4jDriver.VERSION) - .concat(")")); - urlConnection.setRequestProperty( - "Accept", - "text/xml;q=1"); - urlConnection.setRequestProperty( - "Accept-Charset", - getEncodingCharsetName() - .concat(";q=1")); - - // Encode credentials for basic authentication - if (url.getUserInfo() != null) { - String encoding = - Base64.encodeBytes(url.getUserInfo().getBytes(), 0); + // Set headers urlConnection.setRequestProperty( - "Authorization", "Basic " + encoding); - } + "content-type", + "text/xml"); + urlConnection.setRequestProperty( + "User-Agent", + "Olap4j(" + .concat(XmlaOlap4jDriver.VERSION) + .concat(")")); + urlConnection.setRequestProperty( + "Accept", + "text/xml;q=1"); + urlConnection.setRequestProperty( + "Accept-Charset", + getEncodingCharsetName() + .concat(";q=1")); - // Set correct cookies - this.useCookies(urlConnection); + // Encode credentials for basic authentication + if (url.getUserInfo() != null) { + String encoding = + Base64.encodeBytes(url.getUserInfo().getBytes(), 0); + urlConnection.setRequestProperty( + "Authorization", "Basic " + encoding); + } - // Send data (i.e. POST). Use same encoding as specified in the - // header. - final String encoding = getEncodingCharsetName(); - urlConnection.getOutputStream().write(request.getBytes(encoding)); + // Set correct cookies + this.useCookies(urlConnection); - // Get the response, again assuming default encoding. - InputStream is = urlConnection.getInputStream(); - final ByteArrayOutputStream baos = new ByteArrayOutputStream(); - byte[] buf = new byte[1024]; - int count; + // Send data (i.e. POST). Use same encoding as specified in the + // header. + final String encoding = getEncodingCharsetName(); + urlConnection.getOutputStream().write(request.getBytes(encoding)); - while ((count = is.read(buf)) > 0) { - baos.write(buf, 0, count); - } + // Get the response, again assuming default encoding. + InputStream is = urlConnection.getInputStream(); + final ByteArrayOutputStream baos = new ByteArrayOutputStream(); + byte[] buf = new byte[1024]; + int count; - // Save the returned cookies for later use - this.saveCookies(urlConnection); + while ((count = is.read(buf)) > 0) { + baos.write(buf, 0, count); + } - return baos.toByteArray(); + // 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) { + throw new XmlaOlap4jProxyException( + "This proxy encountered an exception while processing the query.",e); + } } @Override diff --git a/src/org/olap4j/driver/xmla/proxy/XmlaOlap4jProxy.java b/src/org/olap4j/driver/xmla/proxy/XmlaOlap4jProxy.java index f74a3a4..c47a275 100644 --- a/src/org/olap4j/driver/xmla/proxy/XmlaOlap4jProxy.java +++ b/src/org/olap4j/driver/xmla/proxy/XmlaOlap4jProxy.java @@ -23,10 +23,20 @@ public interface XmlaOlap4jProxy { * * @param url Target URL * @param request Request string - * @return Response - * @throws IOException + * @return Response The byte array that contains the whole response + * from the server. + * @throws IOException This exception declaration will be removed soon. + * Don't catch this. Catch XmlaOlap4jProxyException instead. + * @throws XmlaOlap4jProxyException If anything occurs during the + * request execution. */ - byte[] get(URL url, String request) throws IOException; + /* + * FIXME We will need to remove the IOException declaration because + * this type of error is linked to the proxy type. A wrapper + * class was created, but some proxies out there (MondrianInprocProxy...) + * still uses this. + */ + byte[] get(URL url, String request) throws XmlaOlap4jProxyException,IOException; /** * Submits a request for background execution. diff --git a/src/org/olap4j/driver/xmla/proxy/XmlaOlap4jProxyException.java b/src/org/olap4j/driver/xmla/proxy/XmlaOlap4jProxyException.java new file mode 100644 index 0000000..747ed75 --- /dev/null +++ b/src/org/olap4j/driver/xmla/proxy/XmlaOlap4jProxyException.java @@ -0,0 +1,25 @@ +/* +// $Id:$ +// This software is subject to the terms of the Common Public License +// Agreement, available at the following URL: +// http://www.opensource.org/licenses/cpl.html. +// Copyright (C) 2007-2007 Julian Hyde +// All Rights Reserved. +// You must accept the terms of that agreement to use this software. +*/ +package org.olap4j.driver.xmla.proxy; + +/** + * Gets thrown whenever an exception is encountered during the querying + * of an XmlaOlap4jProxy subclass. + * + * @author Luc Boudreau + * @version $Id:$ + */ +public class XmlaOlap4jProxyException extends Exception { + private static final long serialVersionUID = 1729906649527317997L; + public XmlaOlap4jProxyException(String message, Throwable cause) { + super(message, cause); + } +} +//End XmlaOlap4jProxyException.java \ No newline at end of file