KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > mondrian > tui > XmlaSupport


1 /*
2 // $Id: //open/mondrian/src/main/mondrian/tui/XmlaSupport.java#9 $
3 // This software is subject to the terms of the Common Public License
4 // Agreement, available at the following URL:
5 // http://www.opensource.org/licenses/cpl.html.
6 // Copyright (C) 2005-2007 Julian Hyde and others
7 // All Rights Reserved.
8 // You must accept the terms of that agreement to use this software.
9 */

10
11 package mondrian.tui;
12
13 import mondrian.spi.CatalogLocator;
14 import mondrian.spi.impl.CatalogLocatorImpl;
15 import mondrian.xmla.DataSourcesConfig;
16 import mondrian.olap.Util;
17 import mondrian.xmla.XmlaConstants;
18 import mondrian.xmla.XmlaHandler;
19 import mondrian.xmla.XmlaRequest;
20 import mondrian.xmla.XmlaResponse;
21 import mondrian.xmla.XmlaServlet;
22 import mondrian.xmla.impl.DefaultXmlaServlet;
23 import mondrian.xmla.impl.DefaultXmlaRequest;
24 import mondrian.xmla.impl.DefaultXmlaResponse;
25 import org.eigenbase.xom.DOMWrapper;
26 import org.eigenbase.xom.Parser;
27 import org.eigenbase.xom.XOMUtil;
28 import org.eigenbase.xom.XOMException;
29 import org.apache.log4j.Logger;
30 import org.w3c.dom.Element JavaDoc;
31 import org.w3c.dom.Node JavaDoc;
32 import org.w3c.dom.Document JavaDoc;
33 import org.xml.sax.SAXException JavaDoc;
34
35 import java.io.ByteArrayOutputStream JavaDoc;
36 import java.io.File JavaDoc;
37 import java.io.FileReader JavaDoc;
38 import java.io.StringReader JavaDoc;
39 import java.io.BufferedReader JavaDoc;
40 import java.io.OutputStream JavaDoc;
41 import java.io.FileOutputStream JavaDoc;
42 import java.io.IOException JavaDoc;
43 import java.util.HashMap JavaDoc;
44 import java.util.Map JavaDoc;
45 import javax.servlet.Servlet JavaDoc;
46 import javax.servlet.ServletException JavaDoc;
47 import javax.xml.parsers.ParserConfigurationException JavaDoc;
48 import javax.xml.transform.TransformerException JavaDoc;
49 import javax.xml.transform.TransformerConfigurationException JavaDoc;
50
51 /**
52  * This files provide support for making XMLA requests and looking at
53  * the responses.
54  *
55  * @author <a>Richard M. Emberson</a>
56  * @version
57  */

