KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > openi > olap > drillthrough > DrillthroughHelper


1 /*********************************************************************************
2  * The contents of this file are subject to the OpenI Public License Version 1.0
3  * ("License"); You may not use this file except in compliance with the
4  * License. You may obtain a copy of the License at
5  * http://www.openi.org/docs/LICENSE.txt
6  *
7  * Software distributed under the License is distributed on an "AS IS" basis,
8  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
9  * the specific language governing rights and limitations under the License.
10  *
11  * The Original Code is: OpenI Open Source
12  *
13  * The Initial Developer of the Original Code is Loyalty Matrix, Inc.
14  * Portions created by Loyalty Matrix, Inc. are
15  * Copyright (C) 2005 Loyalty Matrix, Inc.; All Rights Reserved.
16  *
17  * Contributor(s): ______________________________________.
18  *
19  ********************************************************************************/

20 package org.openi.olap.drillthrough;
21
22 import org.xml.sax.Attributes JavaDoc;
23 import org.xml.sax.SAXException JavaDoc;
24
25 import org.xml.sax.helpers.DefaultHandler JavaDoc;
26 import sun.misc.BASE64Encoder;
27
28 import java.io.BufferedInputStream JavaDoc;
29 import java.io.ByteArrayInputStream JavaDoc;
30 import java.io.ByteArrayOutputStream JavaDoc;
31 import java.io.IOException JavaDoc;
32 import java.io.InputStream JavaDoc;
33 import java.io.OutputStream JavaDoc;
34
35 import java.net.MalformedURLException JavaDoc;
36 import java.net.URL JavaDoc;
37 import java.util.ArrayList JavaDoc;
38 import java.util.HashMap JavaDoc;
39 import java.util.Iterator JavaDoc;
40 import java.util.List JavaDoc;
41 import java.util.Map JavaDoc;
42 import java.util.StringTokenizer JavaDoc;
43
44 import javax.xml.parsers.SAXParser JavaDoc;
45 import javax.xml.parsers.SAXParserFactory JavaDoc;
46 import javax.xml.soap.MessageFactory JavaDoc;
47 import javax.xml.soap.MimeHeader JavaDoc;
48 import javax.xml.soap.MimeHeaders JavaDoc;
49 import javax.xml.soap.Name JavaDoc;
50 import javax.xml.soap.SOAPBody JavaDoc;
51 import javax.xml.soap.SOAPElement JavaDoc;
52 import javax.xml.soap.SOAPEnvelope JavaDoc;
53 import javax.xml.soap.SOAPException JavaDoc;
54 import javax.xml.soap.SOAPMessage JavaDoc;
55 import javax.xml.soap.SOAPPart JavaDoc;
56
57 import org.apache.commons.httpclient.Header;
58 import org.apache.commons.httpclient.HttpClient;
59 import org.apache.commons.httpclient.HttpStatus;
60 import org.apache.commons.httpclient.methods.InputStreamRequestEntity;
61 import org.apache.commons.httpclient.methods.PostMethod;
62 import org.apache.log4j.Logger;
63
64 /**
65  * executes DT mdx and parses the results in CSV format and writes it to
66  * outputstream
67  */

