001/* 002// This software is subject to the terms of the Eclipse Public License v1.0 003// Agreement, available at the following URL: 004// http://www.eclipse.org/legal/epl-v10.html. 005// You must accept the terms of that agreement to use this software. 006// 007// Copyright (C) 2005-2011 Pentaho 008// All Rights Reserved. 009*/ 010package mondrian.xmla.impl; 011 012import mondrian.olap.Util; 013import mondrian.xmla.*; 014 015import org.apache.log4j.Logger; 016 017import org.w3c.dom.*; 018 019import java.util.*; 020 021import static org.olap4j.metadata.XmlaConstants.Method; 022 023/** 024 * Default implementation of {@link mondrian.xmla.XmlaRequest} by DOM API. 025 * 026 * @author Gang Chen 027 */ 028public class DefaultXmlaRequest 029 implements XmlaRequest, XmlaConstants 030{ 031 private static final Logger LOGGER = 032 Logger.getLogger(DefaultXmlaRequest.class); 033 034 private static final String MSG_INVALID_XMLA = "Invalid XML/A message"; 035 036 /* common content */ 037 private Method method; 038 private Map<String, String> properties; 039 private final String roleName; 040 041 /* EXECUTE content */ 042 private String statement; 043 private boolean drillthrough; 044 045 /* DISCOVER contnet */ 046 private String requestType; 047 private Map<String, Object> restrictions; 048 049 private final String username; 050 private final String password; 051 private final String sessionId; 052 053 public DefaultXmlaRequest( 054 final Element xmlaRoot, 055 final String roleName, 056 final String username, 057 final String password, 058 final String sessionId) 059 throws XmlaException 060 { 061 init(xmlaRoot); 062 this.roleName = roleName; 063 this.username = username; 064 this.password = password; 065 this.sessionId = sessionId; 066 } 067 068 public String getSessionId() { 069 return sessionId; 070 } 071 072 public String getUsername() { 073 return username; 074 } 075 076 public String getPassword() { 077 return password; 078 } 079 080 public Method getMethod() { 081 return method; 082 } 083 084 public Map<String, String> getProperties() { 085 return properties; 086 } 087 088 public Map<String, Object> getRestrictions() { 089 if (method != Method.DISCOVER) { 090 throw new IllegalStateException( 091 "Only METHOD_DISCOVER has restrictions"); 092 } 093 return restrictions; 094 } 095 096 public String getStatement() { 097 if (method != Method.EXECUTE) { 098 throw new IllegalStateException( 099 "Only METHOD_EXECUTE has statement"); 100 } 101 return statement; 102 } 103 104 public String getRoleName() { 105 return roleName; 106 } 107 108 public String getRequestType() { 109 if (method != Method.DISCOVER) { 110 throw new IllegalStateException( 111 "Only METHOD_DISCOVER has requestType"); 112 } 113 return requestType; 114 } 115 116 public boolean isDrillThrough() { 117 if (method != Method.EXECUTE) { 118 throw new IllegalStateException( 119 "Only METHOD_EXECUTE determines drillthrough"); 120 } 121 return drillthrough; 122 } 123 124 125 protected final void init(Element xmlaRoot) throws XmlaException { 126 if (NS_XMLA.equals(xmlaRoot.getNamespaceURI())) { 127 String lname = xmlaRoot.getLocalName(); 128 if ("Discover".equals(lname)) { 129 method = Method.DISCOVER; 130 initDiscover(xmlaRoot); 131 } else if ("Execute".equals(lname)) { 132 method = Method.EXECUTE; 133 initExecute(xmlaRoot); 134 } else { 135 // Note that is code will never be reached because 136 // the error will be caught in 137 // DefaultXmlaServlet.handleSoapBody first 138 StringBuilder buf = new StringBuilder(100); 139 buf.append(MSG_INVALID_XMLA); 140 buf.append(": Bad method name \""); 141 buf.append(lname); 142 buf.append("\""); 143 throw new XmlaException( 144 CLIENT_FAULT_FC, 145 HSB_BAD_METHOD_CODE, 146 HSB_BAD_METHOD_FAULT_FS, 147 Util.newError(buf.toString())); 148 } 149 } else { 150 // Note that is code will never be reached because 151 // the error will be caught in 152 // DefaultXmlaServlet.handleSoapBody first 153 StringBuilder buf = new StringBuilder(100); 154 buf.append(MSG_INVALID_XMLA); 155 buf.append(": Bad namespace url \""); 156 buf.append(xmlaRoot.getNamespaceURI()); 157 buf.append("\""); 158 throw new XmlaException( 159 CLIENT_FAULT_FC, 160 HSB_BAD_METHOD_NS_CODE, 161 HSB_BAD_METHOD_NS_FAULT_FS, 162 Util.newError(buf.toString())); 163 } 164 } 165 166 private void initDiscover(Element discoverRoot) throws XmlaException { 167 Element[] childElems = 168 XmlaUtil.filterChildElements( 169 discoverRoot, 170 NS_XMLA, 171 "RequestType"); 172 if (childElems.length != 1) { 173 StringBuilder buf = new StringBuilder(100); 174 buf.append(MSG_INVALID_XMLA); 175 buf.append(": Wrong number of RequestType elements: "); 176 buf.append(childElems.length); 177 throw new XmlaException( 178 CLIENT_FAULT_FC, 179 HSB_BAD_REQUEST_TYPE_CODE, 180 HSB_BAD_REQUEST_TYPE_FAULT_FS, 181 Util.newError(buf.toString())); 182 } 183 requestType = XmlaUtil.textInElement(childElems[0]); // <RequestType> 184 185 childElems = 186 XmlaUtil.filterChildElements( 187 discoverRoot, 188 NS_XMLA, 189 "Properties"); 190 if (childElems.length != 1) { 191 StringBuilder buf = new StringBuilder(100); 192 buf.append(MSG_INVALID_XMLA); 193 buf.append(": Wrong number of Properties elements: "); 194 buf.append(childElems.length); 195 throw new XmlaException( 196 CLIENT_FAULT_FC, 197 HSB_BAD_PROPERTIES_CODE, 198 HSB_BAD_PROPERTIES_FAULT_FS, 199 Util.newError(buf.toString())); 200 } 201 initProperties(childElems[0]); // <Properties><PropertyList> 202 203 childElems = 204 XmlaUtil.filterChildElements( 205 discoverRoot, 206 NS_XMLA, 207 "Restrictions"); 208 if (childElems.length != 1) { 209 StringBuilder buf = new StringBuilder(100); 210 buf.append(MSG_INVALID_XMLA); 211 buf.append(": Wrong number of Restrictions elements: "); 212 buf.append(childElems.length); 213 throw new XmlaException( 214 CLIENT_FAULT_FC, 215 HSB_BAD_RESTRICTIONS_CODE, 216 HSB_BAD_RESTRICTIONS_FAULT_FS, 217 Util.newError(buf.toString())); 218 } 219 initRestrictions(childElems[0]); // <Restriciotns><RestrictionList> 220 } 221 222 private void initExecute(Element executeRoot) throws XmlaException { 223 Element[] childElems = 224 XmlaUtil.filterChildElements( 225 executeRoot, 226 NS_XMLA, 227 "Command"); 228 if (childElems.length != 1) { 229 StringBuilder buf = new StringBuilder(100); 230 buf.append(MSG_INVALID_XMLA); 231 buf.append(": Wrong number of Command elements: "); 232 buf.append(childElems.length); 233 throw new XmlaException( 234 CLIENT_FAULT_FC, 235 HSB_BAD_COMMAND_CODE, 236 HSB_BAD_COMMAND_FAULT_FS, 237 Util.newError(buf.toString())); 238 } 239 initCommand(childElems[0]); // <Command><Statement> 240 241 childElems = 242 XmlaUtil.filterChildElements( 243 executeRoot, 244 NS_XMLA, 245 "Properties"); 246 if (childElems.length != 1) { 247 StringBuilder buf = new StringBuilder(100); 248 buf.append(MSG_INVALID_XMLA); 249 buf.append(": Wrong number of Properties elements: "); 250 buf.append(childElems.length); 251 throw new XmlaException( 252 CLIENT_FAULT_FC, 253 HSB_BAD_PROPERTIES_CODE, 254 HSB_BAD_PROPERTIES_FAULT_FS, 255 Util.newError(buf.toString())); 256 } 257 initProperties(childElems[0]); // <Properties><PropertyList> 258 } 259 260 private void initRestrictions(Element restrictionsRoot) 261 throws XmlaException 262 { 263 Map<String, List<String>> restrictions = 264 new HashMap<String, List<String>>(); 265 Element[] childElems = 266 XmlaUtil.filterChildElements( 267 restrictionsRoot, 268 NS_XMLA, 269 "RestrictionList"); 270 if (childElems.length == 1) { 271 NodeList nlst = childElems[0].getChildNodes(); 272 for (int i = 0, nlen = nlst.getLength(); i < nlen; i++) { 273 Node n = nlst.item(i); 274 if (n instanceof Element) { 275 Element e = (Element) n; 276 if (NS_XMLA.equals(e.getNamespaceURI())) { 277 String key = e.getLocalName(); 278 String value = XmlaUtil.textInElement(e); 279 280 List<String> values; 281 if (restrictions.containsKey(key)) { 282 values = restrictions.get(key); 283 } else { 284 values = new ArrayList<String>(); 285 restrictions.put(key, values); 286 } 287 288 if (LOGGER.isDebugEnabled()) { 289 LOGGER.debug( 290 "DefaultXmlaRequest.initRestrictions: " 291 + " key=\"" 292 + key 293 + "\", value=\"" 294 + value 295 + "\""); 296 } 297 298 values.add(value); 299 } 300 } 301 } 302 } else if (childElems.length > 1) { 303 StringBuilder buf = new StringBuilder(100); 304 buf.append(MSG_INVALID_XMLA); 305 buf.append(": Wrong number of RestrictionList elements: "); 306 buf.append(childElems.length); 307 throw new XmlaException( 308 CLIENT_FAULT_FC, 309 HSB_BAD_RESTRICTION_LIST_CODE, 310 HSB_BAD_RESTRICTION_LIST_FAULT_FS, 311 Util.newError(buf.toString())); 312 } 313 314 // If there is a Catalog property, 315 // we have to consider it a constraint as well. 316 String key = 317 org.olap4j.metadata.XmlaConstants 318 .Literal.CATALOG_NAME.name(); 319 320 if (this.properties.containsKey(key) 321 && !restrictions.containsKey(key)) 322 { 323 List<String> values; 324 values = new ArrayList<String>(); 325 restrictions.put(this.properties.get(key), values); 326 327 if (LOGGER.isDebugEnabled()) { 328 LOGGER.debug( 329 "DefaultXmlaRequest.initRestrictions: " 330 + " key=\"" 331 + key 332 + "\", value=\"" 333 + this.properties.get(key) 334 + "\""); 335 } 336 } 337 338 this.restrictions = (Map) Collections.unmodifiableMap(restrictions); 339 } 340 341 private void initProperties(Element propertiesRoot) throws XmlaException { 342 Map<String, String> properties = new HashMap<String, String>(); 343 Element[] childElems = 344 XmlaUtil.filterChildElements( 345 propertiesRoot, 346 NS_XMLA, 347 "PropertyList"); 348 if (childElems.length == 1) { 349 NodeList nlst = childElems[0].getChildNodes(); 350 for (int i = 0, nlen = nlst.getLength(); i < nlen; i++) { 351 Node n = nlst.item(i); 352 if (n instanceof Element) { 353 Element e = (Element) n; 354 if (NS_XMLA.equals(e.getNamespaceURI())) { 355 String key = e.getLocalName(); 356 String value = XmlaUtil.textInElement(e); 357 358 if (LOGGER.isDebugEnabled()) { 359 LOGGER.debug( 360 "DefaultXmlaRequest.initProperties: " 361 + " key=\"" 362 + key 363 + "\", value=\"" 364 + value 365 + "\""); 366 } 367 368 properties.put(key, value); 369 } 370 } 371 } 372 } else if (childElems.length > 1) { 373 StringBuilder buf = new StringBuilder(100); 374 buf.append(MSG_INVALID_XMLA); 375 buf.append(": Wrong number of PropertyList elements: "); 376 buf.append(childElems.length); 377 throw new XmlaException( 378 CLIENT_FAULT_FC, 379 HSB_BAD_PROPERTIES_LIST_CODE, 380 HSB_BAD_PROPERTIES_LIST_FAULT_FS, 381 Util.newError(buf.toString())); 382 } else { 383 } 384 this.properties = Collections.unmodifiableMap(properties); 385 } 386 387 388 private void initCommand(Element commandRoot) throws XmlaException { 389 Element[] childElems = 390 XmlaUtil.filterChildElements( 391 commandRoot, 392 NS_XMLA, 393 "Statement"); 394 if (childElems.length != 1) { 395 StringBuilder buf = new StringBuilder(100); 396 buf.append(MSG_INVALID_XMLA); 397 buf.append(": Wrong number of Statement elements: "); 398 buf.append(childElems.length); 399 throw new XmlaException( 400 CLIENT_FAULT_FC, 401 HSB_BAD_STATEMENT_CODE, 402 HSB_BAD_STATEMENT_FAULT_FS, 403 Util.newError(buf.toString())); 404 } 405 statement = XmlaUtil.textInElement(childElems[0]).replaceAll("\\r", ""); 406 drillthrough = statement.toUpperCase().indexOf("DRILLTHROUGH") != -1; 407 } 408} 409 410// End DefaultXmlaRequest.java