58 public class XmlaSupport {
59     private static final Logger LOGGER = Logger.getLogger(XmlaSupport.class);
60
61     public static final String JavaDoc nl = Util.nl;
62     public static final String JavaDoc SOAP_PREFIX = XmlaConstants.SOAP_PREFIX;
63
64     public static final String JavaDoc CATALOG_NAME = "FoodMart";
65     public static final String JavaDoc DATASOURCE_NAME = "MondrianFoodMart";
66     public static final String JavaDoc DATASOURCE_DESCRIPTION =
67             "Mondrian FoodMart data source";
68     public static final String JavaDoc DATASOURCE_INFO =
69             "Provider=Mondrian;DataSource=MondrianFoodMart;";
70
71     public static final Map JavaDoc<String JavaDoc, String JavaDoc> ENV;
72
73     // Setup the Map used to instantiate XMLA template documents.
74
// Have to see if we need to be able to dynamically change these values.
75
static {
76         ENV = new HashMap JavaDoc<String JavaDoc, String JavaDoc>();
77         ENV.put("catalog", CATALOG_NAME);
78         ENV.put("datasource", DATASOURCE_INFO);
79     }
80
81     /**
82      * This is a parameterized XSLT.
83      * The parameters are:
84      * "soap" with values "none" or empty
85      * "content" with values "schemadata", "schema", "data" or empty
86      * With these setting one can extract from an XMLA SOAP message
87      * the soap wrapper plus body or simply the body; the complete
88      * body (schema and data), only the schema of the body, only the
89      * data of the body or none of the body
90      *
91      */

92     public static String JavaDoc getXmlaTransform(String JavaDoc xmlaPrefix) {
93         return
94         "<?xml version='1.0'?>" +
95         "<xsl:stylesheet " +
96         " xmlns:xsl='http://www.w3.org/1999/XSL/Transform' " +
97         " xmlns:xalan='http://xml.apache.org/xslt'" +
98         " xmlns:xsd='http://www.w3.org/2001/XMLSchema'" +
99         " xmlns:ROW='urn:schemas-microsoft-com:xml-analysis:rowset'" +
100         " xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/' " +
101         " xmlns:" + xmlaPrefix + "='urn:schemas-microsoft-com:xml-analysis'" +
102         " version='1.0'" +
103         ">" +
104         "<xsl:output method='xml' " +
105         " encoding='UTF-8'" +
106         " indent='yes' " +
107         " xalan:indent-amount='2'/>" +
108         "<xsl:param name='content'/>" +
109         "<xsl:param name='soap'/>" +
110         "<!-- consume '/' and apply -->" +
111         "<xsl:template match='/'>" +
112         " <xsl:apply-templates/>" +
113         "</xsl:template>" +
114         "<!-- copy 'Envelope' unless soap==none --> " +
115         "<xsl:template match='SOAP-ENV:Envelope'> " +
116         " <xsl:choose> " +
117         " <xsl:when test=\"$soap='none'\"> " +
118         " <xsl:apply-templates/> " +
119         " </xsl:when> " +
120         " <xsl:otherwise> " +
121         " <xsl:copy> " +
122         " <xsl:apply-templates select='@*|node()'/> " +
123         " </xsl:copy> " +
124         " </xsl:otherwise> " +
125         " </xsl:choose> " +
126         "</xsl:template> " +
127         "<!-- copy 'Header' unless soap==none --> " +
128         "<xsl:template match='SOAP-ENV:Header'> " +
129         " <xsl:choose> " +
130         " <xsl:when test=\"$soap='none'\"> " +
131         " <xsl:apply-templates/> " +
132         " </xsl:when> " +
133         " <xsl:otherwise> " +
134         " <xsl:copy> " +
135         " <xsl:apply-templates select='@*|node()'/> " +
136         " </xsl:copy> " +
137         " </xsl:otherwise> " +
138         " </xsl:choose> " +
139         "</xsl:template> " +
140         "<!-- copy 'Body' unless soap==none --> " +
141         "<xsl:template match='SOAP-ENV:Body'> " +
142         " <xsl:choose> " +
143         " <xsl:when test=\"$soap='none'\"> " +
144         " <xsl:apply-templates/> " +
145         " </xsl:when> " +
146         " <xsl:otherwise> " +
147         " <xsl:copy> " +
148         " <xsl:apply-templates select='@*|node()'/> " +
149         " </xsl:copy> " +
150         " </xsl:otherwise> " +
151         " </xsl:choose> " +
152         "</xsl:template> " +
153         "<!-- copy 'DiscoverResponse' unless soap==none --> " +
154         "<xsl:template match='" + xmlaPrefix + ":DiscoverResponse'> " +
155         " <xsl:choose> " +
156         " <xsl:when test=\"$soap='none'\"> " +
157         " <xsl:apply-templates/> " +
158         " </xsl:when> " +
159         " <xsl:otherwise> " +
160         " <xsl:copy> " +
161         " <xsl:apply-templates select='@*|node()'/> " +
162         " </xsl:copy> " +
163         " </xsl:otherwise> " +
164         " </xsl:choose> " +
165         "</xsl:template> " +
166         "<!-- copy 'return' unless soap==none --> " +
167         "<xsl:template match='" + xmlaPrefix + ":return'> " +
168         " <xsl:choose> " +
169         " <xsl:when test=\"$soap='none'\"> " +
170         " <xsl:apply-templates/> " +
171         " </xsl:when> " +
172         " <xsl:otherwise> " +
173         " <xsl:copy> " +
174         " <xsl:apply-templates select='@*|node()'/> " +
175         " </xsl:copy> " +
176         " </xsl:otherwise> " +
177         " </xsl:choose> " +
178         "</xsl:template> " +
179         "<!-- copy 'root' unless soap==none --> " +
180         "<xsl:template match='ROW:root'> " +
181         " <xsl:choose> " +
182         " <xsl:when test=\"$soap='none'\"> " +
183         " <xsl:apply-templates/> " +
184         " </xsl:when> " +
185         " <xsl:otherwise> " +
186         " <xsl:copy> " +
187         " <xsl:apply-templates select='@*|node()'/> " +
188         " </xsl:copy> " +
189         " </xsl:otherwise > " +
190         " </xsl:choose> " +
191         "</xsl:template> " +
192         "<!-- copy 'schema' if content==schema or schemadata --> " +
193         "<xsl:template match='xsd:schema'> " +
194         " <xsl:choose> " +
195         " <xsl:when test=\"$content='schemadata'\"> " +
196         " <xsl:copy> " +
197         " <xsl:apply-templates select='@*|node()'/> " +
198         " </xsl:copy> " +
199         " </xsl:when> " +
200         " <xsl:when test=\"$content='schema'\"> " +
201         " <xsl:copy> " +
202         " <xsl:apply-templates select='@*|node()'/> " +
203         " </xsl:copy> " +
204         " </xsl:when> " +
205         " <xsl:otherwise/> " +
206         " </xsl:choose> " +
207         "</xsl:template> " +
208         "<!-- copy 'row' if content==data or schemadata --> " +
209         "<xsl:template match='ROW:row'> " +
210         " <xsl:choose> " +
211         " <xsl:when test=\"$content='schemadata'\"> " +
212         " <xsl:copy> " +
213         " <xsl:apply-templates select='@*|node()'/> " +
214         " </xsl:copy> " +
215         " </xsl:when> " +
216         " <xsl:when test=\"$content='data'\"> " +
217         " <xsl:copy> " +
218         " <xsl:apply-templates select='@*|node()'/> " +
219         " </xsl:copy> " +
220         " </xsl:when> " +
221         " <xsl:otherwise/> " +
222         " </xsl:choose> " +
223         "</xsl:template> " +
224         "<!-- copy everything else --> " +
225         "<xsl:template match='*|@*'> " +
226         " <xsl:copy> " +
227         " <xsl:apply-templates select='@*|node()'/> " +
228         " </xsl:copy> " +
229         "</xsl:template> " +
230         "</xsl:stylesheet>";
231     }
232
233     /**
234      * This is the prefix used in xpath and transforms for the xmla rowset
235      * namespace "urn:schemas-microsoft-com:xml-analysis:rowset".
236      */

237     public static final String JavaDoc ROW_SET_PREFIX = "ROW";
238
239     private static CatalogLocator CATALOG_LOCATOR = null;
240     private static String JavaDoc soapFaultXPath = null;
241     private static String JavaDoc soapHeaderAndBodyXPath = null;
242     private static String JavaDoc soapBodyXPath = null;
243     private static String JavaDoc soapXmlaRootXPath = null;
244     private static String JavaDoc xmlaRootXPath = null;
245
246
247     /////////////////////////////////////////////////////////////////////////
248
// xmla help
249
/////////////////////////////////////////////////////////////////////////
250
public static CatalogLocator getCatalogLocator() {
251         if (CATALOG_LOCATOR == null) {
252             CATALOG_LOCATOR = new CatalogLocatorImpl();
253         }
254         return CATALOG_LOCATOR;
255     }
256     public static DataSourcesConfig.DataSources getDataSources(
257             String JavaDoc connectString,
258             String JavaDoc[][] catalogNameUrls)
259             throws XOMException {
260
261         String JavaDoc str = getDataSourcesText(connectString, catalogNameUrls);
262         StringReader JavaDoc dsConfigReader = new StringReader JavaDoc(str);
263
264         final Parser xmlParser = XOMUtil.createDefaultParser();
265         final DOMWrapper def = xmlParser.parse(dsConfigReader);
266
267         DataSourcesConfig.DataSources datasources =
268             new DataSourcesConfig.DataSources(def);
269
270         return datasources;
271     }
272
273     /**
274      * With a connection string, generate the DataSource xml. Since this
275      * is used by directly, same process, communicating with XMLA
276      * Mondrian, the fact that the URL contains "localhost" is not
277      * important.
278      *
279      * @param connectString
280      * @param catalogNameUrls array of catalog names, catalog url pairs
281      */

282     public static String JavaDoc getDataSourcesText(
283             String JavaDoc connectString,
284             String JavaDoc[][] catalogNameUrls) {
285         StringBuilder JavaDoc buf = new StringBuilder JavaDoc(500);
286         buf.append("<?xml version=\"1.0\"?>");
287         buf.append(nl);
288         buf.append("<DataSources>");
289         buf.append(nl);
290         buf.append(" <DataSource>");
291         buf.append(nl);
292         buf.append(" <DataSourceName>");
293         buf.append(DATASOURCE_NAME);
294         buf.append("</DataSourceName>");
295         buf.append(nl);
296         buf.append(" <DataSourceDescription>");
297         buf.append(DATASOURCE_DESCRIPTION);
298         buf.append("</DataSourceDescription>");
299         buf.append(nl);
300         buf.append(" <URL>http://localhost:8080/mondrian/xmla</URL>");
301         buf.append(nl);
302         buf.append(" <DataSourceInfo><![CDATA[");
303         buf.append(connectString);
304         buf.append("]]></DataSourceInfo>");
305         buf.append(nl);
306
307         buf.append(" <ProviderName>Mondrian</ProviderName>");
308         buf.append(nl);
309         buf.append(" <ProviderType>MDP</ProviderType>");
310         buf.append(nl);
311         buf.append(" <AuthenticationMode>Unauthenticated</AuthenticationMode>");
312         buf.append(nl);
313         buf.append(" <Catalogs>");
314         buf.append(nl);
315         for (String JavaDoc[] catalogNameUrl : catalogNameUrls) {
316             String JavaDoc name = catalogNameUrl[0];
317             String JavaDoc url = catalogNameUrl[1];
318             buf.append(" <Catalog name='");
319             buf.append(name);
320             buf.append("'><Definition>");
321             buf.append(url);
322             buf.append("</Definition></Catalog>");
323         }
324         buf.append(" </Catalogs>");
325         buf.append(nl);
326         buf.append(" </DataSource>");
327         buf.append(nl);
328         buf.append("</DataSources>");
329         buf.append(nl);
330         String JavaDoc datasources = buf.toString();
331         if (LOGGER.isDebugEnabled()) {
332             LOGGER.debug("XmlaSupport.getDataSources: datasources="+
333                     datasources);
334         }
335         return datasources;
336     }
337     public static String JavaDoc getSoapFaultXPath() {
338         if (XmlaSupport.soapFaultXPath == null) {
339             StringBuilder JavaDoc buf = new StringBuilder JavaDoc(100);
340             buf.append('/');
341             buf.append(SOAP_PREFIX);
342             buf.append(":Envelope");
343             buf.append('/');
344             buf.append(SOAP_PREFIX);
345             buf.append(":Body");
346             buf.append('/');
347             buf.append(SOAP_PREFIX);
348             buf.append(":Fault");
349             buf.append("/*");
350             String JavaDoc xpath = buf.toString();
351             XmlaSupport.soapFaultXPath = xpath;
352
353             if (LOGGER.isDebugEnabled()) {
354                 LOGGER.debug(
355                     "XmlaSupport.getSoapFaultXPath: xpath="+ xpath);
356             }
357         }
358         return XmlaSupport.soapFaultXPath;
359     }
360
361     public static String JavaDoc getSoapHeaderAndBodyXPath() {
362         if (XmlaSupport.soapHeaderAndBodyXPath == null) {
363             StringBuilder JavaDoc buf = new StringBuilder JavaDoc(100);
364             buf.append('/');
365             buf.append(SOAP_PREFIX);
366             buf.append(":Envelope");
367             buf.append("/*");
368             String JavaDoc xpath = buf.toString();
369             XmlaSupport.soapHeaderAndBodyXPath = xpath;
370
371             if (LOGGER.isDebugEnabled()) {
372                 LOGGER.debug(
373                     "XmlaSupport.getSoapHeaderAndBodyXPath: xpath="+ xpath);
374             }
375         }
376         return XmlaSupport.soapHeaderAndBodyXPath;
377     }
378     public static String JavaDoc getSoapBodyXPath() {
379         if (XmlaSupport.soapBodyXPath == null) {
380             StringBuilder JavaDoc buf = new StringBuilder JavaDoc(100);
381             buf.append('/');
382             buf.append(SOAP_PREFIX);
383             buf.append(":Envelope");
384             buf.append('/');
385             buf.append(SOAP_PREFIX);
386             buf.append(":Body");
387             buf.append("/*");
388             String JavaDoc xpath = buf.toString();
389             XmlaSupport.soapBodyXPath = xpath;
390
391             if (LOGGER.isDebugEnabled()) {
392                 LOGGER.debug("XmlaSupport.getSoapBodyXPath: xpath="+ xpath);
393             }
394         }
395         return XmlaSupport.soapBodyXPath;
396     }
397
398     public static String JavaDoc getSoapXmlaRootXPath(String JavaDoc xmlaPrefix) {
399         if (XmlaSupport.soapXmlaRootXPath == null) {
400             StringBuilder JavaDoc buf = new StringBuilder JavaDoc(20);
401             buf.append('/');
402             buf.append(SOAP_PREFIX);
403             buf.append(":Envelope");
404             buf.append('/');
405             buf.append(SOAP_PREFIX);
406             buf.append(":Body");
407             buf.append("/").append(xmlaPrefix).append(":DiscoverResponse");
408             buf.append("/").append(xmlaPrefix).append(":return");
409             buf.append('/');
410             buf.append(ROW_SET_PREFIX);
411             buf.append(":root");
412             buf.append("/*");
413             String JavaDoc xpath = buf.toString();
414             XmlaSupport.soapXmlaRootXPath = xpath;
415
416             if (LOGGER.isDebugEnabled()) {
417                 LOGGER.debug("XmlaSupport.getSoapXmlaRootXPath: xpath="+ xpath);
418             }
419         }
420         return XmlaSupport.soapXmlaRootXPath;
421     }
422
423     public static String JavaDoc getXmlaRootXPath(String JavaDoc xmlaPrefix) {
424         if (XmlaSupport.xmlaRootXPath == null) {
425             StringBuilder JavaDoc buf = new StringBuilder JavaDoc(20);
426             buf.append("/").append(xmlaPrefix).append(":DiscoverResponse");
427             buf.append("/").append(xmlaPrefix).append(":return");
428             buf.append('/');
429             buf.append(ROW_SET_PREFIX);
430             buf.append(":root");
431             buf.append("/*");
432             String JavaDoc xpath = buf.toString();
433             XmlaSupport.xmlaRootXPath = xpath;
434
435             if (LOGGER.isDebugEnabled()) {
436                 LOGGER.debug("XmlaSupport.getXmlaRootXPath: xpath="+ xpath);
437             }
438         }
439         return XmlaSupport.xmlaRootXPath;
440     }
441
442
443
444     public static Node JavaDoc[] extractNodesFromSoapXmla(byte[] bytes)
445             throws SAXException JavaDoc, IOException JavaDoc {
446         Document JavaDoc doc = XmlUtil.parse(bytes);
447         return extractNodesFromSoapXmla(doc);
448     }
449
450     public static Node JavaDoc[] extractNodesFromSoapXmla(Document JavaDoc doc)
451             throws SAXException JavaDoc, IOException JavaDoc {
452
453         final String JavaDoc xmlaPrefix = "xmla";
454         String JavaDoc xpath = getSoapXmlaRootXPath(xmlaPrefix);
455
456         // Note that this is SOAP 1.1 version uri
457
String JavaDoc[][] nsArray = new String JavaDoc[][] {
458              { SOAP_PREFIX, XmlaConstants.NS_SOAP_ENV_1_1 },
459              { xmlaPrefix, XmlaConstants.NS_XMLA },
460              { ROW_SET_PREFIX, XmlaConstants.NS_XMLA_ROWSET }
461         };
462
463         return extractNodes(doc, xpath, nsArray);
464
465     }
466
467     public static Node JavaDoc[] extractNodesFromXmla(byte[] bytes)
468             throws SAXException JavaDoc, IOException JavaDoc {
469         Document JavaDoc doc = XmlUtil.parse(bytes);
470         return extractNodesFromXmla(doc);
471     }
472
473     public static Node JavaDoc[] extractNodesFromXmla(Document JavaDoc doc)
474             throws SAXException JavaDoc, IOException JavaDoc {
475
476         final String JavaDoc xmlaPrefix = "xmla";
477         String JavaDoc xpath = getXmlaRootXPath(xmlaPrefix);
478
479         String JavaDoc[][] nsArray = new String JavaDoc[][] {
480              {xmlaPrefix, XmlaConstants.NS_XMLA },
481              { ROW_SET_PREFIX, XmlaConstants.NS_XMLA_ROWSET }
482         };
483
484         return extractNodes(doc, xpath, nsArray);
485     }
486
487     public static Node JavaDoc[] extractFaultNodesFromSoap(byte[] bytes)
488             throws SAXException JavaDoc, IOException JavaDoc {
489         Document JavaDoc doc = XmlUtil.parse(bytes);
490         return extractFaultNodesFromSoap(doc);
491     }
492     public static Node JavaDoc[] extractFaultNodesFromSoap(Document JavaDoc doc)
493             throws SAXException JavaDoc, IOException JavaDoc {
494         String JavaDoc xpath = getSoapFaultXPath();
495
496         String JavaDoc[][] nsArray = new String JavaDoc[][] {
497              { SOAP_PREFIX, XmlaConstants.NS_SOAP_ENV_1_1 },
498         };
499
500         Node JavaDoc[] nodes = extractNodes(doc, xpath, nsArray);
501         return nodes;
502     }
503
504     public static Node JavaDoc[] extractHeaderAndBodyFromSoap(byte[] bytes)
505             throws SAXException JavaDoc, IOException JavaDoc {
506         Document JavaDoc doc = XmlUtil.parse(bytes);
507         return extractHeaderAndBodyFromSoap(doc);
508     }
509     public static Node JavaDoc[] extractHeaderAndBodyFromSoap(Document JavaDoc doc)
510             throws SAXException JavaDoc, IOException JavaDoc {
511         String JavaDoc xpath = getSoapHeaderAndBodyXPath();
512
513         String JavaDoc[][] nsArray = new String JavaDoc[][] {
514              { SOAP_PREFIX, XmlaConstants.NS_SOAP_ENV_1_1 },
515         };
516
517         Node JavaDoc[] nodes = extractNodes(doc, xpath, nsArray);
518         return nodes;
519     }
520     public static Document JavaDoc extractBodyFromSoap(Document JavaDoc doc)
521             throws SAXException JavaDoc, IOException JavaDoc {
522         String JavaDoc xpath = getSoapBodyXPath();
523
524         String JavaDoc[][] nsArray = new String JavaDoc[][] {
525              { SOAP_PREFIX, XmlaConstants.NS_SOAP_ENV_1_1 },
526         };
527
528         Node JavaDoc[] nodes = extractNodes(doc, xpath, nsArray);
529         return (nodes.length == 1)
530             ? XmlUtil.newDocument(nodes[0], true) : null;
531     }
532
533     /**
534      * Given a Document and an xpath/namespace-array pair, extract and return
535      * the Nodes resulting from applying the xpath.
536      *
537      * @throws SAXException
538      * @throws IOException
539      */

540     public static Node JavaDoc[] extractNodes(
541             Node JavaDoc node, String JavaDoc xpath, String JavaDoc[][] nsArray)
542             throws SAXException JavaDoc, IOException JavaDoc {
543
544         Document JavaDoc contextDoc = XmlUtil.createContextDocument(nsArray);
545         Node JavaDoc[] nodes = XmlUtil.selectAsNodes(node, xpath, contextDoc);
546
547         if (LOGGER.isDebugEnabled()) {
548             StringBuilder JavaDoc buf = new StringBuilder JavaDoc(1024);
549             buf.append("XmlaSupport.extractNodes: ");
550             buf.append("nodes.length=");
551             buf.append(nodes.length);
552             buf.append(nl);
553             for (Node JavaDoc n : nodes) {
554                 String JavaDoc str = XmlUtil.toString(n, false);
555                 buf.append(str);
556                 buf.append(nl);
557             }
558             LOGGER.debug(buf.toString());
559         }
560
561         return nodes;
562     }
563     /////////////////////////////////////////////////////////////////////////
564
// soap xmla file
565
/////////////////////////////////////////////////////////////////////////
566
/**
567      * Process the given input file as a SOAP-XMLA request.
568      *
569      */

570     public static byte[] processSoapXmla(
571             File JavaDoc file,
572             String JavaDoc connectString,
573             String JavaDoc[][] catalogNameUrls,
574             String JavaDoc cbClassName)
575                 throws IOException JavaDoc, ServletException JavaDoc, SAXException JavaDoc {
576
577         String JavaDoc requestText = XmlaSupport.readFile(file);
578         return processSoapXmla(requestText, connectString, catalogNameUrls, cbClassName);
579     }
580
581     public static byte[] processSoapXmla(
582             Document JavaDoc doc,
583             String JavaDoc connectString,
584             String JavaDoc[][] catalogNameUrls,
585             String JavaDoc cbClassName)
586                 throws IOException JavaDoc, ServletException JavaDoc, SAXException JavaDoc {
587
588         String JavaDoc requestText = XmlUtil.toString(doc, false);
589         return processSoapXmla(requestText, connectString, catalogNameUrls, cbClassName);
590     }
591
592     public static byte[] processSoapXmla(
593             String JavaDoc requestText,
594             String JavaDoc connectString,
595             String JavaDoc[][] catalogNameUrls,
596             String JavaDoc cbClassName)
597             throws IOException JavaDoc, ServletException JavaDoc, SAXException JavaDoc {
598
599         // read soap file
600
File JavaDoc dsFile = null;
601         try {
602
603
604             // Create datasource file and put datasource xml into it.
605
// Mark it as delete on exit.
606
String JavaDoc dataSourceText =
607                 XmlaSupport.getDataSourcesText(connectString, catalogNameUrls);
608
609             dsFile = File.createTempFile("datasources.xml", null);
610
611             OutputStream JavaDoc out = new FileOutputStream JavaDoc(dsFile);
612             out.write(dataSourceText.getBytes());
613             out.flush();
614
615             byte[] reqBytes = requestText.getBytes();
616             // make request
617
MockHttpServletRequest req = new MockHttpServletRequest(reqBytes);
618             req.setMethod("POST");
619             req.setContentType("text/xml");
620
621             // make response
622
MockHttpServletResponse res = new MockHttpServletResponse();
623             res.setCharacterEncoding("UTF-8");
624
625             // process
626
MockServletContext servletContext = new MockServletContext();
627             MockServletConfig servletConfig = new MockServletConfig(servletContext);
628
629             servletConfig.addInitParameter(XmlaServlet.PARAM_CALLBACKS, cbClassName);
630             servletConfig.addInitParameter(
631                 XmlaServlet.PARAM_CHAR_ENCODING, "UTF-8");
632             servletConfig.addInitParameter(
633                 XmlaServlet.PARAM_DATASOURCES_CONFIG, dsFile.toURL().toString());
634
635             Servlet servlet = new DefaultXmlaServlet();
636             servlet.init(servletConfig);
637             servlet.service(req, res);
638
639             return res.toByteArray();
640         } finally {
641             if (dsFile != null) {
642                 dsFile.delete();
643             }
644         }
645     }
646
647     public static Servlet makeServlet(String JavaDoc connectString,
648             String JavaDoc[][] catalogNameUrls,
649             String JavaDoc cbClassName)
650             throws IOException JavaDoc, ServletException JavaDoc, SAXException JavaDoc {
651
652             // Create datasource file and put datasource xml into it.
653
// Mark it as delete on exit.
654
String JavaDoc dataSourceText =
655                 XmlaSupport.getDataSourcesText(connectString, catalogNameUrls);
656
657             File JavaDoc dsFile = File.createTempFile("datasources.xml", null);
658
659             //////////////////////////////////////////////////////////
660
// NOTE: this is ok for CmdRunner or JUnit testing but
661
// deleteOnExit is NOT good for production
662
//////////////////////////////////////////////////////////
663
dsFile.deleteOnExit();
664
665             OutputStream JavaDoc out = new FileOutputStream JavaDoc(dsFile);
666             out.write(dataSourceText.getBytes());
667             out.flush();
668
669             // process
670
MockServletContext servletContext = new MockServletContext();
671             MockServletConfig servletConfig = new MockServletConfig(servletContext);
672             servletConfig.addInitParameter(XmlaServlet.PARAM_CALLBACKS, cbClassName);
673             servletConfig.addInitParameter(
674                 XmlaServlet.PARAM_CHAR_ENCODING, "UTF-8");
675             servletConfig.addInitParameter(
676                 XmlaServlet.PARAM_DATASOURCES_CONFIG, dsFile.toURL().toString());
677
678             Servlet servlet = new DefaultXmlaServlet();
679             servlet.init(servletConfig);
680
681             return servlet;
682     }
683     public static byte[] processSoapXmla(File JavaDoc file, Servlet servlet)
684             throws IOException JavaDoc, ServletException JavaDoc, SAXException JavaDoc {
685
686         String JavaDoc requestText = XmlaSupport.readFile(file);
687         return processSoapXmla(requestText, servlet);
688     }
689     public static byte[] processSoapXmla(Document JavaDoc doc, Servlet servlet)
690             throws IOException JavaDoc, ServletException JavaDoc, SAXException JavaDoc {
691
692         String JavaDoc requestText = XmlUtil.toString(doc, false);
693         return processSoapXmla(requestText, servlet);
694     }
695     public static byte[] processSoapXmla(String JavaDoc requestText, Servlet servlet)
696             throws IOException JavaDoc, ServletException JavaDoc, SAXException JavaDoc {
697
698         byte[] reqBytes = requestText.getBytes();
699         // make request
700
MockHttpServletRequest req = new MockHttpServletRequest(reqBytes);
701         req.setMethod("POST");
702         req.setContentType("text/xml");
703
704         // make response
705
MockHttpServletResponse res = new MockHttpServletResponse();
706         res.setCharacterEncoding("UTF-8");
707
708         servlet.service(req, res);
709
710         return res.toByteArray();
711     }
712
713
714
715     /**
716      * Check is a byte array containing a SOAP-XMLA response method is valid.
717      * Schema validation occurs if the XMLA response contains both a content
718      * and schmema section. This includes both the SOAP elements and the
719      * SOAP body content, the XMLA response.
720      *
721      */

722     public static boolean validateSchemaSoapXmla(byte[] bytes)
723             throws SAXException JavaDoc, IOException JavaDoc,
724                 ParserConfigurationException JavaDoc,
725                 TransformerException JavaDoc {
726
727         return validateEmbeddedSchema(
728             bytes,
729             XmlUtil.getSoapXmlaXds2xs("xmla"),
730             XmlUtil.getSoapXmlaXds2xd("xmla"));
731     }
732
733
734     /////////////////////////////////////////////////////////////////////////
735
// xmla file
736
/////////////////////////////////////////////////////////////////////////
737

738     /**
739      * Process the given input file as an XMLA request (no SOAP elements).
740      *
741      */

742     public static byte[] processXmla(File JavaDoc file,
743             String JavaDoc connectString,
744             String JavaDoc[][] catalogNameUrls)
745             throws IOException JavaDoc, SAXException JavaDoc, XOMException {
746
747         String JavaDoc requestText = XmlaSupport.readFile(file);
748         return processXmla(requestText, connectString, catalogNameUrls);
749     }
750     public static byte[] processXmla(String JavaDoc requestText,
751             String JavaDoc connectString,
752             String JavaDoc[][] catalogNameUrls)
753                 throws IOException JavaDoc, SAXException JavaDoc, XOMException {
754
755         Document JavaDoc requestDoc = XmlUtil.parseString(requestText);
756         return processXmla(requestDoc, connectString, catalogNameUrls);
757     }
758     public static byte[] processXmla(Document JavaDoc requestDoc,
759             String JavaDoc connectString,
760             String JavaDoc[][] catalogNameUrls)
761                 throws IOException JavaDoc, XOMException {
762
763         Element JavaDoc requestElem = requestDoc.getDocumentElement();
764         return processXmla(requestElem, connectString, catalogNameUrls);
765     }
766     public static byte[] processXmla(Element JavaDoc requestElem,
767             String JavaDoc connectString,
768             String JavaDoc[][] catalogNameUrls)
769                 throws IOException JavaDoc, XOMException {
770         // make request
771
CatalogLocator cl = getCatalogLocator();
772         DataSourcesConfig.DataSources dataSources =
773             getDataSources(connectString, catalogNameUrls);
774         XmlaHandler handler = new XmlaHandler(dataSources, cl, "xmla");
775         XmlaRequest request = new DefaultXmlaRequest(requestElem, null);
776
777         // make response
778
ByteArrayOutputStream JavaDoc resBuf = new ByteArrayOutputStream JavaDoc();
779         XmlaResponse response = new DefaultXmlaResponse(resBuf, "UTF-8");
780
781         handler.process(request, response);
782
783         return resBuf.toByteArray();
784     }
785
786     /**
787      * Check is a byte array containing a XMLA response method is valid.
788      * Schema validation occurs if the XMLA response contains both a content
789      * and schmema section. This should not be used when the byte array
790      * contains both the SOAP elements and content, but only for the content.
791      *
792      */

793     public static boolean validateSchemaXmla(byte[] bytes)
794             throws SAXException JavaDoc, IOException JavaDoc,
795                 ParserConfigurationException JavaDoc,
796                 TransformerException JavaDoc,
797                 TransformerConfigurationException JavaDoc {
798
799         return validateEmbeddedSchema(bytes,
800             XmlUtil.getXmlaXds2xs("xmla"),
801             XmlUtil.getXmlaXds2xd("xmla"));
802     }
803
804     /////////////////////////////////////////////////////////////////////////
805
// helpers
806
/////////////////////////////////////////////////////////////////////////
807

808     /**
809      * This validates a SOAP-XMLA response using xpaths to extract the
810      * schema and data parts. In addition, it does a little surgery on
811      * the DOMs removing the schema nodes from the XMLA root node.
812      */

813     public static boolean validateSoapXmlaUsingXpath(byte[] bytes)
814             throws SAXException JavaDoc, IOException JavaDoc {
815
816         if (! XmlUtil.supportsValidation()) {
817             return false;
818         }
819         Node JavaDoc[] nodes = extractNodesFromSoapXmla(bytes);
820         return validateNodes(nodes);
821     }
822
823     /**
824      * This validates a XMLA response using xpaths to extract the
825      * schema and data parts. In addition, it does a little surgery on
826      * the DOMs removing the schema nodes from the XMLA root node.
827      *
828      */

829     public static boolean validateXmlaUsingXpath(byte[] bytes)
830             throws SAXException JavaDoc, IOException JavaDoc {
831
832         if (! XmlUtil.supportsValidation()) {
833             return false;
834         }
835         Node JavaDoc[] nodes = extractNodesFromXmla(bytes);
836         return validateNodes(nodes);
837     }
838
839     /**
840      * Validate Nodes with throws an error if validation was attempted but
841      * failed, returns true if validation was successful and false if
842      * validation was not tried.
843      *
844      * @return true if validation succeeded, false if validation was not tried
845      */

846     public static boolean validateNodes(Node JavaDoc[] nodes)
847             throws SAXException JavaDoc, IOException JavaDoc {
848
849         if (! XmlUtil.supportsValidation()) {
850             return false;
851         }
852         if (nodes.length == 0) {
853             // no nodes
854
return false;
855         } else if (nodes.length == 1) {
856             // only data or schema but not both
857
return false;
858         } else if (nodes.length > 2) {
859             // TODO: error
860
return false;
861         }
862
863         Node JavaDoc schemaNode = nodes[0];
864         Node JavaDoc rowNode = nodes[1];
865
866         // This is the "root" node that contains both the schemaNode and
867
// the rowNode.
868
Node JavaDoc rootNode = rowNode.getParentNode();
869         // Remove the schemaNode from the root Node.
870
rootNode.removeChild(schemaNode);
871
872         // Convert nodes to Documents.
873
Document JavaDoc schemaDoc = XmlUtil.newDocument(schemaNode , true);
874         Document JavaDoc dataDoc = XmlUtil.newDocument(rootNode , true);
875
876         String JavaDoc xmlns = XmlUtil.getNamespaceAttributeValue(dataDoc);
877         String JavaDoc schemaLocationPropertyValue = xmlns + ' ' + "xmlschema";
878         org.xml.sax.EntityResolver JavaDoc resolver = new XmlUtil.Resolver(schemaDoc);
879         XmlUtil.validate(dataDoc, schemaLocationPropertyValue, resolver);
880
881         return true;
882     }
883
884
885     /**
886      * See next method for JavaDoc {@link #validateEmbeddedSchema(org.w3c.dom.Document, String, String)}.
887      *
888      */

889     public static boolean validateEmbeddedSchema(
890             byte[] bytes,
891             String JavaDoc schemaTransform,
892             String JavaDoc dataTransform)
893             throws SAXException JavaDoc, IOException JavaDoc,
894                 ParserConfigurationException JavaDoc,
895                 TransformerException JavaDoc,
896                 TransformerConfigurationException JavaDoc {
897
898         if (! XmlUtil.supportsValidation()) {
899             return false;
900         }
901
902         Document JavaDoc doc = XmlUtil.parse(bytes);
903         return validateEmbeddedSchema(doc, schemaTransform, dataTransform);
904     }
905
906     /**
907      * A given Document has both content and an embedded schema (where
908      * the schema has a single root node and the content has a single
909      * root node - they are not interwoven). A single xsl transform is
910      * provided to extract the schema part of the Document and another
911      * xsl transform is provided to extract the content part and then
912      * the content is validated against the schema.
913      * <p>
914      * If the content is valid, then nothing happens, but if the content
915      * is not valid an execption is thrown (currently a RuntimeException).
916      * <p>
917      * When Mondrian moves to Java 5 or includes the JAXP 1.3 jar, then
918      * there is a utility in JAXP that does something like this (but allows
919      * for multiple schema/content parts).
920      *
921      */

922     public static boolean validateEmbeddedSchema(
923             Document JavaDoc doc,
924             String JavaDoc schemaTransform,
925             String JavaDoc dataTransform)
926             throws SAXException JavaDoc, IOException JavaDoc,
927                 ParserConfigurationException JavaDoc,
928                 TransformerException JavaDoc,
929                 TransformerConfigurationException JavaDoc {
930
931         if (! XmlUtil.supportsValidation()) {
932             return false;
933         }
934
935         Node JavaDoc dataDoc = XmlUtil.transform(doc,
936             new BufferedReader JavaDoc(new StringReader JavaDoc(dataTransform)));
937         if (dataDoc == null) {
938             LOGGER.debug("XmlaSupport.validateEmbeddedSchema: dataDoc is null");
939             return false;
940         }
941         if (! dataDoc.hasChildNodes()) {
942             LOGGER.debug("XmlaSupport.validateEmbeddedSchema: dataDoc has no children");
943             return false;
944         }
945         String JavaDoc dataStr = XmlUtil.toString(dataDoc, false);
946         if (LOGGER.isDebugEnabled()) {
947             LOGGER.debug("XmlaSupport.validateEmbeddedSchema: dataDoc:\n="+dataStr);
948         }
949         if (! (dataDoc instanceof Document JavaDoc)) {
950             LOGGER.warn("XmlaSupport.validateEmbeddedSchema: dataDoc not Document");
951             return false;
952         }
953
954
955         Node JavaDoc schemaDoc = XmlUtil.transform(doc,
956             new BufferedReader JavaDoc(new StringReader JavaDoc(schemaTransform)));
957         if (schemaDoc == null) {
958             LOGGER.debug("XmlaSupport.validateEmbeddedSchema: schemaDoc is null");
959             return false;
960         }
961         if (! schemaDoc.hasChildNodes()) {
962             LOGGER.debug("XmlaSupport.validateEmbeddedSchema: schemaDoc has no children");
963             return false;
964         }
965         String JavaDoc schemaStr = XmlUtil.toString(schemaDoc, false);
966         if (LOGGER.isDebugEnabled()) {
967             LOGGER.debug("XmlaSupport.validateEmbeddedSchema: schemaDoc:\n="+schemaStr);
968         }
969         if (! (schemaDoc instanceof Document JavaDoc)) {
970             LOGGER.warn("XmlaSupport.validateEmbeddedSchema: schemaDoc not Document");
971             return false;
972         }
973
974
975         String JavaDoc xmlns = XmlUtil.getNamespaceAttributeValue((Document JavaDoc)dataDoc);
976         String JavaDoc schemaLocationPropertyValue = xmlns + ' ' + "xmlschema";
977         org.xml.sax.EntityResolver JavaDoc resolver = new XmlUtil.Resolver(schemaStr);
978         XmlUtil.validate(dataStr, schemaLocationPropertyValue, resolver);
979
980         return true;
981     }
982
983     public static Document JavaDoc transformSoapXmla(
984         Document JavaDoc doc, String JavaDoc[][] namevalueParameters, String JavaDoc ns)
985         throws SAXException JavaDoc, IOException JavaDoc,
986         ParserConfigurationException JavaDoc,
987         TransformerException JavaDoc
988     {
989         Node JavaDoc node = XmlUtil.transform(
990             doc,
991             new BufferedReader JavaDoc(new StringReader JavaDoc(getXmlaTransform(ns))),
992             namevalueParameters);
993
994         return (node instanceof Document JavaDoc) ? (Document JavaDoc) node : null;
995     }
996
997
998     /**
999      * Reads a file line by line, adds a '\n' after each line and
1000     * returns in a String.
1001     *
1002     */

1003    public static String JavaDoc readFile(File JavaDoc file) throws IOException JavaDoc {
1004        StringBuilder JavaDoc buf = new StringBuilder JavaDoc(1024);
1005        BufferedReader JavaDoc reader = null;
1006        try {
1007            reader = new BufferedReader JavaDoc(new FileReader JavaDoc(file));
1008            String JavaDoc line;
1009            while ((line = reader.readLine()) != null) {
1010                buf.append(line);
1011                buf.append('\n');
1012            }
1013        } finally {
1014            if (reader != null) {
1015                try {
1016                    reader.close();
1017                } catch (Exception JavaDoc ignored) {
1018                }
1019            }
1020        }
1021
1022        return buf.toString();
1023    }
1024
1025
1026    private XmlaSupport() {}
1027}
1028
Popular Tags