68 public class DrillthroughHelper {
69     private static Logger logger = Logger.getLogger(DrillthroughHelper.class);
70
71     public static int BUFFER_SIZE = 4048;
72
73     /**
74      *
75      * @param url
76      * @param request
77      * @param outstream
78      * @throws Exception
79      */

80     public static void executeDrillthrough(URL JavaDoc url, SOAPMessage JavaDoc request,
81             OutputStream JavaDoc outstream) throws Exception JavaDoc {
82         try {
83
84             logger.info("Executing SOAP Request");
85
86             InputStream JavaDoc instream = executeSOAP(request, url.toString());
87
88             logger.debug("Parsing results");
89             parseAndWriteCSV(new BufferedInputStream JavaDoc(instream, 1024), outstream);
90             instream.close();
91             logger.debug("Done");
92
93         } catch (Exception JavaDoc ex) {
94             ex.printStackTrace();
95             throw ex;
96         }
97     }
98
99     /**
100      * executes dt soap request and writes result to the output stream
101      *
102      * @param url
103      * @param request
104      * @param outstream
105      * @throws Exception
106      */

107     public static void executeDrillthrough(URL JavaDoc url, String JavaDoc mdxQuery,
108             String JavaDoc datasource, String JavaDoc catalog, OutputStream JavaDoc outstream)
109             throws Exception JavaDoc {
110         SOAPMessage JavaDoc message = constructDrillthroughSoapMessage(mdxQuery,
111                 datasource, catalog);
112         InputStream JavaDoc instream = executeSOAP(message, url.toString());
113         readAndWriteStream(instream, outstream);
114         try {
115             instream.close();
116         } catch (Exception JavaDoc ex) {
117             logger.warn("Exception occured while closing input stream", ex);
118         }
119
120     }
121
122     /**
123      * reads from input stream and writes to the outputstream
124      *
125      * @param in
126      * @param out
127      * @throws IOException
128      */

129     private static void readAndWriteStream(InputStream JavaDoc in, OutputStream JavaDoc out)
130             throws IOException JavaDoc {
131         // BufferedInputStream instream = new BufferedInputStream(in,
132
// BUFFER_SIZE);
133
// BufferedOutputStream outstream = new BufferedOutputStream(out,
134
// BUFFER_SIZE);
135
byte array[] = new byte[BUFFER_SIZE];
136         int count;
137         while ((count = in.read(array, 0, BUFFER_SIZE)) != -1) {
138             out.write(array, 0, count);
139         }
140
141     }
142
143     /**
144      * creates drillthrough xmla soap request message
145      *
146      * @param mdxQuery
147      * drillthrough MDX
148      * @param datasource
149      * xmla datasourcename - used in request as DataSourceInfo
150      * @param catalog -
151      * catalog
152      * @return
153      * @throws SOAPException
154      */

155     public static SOAPMessage JavaDoc constructDrillthroughSoapMessage(String JavaDoc mdxQuery,
156             String JavaDoc datasource, String JavaDoc catalog) throws SOAPException JavaDoc {
157
158         logger.debug("Creating SOAP Envelope");
159         MessageFactory JavaDoc mf = MessageFactory.newInstance();
160         SOAPMessage JavaDoc msg = mf.createMessage();
161         MimeHeaders JavaDoc mh = msg.getMimeHeaders();
162         mh.setHeader("SOAPAction",
163                 "\"urn:schemas-microsoft-com:xml-analysis:Execute\"");
164
165         SOAPPart JavaDoc soapPart = msg.getSOAPPart();
166         SOAPEnvelope JavaDoc envelope = soapPart.getEnvelope();
167         SOAPBody JavaDoc body = envelope.getBody();
168         Name JavaDoc nEx = envelope.createName("Execute", "",
169                 "urn:schemas-microsoft-com:xml-analysis");
170         SOAPElement JavaDoc eEx = body.addChildElement(nEx);
171
172         // add the parameters
173
// COMMAND parameter
174
// <Command>
175
// <Statement>select [Measures].members on Columns from
176
// Sales</Statement>
177
// </Command>
178
Name JavaDoc nCom = envelope.createName("Command");
179         SOAPElement JavaDoc eCommand = eEx.addChildElement(nCom);
180         Name JavaDoc nSta = envelope.createName("Statement");
181         SOAPElement JavaDoc eStatement = eCommand.addChildElement(nSta);
182         eStatement.addTextNode(mdxQuery);
183
184         Map JavaDoc paraList = new HashMap JavaDoc();
185         logger.debug("DT MDX :" + mdxQuery);
186         logger.debug("Datasource :" + datasource);
187         logger.debug("Catalog :" + catalog);
188         paraList.put("DataSourceInfo", datasource);
189         paraList.put("Catalog", catalog);
190
191         // dsf : Note the use of tabular format instead of multidimensional.
192
// This is crucial
193
// otherwise the drillthrough will fail
194
paraList.put("Format", "Tabular");
195         addParameterList(envelope, eEx, "Properties", "PropertyList", paraList);
196         msg.saveChanges();
197
198         return msg;
199     }
200
201     /**
202      * executes drillthrough soap request and returns response inputstream
203      *
204      * @param message
205      * @param endUrl
206      * @return
207      * @throws SOAPException
208      */

209     public static InputStream JavaDoc executeSOAP(SOAPMessage JavaDoc message, String JavaDoc endUrl)
210             throws SOAPException JavaDoc {
211
212         URL JavaDoc url = null;
213
214         try {
215             url = new URL JavaDoc(endUrl);
216         } catch (MalformedURLException JavaDoc ex) {
217             ex.printStackTrace();
218             throw new SOAPException JavaDoc("Mailformed url", ex);
219         }
220
221         PostMethod post = new PostMethod(url.toString());
222         HttpClient client = new HttpClient();
223
224         MimeHeaders JavaDoc headers = message.getMimeHeaders();
225         Iterator JavaDoc it = headers.getAllHeaders();
226
227         boolean hasAuth = false; // true if we find explicit Auth header
228
boolean isFailure = false;
229         while (it.hasNext()) {
230             MimeHeader JavaDoc header = (MimeHeader JavaDoc) it.next();
231
232             String JavaDoc[] values = headers.getHeader(header.getName());
233
234             if (values.length == 1)
235                 post.setRequestHeader(header.getName(), header.getValue());
236             else {
237                 StringBuffer JavaDoc concat = new StringBuffer JavaDoc();
238                 int i = 0;
239                 while (i < values.length) {
240                     if (i != 0)
241                         concat.append(',');
242                     concat.append(values[i]);
243                     i++;
244                 }
245
246                 post.setRequestHeader(header.getName(), concat.toString());
247             }
248
249             if ("Authorization".equals(header.getName()))
250                 hasAuth = true;
251         }
252
253         if (!hasAuth && url.getUserInfo() != null) {
254             post.setRequestHeader("Authorization", "Basic "
255                     + new BASE64Encoder().encode(url.getUserInfo().getBytes()));
256         }
257
258         try {
259             ByteArrayOutputStream JavaDoc outstream = new ByteArrayOutputStream JavaDoc();
260             message.writeTo(outstream);
261             ByteArrayInputStream JavaDoc instream = new ByteArrayInputStream JavaDoc(outstream
262                     .toByteArray());
263
264             post.setRequestEntity(new InputStreamRequestEntity(instream,
265                     outstream.size()));
266
267             client.executeMethod(post);
268             if (post.getStatusCode() == HttpStatus.SC_INTERNAL_SERVER_ERROR) {
269                 isFailure = true;
270             } else if ((post.getStatusCode() / 100) != 2) {
271                 throw new SOAPException JavaDoc("Bad response: "
272                         + post.getStatusLine().toString());
273             }
274
275             headers = new MimeHeaders JavaDoc();
276             String JavaDoc key, value;
277
278             Header JavaDoc[] responseHeaders = post.getResponseHeaders();
279             for (int i = 0; i < responseHeaders.length; i++) {
280
281                 key = responseHeaders[i].getName();
282                 value = responseHeaders[i].getValue();
283
284                 if (key == null && value == null)
285                     break;
286
287                 if (key != null) {
288                     StringTokenizer JavaDoc values = new StringTokenizer JavaDoc(value, ",");
289                     while (values.hasMoreTokens())
290                         headers.addHeader(key, values.nextToken().trim());
291                 }
292             }
293             if (isFailure) {
294                 String JavaDoc msg = "SOAP Request Error\r\n"
295                         + post.getResponseBodyAsString();
296                 post.releaseConnection();
297                 throw new SOAPException JavaDoc(msg);
298             }
299
300             return post.getResponseBodyAsStream();
301
302         } catch (SOAPException JavaDoc ex) {
303             ex.printStackTrace();
304             throw ex;
305         } catch (Exception JavaDoc ex) {
306             ex.printStackTrace();
307             throw new SOAPException JavaDoc(ex);
308         }
309
310     }
311
312     // soap helper
313
private static void addParameterList(SOAPEnvelope JavaDoc envelope,
314             SOAPElement JavaDoc eParent, String JavaDoc typeName, String JavaDoc listName, Map JavaDoc params)
315             throws SOAPException JavaDoc {
316         Name JavaDoc nPara = envelope.createName(typeName, "",
317                 "urn:schemas-microsoft-com:xml-analysis");
318         SOAPElement JavaDoc eType = eParent.addChildElement(nPara);
319         nPara = envelope.createName(listName, "",
320                 "urn:schemas-microsoft-com:xml-analysis");
321
322         SOAPElement JavaDoc eList = eType.addChildElement(nPara);
323
324         if (params == null) {
325             return;
326         }
327
328         Iterator JavaDoc it = params.keySet().iterator();
329
330         while (it.hasNext()) {
331             String JavaDoc tag = (String JavaDoc) it.next();
332             String JavaDoc value = (String JavaDoc) params.get(tag);
333             nPara = envelope.createName(tag, "",
334                     "urn:schemas-microsoft-com:xml-analysis");
335
336             SOAPElement JavaDoc eTag = eList.addChildElement(nPara);
337             eTag.addTextNode(value);
338         }
339     }
340
341     // process results(using sax) and writes results to output stream in
342
// CSV format
343
private static void parseAndWriteCSV(InputStream JavaDoc in, OutputStream JavaDoc out)
344             throws Exception JavaDoc {
345         final OutputStream JavaDoc writer = out;
346         DefaultHandler JavaDoc rowHandler = new DefaultHandler JavaDoc() {
347             // flags used to process results row
348
boolean rowStarted = false;
349
350             boolean inRowItemElement = false;
351
352             boolean isFirstRow = true;
353
354             // string list populated on each row
355
// each row cell values list
356
List JavaDoc stringList = new ArrayList JavaDoc();
357
358             // col names, are scaned from first row
359
// ->MS-XMLA results column name in header, but mondrian does not.
360
// ->So column names are restrieved from first row
361
List JavaDoc colNames = new ArrayList JavaDoc();
362
363             // sax handler
364
public void startElement(String JavaDoc namespaceURI, String JavaDoc localName,
365                     String JavaDoc qName, Attributes JavaDoc atts) throws SAXException JavaDoc {
366                 // porcessing drillresults row
367
// <row>
368
// <fieldname>fieldvalue</fieldname>
369
// ........
370
// </row>
371
//
372
if ("row".equals(localName)) {
373                     rowStarted = true;
374                 } else if (rowStarted) {
375                     inRowItemElement = true;
376
377                     if (isFirstRow) {
378                         colNames.add(localName);
379                     }
380                 } else {
381                     rowStarted = false;
382                     inRowItemElement = false;
383                 }
384             }
385
386             public void characters(char[] ch, int start, int length)
387                     throws SAXException JavaDoc {
388                 // only for cell value
389
if (inRowItemElement) {
390                     String JavaDoc value = new String JavaDoc(ch, start, length);
391                     stringList.add(value);
392                 }
393             }
394
395             public void endElement(String JavaDoc namespaceURI, String JavaDoc localName,
396                     String JavaDoc qName) throws SAXException JavaDoc {
397                 try {
398                     if (inRowItemElement) {
399                         // in each cell value ending
400
inRowItemElement = false;
401                     } else if (rowStarted && !inRowItemElement) {
402                         // row ending
403
rowStarted = false;
404
405                         if (isFirstRow) {
406                             // write column header
407
isFirstRow = false;
408                             writeRow(colNames);
409                         }
410
411                         // write cell values for a row
412
writeRow(stringList);
413                         stringList.clear();
414                     }
415                 } catch (Exception JavaDoc ex) {
416                     throw new SAXException JavaDoc(ex);
417                 }
418             }
419
420             // iterates and write each column value of a row composed in
421
// stringlist
422
public void writeRow(List JavaDoc stringList) throws IOException JavaDoc {
423
424                 for (int i = 0; i < stringList.size(); i++) {
425                     writer.write(stringList.get(i).toString().getBytes());
426
427                     if (i == (stringList.size() - 1)) {
428                         writer.write("\n".getBytes());
429                     } else {
430                         writer.write(",".getBytes());
431                     }
432                 }
433
434                 writer.flush();
435             }
436         };
437
438         try {
439             SAXParserFactory JavaDoc factory = SAXParserFactory.newInstance();
440             factory.setNamespaceAware(true);
441             factory.setValidating(true);
442
443             SAXParser JavaDoc saxParser = factory.newSAXParser();
444             saxParser.parse(in, rowHandler);
445             saxParser = null;
446             rowHandler = null;
447             in.close();
448             in = null;
449         } catch (Exception JavaDoc ex) {
450             throw new SAXException JavaDoc(
451                     "An error occured while parsing drillthrough results", ex);
452         }
453     }
454 }
455
Popular Tags