KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > mondrian > xmla > impl > DefaultXmlaRequest


1 /*
2 // $Id: //open/mondrian/src/main/mondrian/xmla/impl/DefaultXmlaRequest.java#7 $
3 // This software is subject to the terms of the Common Public License
4 // Agreement, available at the following URL:
5 // http://www.opensource.org/licenses/cpl.html.
6 // Copyright (C) 2005-2006 Julian Hyde
7 // All Rights Reserved.
8 // You must accept the terms of that agreement to use this software.
9 */

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 JavaDoc;
22 import org.w3c.dom.Node JavaDoc;
23 import org.w3c.dom.NodeList JavaDoc;
24 import org.apache.log4j.Logger;
25
26 /**
27  * Default implementation of {@link mondrian.xmla.XmlaRequest} by DOM API.
28  *
29  * @author Gang Chen
30  */

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 JavaDoc MSG_INVALID_XMLA = "Invalid XML/A message";
37     private static final String JavaDoc MSG_INVALID_DRILLTHROUGH = "Invalid DRILLTHROUGH statement";
38     private static final String JavaDoc MSG_INVALID_MAXROWS = "MAXROWS is not positive integer";
39     private static final String JavaDoc MSG_INVALID_FIRSTROWSET = "FIRSTROWSET isn't positive integer";
40
41     /* common content */
42     private int method;
43     private Map<String JavaDoc, String JavaDoc> properties;
44     private String JavaDoc role;
45
46     /* EXECUTE content */
47     private String JavaDoc statement;
48     private boolean drillthrough;
49     private int maxRows;
50     private int firstRowset;
51
52     /* DISCOVER contnet */
53     private String JavaDoc requestType;
54     private Map<String JavaDoc, List JavaDoc<String JavaDoc>> restrictions;
55
56
57     public DefaultXmlaRequest(Element JavaDoc xmlaRoot) {
58         this(xmlaRoot, null);
59     }
60
61     public DefaultXmlaRequest(Element JavaDoc xmlaRoot, String JavaDoc role)
62             throws XmlaException {
63         init(xmlaRoot);
64         this.role = role;
65     }
66
67     /* Interface implmentation */
68
69     public int getMethod() {
70         return method;
71     }
72
73     public Map<String JavaDoc, String JavaDoc> getProperties() {
74         return properties;
75     }
76
77     public Map<String JavaDoc, List JavaDoc<String JavaDoc>> getRestrictions() {
78         if (method != METHOD_DISCOVER) {
79             throw new IllegalStateException JavaDoc("Only METHOD_DISCOVER has restrictions");
80         }
81         return restrictions;
82     }
83
84     public String JavaDoc getStatement() {
85         if (method != METHOD_EXECUTE) {
86             throw new IllegalStateException JavaDoc("Only METHOD_EXECUTE has statement");
87         }
88         return statement;
89     }
90
91     public String JavaDoc getRole() {
92         return role;
93     }
94
95     public void setRole(String JavaDoc role) {
96         this.role = role;
97     }
98
99     public String JavaDoc getRequestType() {
100         if (method != METHOD_DISCOVER)
101             throw new IllegalStateException JavaDoc("Only METHOD_DISCOVER has requestType");
102         return requestType;
103     }
104
105     public boolean isDrillThrough() {
106         if (method != METHOD_EXECUTE)
107             throw new IllegalStateException JavaDoc("Only METHOD_EXECUTE determines drillthrough");
108         return drillthrough;
109     }
110
111     public int drillThroughMaxRows() {
112         if (method != METHOD_EXECUTE)
113             throw new IllegalStateException JavaDoc("Only METHOD_EXECUTE determines drillthrough");
114         return maxRows;
115     }
116
117     public int drillThroughFirstRowset() {
118         if (method != METHOD_EXECUTE)
119             throw new IllegalStateException JavaDoc("Only METHOD_EXECUTE determines drillthrough");
120         return firstRowset;
121     }
122
123
124     protected final void init(Element JavaDoc xmlaRoot) throws XmlaException {
125         if (NS_XMLA.equals(xmlaRoot.getNamespaceURI())) {
126             String JavaDoc 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                 // Note that is code will never be reached because
135
// the error will be caught in
136
// DefaultXmlaServlet.handleSoapBody first
137
StringBuilder JavaDoc buf = new StringBuilder JavaDoc(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             // Note that is code will never be reached because
150
// the error will be caught in
151
// DefaultXmlaServlet.handleSoapBody first
152
StringBuilder JavaDoc buf = new StringBuilder JavaDoc(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 JavaDoc discoverRoot) throws XmlaException {
166         Element JavaDoc[] childElems = XmlaUtil.filterChildElements(discoverRoot,
167                                                             NS_XMLA,
168                                                             "RequestType");
169         if (childElems.length != 1) {
170             StringBuilder JavaDoc buf = new StringBuilder JavaDoc(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]); // <RequestType>
181

182         childElems = XmlaUtil.filterChildElements(discoverRoot,
183                                                   NS_XMLA,
184                                                   "Restrictions");
185         if (childElems.length != 1) {
186             StringBuilder JavaDoc buf = new StringBuilder JavaDoc(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]); // <Restriciotns><RestrictionList>
197

198         childElems = XmlaUtil.filterChildElements(discoverRoot,
199                                                   NS_XMLA,
200                                                   "Properties");
201         if (childElems.length != 1) {
202             StringBuilder JavaDoc buf = new StringBuilder JavaDoc(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]); // <Properties><PropertyList>
213
}
214
215     private void initExecute(Element JavaDoc executeRoot) throws XmlaException {
216         Element JavaDoc[] childElems = XmlaUtil.filterChildElements(executeRoot,
217                                                             NS_XMLA,
218                                                             "Command");
219         if (childElems.length != 1) {
220             StringBuilder JavaDoc buf = new StringBuilder JavaDoc(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]); // <Command><Statement>
231

232         childElems = XmlaUtil.filterChildElements(executeRoot,
233                                                   NS_XMLA,
234                                                   "Properties");
235         if (childElems.length != 1) {
236             StringBuilder JavaDoc buf = new StringBuilder JavaDoc(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]); // <Properties><PropertyList>
247
}
248
249     private void initRestrictions(Element JavaDoc restrictionsRoot) throws XmlaException {
250         Map<String JavaDoc, List JavaDoc<String JavaDoc>> restrictions = new HashMap<String JavaDoc, List JavaDoc<String JavaDoc>>();
251         Element JavaDoc[] childElems =
252             XmlaUtil.filterChildElements(
253                 restrictionsRoot,
254                 NS_XMLA,
255                 "RestrictionList");
256         if (childElems.length == 1) {
257             NodeList JavaDoc nlst = childElems[0].getChildNodes();
258             for (int i = 0, nlen = nlst.getLength(); i < nlen; i++) {
259                 Node JavaDoc n = nlst.item(i);
260                 if (n instanceof Element JavaDoc) {
261                     Element JavaDoc e = (Element JavaDoc) n;
262                     if (NS_XMLA.equals(e.getNamespaceURI())) {
263                         String JavaDoc key = e.getLocalName();
264                         String JavaDoc value = XmlaUtil.textInElement(e);
265
266                         List JavaDoc<String JavaDoc> values;
267                         if (restrictions.containsKey(key)) {
268                             values = restrictions.get(key);
269                         } else {
270                             values = new ArrayList<String JavaDoc>();
271                             restrictions.put(key, values);
272                         }
273
274                         if (LOGGER.isDebugEnabled()) {
275                             StringBuilder JavaDoc buf = new StringBuilder JavaDoc(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 JavaDoc buf = new StringBuilder JavaDoc(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 JavaDoc propertiesRoot) throws XmlaException {
305         Map<String JavaDoc, String JavaDoc> properties = new HashMap<String JavaDoc, String JavaDoc>();
306         Element JavaDoc[] childElems = XmlaUtil.filterChildElements(propertiesRoot,
307                                                             NS_XMLA,
308                                                             "PropertyList");
309         if (childElems.length == 1) {
310             NodeList JavaDoc nlst = childElems[0].getChildNodes();
311             for (int i = 0, nlen = nlst.getLength(); i < nlen; i++) {
312                 Node JavaDoc n = nlst.item(i);
313                 if (n instanceof Element JavaDoc) {
314                     Element JavaDoc e = (Element JavaDoc) n;
315                     if (NS_XMLA.equals(e.getNamespaceURI())) {
316
317                         String JavaDoc key = e.getLocalName();
318                         String JavaDoc value = XmlaUtil.textInElement(e);
319
320                         if (LOGGER.isDebugEnabled()) {
321                             StringBuilder JavaDoc buf = new StringBuilder JavaDoc(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 JavaDoc buf = new StringBuilder JavaDoc(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 JavaDoc commandRoot) throws XmlaException {
352         Element JavaDoc[] childElems = XmlaUtil.filterChildElements(commandRoot,
353                                                             NS_XMLA,
354                                                             "Statement");
355         if (childElems.length != 1) {
356             StringBuilder JavaDoc buf = new StringBuilder JavaDoc(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 JavaDoc 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             /*
378              * <drillthrough> := DRILLTHROUGH
379              * [<Max_Rows>] [<First_Rowset>] <MDX select> [<Return_Columns>]
380              * <Max_Rows> := MAXROWS <positive number>
381              * <First_Rowset> := FIRSTROWSET <positive number>
382              * <Return_Columns> := RETURN <member or attribute>
383              * [, <member or attribute>]
384              */

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 JavaDoc buf = new StringBuilder JavaDoc(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 JavaDoc buf = new StringBuilder JavaDoc(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 JavaDoc 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 JavaDoc dtStmtBuf = new StringBuilder JavaDoc();
432                 dtStmtBuf.append(statement.substring(0, dtOffset)); // formulas
433
dtStmtBuf.append(statement.substring(slOffset)); // select to end
434
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 JavaDoc option) {
448         String JavaDoc[] opts = option.split("[ \t\n]");
449         return Integer.parseInt(opts[1]);
450     }
451
452 }
453
454 // End DefaultXmlaRequest.java
455
Popular Tags