1 28 package net.sf.jasperreports.olap.xmla; 29 30 import java.net.MalformedURLException ; 31 import java.net.URL ; 32 import java.util.HashMap ; 33 import java.util.Iterator ; 34 import java.util.Map ; 35 import java.util.Properties ; 36 import java.util.regex.Matcher ; 37 import java.util.regex.Pattern ; 38 39 import javax.xml.soap.MessageFactory ; 40 import javax.xml.soap.MimeHeaders ; 41 import javax.xml.soap.Name ; 42 import javax.xml.soap.SOAPBody ; 43 import javax.xml.soap.SOAPConnection ; 44 import javax.xml.soap.SOAPConnectionFactory ; 45 import javax.xml.soap.SOAPElement ; 46 import javax.xml.soap.SOAPEnvelope ; 47 import javax.xml.soap.SOAPException ; 48 import javax.xml.soap.SOAPFactory ; 49 import javax.xml.soap.SOAPFault ; 50 import javax.xml.soap.SOAPMessage ; 51 import javax.xml.soap.SOAPPart ; 52 53 import net.sf.jasperreports.engine.JRDataSource; 54 import net.sf.jasperreports.engine.JRDataset; 55 import net.sf.jasperreports.engine.JRException; 56 import net.sf.jasperreports.engine.JRRuntimeException; 57 import net.sf.jasperreports.engine.query.JRAbstractQueryExecuter; 58 import net.sf.jasperreports.olap.JROlapDataSource; 59 60 import org.apache.commons.logging.Log; 61 import org.apache.commons.logging.LogFactory; 62 63 64 68 public class JRXmlaQueryExecuter extends JRAbstractQueryExecuter 69 { 70 71 private static final Log log = LogFactory.getLog(JRXmlaQueryExecuter.class); 72 73 private static final String SLICER_AXIS_NAME = "SlicerAxis"; 74 private static final String MDD_URI = "urn:schemas-microsoft-com:xml-analysis:mddataset"; 75 private static final String XMLA_URI = "urn:schemas-microsoft-com:xml-analysis"; 76 77 private static final Pattern LEVEL_UNIQUE_NAME_PATTERN = Pattern.compile("\\[[^\\]]+\\]\\.\\[([^\\]]+)\\]"); 78 private static final int LEVEL_UNIQUE_NAME_PATTERN_NAME_GROUP = 1; 79 80 private Properties soapProperties; 81 82 private SOAPFactory sf; 83 private SOAPConnection connection; 84 private JRXmlaResult xmlaResult; 85 86 87 protected JRXmlaQueryExecuter(JRDataset dataset, Map parametersMap) 88 { 89 super(dataset, parametersMap); 90 91 soapProperties = new Properties (); 92 93 String soapURL = (String ) getParameterValue(JRXmlaQueryExecuterFactory.PARAMETER_XMLA_URL); 94 soapProperties.put("url", soapURL); 95 if (soapURL == null) 96 { 97 log.warn("The SOAP-URL is null."); 98 } 99 100 soapProperties.put("dataSource", getParameterValue(JRXmlaQueryExecuterFactory.PARAMETER_XMLA_DATASOURCE)); 101 soapProperties.put("catalog", getParameterValue(JRXmlaQueryExecuterFactory.PARAMETER_XMLA_CATALOG)); 102 103 parseQuery(); 104 } 105 106 protected String getParameterReplacement(String parameterName) 107 { 108 return String.valueOf(getParameterValue(parameterName)); 109 } 110 111 112 public JRDataSource createDatasource() throws JRException 113 { 114 try 115 { 116 this.sf = SOAPFactory.newInstance(); 117 this.connection = createSOAPConnection(); 118 SOAPMessage queryMessage = createQueryMessage(); 119 120 URL soapURL = new URL (soapProperties.getProperty("url")); 121 SOAPMessage resultMessage = executeQuery(queryMessage, soapURL); 122 123 xmlaResult = new JRXmlaResult(); 124 parseResult(resultMessage); 125 } 126 catch (MalformedURLException e) 127 { 128 log.error(e); 129 throw new JRRuntimeException(e); 130 } 131 catch (SOAPException e) 132 { 133 log.error(e); 134 throw new JRRuntimeException(e); 135 } 136 137 JROlapDataSource olapDS = new JROlapDataSource(dataset, xmlaResult); 138 return olapDS; 139 } 140 141 public boolean cancelQuery() throws JRException 142 { 143 return false; 144 } 145 146 public void close() 147 { 148 if (connection != null) 149 { 150 try 151 { 152 connection.close(); 153 } 154 catch (SOAPException e) 155 { 156 log.error(e); 157 throw new JRRuntimeException(e); 158 } 159 connection = null; 160 } 161 } 162 163 protected SOAPConnection createSOAPConnection() 164 { 165 try 166 { 167 SOAPConnectionFactory scf = SOAPConnectionFactory.newInstance(); 168 SOAPConnection soapConnection = scf.createConnection(); 169 return soapConnection; 170 } 171 catch (UnsupportedOperationException e) 172 { 173 log.error(e); 174 throw new JRRuntimeException(e); 175 } 176 catch (SOAPException e) 177 { 178 log.error(e); 179 throw new JRRuntimeException(e); 180 } 181 } 182 183 protected SOAPMessage createQueryMessage() 184 { 185 String queryStr = getQueryString(); 186 187 if (log.isDebugEnabled()) 188 { 189 log.debug("MDX query: " + queryStr); 190 } 191 192 try 193 { 194 MessageFactory mf = MessageFactory.newInstance(); 195 SOAPMessage message = mf.createMessage(); 196 197 MimeHeaders mh = message.getMimeHeaders(); 198 mh.setHeader("SOAPAction", "\"urn:schemas-microsoft-com:xml-analysis:Execute\""); 199 200 SOAPPart soapPart = message.getSOAPPart(); 201 SOAPEnvelope envelope = soapPart.getEnvelope(); 202 SOAPBody body = envelope.getBody(); 203 Name nEx = envelope.createName("Execute", "", XMLA_URI); 204 205 SOAPElement eEx = body.addChildElement(nEx); 206 207 209 Name nCom = envelope.createName("Command", "", XMLA_URI); 214 SOAPElement eCommand = eEx.addChildElement(nCom); 215 Name nSta = envelope.createName("Statement", "", XMLA_URI); 216 SOAPElement eStatement = eCommand.addChildElement(nSta); 217 eStatement.addTextNode(queryStr); 218 219 Map paraList = new HashMap (); 228 paraList.put("DataSourceInfo", soapProperties.getProperty("dataSource")); 229 paraList.put("Catalog", soapProperties.getProperty("catalog")); 230 paraList.put("Format", "Multidimensional"); 231 paraList.put("AxisFormat", "TupleFormat"); 232 addParameterList(envelope, eEx, "Properties", "PropertyList", paraList); 233 message.saveChanges(); 234 235 if (log.isDebugEnabled()) 236 { 237 log.debug("XML/A query message: " + message.toString()); 238 } 239 240 return message; 241 } 242 catch (SOAPException e) 243 { 244 log.error(e); 245 throw new JRRuntimeException(e); 246 } 247 } 248 249 protected void addParameterList(SOAPEnvelope envelope, SOAPElement eParent, String typeName, String listName, Map params) throws SOAPException 250 { 251 Name nPara = envelope.createName(typeName, "", XMLA_URI); 252 SOAPElement eType = eParent.addChildElement(nPara); 253 nPara = envelope.createName(listName, "", XMLA_URI); 254 SOAPElement eList = eType.addChildElement(nPara); 255 if (params == null) 256 return; 257 258 Iterator it = params.keySet().iterator(); 259 while (it.hasNext()) 260 { 261 String tag = (String ) it.next(); 262 String value = (String ) params.get(tag); 263 nPara = envelope.createName(tag, "", XMLA_URI); 264 SOAPElement eTag = eList.addChildElement(nPara); 265 eTag.addTextNode(value); 266 } 267 } 268 269 275 protected SOAPMessage executeQuery(SOAPMessage message, URL url) 276 { 277 try 278 { 279 SOAPMessage soapResult = connection.call(message, url); 280 return soapResult; 281 } 282 catch (SOAPException e) 283 { 284 log.error("Message-Call failed.", e); 285 throw new JRRuntimeException(e); 286 } 287 } 288 289 295 protected void parseResult(SOAPMessage reply) throws SOAPException 296 { 297 SOAPPart soapPart = reply.getSOAPPart(); 298 SOAPEnvelope soapEnvelope = soapPart.getEnvelope(); 299 SOAPBody soapBody = soapEnvelope.getBody(); 300 SOAPElement eElement = null; 301 302 if (log.isDebugEnabled()) 303 { 304 log.debug("XML/A result envelope: " + soapEnvelope.toString()); 305 } 306 307 SOAPFault fault = soapBody.getFault(); 308 if (fault != null) 309 { 310 handleResultFault(fault); 311 } 312 313 Name eName = soapEnvelope.createName("ExecuteResponse", "", XMLA_URI); 314 315 Iterator responseElements = soapBody.getChildElements(eName); 317 if (responseElements.hasNext()) 318 { 319 Object eObj = responseElements.next(); 320 if (eObj == null) 321 { 322 log.error("ExecuteResponse Element is null."); 323 throw new JRRuntimeException("ExecuteResponse Element is null."); 324 } 325 eElement = (SOAPElement ) eObj; 326 } 327 else 328 { 329 log.error("Could not retrieve ExecuteResponse Element."); 330 throw new JRRuntimeException("Could not retrieve ExecuteResponse Element."); 331 } 332 333 Name rName = soapEnvelope.createName("return", "", XMLA_URI); 335 Iterator returnElements = eElement.getChildElements(rName); 336 SOAPElement returnElement = null; 337 if (returnElements.hasNext()) 338 { 339 Object eObj = returnElements.next(); 340 if (eObj == null) 341 { 342 log.error("return Element is null."); 343 throw new JRRuntimeException("return Element is null."); 344 } 345 returnElement = (SOAPElement ) eObj; 346 } 347 else 348 { 349 Name rName2 = soapEnvelope.createName("return", "", ""); 351 returnElements = eElement.getChildElements(rName2); 352 if (returnElements.hasNext()) 353 { 354 Object eObj = returnElements.next(); 355 if (eObj == null) 356 { 357 log.error("return Element is null."); 358 throw new JRRuntimeException("return Element is null."); 359 } 360 returnElement = (SOAPElement ) eObj; 361 } 362 else 363 { 364 log.error("Could not retrieve return Element."); 365 throw new JRRuntimeException("Could not retrieve return Element."); 366 } 367 } 368 369 Name rootName = soapEnvelope.createName("root", "", MDD_URI); 371 SOAPElement rootElement = null; 372 Iterator rootElements = returnElement.getChildElements(rootName); 373 if (rootElements.hasNext()) 374 { 375 Object eObj = rootElements.next(); 376 if (eObj == null) 377 { 378 log.error("root Element is null."); 379 throw new JRRuntimeException("root Element is null."); 380 } 381 rootElement = (SOAPElement ) eObj; 382 } 383 else 384 { 385 log.error("Could not retrieve root Element."); 386 throw new JRRuntimeException("Could not retrieve root Element."); 387 } 388 Name olapInfoName = soapEnvelope.createName("OlapInfo", "", MDD_URI); 390 SOAPElement olapInfoElement = null; 391 Iterator olapInfoElements = rootElement.getChildElements(olapInfoName); 392 if (olapInfoElements.hasNext()) 393 { 394 Object eObj = olapInfoElements.next(); 395 if (eObj == null) 396 { 397 log.error("OlapInfo Element is null."); 398 throw new JRRuntimeException("OlapInfo Element is null."); 399 } 400 olapInfoElement = (SOAPElement ) eObj; 401 } 402 else 403 { 404 log.error("Could not retrieve OlapInfo Element."); 405 throw new JRRuntimeException("Could not retrieve OlapInfo Element."); 406 } 407 408 parseOLAPInfoElement(olapInfoElement); 409 410 Name axesName = soapEnvelope.createName("Axes", "", MDD_URI); 412 SOAPElement axesElement = null; 413 Iterator axesElements = rootElement.getChildElements(axesName); 414 if (axesElements.hasNext()) 415 { 416 Object eObj = axesElements.next(); 417 if (eObj == null) 418 { 419 log.error("Axes Element is null"); 420 throw new JRRuntimeException("Axes Element is null"); 421 } 422 axesElement = (SOAPElement ) eObj; 423 } 424 else 425 { 426 log.error("Could not retrieve Axes Element."); 427 throw new JRRuntimeException("Could not retrieve Axes Element."); 428 } 429 430 parseAxesElement(axesElement); 431 432 Name cellDataName = soapEnvelope.createName("CellData", "", MDD_URI); 434 SOAPElement cellDataElement = null; 435 Iterator cellDataElements = rootElement.getChildElements(cellDataName); 436 if (cellDataElements.hasNext()) 437 { 438 Object eObj = cellDataElements.next(); 439 if (eObj == null) 440 { 441 log.error("CellData element is null"); 442 throw new JRRuntimeException("CellData element is null"); 443 } 444 cellDataElement = (SOAPElement ) eObj; 445 } 446 else 447 { 448 log.error("Could not retrieve CellData Element."); 449 throw new JRRuntimeException("Could not retrieve CellData Element."); 450 } 451 parseCellDataElement(cellDataElement); 452 } 453 454 protected void handleResultFault(SOAPFault fault) 455 { 456 StringBuffer errorMsg = new StringBuffer (); 457 errorMsg.append("XML/A fault: "); 458 459 String faultString = fault.getFaultString(); 460 if (faultString != null) 461 { 462 errorMsg.append(faultString); 463 errorMsg.append("; "); 464 } 465 466 String faultActor = fault.getFaultActor(); 467 if (faultActor != null) 468 { 469 errorMsg.append("Actor: "); 470 errorMsg.append(faultActor); 471 errorMsg.append("; "); 472 } 473 474 String faultCode = fault.getFaultCode(); 475 if (faultCode != null) 476 { 477 errorMsg.append("Code: "); 478 errorMsg.append(faultCode); 479 errorMsg.append("; "); 480 } 481 482 throw new JRRuntimeException(errorMsg.toString()); 483 } 484 485 protected void parseOLAPInfoElement(SOAPElement olapInfoElement) throws SOAPException 486 { 487 489 Name axesInfoName = sf.createName("AxesInfo", "", MDD_URI); 491 SOAPElement axesElement = null; 492 Iterator axesInfoElements = olapInfoElement.getChildElements(axesInfoName); 493 if (axesInfoElements.hasNext()) 494 { 495 Object axesObj = axesInfoElements.next(); 496 if (axesObj == null) 497 { 498 log.error("AxisInfo Element is null."); 499 throw new JRRuntimeException("AxisInfo Element is null."); 500 } 501 axesElement = (SOAPElement ) axesObj; 502 } 503 else 504 { 505 log.error("Could not retrieve AxesInfo Element."); 506 throw new JRRuntimeException("Could not retrieve AxesInfo Element."); 507 } 508 509 parseAxesInfoElement(axesElement); 510 511 } 513 514 protected void parseAxesInfoElement(SOAPElement axesInfoElement) throws SOAPException 515 { 516 Name axisInfoName = sf.createName("AxisInfo", "", MDD_URI); 518 Iterator itAxis = axesInfoElement.getChildElements(axisInfoName); 519 while (itAxis.hasNext()) 520 { 521 SOAPElement axisElement = (SOAPElement ) itAxis.next(); 522 Name name = sf.createName("name"); 523 String axisName = axisElement.getAttributeValue(name); 524 if (axisName.equals(SLICER_AXIS_NAME)) 525 { 526 continue; 527 } 528 529 JRXmlaResultAxis axis = new JRXmlaResultAxis(axisName); 530 xmlaResult.addAxis(axis); 531 532 name = sf.createName("HierarchyInfo", "", MDD_URI); 534 Iterator itHierInfo = axisElement.getChildElements(name); 535 while (itHierInfo.hasNext()) 536 { 537 SOAPElement eHierInfo = (SOAPElement ) itHierInfo.next(); 538 handleHierInfo(axis, eHierInfo); 539 } 540 } 541 } 542 543 protected void parseAxesElement(SOAPElement axesElement) throws SOAPException 544 { 545 Name aName = sf.createName("Axis", "", MDD_URI); 547 Iterator itAxis = axesElement.getChildElements(aName); 548 while (itAxis.hasNext()) 549 { 550 SOAPElement axisElement = (SOAPElement ) itAxis.next(); 551 Name name = sf.createName("name"); 552 String axisName = axisElement.getAttributeValue(name); 553 554 if (axisName.equals(SLICER_AXIS_NAME)) 555 { 556 continue; 557 } 558 559 JRXmlaResultAxis axis = xmlaResult.getAxisByName(axisName); 561 562 name = sf.createName("Tuples", "", MDD_URI); 564 Iterator itTuples = axisElement.getChildElements(name); 565 if (itTuples.hasNext()) 566 { 567 SOAPElement eTuples = (SOAPElement ) itTuples.next(); 568 handleTuplesElement(axis, eTuples); 569 } 570 } 571 } 572 573 protected void parseCellDataElement(SOAPElement cellDataElement) throws SOAPException 574 { 575 Name name = sf.createName("Cell", "", MDD_URI); 576 Iterator itCells = cellDataElement.getChildElements(name); 577 while (itCells.hasNext()) 578 { 579 SOAPElement cellElement = (SOAPElement ) itCells.next(); 580 581 Name errorName = sf.createName("Error", "", MDD_URI); 582 Iterator errorElems = cellElement.getChildElements(errorName); 583 if (errorElems.hasNext()) 584 { 585 handleCellErrors(errorElems); 586 } 587 588 Name ordinalName = sf.createName("CellOrdinal"); 589 String cellOrdinal = cellElement.getAttributeValue(ordinalName); 590 591 Object value = null; 592 Iterator valueElements = cellElement.getChildElements(sf.createName("Value", "", MDD_URI)); 593 if (valueElements.hasNext()) 594 { 595 SOAPElement valueElement = (SOAPElement ) valueElements.next(); 596 String valueType = valueElement.getAttribute("xsi:type"); 597 if (valueType.equals("xsd:int")) 598 value = new Long (valueElement.getValue()); 599 else if (valueType.equals("xsd:double")) 600 value = new Double (valueElement.getValue()); 601 else if (valueType.equals("xsd:decimal")) 602 value = new Double (valueElement.getValue()); 603 else 604 value = valueElement.getValue(); 605 } 606 607 String fmtValue = ""; 608 Iterator fmtValueElements = cellElement.getChildElements(sf.createName("FmtValue", "", MDD_URI)); 609 if (fmtValueElements.hasNext()) 610 { 611 SOAPElement fmtValueElement = ((SOAPElement ) fmtValueElements.next()); 612 fmtValue = fmtValueElement.getValue(); 613 } 614 615 int pos = Integer.parseInt(cellOrdinal); 616 JRXmlaCell cell = new JRXmlaCell(value, fmtValue); 617 xmlaResult.setCell(cell, pos); 618 } 619 } 620 621 protected void handleCellErrors(Iterator errorElems) throws SOAPException 622 { 623 SOAPElement errorElem = (SOAPElement ) errorElems.next(); 624 625 StringBuffer errorMsg = new StringBuffer (); 626 errorMsg.append("Cell error: "); 627 628 Iterator descriptionElems = errorElem.getChildElements(sf.createName("Description", "", MDD_URI)); 629 if (descriptionElems.hasNext()) 630 { 631 SOAPElement descrElem = (SOAPElement ) descriptionElems.next(); 632 errorMsg.append(descrElem.getValue()); 633 errorMsg.append("; "); 634 } 635 636 Iterator sourceElems = errorElem.getChildElements(sf.createName("Source", "", MDD_URI)); 637 if (sourceElems.hasNext()) 638 { 639 SOAPElement sourceElem = (SOAPElement ) sourceElems.next(); 640 errorMsg.append("Source: "); 641 errorMsg.append(sourceElem.getValue()); 642 errorMsg.append("; "); 643 } 644 645 Iterator codeElems = errorElem.getChildElements(sf.createName("ErrorCode", "", MDD_URI)); 646 if (codeElems.hasNext()) 647 { 648 SOAPElement codeElem = (SOAPElement ) codeElems.next(); 649 errorMsg.append("Code: "); 650 errorMsg.append(codeElem.getValue()); 651 errorMsg.append("; "); 652 } 653 654 throw new JRRuntimeException(errorMsg.toString()); 655 } 656 657 protected void handleHierInfo(JRXmlaResultAxis axis, SOAPElement hierInfoElement) throws SOAPException 658 { 659 Name name = sf.createName("name"); 660 String dimName = hierInfoElement.getAttributeValue(name); 662 JRXmlaHierarchy hier = new JRXmlaHierarchy(dimName); 663 axis.addHierarchy(hier); 664 } 665 666 protected void handleTuplesElement(JRXmlaResultAxis axis, SOAPElement tuplesElement) throws SOAPException 667 { 668 Name tName = sf.createName("Tuple", "", MDD_URI); 669 for (Iterator itTuple = tuplesElement.getChildElements(tName); itTuple.hasNext();) 670 { 671 SOAPElement eTuple = (SOAPElement ) itTuple.next(); 672 handleTupleElement(axis, eTuple); 673 } 674 } 675 676 protected void handleTupleElement(JRXmlaResultAxis axis, SOAPElement tupleElement) throws SOAPException 677 { 678 JRXmlaMemberTuple tuple = new JRXmlaMemberTuple(axis.getHierarchiesOnAxis().length); 679 680 Name memName = sf.createName("Member", "", MDD_URI); 681 Iterator itMember = tupleElement.getChildElements(memName); 682 int memNum = 0; 683 while (itMember.hasNext()) 684 { 685 SOAPElement memElement = (SOAPElement ) itMember.next(); 686 687 Name name = sf.createName("Hierarchy", "", ""); 688 String hierName = memElement.getAttributeValue(name); 689 690 String uName = ""; 691 Iterator uNameElements = memElement.getChildElements(sf.createName("UName", "", MDD_URI)); 692 if (uNameElements.hasNext()) 693 uName = ((SOAPElement ) uNameElements.next()).getValue(); 694 695 String caption = ""; 696 Iterator captionElements = memElement.getChildElements(sf.createName("Caption", "", MDD_URI)); 697 if (captionElements.hasNext()) 698 caption = ((SOAPElement ) captionElements.next()).getValue(); 699 700 String lName = ""; 701 Iterator lNameElements = memElement.getChildElements(sf.createName("LName", "", MDD_URI)); 702 if (lNameElements.hasNext()) 703 { 704 String levelUniqueName = ((SOAPElement ) lNameElements.next()).getValue(); 705 Matcher matcher = LEVEL_UNIQUE_NAME_PATTERN.matcher(levelUniqueName); 706 if (matcher.matches()) 707 { 708 lName = matcher.group(LEVEL_UNIQUE_NAME_PATTERN_NAME_GROUP); 709 } 710 } 711 712 int lNum = 0; 713 Iterator lNumElements = memElement.getChildElements(sf.createName("LNum", "", MDD_URI)); 714 if (lNumElements.hasNext()) 715 lNum = Integer.parseInt(((SOAPElement ) lNumElements.next()).getValue()); 716 717 JRXmlaMember member = new JRXmlaMember(caption, uName, hierName, lName, lNum); 718 tuple.setMember(memNum++, member); 719 } 720 721 axis.addTuple(tuple); 722 } 723 } 724 | Popular Tags |