xmlamediator.java
来自「数据仓库展示程序」· Java 代码 · 共 827 行 · 第 1/3 页
JAVA
827 行
/*
// $Id: //open/mondrian/src/main/mondrian/xmla/XmlaMediator.java#19 $
// 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.
// (C) Copyright 2003-2005 Julian Hyde
// All Rights Reserved.
// You must accept the terms of that agreement to use this software.
*/
package mondrian.xmla;
import java.io.*;
import java.math.BigDecimal;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import javax.servlet.ServletContext;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import mondrian.olap.*;
import mondrian.rolap.RolapConnection;
import mondrian.util.SAXHandler;
import mondrian.util.SAXWriter;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.apache.log4j.Logger;
/**
* An <code>XmlaMediator</code> responds to XML for Analysis requests.
*
* @author jhyde
* @since 27 April, 2003
* @version $Id: //open/mondrian/src/main/mondrian/xmla/XmlaMediator.java#19 $
*/
public class XmlaMediator {
private static final boolean DRILLTHROUGH_EXTENDS_CONTEXT = true;
private static final Logger LOGGER = Logger.getLogger(XmlaMediator.class);
private static final String XSD_NS = "http://www.w3.org/2001/XMLSchema";
private static final String XSI_NS = "http://www.w3.org/2001/XMLSchema-instance";
private static final String XMLA_NS = "urn:schemas-microsoft-com:xml-analysis";
private static final String XMLA_MDDATASET_NS = "urn:schemas-microsoft-com:xml-analysis:mddataset";
private static final String XMLA_ROWSET_NS = "urn:schemas-microsoft-com:xml-analysis:rowset";
static ThreadLocal threadServletContext = new ThreadLocal();
static Map dataSourcesMap = new HashMap();
/**
* Please call this method before any usage of XmlaMediator.
* @param dataSources
*/
public static void initDataSourcesMap(DataSourcesConfig.DataSources dataSources) {
Map map = new HashMap();
for (int i = 0; i < dataSources.dataSources.length; i++) {
DataSourcesConfig.DataSource ds = dataSources.dataSources[i];
if (map.containsKey(ds.getDataSourceName())) {
throw Util.newError("duplicated data source name '" + ds.getDataSourceName() + "'");
}
map.put(ds.getDataSourceName(), ds);
}
dataSourcesMap = Collections.unmodifiableMap(map);
}
/**
* Processes a request.
* @param request XML request, for example, "<SOAP-ENV:Envelope ...>".
* @param response Destination for response
*/
public void process(String request, Writer response) {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
DocumentBuilder documentBuilder;
try {
documentBuilder = factory.newDocumentBuilder();
} catch (ParserConfigurationException e) {
throw Util.newError(e, "Error processing '" + request + "'");
}
Document document;
try {
document = documentBuilder.parse(new InputSource(new StringReader(request)));
} catch (SAXException e) {
throw Util.newError(e, "Error processing '" + request + "'");
} catch (IOException e) {
throw Util.newError(e, "Error processing '" + request + "'");
}
Element documentElement = document.getDocumentElement();
try {
process(documentElement, new SAXHandler(new SAXWriter(response)));
} catch (SAXException e) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Request " + request + " failed", e);
}
}
}
/**
* Processes a request, specified as a <Discover> or <Execute>
* {@link Element DOM element}, and writes the response as a set of SAX
* events.
* @param element <Discover> or <Execute>
* {@link Element DOM element}
* @param saxHandler Object to write SAX events to
*/
public void process(Element element, SAXHandler saxHandler) throws SAXException {
saxHandler.startDocument();
processEnvelope(element, saxHandler);
saxHandler.endDocument();
}
private void processEnvelope(Element element, SAXHandler saxHandler) throws SAXException {
String tagName = element.getLocalName();
Util.assertTrue(tagName.equals("Envelope"));
//final NodeList childNodes = element.getChildNodes();
saxHandler.startElement("SOAP-ENV:Envelope", new String[] {
"xmlns:SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/",
"SOAP-ENV:encodingStyle", "http://schemas.xmlsoap.org/soap/encoding/",
});
saxHandler.startElement("SOAP-ENV:Body");
processBody(firstElement(element, "Body"), saxHandler);
saxHandler.endElement();
saxHandler.endElement();
}
private void processBody(Element element, SAXHandler saxHandler) {
String tagName = element.getLocalName();
Util.assertTrue(tagName.equals("Body"));
final NodeList childNodes = element.getChildNodes();
for (int i = 0; i < childNodes.getLength(); i++) {
final Node node = childNodes.item(i);
if (node instanceof Element) {
processRequest((Element) node, saxHandler);
}
}
}
private void processRequest(Element element, SAXHandler saxHandler) {
String tagName = element.getLocalName();
if (tagName.equals("Discover")) {
discover(element, saxHandler);
} else if (tagName.equals("Execute")) {
execute(element, saxHandler);
} else {
throw Util.newError("Element <" + tagName + "> not supported");
}
}
private void execute(Element execute, SAXHandler saxHandler) {
Element command = firstElement(execute, "Command");
if (command == null) {
throw Util.newError("<Command> parameter is required");
}
String statement = firstElementCDATA(command, "Statement");
if (statement == null) {
throw Util.newError("<Statement> parameter is required");
}
final Properties properties = getProperties(execute);
boolean isDrillThrough = false;
// No usage of Regex in 1.4
String upperStatement = statement.toUpperCase();
int dtOffset = upperStatement.indexOf("DRILLTHROUGH");
int slOffset = upperStatement.indexOf("SELECT");
if (dtOffset != -1 && dtOffset < slOffset) {
String format = properties.getProperty(PropertyDefinition.Format.name);
if ("Tabular".compareToIgnoreCase(format) == 0)
isDrillThrough = true;
else
throw Util.newError("Must set property 'Format' to 'Tabular' for DrillThrough");
}
try {
saxHandler.startElement("ExecuteResponse", new String[] {
"xmlns", XMLA_NS});
saxHandler.startElement("return", new String[] {
"xmlns:xsi", XSI_NS,
"xmlns:xsd", XSD_NS,});
saxHandler.startElement("root", new String[] {
"xmlns", isDrillThrough ? XMLA_ROWSET_NS : XMLA_MDDATASET_NS});
saxHandler.startElement("xsd:schema", new String[] {
"xmlns:xsd", XSD_NS});
// todo: schema definition
saxHandler.endElement();
try {
if (isDrillThrough) {
StringBuffer dtStatement = new StringBuffer();
dtStatement.append(statement.substring(0, dtOffset)); // formulas
dtStatement.append(statement.substring(dtOffset + "DRILLTHROUGH".length())); // select to end
executeDrillThroughQuery(dtStatement.toString(), properties).unparse(saxHandler);
} else {
executeQuery(statement, properties).unparse(saxHandler);
}
} catch(RuntimeException re) { // MondrianException is subclass of RuntimeException
saxHandler.completeBeforeElement("root");
reportXmlaError(saxHandler, re);
} finally {
saxHandler.endElement();
saxHandler.endElement();
saxHandler.endElement();
}
} catch (SAXException e) {
throw Util.newError(e, "Error while processing execute request");
}
}
private TabularRowSet executeDrillThroughQuery(String statement, Properties properties) {
final Connection connection = getConnection(properties);
final Query query = connection.parseQuery(statement);
final Result result = connection.execute(query);
Cell dtCell = result.getCell(new int[] {0,0});
if (!dtCell.canDrillThrough()) {
throw Util.newError("Cannot do DillThrough operation on the cell");
}
String dtSql = dtCell.getDrillThroughSQL(DRILLTHROUGH_EXTENDS_CONTEXT);
TabularRowSet rowset = null;
java.sql.Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
conn = ((RolapConnection)connection).getDataSource().getConnection();
stmt = conn.createStatement();
rs = stmt.executeQuery(dtSql);
rowset = new TabularRowSet(rs);
} catch (SQLException sqle) {
Util.newError(sqle, "Error while executing DrillThrough sql '" + dtSql + "'");
} finally {
try {
if (rs != null) rs.close();
} catch (SQLException ignored){}
try {
if (stmt != null) stmt.close();
} catch (SQLException ignored){}
try {
if (conn != null && !conn.isClosed()) conn.close();
} catch (SQLException ignored){}
}
return rowset;
}
static class TabularRowSet {
private String[] header;
private List rows;
public TabularRowSet(ResultSet rs) throws SQLException {
ResultSetMetaData md = rs.getMetaData();
int columnCount = md.getColumnCount();
// populate header
header = new String[columnCount];
for (int i = 0; i < columnCount; i++) {
header[i] = md.getColumnName(i+1);
}
// populate data
rows = new ArrayList();
while(rs.next()) {
Object[] row = new Object[columnCount];
for (int i = 0; i < columnCount; i++) {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?