1 10 package mondrian.xmla.impl; 11 12 import java.util.*; 13 14 import mondrian.olap.MondrianProperties; 15 import mondrian.olap.Util; 16 import mondrian.xmla.XmlaConstants; 17 import mondrian.xmla.XmlaException; 18 import mondrian.xmla.XmlaRequest; 19 import mondrian.xmla.XmlaUtil; 20 21 import org.w3c.dom.Element ; 22 import org.w3c.dom.Node ; 23 import org.w3c.dom.NodeList ; 24 import org.apache.log4j.Logger; 25 26 31 public class DefaultXmlaRequest implements XmlaRequest, 32 XmlaConstants { 33 34 private static final Logger LOGGER = Logger.getLogger(DefaultXmlaRequest.class); 35 36 private static final String MSG_INVALID_XMLA = "Invalid XML/A message"; 37 private static final String MSG_INVALID_DRILLTHROUGH = "Invalid DRILLTHROUGH statement"; 38 private static final String MSG_INVALID_MAXROWS = "MAXROWS is not positive integer"; 39 private static final String MSG_INVALID_FIRSTROWSET = "FIRSTROWSET isn't positive integer"; 40 41 42 private int method; 43 private Map<String , String > properties; 44 private String role; 45 46 47 private String statement; 48 private boolean drillthrough; 49 private int maxRows; 50 private int firstRowset; 51 52 53 private String requestType; 54 private Map<String , List <String >> restrictions; 55 56 57 public DefaultXmlaRequest(Element xmlaRoot) { 58 this(xmlaRoot, null); 59 } 60 61 public DefaultXmlaRequest(Element xmlaRoot, String role) 62 throws XmlaException { 63 init(xmlaRoot); 64 this.role = role; 65 } 66 67 68 69 public int getMethod() { 70 return method; 71 } 72 73 public Map<String , String > getProperties() { 74 return properties; 75 } 76 77 public Map<String , List <String >> getRestrictions() { 78 if (method != METHOD_DISCOVER) { 79 throw new IllegalStateException ("Only METHOD_DISCOVER has restrictions"); 80 } 81 return restrictions; 82 } 83 84 public String getStatement() { 85 if (method != METHOD_EXECUTE) { 86 throw new IllegalStateException ("Only METHOD_EXECUTE has statement"); 87 } 88 return statement; 89 } 90 91 public String getRole() { 92 return role; 93 } 94 95 public void setRole(String role) { 96 this.role = role; 97 } 98 99 public String getRequestType() { 100 if (method != METHOD_DISCOVER) 101 throw new IllegalStateException ("Only METHOD_DISCOVER has requestType"); 102 return requestType; 103 } 104 105 public boolean isDrillThrough() { 106 if (method != METHOD_EXECUTE) 107 throw new IllegalStateException ("Only METHOD_EXECUTE determines drillthrough"); 108 return drillthrough; 109 } 110 111 public int drillThroughMaxRows() { 112 if (method != METHOD_EXECUTE) 113 throw new IllegalStateException ("Only METHOD_EXECUTE determines drillthrough"); 114 return maxRows; 115 } 116 117 public int drillThroughFirstRowset() { 118 if (method != METHOD_EXECUTE) 119 throw new IllegalStateException ("Only METHOD_EXECUTE determines drillthrough"); 120 return firstRowset; 121 } 122 123 124 protected final void init(Element xmlaRoot) throws XmlaException { 125 if (NS_XMLA.equals(xmlaRoot.getNamespaceURI())) { 126 String lname = xmlaRoot.getLocalName(); 127 if ("Discover".equals(lname)) { 128 method = METHOD_DISCOVER; 129 initDiscover(xmlaRoot); 130 } else if ("Execute".equals(lname)) { 131 method = METHOD_EXECUTE; 132 initExecute(xmlaRoot); 133 } else { 134 StringBuilder buf = new StringBuilder (100); 138 buf.append(MSG_INVALID_XMLA); 139 buf.append(": Bad method name \""); 140 buf.append(lname); 141 buf.append("\""); 142 throw new XmlaException( 143 CLIENT_FAULT_FC, 144 HSB_BAD_METHOD_CODE, 145 HSB_BAD_METHOD_FAULT_FS, 146 Util.newError(buf.toString())); 147 } 148 } else { 149 StringBuilder buf = new StringBuilder (100); 153 buf.append(MSG_INVALID_XMLA); 154 buf.append(": Bad namespace url \""); 155 buf.append(xmlaRoot.getNamespaceURI()); 156 buf.append("\""); 157 throw new XmlaException( 158 CLIENT_FAULT_FC, 159 HSB_BAD_METHOD_NS_CODE, 160 HSB_BAD_METHOD_NS_FAULT_FS, 161 Util.newError(buf.toString())); 162 } 163 } 164 165 private void initDiscover(Element discoverRoot) throws XmlaException { 166 Element [] childElems = XmlaUtil.filterChildElements(discoverRoot, 167 NS_XMLA, 168 "RequestType"); 169 if (childElems.length != 1) { 170 StringBuilder buf = new StringBuilder (100); 171 buf.append(MSG_INVALID_XMLA); 172 buf.append(": Wrong number of RequestType elements: "); 173 buf.append(childElems.length); 174 throw new XmlaException( 175 CLIENT_FAULT_FC, 176 HSB_BAD_REQUEST_TYPE_CODE, 177 HSB_BAD_REQUEST_TYPE_FAULT_FS, 178 Util.newError(buf.toString())); 179 } 180 requestType = XmlaUtil.textInElement(childElems[0]); 182 childElems = XmlaUtil.filterChildElements(discoverRoot, 183 NS_XMLA, 184 "Restrictions"); 185 if (childElems.length != 1) { 186 StringBuilder buf = new StringBuilder (100); 187 buf.append(MSG_INVALID_XMLA); 188 buf.append(": Wrong number of Restrictions elements: "); 189 buf.append(childElems.length); 190 throw new XmlaException( 191 CLIENT_FAULT_FC, 192 HSB_BAD_RESTRICTIONS_CODE, 193 HSB_BAD_RESTRICTIONS_FAULT_FS, 194 Util.newError(buf.toString())); 195 } 196 initRestrictions(childElems[0]); 198 childElems = XmlaUtil.filterChildElements(discoverRoot, 199 NS_XMLA, 200 "Properties"); 201 if (childElems.length != 1) { 202 StringBuilder buf = new StringBuilder (100); 203 buf.append(MSG_INVALID_XMLA); 204 buf.append(": Wrong number of Properties elements: "); 205 buf.append(childElems.length); 206 throw new XmlaException( 207 CLIENT_FAULT_FC, 208 HSB_BAD_PROPERTIES_CODE, 209 HSB_BAD_PROPERTIES_FAULT_FS, 210 Util.newError(buf.toString())); 211 } 212 initProperties(childElems[0]); } 214 215 private void initExecute(Element executeRoot) throws XmlaException { 216 Element [] childElems = XmlaUtil.filterChildElements(executeRoot, 217 NS_XMLA, 218 "Command"); 219 if (childElems.length != 1) { 220 StringBuilder buf = new StringBuilder (100); 221 buf.append(MSG_INVALID_XMLA); 222 buf.append(": Wrong number of Command elements: "); 223 buf.append(childElems.length); 224 throw new XmlaException( 225 CLIENT_FAULT_FC, 226 HSB_BAD_COMMAND_CODE, 227 HSB_BAD_COMMAND_FAULT_FS, 228 Util.newError(buf.toString())); 229 } 230 initCommand(childElems[0]); 232 childElems = XmlaUtil.filterChildElements(executeRoot, 233 NS_XMLA, 234 "Properties"); 235 if (childElems.length != 1) { 236 StringBuilder buf = new StringBuilder (100); 237 buf.append(MSG_INVALID_XMLA); 238 buf.append(": Wrong number of Properties elements: "); 239 buf.append(childElems.length); 240 throw new XmlaException( 241 CLIENT_FAULT_FC, 242 HSB_BAD_PROPERTIES_CODE, 243 HSB_BAD_PROPERTIES_FAULT_FS, 244 Util.newError(buf.toString())); 245 } 246 initProperties(childElems[0]); } 248 249 private void initRestrictions(Element restrictionsRoot) throws XmlaException { 250 Map<String , List <String >> restrictions = new HashMap<String , List <String >>(); 251 Element [] childElems = 252 XmlaUtil.filterChildElements( 253 restrictionsRoot, 254 NS_XMLA, 255 "RestrictionList"); 256 if (childElems.length == 1) { 257 NodeList nlst = childElems[0].getChildNodes(); 258 for (int i = 0, nlen = nlst.getLength(); i < nlen; i++) { 259 Node n = nlst.item(i); 260 if (n instanceof Element ) { 261 Element e = (Element ) n; 262 if (NS_XMLA.equals(e.getNamespaceURI())) { 263 String key = e.getLocalName(); 264 String value = XmlaUtil.textInElement(e); 265 266 List <String > values; 267 if (restrictions.containsKey(key)) { 268 values = restrictions.get(key); 269 } else { 270 values = new ArrayList<String >(); 271 restrictions.put(key, values); 272 } 273 274 if (LOGGER.isDebugEnabled()) { 275 StringBuilder buf = new StringBuilder (100); 276 buf.append("DefaultXmlaRequest.initRestrictions: "); 277 buf.append(" key=\""); 278 buf.append(key); 279 buf.append("\", value=\""); 280 buf.append(value); 281 buf.append("\""); 282 LOGGER.debug(buf.toString()); 283 } 284 285 values.add(value); 286 } 287 } 288 } 289 } else if (childElems.length > 1) { 290 StringBuilder buf = new StringBuilder (100); 291 buf.append(MSG_INVALID_XMLA); 292 buf.append(": Wrong number of RestrictionList elements: "); 293 buf.append(childElems.length); 294 throw new XmlaException( 295 CLIENT_FAULT_FC, 296 HSB_BAD_RESTRICTION_LIST_CODE, 297 HSB_BAD_RESTRICTION_LIST_FAULT_FS, 298 Util.newError(buf.toString())); 299 } else { 300 } 301 this.restrictions = Collections.unmodifiableMap(restrictions); 302 } 303 304 private void initProperties(Element propertiesRoot) throws XmlaException { 305 Map<String , String > properties = new HashMap<String , String >(); 306 Element [] childElems = XmlaUtil.filterChildElements(propertiesRoot, 307 NS_XMLA, 308 "PropertyList"); 309 if (childElems.length == 1) { 310 NodeList nlst = childElems[0].getChildNodes(); 311 for (int i = 0, nlen = nlst.getLength(); i < nlen; i++) { 312 Node n = nlst.item(i); 313 if (n instanceof Element ) { 314 Element e = (Element ) n; 315 if (NS_XMLA.equals(e.getNamespaceURI())) { 316 317 String key = e.getLocalName(); 318 String value = XmlaUtil.textInElement(e); 319 320 if (LOGGER.isDebugEnabled()) { 321 StringBuilder buf = new StringBuilder (100); 322 buf.append("DefaultXmlaRequest.initProperties: "); 323 buf.append(" key=\""); 324 buf.append(key); 325 buf.append("\", value=\""); 326 buf.append(value); 327 buf.append("\""); 328 LOGGER.debug(buf.toString()); 329 } 330 331 properties.put(key, value); 332 } 333 } 334 } 335 } else if (childElems.length > 1) { 336 StringBuilder buf = new StringBuilder (100); 337 buf.append(MSG_INVALID_XMLA); 338 buf.append(": Wrong number of PropertyList elements: "); 339 buf.append(childElems.length); 340 throw new XmlaException( 341 CLIENT_FAULT_FC, 342 HSB_BAD_PROPERTIES_LIST_CODE, 343 HSB_BAD_PROPERTIES_LIST_FAULT_FS, 344 Util.newError(buf.toString())); 345 } else { 346 } 347 this.properties = Collections.unmodifiableMap(properties); 348 } 349 350 351 private void initCommand(Element commandRoot) throws XmlaException { 352 Element [] childElems = XmlaUtil.filterChildElements(commandRoot, 353 NS_XMLA, 354 "Statement"); 355 if (childElems.length != 1) { 356 StringBuilder buf = new StringBuilder (100); 357 buf.append(MSG_INVALID_XMLA); 358 buf.append(": Wrong number of Statement elements: "); 359 buf.append(childElems.length); 360 throw new XmlaException( 361 CLIENT_FAULT_FC, 362 HSB_BAD_STATEMENT_CODE, 363 HSB_BAD_STATEMENT_FAULT_FS, 364 Util.newError(buf.toString())); 365 } 366 statement = XmlaUtil.textInElement(childElems[0]).replaceAll("\\r", ""); 367 368 String upperStatement = statement.toUpperCase(); 369 int dtOffset = upperStatement.indexOf("DRILLTHROUGH"); 370 int mrOffset = upperStatement.indexOf("MAXROWS"); 371 int frOffset = upperStatement.indexOf("FIRSTROWSET"); 372 int slOffset = upperStatement.indexOf("SELECT"); 373 374 if (dtOffset == -1) { 375 drillthrough = false; 376 } else { 377 385 if (dtOffset < slOffset) { 386 maxRows = firstRowset = -1; 387 try { 388 if (mrOffset > dtOffset && mrOffset < slOffset) { 389 maxRows = parseIntValue(statement.substring(mrOffset, slOffset)); 390 if (maxRows <= 0) { 391 StringBuilder buf = new StringBuilder (100); 392 buf.append(MSG_INVALID_MAXROWS); 393 buf.append(": "); 394 buf.append(maxRows); 395 throw new XmlaException( 396 CLIENT_FAULT_FC, 397 HSB_DRILLDOWN_BAD_MAXROWS_CODE, 398 HSB_DRILLDOWN_BAD_MAXROWS_FAULT_FS, 399 Util.newError(buf.toString())); 400 } 401 } 402 if (frOffset > dtOffset && frOffset > mrOffset && frOffset < slOffset) { 403 firstRowset = parseIntValue(statement.substring(frOffset, slOffset)); 404 if (firstRowset <= 0) { 405 StringBuilder buf = new StringBuilder (100); 406 buf.append(MSG_INVALID_FIRSTROWSET); 407 buf.append(": "); 408 buf.append(firstRowset); 409 throw new XmlaException( 410 CLIENT_FAULT_FC, 411 HSB_DRILLDOWN_BAD_FIRST_ROWSET_CODE, 412 HSB_DRILLDOWN_BAD_FIRST_ROWSET_FAULT_FS, 413 Util.newError(buf.toString())); 414 } 415 } 416 } catch (XmlaException xex) { 417 throw xex; 418 } catch (Exception e) { 419 throw new XmlaException( 420 CLIENT_FAULT_FC, 421 HSB_DRILLDOWN_ERROR_CODE, 422 HSB_DRILLDOWN_ERROR_FAULT_FS, 423 Util.newError(e, MSG_INVALID_DRILLTHROUGH)); 424 } 425 426 int configMaxRows = MondrianProperties.instance().MaxRows.get(); 427 if (configMaxRows > 0 && maxRows > configMaxRows) { 428 maxRows = configMaxRows; 429 } 430 431 StringBuilder dtStmtBuf = new StringBuilder (); 432 dtStmtBuf.append(statement.substring(0, dtOffset)); dtStmtBuf.append(statement.substring(slOffset)); statement = dtStmtBuf.toString(); 435 436 drillthrough = true; 437 } else { 438 throw new XmlaException( 439 CLIENT_FAULT_FC, 440 HSB_DRILLDOWN_ERROR_CODE, 441 HSB_DRILLDOWN_ERROR_FAULT_FS, 442 Util.newError(MSG_INVALID_DRILLTHROUGH)); 443 } 444 } 445 } 446 447 private int parseIntValue(String option) { 448 String [] opts = option.split("[ \t\n]"); 449 return Integer.parseInt(opts[1]); 450 } 451 452 } 453 454 | Popular Tags |