xmlamediator.java
来自「数据仓库展示程序」· Java 代码 · 共 827 行 · 第 1/3 页
JAVA
827 行
valueType = "xsd:double";
} else {
valueType = "xsd:string";
}
if (value != null) {
if (cellPropLong.equals(Property.VALUE.name)) {
saxHandler.startElement(cellProps[i], new String[]{"xsi:type", valueType});
} else {
saxHandler.startElement(cellProps[i]);
}
String valueString = value.toString();
if (cellPropLong.equals(Property.VALUE.name) &&
value instanceof Number) {
valueString = normalizeNumricString(valueString);
}
saxHandler.characters(valueString);
saxHandler.endElement();
}
}
saxHandler.endElement(); // Cell
}
}
private void discover(Element discover, SAXHandler saxHandler) {
String requestType = firstElementCDATA(discover, "RequestType");
if (requestType == null) {
throw Util.newError("<RequestType> parameter is required");
}
HashMap restrictionsProperties = getRestrictions(discover);
Properties propertyProperties = getProperties(discover);
final RowsetDefinition rowsetDefinition = RowsetDefinition.getValue(requestType);
Rowset rowset = rowsetDefinition.getRowset(restrictionsProperties, propertyProperties);
try {
saxHandler.startElement("DiscoverResponse", new String[] {
"xmlns", XMLA_NS});
saxHandler.startElement("return");
saxHandler.startElement("root", new String[] {
"xmlns", XMLA_ROWSET_NS});
saxHandler.startElement("xsd:schema", new String[] {
"xmlns:xsd", XSD_NS,
"targetNamespace", XMLA_ROWSET_NS,
"xmlns:xsi", XSI_NS,
"xmlns:sql", "urn:schemas-microsoft-com:xml-sql",
"elementFormDefault", "qualified"});
//TODO: add schema
saxHandler.endElement();
try {
rowset.unparse(saxHandler);
} catch(RuntimeException re) { // MondrianException is subclass of RuntimeException
saxHandler.completeBeforeElement("root");
reportXmlaError(saxHandler, re);
} finally {
// keep the tags balanced, even if there's an error
saxHandler.endElement();
saxHandler.endElement();
saxHandler.endElement();
}
} catch (SAXException e) {
throw Util.newError(e, "Error while processing '" + requestType + "' discovery request");
}
}
private void reportXmlaError(SAXHandler saxHandler, Exception exception) throws SAXException {
Throwable throwable = gotoRootThrowable(exception);
saxHandler.startElement("Messages");
saxHandler.startElement("Error", new String[] {
"ErrorCode", throwable.getClass().getName(),
"Description", throwable.getMessage(),
"Source", "Mondrian",
"Help", "",
});
// Don't dump stack trace to client
// StringWriter stackWriter = new StringWriter();
// throwable.printStackTrace(new PrintWriter(stackWriter));
// saxHandler.characters(stackWriter.getBuffer().toString());
saxHandler.endElement();
saxHandler.endElement();
}
private HashMap getRestrictions(Element discover) {
Element restrictions = firstElement(discover, "Restrictions");
if (restrictions == null) {
throw Util.newError("<Restrictions> parameter is required (but may be empty)");
}
Element restrictionList = firstElement(restrictions, "RestrictionList");
HashMap restrictionsMap = new HashMap();
if (restrictionList != null) {
NodeList childNodes = restrictionList.getChildNodes();
for (int i = 0, n = childNodes.getLength(); i < n; i++) {
Node childNode = childNodes.item(i);
if (childNode instanceof Element) {
Element childElement = (Element) childNode;
String childTag = childElement.getLocalName();
Object childValue = getCDATA2(childElement);
restrictionsMap.put(childTag, childValue);
}
}
}
return restrictionsMap;
}
/**
* Returns the <Properties> contained within a <Execute> or
* <Discover> element.
*/
private Properties getProperties(Element method) {
Element properties = firstElement(method, "Properties");
if (properties == null) {
throw Util.newError("<Properties> parameter is required (but may be epmty)");
}
Element propertyList = firstElement(properties, "PropertyList");
Properties propertyProperties = new Properties();
if (propertyList != null) {
NodeList childNodes = propertyList.getChildNodes();
for (int i = 0, n = childNodes.getLength(); i < n; i++) {
Node childNode = childNodes.item(i);
if (childNode instanceof Element) {
Element childElement = (Element) childNode;
String childTag = childElement.getLocalName();
String childValue = getCDATA(childElement);
propertyProperties.setProperty(childTag, childValue);
}
}
}
return propertyProperties;
}
/**
* Returns a Mondrian connection as specified by a set of properties
* (especially the "Connect string" property).
* @param properties
* @return
*/
static Connection getConnection(Properties properties) {
final String dataSourceInfo = properties.getProperty(PropertyDefinition.DataSourceInfo.name);
if (!dataSourcesMap.containsKey(dataSourceInfo)) {
throw Util.newError("no data source is configured with name '" + dataSourceInfo + "'");
}
DataSourcesConfig.DataSource ds = (DataSourcesConfig.DataSource)dataSourcesMap.get(dataSourceInfo);
Util.PropertyList connectProperties = Util.parseConnectString(ds.getDataSourceInfo());
final String catalog = properties.getProperty(PropertyDefinition.Catalog.name);
if (catalog != null) {
connectProperties.put("CatalogName", catalog);
}
final ServletContext servletContext =
(ServletContext) threadServletContext.get();
return DriverManager.getConnection(connectProperties, servletContext,
false);
}
/**
* Retrieving the root MondrianException in an exception chain if exists.
* @param throwable the last one in exception chain.
* @return the root MondrianException if exists, otherwise the input exception.
*/
static Throwable gotoRootThrowable(Throwable throwable) {
Throwable rootThrowable = throwable.getCause();
if (rootThrowable != null && rootThrowable instanceof MondrianException) {
return gotoRootThrowable(rootThrowable);
}
return throwable;
}
/**
* Returns the first child element with a given tag, or null if there are
* none.
*/
private Element firstElement(Element element, String tagName) {
NodeList elements = element.getElementsByTagNameNS("*", tagName);
for (int i = 0; i < elements.getLength(); i++) {
Node node = elements.item(i);
if (node instanceof Element) {
return (Element) node;
}
}
return null;
}
/**
* Returns the text content of the first child element with a
* given tag, or null if there is no such child.
*/
private String firstElementCDATA(Element element, String tagName) {
Element child = firstElement(element, tagName);
if (child == null) {
return null;
}
return getCDATA(child);
}
private String getCDATA(Element child) {
child.normalize();
NodeList childNodes = child.getChildNodes();
switch (childNodes.getLength()) {
case 0:
return "";
case 1:
final Text grandChild = (Text) childNodes.item(0);
return grandChild.getData();
default:
StringBuffer sb = new StringBuffer();
for (int i = 0, n = childNodes.getLength(); i < n; i++) {
sb.append(childNodes.item(i).toString());
}
return sb.toString();
}
}
private Object getCDATA2(Element child) {
child.normalize();
NodeList childNodes = child.getChildNodes();
if (valuesExist(childNodes)) {
ArrayList list = new ArrayList();
for (int i = 0, n = childNodes.getLength(); i < n; i++) {
final Node node = childNodes.item(i);
if (node instanceof Element && node.getLocalName().equals("Value")) {
list.add(getCDATA((Element) node));
}
}
return (String[]) list.toArray(new String[0]);
} else {
return getCDATA(child);
}
}
private static boolean valuesExist(NodeList childNodes) {
for (int i = 0, n = childNodes.getLength(); i < n; i++) {
final Node node = childNodes.item(i);
if (node instanceof Element && node.getLocalName().equals("Value")) {
return true;
}
}
return false;
}
private static String normalizeNumricString(String numericStr) {
// This is here because different JDBC drivers
// use different Number classes to return
// numeric values (Double vs BigDecimal) and
// these have different toString() behavior.
// If it contains a decimal point, then
// strip off trailing '0's. After stripping off
// the '0's, if there is nothing right of the
// decimal point, then strip off decimal point.
int index = numericStr.indexOf('.');
if (index > 0) {
boolean found = false;
int p = numericStr.length();
char c = numericStr.charAt(p-1);
while (c == '0') {
found = true;
p--;
c = numericStr.charAt(p-1);
}
if (c == '.') {
p--;
}
if (found)
return numericStr.substring(0, p);
}
return numericStr;
}
}
// End XmlaMediator.java
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?