KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > mondrian > tui > CmdRunner


1 /*
2 // $Id: //open/mondrian/src/main/mondrian/tui/CmdRunner.java#41 $
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 and others
7 // All Rights Reserved.
8 // You must accept the terms of that agreement to use this software.
9 */

10
11 package mondrian.tui;
12
13 import mondrian.olap.*;
14 import mondrian.olap.type.TypeUtil;
15 import mondrian.olap.fun.FunInfo;
16 import mondrian.rolap.RolapConnectionProperties;
17 import mondrian.rolap.RolapCube;
18 import org.apache.log4j.Level;
19 import org.apache.log4j.Logger;
20 import org.apache.log4j.LogManager;
21 import org.eigenbase.util.property.Property;
22
23 import java.io.*;
24 import java.text.NumberFormat JavaDoc;
25 import java.text.ParseException JavaDoc;
26 import java.util.ArrayList JavaDoc;
27 import java.util.Enumeration JavaDoc;
28 import java.util.Iterator JavaDoc;
29 import java.util.List JavaDoc;
30 import java.util.HashMap JavaDoc;
31 import java.util.Map JavaDoc;
32 import java.util.regex.Matcher JavaDoc;
33 import java.util.regex.Pattern JavaDoc;
34 import java.lang.reflect.Field JavaDoc;
35 import java.lang.reflect.Modifier JavaDoc;
36
37 /**
38  * Command line utility which reads and executes MDX commands.
39  *
40  * <p>TODO: describe how to use this class.</p>
41  *
42  * @author Richard Emberson
43  * @version $Id: //open/mondrian/src/main/mondrian/tui/CmdRunner.java#41 $
44  */

45 public class CmdRunner {
46
47     private static final String JavaDoc nl = Util.nl;
48
49     private static boolean RELOAD_CONNECTION = true;
50     private static String JavaDoc CATALOG_NAME = "FoodMart";
51
52     private static final Map JavaDoc<Object JavaDoc, String JavaDoc> paraNameValues =
53         new HashMap JavaDoc<Object JavaDoc, String JavaDoc>();
54
55     private static String JavaDoc[][] commentDelim;
56     private static char[] commentStartChars;
57     private static boolean allowNestedComments;
58
59     private final Options options;
60     private long queryTime;
61     private long totalQueryTime;
62     private String JavaDoc filename;
63     private String JavaDoc mdxCmd;
64     private String JavaDoc mdxResult;
65     private String JavaDoc error;
66     private String JavaDoc stack;
67     private String JavaDoc connectString;
68     private Connection connection;
69     private final PrintWriter out;
70
71     static {
72         setDefaultCommentState();
73     }
74
75     /**
76      * Creates a <code>CmdRunner</code>.
77      *
78      * @param options Option set, or null to use default options
79      * @param out Output writer, or null to use {@link System#out}.
80      */

81     public CmdRunner(Options options, PrintWriter out) {
82         if (options == null) {
83             options = new Options();
84         }
85         this.options = options;
86         this.filename = null;
87         this.mdxResult = null;
88         this.error = null;
89         this.queryTime = -1;
90         if (out == null) {
91             out = new PrintWriter(System.out);
92         }
93         this.out = out;
94     }
95
96     public void setTimeQueries(boolean timeQueries) {
97         this.options.timeQueries = timeQueries;
98     }
99
100     public boolean getTimeQueries() {
101         return options.timeQueries;
102     }
103
104     public long getQueryTime() {
105         return queryTime;
106     }
107
108     public long getTotalQueryTime() {
109         return totalQueryTime;
110     }
111
112     public void noCubeCaching() {
113         Cube[] cubes = getCubes();
114         for (Cube cube : cubes) {
115             RolapCube rcube = (RolapCube) cube;
116             rcube.setCacheAggregations(false);
117         }
118     }
119
120     void setError(String JavaDoc s) {
121         this.error = s;
122     }
123
124     void setError(Throwable JavaDoc t) {
125         this.error = formatError(t);
126         StringWriter sw = new StringWriter();
127         PrintWriter pw = new PrintWriter(sw);
128         t.printStackTrace(pw);
129         pw.flush();
130         this.stack = sw.toString();
131     }
132
133     void clearError() {
134         this.error = null;
135         this.stack = null;
136     }
137
138     private String JavaDoc formatError(Throwable JavaDoc mex) {
139             String JavaDoc message = mex.getMessage();
140             if (message == null) {
141                 message = mex.toString();
142             }
143             if (mex.getCause() != null && mex.getCause() != mex) {
144                     message = message + nl + formatError(mex.getCause());
145             }
146             return message;
147     }
148
149     public static void listPropertyNames(StringBuilder JavaDoc buf) {
150         PropertyInfo propertyInfo =
151                 new PropertyInfo(MondrianProperties.instance());
152         for (int i = 0; i < propertyInfo.size(); i++) {
153             buf.append(propertyInfo.getProperty(i).getPath());
154             buf.append(nl);
155         }
156     }
157
158     public static void listPropertiesAll(StringBuilder JavaDoc buf) {
159         PropertyInfo propertyInfo =
160                 new PropertyInfo(MondrianProperties.instance());
161         for (int i = 0; i < propertyInfo.size(); i++) {
162             String JavaDoc propertyName = propertyInfo.getPropertyName(i);
163             String JavaDoc propertyValue = propertyInfo.getProperty(i).getString();
164             buf.append(propertyName);
165             buf.append('=');
166             buf.append(propertyValue);
167             buf.append(nl);
168         }
169     }
170
171     /**
172      * Returns the value of a property, or null if it is not set.
173      */

174     private static String JavaDoc getPropertyValue(String JavaDoc propertyName) {
175         final Property property = PropertyInfo.lookupProperty(
176                 MondrianProperties.instance(),
177                 propertyName);
178         return property.isSet() ?
179                 property.getString() :
180                 null;
181     }
182
183     public static void listProperty(String JavaDoc propertyName, StringBuilder JavaDoc buf) {
184         buf.append(getPropertyValue(propertyName));
185     }
186
187     public static boolean isProperty(String JavaDoc propertyName) {
188         final Property property = PropertyInfo.lookupProperty(
189                 MondrianProperties.instance(),
190                 propertyName);
191         return property != null;
192     }
193
194     public static boolean setProperty(String JavaDoc name, String JavaDoc value) {
195         final Property property = PropertyInfo.lookupProperty(
196                 MondrianProperties.instance(),
197                 name);
198         String JavaDoc oldValue = property.getString();
199         if (! Util.equals(oldValue, value)) {
200             property.setString(value);
201             return true;
202         } else {
203             return false;
204         }
205     }
206
207     public void loadParameters(Query query) {
208         Parameter[] params = query.getParameters();
209         for (Parameter param : params) {
210             loadParameter(query, param);
211         }
212     }
213
214     /**
215      * Looks up the definition of a property with a given name.
216      */

217     private static class PropertyInfo {
218         private final List JavaDoc<Property> propertyList = new ArrayList JavaDoc<Property>();
219         private final List JavaDoc<String JavaDoc> propertyNameList = new ArrayList JavaDoc<String JavaDoc>();
220
221         PropertyInfo(MondrianProperties properties) {
222             final Class JavaDoc<? extends Object JavaDoc> clazz = properties.getClass();
223             final Field JavaDoc[] fields = clazz.getFields();
224             for (Field JavaDoc field : fields) {
225                 if (!Modifier.isPublic(field.getModifiers()) ||
226                     Modifier.isStatic(field.getModifiers()) ||
227                     !Property.class.isAssignableFrom(
228                         field.getType())) {
229                     continue;
230                 }
231                 final Property property;
232                 try {
233                     property = (Property) field.get(properties);
234                 } catch (IllegalAccessException JavaDoc e) {
235                     continue;
236                 }
237                 propertyList.add(property);
238                 propertyNameList.add(field.getName());
239             }
240         }
241
242         public int size() {
243             return propertyList.size();
244         }
245
246         public Property getProperty(int i) {
247             return propertyList.get(i);
248         }
249
250         public String JavaDoc getPropertyName(int i) {
251             return propertyNameList.get(i);
252         }
253
254         /**
255          * Looks up the definition of a property with a given name.
256          */

257         public static Property lookupProperty(
258                 MondrianProperties properties,
259                 String JavaDoc propertyName)
260         {
261             final Class JavaDoc<? extends Object JavaDoc> clazz = properties.getClass();
262             final Field JavaDoc field;
263             try {
264                 field = clazz.getField(propertyName);
265             } catch (NoSuchFieldException JavaDoc e) {
266                 return null;
267             }
268             if (!Modifier.isPublic(field.getModifiers()) ||
269                     Modifier.isStatic(field.getModifiers()) ||
270                     !Property.class.isAssignableFrom(field.getType())) {
271                 return null;
272             }
273             try {
274                 return (Property) field.get(properties);
275             } catch (IllegalAccessException JavaDoc e) {
276                 return null;
277             }
278         }
279     }
280
281     private static class Expr {
282         enum Type {
283             STRING,
284             NUMERIC,
285             MEMBER
286         }
287
288         final Object JavaDoc value;
289         final Type type;
290         Expr(Object JavaDoc value, Type type) {
291             this.value = value;
292             this.type = type;
293         }
294     }
295
296     public void loadParameter(Query query, Parameter param) {
297         int category = TypeUtil.typeToCategory(param.getType());
298         String JavaDoc name = param.getName();
299         String JavaDoc value = CmdRunner.paraNameValues.get(name);
300         debug("loadParameter: name=" +name+ ", value=" + value);
301         if (value == null) {
302             return;
303         }
304         Expr expr = parseParameter(value);
305         if (expr == null) {
306             return;
307         }
308         Expr.Type type = expr.type;
309         // found the parameter with the given name in the query
310
switch (category) {
311         case Category.Numeric:
312             if (type != Expr.Type.NUMERIC) {
313                 String JavaDoc msg = "For parameter named \""
314                         + name
315                         + "\" of Catetory.Numeric, "
316                         + "the value was type \""
317                         + type
318                         + "\"";
319                 throw new IllegalArgumentException JavaDoc(msg);
320             }
321             break;
322         case Category.String:
323             if (type != Expr.Type.STRING) {
324                 String JavaDoc msg = "For parameter named \""
325                         + name
326                         + "\" of Catetory.String, "
327                         + "the value was type \""
328                         + type
329                         + "\"";
330                 throw new IllegalArgumentException JavaDoc(msg);
331             }
332             break;
333
334         case Category.Member:
335             if (type != Expr.Type.MEMBER) {
336                 String JavaDoc msg = "For parameter named \""
337                         + name
338                         + "\" of Catetory.Member, "
339                         + "the value was type \""
340                         + type
341                         + "\"";
342                 throw new IllegalArgumentException JavaDoc(msg);
343             }
344             break;
345
346         default:
347             throw Util.newInternal("unexpected category " + category);
348         }
349         query.setParameter(param.getName(), String.valueOf(expr.value));
350     }
351
352     static NumberFormat JavaDoc nf = NumberFormat.getInstance();
353
354     // this is taken from JPivot
355
public Expr parseParameter(String JavaDoc value) {
356         // is it a String (enclose in double or single quotes ?
357
String JavaDoc trimmed = value.trim();
358         int len = trimmed.length();
359         if (trimmed.charAt(0) == '"' && trimmed.charAt(len - 1) == '"') {
360             debug("parseParameter. STRING_TYPE: " +trimmed);
361             return new Expr(
362                 trimmed.substring(1, trimmed.length() - 1),
363                 Expr.Type.STRING);
364         }
365         if (trimmed.charAt(0) == '\'' && trimmed.charAt(len - 1) == '\'') {
366             debug("parseParameter. STRING_TYPE: " +trimmed);
367             return new Expr(
368                 trimmed.substring(1, trimmed.length() - 1),
369                 Expr.Type.STRING);
370         }
371
372         // is it a Number ?
373
Number JavaDoc number = null;
374         try {
375             number = nf.parse(trimmed);
376         } catch (ParseException JavaDoc pex) {
377             // nothing to do, should be member
378
}
379         if (number != null) {
380             debug("parseParameter. NUMERIC_TYPE: " +number);
381             return new Expr(number, Expr.Type.NUMERIC);
382         }
383
384         debug("parseParameter. MEMBER_TYPE: " +trimmed);
385         Query query = this.connection.parseQuery(this.mdxCmd);
386         // dont have to execute
387
//this.connection.execute(query);
388

389         // assume member, dimension, hierarchy, level
390
OlapElement element = Util.lookup(query, Util.explode(trimmed));
391
392         debug("parseParameter. exp="
393             +((element == null) ? "null" : element.getClass().getName()));
394
395         if (element instanceof Member) {
396             Member member = (Member) element;
397             return new Expr(member, Expr.Type.MEMBER);
398         } else if (element instanceof mondrian.olap.Level) {
399             mondrian.olap.Level level = (mondrian.olap.Level) element;
400             return new Expr(level, Expr.Type.MEMBER);
401         } else if (element instanceof Hierarchy) {
402             Hierarchy hier = (Hierarchy) element;
403             return new Expr(hier, Expr.Type.MEMBER);
404         } else if (element instanceof Dimension) {
405             Dimension dim = (Dimension) element;
406             return new Expr(dim, Expr.Type.MEMBER);
407         }
408         return null;
409     }
410
411     public static void listParameterNameValues(StringBuilder JavaDoc buf) {
412         for (Map.Entry JavaDoc<Object JavaDoc, String JavaDoc> e : CmdRunner.paraNameValues.entrySet()) {
413             buf.append(e.getKey());
414             buf.append('=');
415             buf.append(e.getValue());
416             buf.append(nl);
417         }
418     }
419
420     public static void listParam(String JavaDoc name, StringBuilder JavaDoc buf) {
421         String JavaDoc v = CmdRunner.paraNameValues.get(name);
422         buf.append(v);
423     }
424
425     public static boolean isParam(String JavaDoc name) {
426         String JavaDoc v = CmdRunner.paraNameValues.get(name);
427         return (v != null);
428     }
429
430     public static void setParameter(String JavaDoc name, String JavaDoc value) {
431         if (name == null) {
432             CmdRunner.paraNameValues.clear();
433         } else {
434             if (value == null) {
435                 CmdRunner.paraNameValues.remove(name);
436             } else {
437                 CmdRunner.paraNameValues.put(name, value);
438             }
439         }
440     }
441
442     /////////////////////////////////////////////////////////////////////////
443
//
444
// cubes
445
//
446
public Cube[] getCubes() {
447         Connection conn = getConnection();
448         return conn.getSchemaReader().getCubes();
449     }
450
451     public Cube getCube(String JavaDoc name) {
452         Cube[] cubes = getCubes();
453         for (Cube cube : cubes) {
454             if (cube.getName().equals(name)) {
455                 return cube;
456             }
457         }
458         return null;
459     }
460
461     public void listCubeName(StringBuilder JavaDoc buf) {
462         Cube[] cubes = getCubes();
463         for (Cube cube : cubes) {
464             buf.append(cube.getName());
465             buf.append(nl);
466         }
467     }
468
469     public void listCubeAttribues(String JavaDoc name, StringBuilder JavaDoc buf) {
470         Cube cube = getCube(name);
471         if (cube == null) {
472             buf.append("No cube found with name \"");
473             buf.append(name);
474             buf.append("\"");
475         } else {
476             RolapCube rcube = (RolapCube) cube;
477             buf.append("facttable=");
478             buf.append(rcube.getStar().getFactTable().getAlias());
479             buf.append(nl);
480             buf.append("caching=");
481             buf.append(rcube.isCacheAggregations());
482             buf.append(nl);
483         }
484     }
485
486     public void executeCubeCommand(
487             String JavaDoc cubename,
488             String JavaDoc command,
489             StringBuilder JavaDoc buf) {
490         Cube cube = getCube(cubename);
491         if (cube == null) {
492             buf.append("No cube found with name \"");
493             buf.append(cubename);
494             buf.append("\"");
495         } else {
496             if (command.equals("clearCache")) {
497                 RolapCube rcube = (RolapCube) cube;
498                 rcube.clearCachedAggregations();
499             } else {
500                 buf.append("For cube \"");
501                 buf.append(cubename);
502                 buf.append("\" there is no command \"");
503                 buf.append(command);
504                 buf.append("\"");
505             }
506         }
507     }
508
509     public void setCubeAttribute(
510             String JavaDoc cubename,
511             String JavaDoc name,
512             String JavaDoc value,
513             StringBuilder JavaDoc buf) {
514         Cube cube = getCube(cubename);
515         if (cube == null) {
516             buf.append("No cube found with name \"");
517             buf.append(cubename);
518             buf.append("\"");
519         } else {
520             if (name.equals("caching")) {
521                 RolapCube rcube = (RolapCube) cube;
522                 boolean isCache = Boolean.valueOf(value);
523                 rcube.setCacheAggregations(isCache);
524             } else {
525                 buf.append("For cube \"");
526                 buf.append(cubename);
527                 buf.append("\" there is no attribute \"");
528                 buf.append(name);
529                 buf.append("\"");
530             }
531         }
532     }
533     //
534
/////////////////////////////////////////////////////////////////////////
535

536     /**
537      * Executes a query and returns the result as a string.
538      *
539      * @param queryString MDX query text
540      * @return result String
541      */

542     public String JavaDoc execute(String JavaDoc queryString) {
543         Result result = runQuery(queryString, true);
544         return toString(result);
545     }
546
547     /**
548      * Executes a query and returns the result.
549      *
550      * @param queryString MDX query text
551      * @return a {@link Result} object
552      */

553     public Result runQuery(String JavaDoc queryString, boolean loadParams) {
554         debug("CmdRunner.runQuery: TOP");
555         Result result = null;
556         long start = System.currentTimeMillis();
557         try {
558             this.connection = getConnection();
559             debug("CmdRunner.runQuery: AFTER getConnection");
560             Query query = this.connection.parseQuery(queryString);
561             debug("CmdRunner.runQuery: AFTER parseQuery");
562             if (loadParams) {
563                 loadParameters(query);
564             }
565             start = System.currentTimeMillis();
566             result = this.connection.execute(query);
567         } finally {
568             queryTime = (System.currentTimeMillis() - start);
569             totalQueryTime += queryTime;
570             debug("CmdRunner.runQuery: BOTTOM");
571         }
572         return result;
573     }
574
575
576     /**
577      * Converts a {@link Result} object to a string
578      *
579      * @return String version of mondrian Result object.
580      */

581     public String JavaDoc toString(Result result) {
582         StringWriter sw = new StringWriter();
583         PrintWriter pw = new PrintWriter(sw);
584         result.print(pw);
585         pw.flush();
586         return sw.toString();
587     }
588
589
590     public void makeConnectString() {
591         String JavaDoc connectString = CmdRunner.getConnectStringProperty();
592         debug("CmdRunner.makeConnectString: connectString="+connectString);
593
594         Util.PropertyList connectProperties;
595         if (connectString == null || connectString.equals("")) {
596             // create new and add provider
597
connectProperties = new Util.PropertyList();
598             connectProperties.put(RolapConnectionProperties.Provider.name(),"mondrian");
599         } else {
600             // load with existing connect string
601
connectProperties = Util.parseConnectString(connectString);
602         }
603
604         // override jdbc url
605
String JavaDoc jdbcURL = CmdRunner.getJdbcURLProperty();
606
607         debug("CmdRunner.makeConnectString: jdbcURL="+jdbcURL);
608
609         if (jdbcURL != null) {
610             // add jdbc url to connect string
611
connectProperties.put(RolapConnectionProperties.Jdbc.name(), jdbcURL);
612         }
613
614         // override jdbc drivers
615
String JavaDoc jdbcDrivers = CmdRunner.getJdbcDriversProperty();
616
617         debug("CmdRunner.makeConnectString: jdbcDrivers="+jdbcDrivers);
618         if (jdbcDrivers != null) {
619             // add jdbc drivers to connect string
620
connectProperties.put(RolapConnectionProperties.JdbcDrivers.name(), jdbcDrivers);
621         }
622
623         // override catalog url
624
String JavaDoc catalogURL = CmdRunner.getCatalogURLProperty();
625
626         debug("CmdRunner.makeConnectString: catalogURL="+catalogURL);
627
628         if (catalogURL != null) {
629             // add catalog url to connect string
630
connectProperties.put(RolapConnectionProperties.Catalog.name(), catalogURL);
631         }
632
633         // override JDBC user
634
String JavaDoc jdbcUser = CmdRunner.getJdbcUserProperty();
635
636         debug("CmdRunner.makeConnectString: jdbcUser="+jdbcUser);
637
638         if (jdbcUser != null) {
639             // add user to connect string
640
connectProperties.put(RolapConnectionProperties.JdbcUser.name(), jdbcUser);
641         }
642
643         // override JDBC password
644
String JavaDoc jdbcPassword = CmdRunner.getJdbcPasswordProperty();
645
646         debug("CmdRunner.makeConnectString: jdbcPassword="+jdbcPassword);
647
648         if (jdbcPassword != null) {
649             // add password to connect string
650
connectProperties.put(RolapConnectionProperties.JdbcPassword.name(), jdbcPassword);
651         }
652
653         debug("CmdRunner.makeConnectString: connectProperties="+connectProperties);
654
655         this.connectString = connectProperties.toString();
656     }
657
658     /**
659      * Gets a connection to Mondrian.
660      *
661      * @return Mondrian {@link Connection}
662      */

663     public Connection getConnection() {
664         return getConnection(CmdRunner.RELOAD_CONNECTION);
665     }
666
667     /**
668      * Gets a Mondrian connection, creating a new one if fresh is true.
669      *
670      * @return mondrian Connection.
671      */

672     public synchronized Connection getConnection(boolean fresh) {
673         if (this.connectString == null) {
674             makeConnectString();
675         }
676         if (fresh) {
677             return DriverManager.getConnection(this.connectString, null, fresh);
678         } else if (this.connection == null) {
679             this.connection =
680                 DriverManager.getConnection(this.connectString, null, fresh);
681         }
682         return this.connection;
683     }
684     public String JavaDoc getConnectString() {
685         return getConnectString(CmdRunner.RELOAD_CONNECTION);
686     }
687     public synchronized String JavaDoc getConnectString(boolean fresh) {
688         if (this.connectString == null) {
689             makeConnectString();
690         }
691         return this.connectString;
692     }
693
694     /////////////////////////////////////////////////////////////////////////
695
/////////////////////////////////////////////////////////////////////////
696
//
697
// static methods
698
//
699
/////////////////////////////////////////////////////////////////////////
700
/////////////////////////////////////////////////////////////////////////
701

702     protected void debug(String JavaDoc msg) {
703         if (options.debug) {
704             out.println(msg);
705         }
706     }
707
708     /////////////////////////////////////////////////////////////////////////
709
// properties
710
/////////////////////////////////////////////////////////////////////////
711
protected static String JavaDoc getConnectStringProperty() {
712         return MondrianProperties.instance().TestConnectString.get();
713     }
714     protected static String JavaDoc getJdbcURLProperty() {
715         return MondrianProperties.instance().TestJdbcURL.get();
716     }
717
718     protected static String JavaDoc getJdbcUserProperty() {
719         return MondrianProperties.instance().TestJdbcUser.get();
720     }
721
722     protected static String JavaDoc getJdbcPasswordProperty() {
723         return MondrianProperties.instance().TestJdbcPassword.get();
724     }
725     protected static String JavaDoc getCatalogURLProperty() {
726         return MondrianProperties.instance().CatalogURL.get();
727     }
728     protected static String JavaDoc getJdbcDriversProperty() {
729         return MondrianProperties.instance().JdbcDrivers.get();
730     }
731
732     /////////////////////////////////////////////////////////////////////////
733
// command loop
734
/////////////////////////////////////////////////////////////////////////
735

736     protected void commandLoop(boolean interactive) throws IOException {
737         commandLoop(
738                 new BufferedReader(
739                         new InputStreamReader(System.in)),
740                 interactive);
741     }
742
743     protected void commandLoop(File file) throws IOException {
744         // If we open a stream, then we close it.
745
FileReader in = new FileReader(file);
746         try {
747             commandLoop(new BufferedReader(in), false);
748         } finally {
749             try {
750                 in.close();
751             } catch (Exception JavaDoc ex) {
752                 // ignore
753
}
754         }
755     }
756
757     protected void commandLoop(String JavaDoc mdxCmd, boolean interactive)
758         throws IOException {
759
760         StringReader is = new StringReader(mdxCmd);
761         commandLoop(is, interactive);
762     }
763
764     private static final String JavaDoc COMMAND_PROMPT_START = "> ";
765     private static final String JavaDoc COMMAND_PROMPT_MID = "? ";
766
767     /**
768      * The Command Loop where lines are read from the InputStream and
769      * interpreted. If interactive then prompts are printed.
770      *
771      * @param in Input reader (preferably buffered)
772      * @param interactive Whether the session is interactive
773      */

774     protected void commandLoop(Reader in, boolean interactive) {
775
776         StringBuilder JavaDoc buf = new StringBuilder JavaDoc(2048);
777         boolean inMdxCmd = false;
778         String JavaDoc resultString = null;
779
780         for(;;) {
781             if (resultString != null) {
782                 printResults(resultString);
783                 printQueryTime();
784                 resultString = null;
785                 buf.setLength(0);
786             } else if (interactive && (error != null)) {
787                 printResults(error);
788                 printQueryTime();
789             }
790             if (interactive) {
791                 if (inMdxCmd) {
792                     out.print(COMMAND_PROMPT_MID);
793                 } else {
794                     out.print(COMMAND_PROMPT_START);
795                 }
796                 out.flush();
797             }
798             if (!inMdxCmd) {
799                 buf.setLength(0);
800             }
801             String JavaDoc line;
802             try {
803                 line = readLine(in, inMdxCmd);
804             } catch (IOException e) {
805                 throw new RuntimeException JavaDoc(
806                         "Exception while reading command line", e);
807             }
808             if (line != null) {
809                 line = line.trim();
810             }
811             debug("line="+line);
812
813             if (! inMdxCmd) {
814                 // If not in the middle of reading an mdx query and
815
// we reach end of file on the stream, then we are over.
816
if (line == null) {
817                     return;
818                 }
819             }
820
821             // If not reading an mdx query, then check if the line is a
822
// user command.
823
if (! inMdxCmd) {
824                 String JavaDoc cmd = line;
825                 if (cmd.startsWith("help")) {
826                     resultString = executeHelp(cmd);
827                 } else if (cmd.startsWith("set")) {
828                     resultString = executeSet(cmd);
829                 } else if (cmd.startsWith("log")) {
830                     resultString = executeLog(cmd);
831                 } else if (cmd.startsWith("file")) {
832                     resultString = executeFile(cmd);
833                 } else if (cmd.startsWith("list")) {
834                     resultString = executeList(cmd);
835                 } else if (cmd.startsWith("func")) {
836                     resultString = executeFunc(cmd);
837                 } else if (cmd.startsWith("param")) {
838                     resultString = executeParam(cmd);
839                 } else if (cmd.startsWith("cube")) {
840                     resultString = executeCube(cmd);
841                 } else if (cmd.startsWith("error")) {
842                     resultString = executeError(cmd);
843                 } else if (cmd.startsWith("echo")) {
844                     resultString = executeEcho(cmd);
845                 } else if (cmd.startsWith("expr")) {
846                     resultString = executeExpr(cmd);
847                 } else if (cmd.equals("=")) {
848                     resultString = reExecuteMdxCmd();
849                 } else if (cmd.startsWith("exit")) {
850                     break;
851                 }
852                 if (resultString != null) {
853                     inMdxCmd = false;
854                     continue;
855                 }
856             }
857
858             // Are we ready to execute an mdx query.
859
if ((line == null) ||
860                     ((line.length() == 1) &&
861                     ((line.charAt(0) == EXECUTE_CHAR) ||
862                         (line.charAt(0) == CANCEL_CHAR)) )) {
863
864                 // If EXECUTE_CHAR, then execute, otherwise its the
865
// CANCEL_CHAR and simply empty buffer.
866
if ((line == null) || (line.charAt(0) == EXECUTE_CHAR)) {
867                     String JavaDoc mdxCmd = buf.toString().trim();
868                     debug("mdxCmd=\""+mdxCmd+"\"");
869                     resultString = executeMdxCmd(mdxCmd);
870                 }
871
872                 inMdxCmd = false;
873
874             } else if (line.length() > 0) {
875
876                 // OK, just add the line to the mdx query we are building.
877
inMdxCmd = true;
878
879                 if (line.endsWith(SEMI_COLON_STRING)) {
880                     // Remove the ';' character.
881
buf.append(line.substring(0, line.length() - 1));
882                     String JavaDoc mdxCmd = buf.toString().trim();
883                     debug("mdxCmd=\"" + mdxCmd + "\"");
884                     resultString = executeMdxCmd(mdxCmd);
885                     inMdxCmd = false;
886                 } else {
887                     buf.append(line);
888                     // add carriage return so that query keeps formatting
889
buf.append(nl);
890                 }
891             }
892         }
893     }
894
895     protected void printResults(String JavaDoc resultString) {
896         if (resultString != null) {
897             resultString = resultString.trim();
898             if (resultString.length() > 0) {
899                 out.println(resultString);
900                 out.flush();
901             }
902         }
903     }
904     protected void printQueryTime() {
905         if (options.timeQueries && (queryTime != -1)) {
906             out.println("time[" +queryTime+ "ms]");
907             out.flush();
908             queryTime = -1;
909         }
910     }
911
912     /**
913      * Gather up a line ending in '\n' or EOF.
914      * Returns null if at EOF.
915      * Strip out comments. If a comment character appears within a
916      * string then its not a comment. Strings are defined with "\"" or
917      * "'" characters. Also, a string can span more than one line (a
918      * nice little complication). So, if we read a string, then we consume
919      * the whole string as part of the "line" returned,
920      * including EOL characters.
921      * If an escape character is seen '\\', then it and the next character
922      * is added to the line regardless of what the next character is.
923      */

924     protected static String JavaDoc readLine(Reader reader, boolean inMdxCmd)
925         throws IOException {
926
927         StringBuilder JavaDoc buf = new StringBuilder JavaDoc(128);
928         StringBuilder JavaDoc line = new StringBuilder JavaDoc(128);
929         int offset;
930         int i=getLine(reader, line);
931         boolean inName = false;
932
933         for (offset = 0; offset < line.length(); offset++) {
934             char c = line.charAt(offset);
935
936             if (c == ESCAPE_CHAR) {
937                 buf.append(ESCAPE_CHAR);
938                 buf.append(line.charAt(++offset));
939             } else if (!inName &&
940                     ((c == STRING_CHAR_1) || (c == STRING_CHAR_2))) {
941                 i = readString(reader, line, offset, buf, i);
942                 offset = 0;
943             } else {
944                 int commentType=-1;
945
946                 if (c == BRACKET_START) {
947                     inName = true;
948                 } else if (c == BRACKET_END) {
949                     inName = false;
950                 } else if (! inName) {
951                     // check if we have the start of a comment block
952
// check if we have the start of a comment block
953
for (int x = 0; x < commentDelim.length; x++) {
954                         if (c != commentStartChars[x]) {
955                             continue;
956                         }
957                         String JavaDoc startComment = commentDelim[x][0];
958                         boolean foundCommentStart = true;
959                         for (int j = 1;
960                             j+offset < line.length() && j < startComment.length();
961                                 j++) {
962                             if (line.charAt(j+offset) != startComment.charAt(j)) {
963                                 foundCommentStart = false;
964                             }
965                         }
966
967                         if (foundCommentStart) {
968                             if (x == 0) {
969                                 // A '#' must be the first character on a line
970
if (offset == 0) {
971                                     commentType = x;
972                                     break;
973                                 }
974                             } else {
975                                 commentType = x;
976                                 break;
977                             }
978                         }
979                     }
980                 }
981
982                 // -1 means no comment
983
if (commentType == -1) {
984                     buf.append(c);
985                 } else {
986                     // check for comment to end of line comment
987
if (commentDelim[commentType][1] == null) {
988                         break;
989                     } else {
990                         // handle delimited comment block
991
i = readBlock(reader, line, offset,
992                                 commentDelim[commentType][0],
993                                 commentDelim[commentType][1],
994                                 false, false, buf, i);
995                         offset = 0;
996                     }
997                 }
998             }
999         }
1000
1001        if (i == -1 && buf.length() == 0) {
1002            return null;
1003        } else {
1004            return buf.toString();
1005        }
1006    }
1007
1008   /**
1009     * Read the next line of input. Return the terminating character,
1010     * -1 for end of file, or \n or \r. Add \n and \r to the end of the
1011     * buffer to be included in strings and comment blocks.
1012     */

1013    protected static int getLine(Reader reader, StringBuilder JavaDoc line)
1014        throws IOException {
1015
1016        line.setLength(0);
1017        for (;;) {
1018            int i = reader.read();
1019
1020            if (i == -1) {
1021                return i;
1022            }
1023
1024            line.append((char)i);
1025
1026            if (i == '\n' || i == '\r') {
1027                return i;
1028            }
1029        }
1030    }
1031
1032    /**
1033     * Start of a string, read all of it even if it spans
1034     * more than one line adding each line's <cr> to the
1035     * buffer.
1036     */

1037    protected static int readString(
1038            Reader reader,
1039            StringBuilder JavaDoc line,
1040            int offset,
1041            StringBuilder JavaDoc buf,
1042            int i)
1043            throws IOException {
1044
1045        String JavaDoc delim=line.substring(offset, offset + 1);
1046        return readBlock(reader, line, offset, delim, delim, true, true, buf, i);
1047    }
1048
1049    /**
1050     * Start of a delimted block, read all of it even if it spans
1051     * more than one line adding each line's <cr> to the
1052     * buffer.
1053     *
1054     * A delimited block is a delimited comment (/\* ... *\/), or a string.
1055     */

1056    protected static int readBlock(
1057            Reader reader,
1058            StringBuilder JavaDoc line,
1059            int offset,
1060            final String JavaDoc startDelim,
1061            final String JavaDoc endDelim,
1062            final boolean allowEscape,
1063            final boolean addToBuf,
1064            StringBuilder JavaDoc buf,
1065            int i)
1066            throws IOException {
1067
1068        int depth=1;
1069        if (addToBuf) {
1070            buf.append(startDelim);
1071        }
1072        offset += startDelim.length();
1073
1074        for (;;) {
1075            // see if we are at the end of the block
1076
if (line.substring(offset).startsWith(endDelim)) {
1077                if (addToBuf) {
1078                    buf.append(endDelim);
1079                }
1080                offset += endDelim.length();
1081                if (--depth == 0) {
1082                     break;
1083                }
1084            }
1085            // check for nested block
1086
else if (allowNestedComments &&
1087                     line.substring(offset).startsWith(startDelim)) {
1088                if (addToBuf) {
1089                    buf.append(startDelim);
1090                }
1091                offset += startDelim.length();
1092                depth++;
1093            }
1094            else if (offset < line.length()) {
1095                // not at the end of line, so eat the next char
1096
char c = line.charAt(offset++);
1097                if (allowEscape && c == ESCAPE_CHAR) {
1098                    if (addToBuf) {
1099                        buf.append(ESCAPE_CHAR);
1100                    }
1101
1102                    if (offset < line.length()) {
1103                        if (addToBuf) {
1104                            buf.append(line.charAt(offset));
1105                        }
1106                        offset++;
1107                    }
1108                }
1109                else if (addToBuf) {
1110                    buf.append(c);
1111                }
1112            }
1113            else {
1114                // finished a line; read in the next one and continue
1115
if (i == -1) {
1116                    break;
1117                }
1118                i = getLine(reader, line);
1119
1120                // line will always contain EOL marker at least, unless at EOF
1121
offset = 0;
1122               if (line.length() == 0) {
1123                    break;
1124                }
1125            }
1126        }
1127
1128        // remove to the end of the string, so caller starts at offset 0
1129
if (offset > 0) {
1130            line.delete(0, offset - 1);
1131        }
1132
1133        return i;
1134    }
1135
1136    /////////////////////////////////////////////////////////////////////////
1137
// xmla file
1138
/////////////////////////////////////////////////////////////////////////
1139

1140    /**
1141     * This is called to process a file containing XMLA as the contents
1142     * of SOAP xml.
1143     *
1144     */

1145    protected void processSoapXmla(File file, int validateXmlaResponse)
1146            throws Exception JavaDoc {
1147
1148
1149        String JavaDoc catalogURL = CmdRunner.getCatalogURLProperty();
1150        String JavaDoc[][] catalogNameUrls = new String JavaDoc[][] {
1151                            { CATALOG_NAME, catalogURL }
1152                        };
1153
1154        long start = System.currentTimeMillis();
1155
1156        byte[] bytes = null;
1157        try {
1158            bytes = XmlaSupport.processSoapXmla(file,
1159                        getConnectString(),
1160                        catalogNameUrls,
1161                        null);
1162
1163        } finally {
1164            queryTime = (System.currentTimeMillis() - start);
1165            totalQueryTime += queryTime;
1166        }
1167
1168        String JavaDoc response = new String JavaDoc(bytes);
1169        out.println(response);
1170
1171        switch (validateXmlaResponse) {
1172        case VALIDATE_NONE:
1173            break;
1174        case VALIDATE_TRANSFORM:
1175            XmlaSupport.validateSchemaSoapXmla(bytes);
1176            out.println("XML Data is Valid");
1177            break;
1178        case VALIDATE_XPATH:
1179            XmlaSupport.validateSoapXmlaUsingXpath(bytes);
1180            out.println("XML Data is Valid");
1181            break;
1182        }
1183    }
1184
1185    /**
1186     * This is called to process a file containing XMLA xml.
1187     *
1188     */

1189    protected void processXmla(File file, int validateXmlaResponce)
1190            throws Exception JavaDoc {
1191
1192
1193        String JavaDoc catalogURL = CmdRunner.getCatalogURLProperty();
1194        String JavaDoc[][] catalogNameUrls = new String JavaDoc[][] {
1195                            { CATALOG_NAME, catalogURL }
1196                        };
1197
1198        long start = System.currentTimeMillis();
1199
1200        byte[] bytes = null;
1201        try {
1202            bytes = XmlaSupport.processXmla(file,
1203                        getConnectString(),
1204                        catalogNameUrls);
1205
1206        } finally {
1207            queryTime = (System.currentTimeMillis() - start);
1208            totalQueryTime += queryTime;
1209        }
1210
1211        String JavaDoc response = new String JavaDoc(bytes);
1212        out.println(response);
1213
1214        switch (validateXmlaResponce) {
1215        case VALIDATE_NONE:
1216            break;
1217        case VALIDATE_TRANSFORM:
1218            XmlaSupport.validateSchemaXmla(bytes);
1219            out.println("XML Data is Valid");
1220            break;
1221        case VALIDATE_XPATH:
1222            XmlaSupport.validateXmlaUsingXpath(bytes);
1223            out.println("XML Data is Valid");
1224            break;
1225        }
1226    }
1227
1228    /////////////////////////////////////////////////////////////////////////
1229
// user commands and help messages
1230
/////////////////////////////////////////////////////////////////////////
1231
private static final String JavaDoc INDENT = " ";
1232
1233    private static final int UNKNOWN_CMD = 0x0000;
1234    private static final int HELP_CMD = 0x0001;
1235    private static final int SET_CMD = 0x0002;
1236    private static final int LOG_CMD = 0x0004;
1237    private static final int FILE_CMD = 0x0008;
1238    private static final int LIST_CMD = 0x0010;
1239    private static final int MDX_CMD = 0x0020;
1240    private static final int FUNC_CMD = 0x0040;
1241    private static final int PARAM_CMD = 0x0080;
1242    private static final int CUBE_CMD = 0x0100;
1243    private static final int ERROR_CMD = 0x0200;
1244    private static final int ECHO_CMD = 0x0400;
1245    private static final int EXPR_CMD = 0x0800;
1246    private static final int EXIT_CMD = 0x1000;
1247
1248    private static final int ALL_CMD = HELP_CMD |
1249                                        SET_CMD |
1250                                        LOG_CMD |
1251                                        FILE_CMD |
1252                                        LIST_CMD |
1253                                        MDX_CMD |
1254                                        FUNC_CMD |
1255                                        PARAM_CMD |
1256                                        CUBE_CMD |
1257                                        ERROR_CMD |
1258                                        ECHO_CMD |
1259                                        EXPR_CMD |
1260                                        EXIT_CMD;
1261
1262    private static final char ESCAPE_CHAR = '\\';
1263    private static final char EXECUTE_CHAR = '=';
1264    private static final char CANCEL_CHAR = '~';
1265    private static final char STRING_CHAR_1 = '"';
1266    private static final char STRING_CHAR_2 = '\'';
1267    private static final char BRACKET_START = '[';
1268    private static final char BRACKET_END = ']';
1269
1270    private static final String JavaDoc SEMI_COLON_STRING = ";";
1271
1272    //////////////////////////////////////////////////////////////////////////
1273
// help
1274
//////////////////////////////////////////////////////////////////////////
1275
protected static String JavaDoc executeHelp(String JavaDoc mdxCmd) {
1276        StringBuilder JavaDoc buf = new StringBuilder JavaDoc(200);
1277
1278        String JavaDoc[] tokens = mdxCmd.split("\\s+");
1279
1280        int cmd = UNKNOWN_CMD;
1281
1282        if (tokens.length == 1) {
1283            buf.append("Commands:");
1284            cmd = ALL_CMD;
1285
1286        } else if (tokens.length == 2) {
1287            String JavaDoc cmdName = tokens[1];
1288
1289            if (cmdName.equals("help")) {
1290                cmd = HELP_CMD;
1291            } else if (cmdName.equals("set")) {
1292                cmd = SET_CMD;
1293            } else if (cmdName.equals("log")) {
1294                cmd = LOG_CMD;
1295            } else if (cmdName.equals("file")) {
1296                cmd = FILE_CMD;
1297            } else if (cmdName.equals("list")) {
1298                cmd = LIST_CMD;
1299            } else if (cmdName.equals("func")) {
1300                cmd = FUNC_CMD;
1301            } else if (cmdName.equals("param")) {
1302                cmd = PARAM_CMD;
1303            } else if (cmdName.equals("cube")) {
1304                cmd = CUBE_CMD;
1305            } else if (cmdName.equals("error")) {
1306                cmd = ERROR_CMD;
1307            } else if (cmdName.equals("echo")) {
1308                cmd = ECHO_CMD;
1309            } else if (cmdName.equals("exit")) {
1310                cmd = EXIT_CMD;
1311            } else {
1312                cmd = UNKNOWN_CMD;
1313            }
1314        }
1315
1316        if (cmd == UNKNOWN_CMD) {
1317            buf.append("Unknown help command: ");
1318            buf.append(mdxCmd);
1319            buf.append(nl);
1320            buf.append("Type \"help\" for list of commands");
1321        }
1322
1323        if ((cmd & HELP_CMD) != 0) {
1324            // help
1325
buf.append(nl);
1326            appendIndent(buf, 1);
1327            buf.append("help");
1328            buf.append(nl);
1329            appendIndent(buf, 2);
1330            buf.append("Prints this text");
1331        }
1332
1333        if ((cmd & SET_CMD) != 0) {
1334            // set
1335
buf.append(nl);
1336            appendSet(buf);
1337        }
1338
1339        if ((cmd & LOG_CMD) != 0) {
1340            // set
1341
buf.append(nl);
1342            appendLog(buf);
1343        }
1344
1345        if ((cmd & FILE_CMD) != 0) {
1346            // file
1347
buf.append(nl);
1348            appendFile(buf);
1349
1350        }
1351        if ((cmd & LIST_CMD) != 0) {
1352            // list
1353
buf.append(nl);
1354            appendList(buf);
1355        }
1356
1357        if ((cmd & MDX_CMD) != 0) {
1358            buf.append(nl);
1359            appendIndent(buf, 1);
1360            buf.append("<mdx query> <cr> ( '");
1361            buf.append(EXECUTE_CHAR);
1362            buf.append("' | '");
1363            buf.append(CANCEL_CHAR);
1364            buf.append("' ) <cr>");
1365            buf.append(nl);
1366            appendIndent(buf, 2);
1367            buf.append("Execute or cancel mdx query.");
1368            buf.append(nl);
1369            appendIndent(buf, 2);
1370            buf.append("An mdx query may span one or more lines.");
1371            buf.append(nl);
1372            appendIndent(buf, 2);
1373            buf.append("After the last line of the query has been entered,");
1374            buf.append(nl);
1375            appendIndent(buf, 3);
1376            buf.append("on the next line a single execute character, '");
1377            buf.append(EXECUTE_CHAR);
1378            buf.append("', may be entered");
1379            buf.append(nl);
1380            appendIndent(buf, 3);
1381            buf.append("followed by a carriage return.");
1382            buf.append(nl);
1383            appendIndent(buf, 3);
1384            buf.append("The lone '");
1385            buf.append(EXECUTE_CHAR);
1386            buf.append("' informs the interpreter that the query has");
1387            buf.append(nl);
1388            appendIndent(buf, 3);
1389            buf.append("has been entered and is ready to execute.");
1390            buf.append(nl);
1391            appendIndent(buf, 2);
1392            buf.append("At anytime during the entry of a query the cancel");
1393            buf.append(nl);
1394            appendIndent(buf, 3);
1395            buf.append("character, '");
1396            buf.append(CANCEL_CHAR);
1397            buf.append("', may be entered alone on a line.");
1398            buf.append(nl);
1399            appendIndent(buf, 3);
1400            buf.append("This removes all of the query text from the");
1401            buf.append(nl);
1402            appendIndent(buf, 3);
1403            buf.append("the command interpreter.");
1404            buf.append(nl);
1405            appendIndent(buf, 2);
1406            buf.append("Queries can also be ended by using a semicolon ';'");
1407            buf.append(nl);
1408            appendIndent(buf, 3);
1409            buf.append("at the end of a line.");
1410        }
1411        if ((cmd & FUNC_CMD) != 0) {
1412            buf.append(nl);
1413            appendFunc(buf);
1414        }
1415
1416        if ((cmd & PARAM_CMD) != 0) {
1417            buf.append(nl);
1418            appendParam(buf);
1419        }
1420
1421        if ((cmd & CUBE_CMD) != 0) {
1422            buf.append(nl);
1423            appendCube(buf);
1424        }
1425
1426        if ((cmd & ERROR_CMD) != 0) {
1427            buf.append(nl);
1428            appendError(buf);
1429        }
1430
1431        if ((cmd & ECHO_CMD) != 0) {
1432            buf.append(nl);
1433            appendEcho(buf);
1434        }
1435
1436        if ((cmd & EXPR_CMD) != 0) {
1437            buf.append(nl);
1438            appendExpr(buf);
1439        }
1440
1441        if (cmd == ALL_CMD) {
1442            // reexecute
1443
buf.append(nl);
1444            appendIndent(buf, 1);
1445            buf.append("= <cr>");
1446            buf.append(nl);
1447            appendIndent(buf, 2);
1448            buf.append("Re-Execute mdx query.");
1449        }
1450
1451        if ((cmd & EXIT_CMD) != 0) {
1452            // exit
1453
buf.append(nl);
1454            appendExit(buf);
1455        }
1456
1457
1458        return buf.toString();
1459    }
1460
1461    protected static void appendIndent(StringBuilder JavaDoc buf, int i) {
1462        while (i-- > 0) {
1463            buf.append(CmdRunner.INDENT);
1464        }
1465    }
1466
1467    //////////////////////////////////////////////////////////////////////////
1468
// set
1469
//////////////////////////////////////////////////////////////////////////
1470
protected static void appendSet(StringBuilder JavaDoc buf) {
1471        appendIndent(buf, 1);
1472        buf.append("set [ property[=value ] ] <cr>");
1473        buf.append(nl);
1474        appendIndent(buf, 2);
1475        buf.append("With no args, prints all mondrian properties and values.");
1476        buf.append(nl);
1477        appendIndent(buf, 2);
1478        buf.append("With \"property\" prints property's value.");
1479        buf.append(nl);
1480        appendIndent(buf, 2);
1481        buf.append("With \"property=value\" set property to that value.");
1482    }
1483
1484    protected String JavaDoc executeSet(String JavaDoc mdxCmd) {
1485        StringBuilder JavaDoc buf = new StringBuilder JavaDoc(400);
1486
1487        String JavaDoc[] tokens = mdxCmd.split("\\s+");
1488
1489        if (tokens.length == 1) {
1490            // list all properties
1491
listPropertiesAll(buf);
1492
1493        } else if (tokens.length == 2) {
1494            String JavaDoc arg = tokens[1];
1495            int index = arg.indexOf('=');
1496            if (index == -1) {
1497                listProperty(arg, buf);
1498            } else {
1499                String JavaDoc[] nv = arg.split("=");
1500                String JavaDoc name = nv[0];
1501                String JavaDoc value = nv[1];
1502                if (isProperty(name)) {
1503                    try {
1504                        if (setProperty(name, value)) {
1505                            this.connectString = null;
1506                        }
1507                    } catch (Exception JavaDoc ex) {
1508                        setError(ex);
1509                    }
1510                } else {
1511                    buf.append("Bad property name:");
1512                    buf.append(name);
1513                    buf.append(nl);
1514                }
1515            }
1516
1517        } else {
1518            buf.append("Bad command usage: \"");
1519            buf.append(mdxCmd);
1520            buf.append('"');
1521            buf.append(nl);
1522            appendSet(buf);
1523        }
1524
1525        return buf.toString();
1526    }
1527
1528    //////////////////////////////////////////////////////////////////////////
1529
// log
1530
//////////////////////////////////////////////////////////////////////////
1531
protected static void appendLog(StringBuilder JavaDoc buf) {
1532        appendIndent(buf, 1);
1533        buf.append("log [ classname[=level ] ] <cr>");
1534        buf.append(nl);
1535        appendIndent(buf, 2);
1536        buf.append("With no args, prints the current log level of all classes.");
1537        buf.append(nl);
1538        appendIndent(buf, 2);
1539        buf.append("With \"classname\" prints the current log level of the class.");
1540        buf.append(nl);
1541        appendIndent(buf, 2);
1542        buf.append("With \"classname=level\" set log level to new value.");
1543    }
1544
1545    protected String JavaDoc executeLog(String JavaDoc mdxCmd) {
1546        StringBuilder JavaDoc buf = new StringBuilder JavaDoc(200);
1547
1548        String JavaDoc[] tokens = mdxCmd.split("\\s+");
1549
1550        if (tokens.length == 1) {
1551            Enumeration JavaDoc e = LogManager.getCurrentLoggers();
1552            while (e.hasMoreElements()) {
1553                Logger logger = (Logger) e.nextElement();
1554                buf.append(logger.getName());
1555                buf.append(':');
1556                buf.append(logger.getLevel());
1557                buf.append(nl);
1558            }
1559
1560        } else if (tokens.length == 2) {
1561            String JavaDoc arg = tokens[1];
1562            int index = arg.indexOf('=');
1563            if (index == -1) {
1564                Logger logger = LogManager.exists(arg);
1565                if (logger == null) {
1566                    buf.append("Bad log name: ");
1567                    buf.append(arg);
1568                    buf.append(nl);
1569                } else {
1570                    buf.append(logger.getName());
1571                    buf.append(':');
1572                    buf.append(logger.getLevel());
1573                    buf.append(nl);
1574                }
1575            } else {
1576                String JavaDoc[] nv = arg.split("=");
1577                String JavaDoc classname = nv[0];
1578                String JavaDoc levelStr = nv[1];
1579
1580                Logger logger = LogManager.getLogger(classname);
1581
1582                if (logger == null) {
1583                    buf.append("Bad log name: ");
1584                    buf.append(classname);
1585                    buf.append(nl);
1586                } else {
1587                    Level level = Level.toLevel(levelStr, null);
1588                    if (level == null) {
1589                        buf.append("Bad log level: ");
1590                        buf.append(levelStr);
1591                        buf.append(nl);
1592                    } else {
1593                        logger.setLevel(level);
1594                    }
1595                }
1596            }
1597
1598        } else {
1599            buf.append("Bad command usage: \"");
1600            buf.append(mdxCmd);
1601            buf.append('"');
1602            buf.append(nl);
1603            appendSet(buf);
1604        }
1605
1606        return buf.toString();
1607    }
1608
1609    //////////////////////////////////////////////////////////////////////////
1610
// file
1611
//////////////////////////////////////////////////////////////////////////
1612
protected static void appendFile(StringBuilder JavaDoc buf) {
1613        appendIndent(buf, 1);
1614        buf.append("file [ filename | '=' ] <cr>");
1615        buf.append(nl);
1616        appendIndent(buf, 2);
1617        buf.append("With no args, prints the last filename executed.");
1618        buf.append(nl);
1619        appendIndent(buf, 2);
1620        buf.append("With \"filename\", read and execute filename .");
1621        buf.append(nl);
1622        appendIndent(buf, 2);
1623        buf.append("With \"=\" character, re-read and re-execute previous filename .");
1624    }
1625
1626    protected String JavaDoc executeFile(String JavaDoc mdxCmd) {
1627        StringBuilder JavaDoc buf = new StringBuilder JavaDoc(512);
1628        String JavaDoc[] tokens = mdxCmd.split("\\s+");
1629
1630        if (tokens.length == 1) {
1631            if (this.filename != null) {
1632                buf.append(this.filename);
1633            }
1634
1635        } else if (tokens.length == 2) {
1636            String JavaDoc token = tokens[1];
1637            String JavaDoc nameOfFile = null;
1638            if ((token.length() == 1) && (token.charAt(0) == EXECUTE_CHAR)) {
1639                // file '='
1640
if (this.filename == null) {
1641                    buf.append("Bad command usage: \"");
1642                    buf.append(mdxCmd);
1643                    buf.append("\", no file to re-execute");
1644                    buf.append(nl);
1645                    appendFile(buf);
1646                } else {
1647                    nameOfFile = this.filename;
1648                }
1649            } else {
1650                // file filename
1651
nameOfFile = token;
1652            }
1653
1654            if (nameOfFile != null) {
1655                this.filename = nameOfFile;
1656
1657                try {
1658                    commandLoop(new File(this.filename));
1659                } catch (IOException ex) {
1660                    setError(ex);
1661                    buf.append("Error: " +ex);
1662                }
1663            }
1664
1665        } else {
1666            buf.append("Bad command usage: \"");
1667            buf.append(mdxCmd);
1668            buf.append('"');
1669            buf.append(nl);
1670            appendFile(buf);
1671        }
1672        return buf.toString();
1673    }
1674
1675    //////////////////////////////////////////////////////////////////////////
1676
// list
1677
//////////////////////////////////////////////////////////////////////////
1678
protected static void appendList(StringBuilder JavaDoc buf) {
1679        appendIndent(buf, 1);
1680        buf.append("list [ cmd | result ] <cr>");
1681        buf.append(nl);
1682        appendIndent(buf, 2);
1683        buf.append("With no arguments, list previous cmd and result");
1684        buf.append(nl);
1685        appendIndent(buf, 2);
1686        buf.append("With \"cmd\" argument, list the last mdx query cmd.");
1687        buf.append(nl);
1688        appendIndent(buf, 2);
1689        buf.append("With \"result\" argument, list the last mdx query result.");
1690    }
1691
1692    protected String JavaDoc executeList(String JavaDoc mdxCmd) {
1693        StringBuilder JavaDoc buf = new StringBuilder JavaDoc(200);
1694
1695        String JavaDoc[] tokens = mdxCmd.split("\\s+");
1696
1697        if (tokens.length == 1) {
1698            if (this.mdxCmd != null) {
1699                buf.append(this.mdxCmd);
1700                if (mdxResult != null) {
1701                    buf.append(nl);
1702                    buf.append(mdxResult);
1703                }
1704            } else if (mdxResult != null) {
1705                buf.append(mdxResult);
1706            }
1707
1708        } else if (tokens.length == 2) {
1709            String JavaDoc arg = tokens[1];
1710            if (arg.equals("cmd")) {
1711                if (this.mdxCmd != null) {
1712                    buf.append(this.mdxCmd);
1713                }
1714            } else if (arg.equals("result")) {
1715                if (mdxResult != null) {
1716                    buf.append(mdxResult);
1717                }
1718            } else {
1719                buf.append("Bad sub command usage:");
1720                buf.append(mdxCmd);
1721                buf.append(nl);
1722                appendList(buf);
1723            }
1724        } else {
1725            buf.append("Bad command usage: \"");
1726            buf.append(mdxCmd);
1727            buf.append('"');
1728            buf.append(nl);
1729            appendList(buf);
1730        }
1731
1732        return buf.toString();
1733    }
1734
1735    //////////////////////////////////////////////////////////////////////////
1736
// func
1737
//////////////////////////////////////////////////////////////////////////
1738
protected static void appendFunc(StringBuilder JavaDoc buf) {
1739        appendIndent(buf, 1);
1740        buf.append("func [ name ] <cr>");
1741        buf.append(nl);
1742        appendIndent(buf, 2);
1743        buf.append("With no arguments, list all defined function names");
1744        buf.append(nl);
1745        appendIndent(buf, 2);
1746        buf.append("With \"name\" argument, display the functions:");
1747        buf.append(nl);
1748        appendIndent(buf, 3);
1749        buf.append("name, description, and syntax");
1750    }
1751    protected String JavaDoc executeFunc(String JavaDoc mdxCmd) {
1752        StringBuilder JavaDoc buf = new StringBuilder JavaDoc(200);
1753
1754        String JavaDoc[] tokens = mdxCmd.split("\\s+");
1755
1756        final FunTable funTable = getConnection().getSchema().getFunTable();
1757        if (tokens.length == 1) {
1758            // prints names only once
1759
List JavaDoc<FunInfo> funInfoList = funTable.getFunInfoList();
1760            Iterator JavaDoc<FunInfo> it = funInfoList.iterator();
1761            String JavaDoc prevName = null;
1762            while (it.hasNext()) {
1763                FunInfo fi = it.next();
1764                String JavaDoc name = fi.getName();
1765                if (prevName == null || ! prevName.equals(name)) {
1766                    buf.append(name);
1767                    buf.append(nl);
1768                    prevName = name;
1769                }
1770            }
1771
1772        } else if (tokens.length == 2) {
1773            String JavaDoc funcname = tokens[1];
1774            List JavaDoc<FunInfo> funInfoList = funTable.getFunInfoList();
1775            List JavaDoc<FunInfo> matches = new ArrayList JavaDoc<FunInfo>();
1776
1777            Iterator JavaDoc<FunInfo> it = funInfoList.iterator();
1778            while (it.hasNext()) {
1779                FunInfo fi = it.next();
1780                if (fi.getName().equalsIgnoreCase(funcname)) {
1781                    matches.add(fi);
1782                }
1783            }
1784
1785            if (matches.size() == 0) {
1786                buf.append("Bad function name \"");
1787                buf.append(funcname);
1788                buf.append("\", usage:");
1789                buf.append(nl);
1790                appendList(buf);
1791            } else {
1792                it = matches.iterator();
1793                boolean doname = true;
1794                while (it.hasNext()) {
1795                    FunInfo fi = it.next();
1796                    if (doname) {
1797                        buf.append(fi.getName());
1798                        buf.append(nl);
1799                        doname = false;
1800                    }
1801
1802                    appendIndent(buf, 1);
1803                    buf.append(fi.getDescription());
1804                    buf.append(nl);
1805
1806                    String JavaDoc[] sigs = fi.getSignatures();
1807                    if (sigs == null) {
1808                        appendIndent(buf, 2);
1809                        buf.append("Signature: ");
1810                        buf.append("NONE");
1811                        buf.append(nl);
1812                    } else {
1813                        for (int i = 0; i < sigs.length; i++) {
1814                            appendIndent(buf, 2);
1815                            buf.append(sigs[i]);
1816                            buf.append(nl);
1817                        }
1818                    }
1819/*
1820                    appendIndent(buf, 1);
1821                    buf.append("Return Type: ");
1822                    int returnType = fi.getReturnTypes();
1823                    if (returnType >= 0) {
1824                        buf.append(cat.getName(returnType));
1825                    } else {
1826                        buf.append("NONE");
1827                    }
1828                    buf.append(nl);
1829                    int[][] paramsArray = fi.getParameterTypes();
1830                    if (paramsArray == null) {
1831                        appendIndent(buf, 1);
1832                        buf.append("Paramter Types: ");
1833                        buf.append("NONE");
1834                        buf.append(nl);
1835
1836                    } else {
1837
1838                        for (int j = 0; j < paramsArray.length; j++) {
1839                            int[] params = paramsArray[j];
1840                            appendIndent(buf, 1);
1841                            buf.append("Paramter Types: ");
1842                            for (int k = 0; k < params.length; k++) {
1843                                int param = params[k];
1844                                buf.append(cat.getName(param));
1845                                buf.append(' ');
1846                            }
1847                            buf.append(nl);
1848                        }
1849                    }
1850*/

1851                }
1852            }
1853        } else {
1854            buf.append("Bad command usage: \"");
1855            buf.append(mdxCmd);
1856            buf.append('"');
1857            buf.append(nl);
1858            appendList(buf);
1859        }
1860
1861        return buf.toString();
1862    }
1863    //////////////////////////////////////////////////////////////////////////
1864
// param
1865
//////////////////////////////////////////////////////////////////////////
1866
protected static void appendParam(StringBuilder JavaDoc buf) {
1867        appendIndent(buf, 1);
1868        buf.append("param [ name[=value ] ] <cr>");
1869        buf.append(nl);
1870        appendIndent(buf, 2);
1871        buf.append("With no argumnts, all param name/value pairs are printed.");
1872        buf.append(nl);
1873        appendIndent(buf, 2);
1874        buf.append("With \"name\" argument, the value of the param is printed.");
1875        buf.append(nl);
1876        appendIndent(buf, 2);
1877        buf.append("With \"name=value\" sets the parameter with name to value.");
1878        buf.append(nl);
1879        appendIndent(buf, 3);
1880        buf.append(" If name is null, then unsets all parameters");
1881        buf.append(nl);
1882        appendIndent(buf, 3);
1883        buf.append(" If value is null, then unsets the parameter associated with value");
1884    }
1885    protected String JavaDoc executeParam(String JavaDoc mdxCmd) {
1886        StringBuilder JavaDoc buf = new StringBuilder JavaDoc(200);
1887
1888        String JavaDoc[] tokens = mdxCmd.split("\\s+");
1889
1890        if (tokens.length == 1) {
1891            // list all properties
1892
listParameterNameValues(buf);
1893
1894        } else if (tokens.length == 2) {
1895            String JavaDoc arg = tokens[1];
1896            int index = arg.indexOf('=');
1897            if (index == -1) {
1898                String JavaDoc name = arg;
1899                if (isParam(name)) {
1900                    listParam(name, buf);
1901                } else {
1902                    buf.append("Bad parameter name:");
1903                    buf.append(name);
1904                    buf.append(nl);
1905                }
1906            } else {
1907                String JavaDoc[] nv = arg.split("=");
1908                String JavaDoc name = (nv.length == 0) ? null : nv[0];
1909                String JavaDoc value = (nv.length == 2) ? nv[1] : null;
1910                setParameter(name, value);
1911            }
1912
1913        } else {
1914            buf.append("Bad command usage: \"");
1915            buf.append(mdxCmd);
1916            buf.append('"');
1917            buf.append(nl);
1918            appendSet(buf);
1919        }
1920
1921        return buf.toString();
1922    }
1923    //////////////////////////////////////////////////////////////////////////
1924
// cube
1925
//////////////////////////////////////////////////////////////////////////
1926
protected static void appendCube(StringBuilder JavaDoc buf) {
1927        appendIndent(buf, 1);
1928        buf.append("cube [ cubename [ name [=value | command] ] ] <cr>");
1929        buf.append(nl);
1930        appendIndent(buf, 2);
1931        buf.append("With no argumnts, all cubes are listed by name.");
1932        buf.append(nl);
1933        appendIndent(buf, 2);
1934        buf.append("With \"cubename\" argument, cube attribute name/values for:");
1935        buf.append(nl);
1936        appendIndent(buf, 3);
1937        buf.append("fact table (readonly)");
1938        buf.append(nl);
1939        appendIndent(buf, 3);
1940        buf.append("aggregate caching (readwrite)");
1941        buf.append(nl);
1942        appendIndent(buf, 2);
1943        buf.append("are printed");
1944        buf.append(nl);
1945        appendIndent(buf, 2);
1946        buf.append("With \"cubename name=value\" sets the readwrite attribute with name to value.");
1947        buf.append(nl);
1948        appendIndent(buf, 2);
1949        buf.append("With \"cubename command\" executes the commands:");
1950        buf.append(nl);
1951        appendIndent(buf, 3);
1952        buf.append("clearCache");
1953    }
1954
1955    protected String JavaDoc executeCube(String JavaDoc mdxCmd) {
1956        StringBuilder JavaDoc buf = new StringBuilder JavaDoc(200);
1957
1958        String JavaDoc[] tokens = mdxCmd.split("\\s+");
1959
1960        if (tokens.length == 1) {
1961            // list all properties
1962
listCubeName(buf);
1963        } else if (tokens.length == 2) {
1964            String JavaDoc cubename = tokens[1];
1965            listCubeAttribues(cubename, buf);
1966
1967        } else if (tokens.length == 3) {
1968            String JavaDoc cubename = tokens[1];
1969            String JavaDoc arg = tokens[2];
1970            int index = arg.indexOf('=');
1971            if (index == -1) {
1972                // its a commnd
1973
String JavaDoc command = arg;
1974                executeCubeCommand(cubename, command, buf);
1975            } else {
1976                String JavaDoc[] nv = arg.split("=");
1977                String JavaDoc name = (nv.length == 0) ? null : nv[0];
1978                String JavaDoc value = (nv.length == 2) ? nv[1] : null;
1979                setCubeAttribute(cubename, name, value, buf);
1980            }
1981
1982        } else {
1983            buf.append("Bad command usage: \"");
1984            buf.append(mdxCmd);
1985            buf.append('"');
1986            buf.append(nl);
1987            appendSet(buf);
1988        }
1989
1990        return buf.toString();
1991    }
1992    //////////////////////////////////////////////////////////////////////////
1993
// error
1994
//////////////////////////////////////////////////////////////////////////
1995
protected static void appendError(StringBuilder JavaDoc buf) {
1996        appendIndent(buf, 1);
1997        buf.append("error [ msg | stack ] <cr>");
1998        buf.append(nl);
1999        appendIndent(buf, 2);
2000        buf.append("With no argumnts, both message and stack are printed.");
2001        buf.append(nl);
2002        appendIndent(buf, 2);
2003        buf.append("With \"msg\" argument, the Error message is printed.");
2004        buf.append(nl);
2005        appendIndent(buf, 2);
2006        buf.append("With \"stack\" argument, the Error stack trace is printed.");
2007    }
2008
2009    protected String JavaDoc executeError(String JavaDoc mdxCmd) {
2010        StringBuilder JavaDoc buf = new StringBuilder JavaDoc(200);
2011
2012        String JavaDoc[] tokens = mdxCmd.split("\\s+");
2013
2014        if (tokens.length == 1) {
2015            if (error != null) {
2016                buf.append(error);
2017                if (stack != null) {
2018                    buf.append(nl);
2019                    buf.append(stack);
2020                }
2021            } else if (stack != null) {
2022                buf.append(stack);
2023            }
2024
2025        } else if (tokens.length == 2) {
2026            String JavaDoc arg = tokens[1];
2027            if (arg.equals("msg")) {
2028                if (error != null) {
2029                    buf.append(error);
2030                }
2031            } else if (arg.equals("stack")) {
2032                if (stack != null) {
2033                    buf.append(stack);
2034                }
2035            } else {
2036                buf.append("Bad sub command usage:");
2037                buf.append(mdxCmd);
2038                buf.append(nl);
2039                appendList(buf);
2040            }
2041        } else {
2042            buf.append("Bad command usage: \"");
2043            buf.append(mdxCmd);
2044            buf.append('"');
2045            buf.append(nl);
2046            appendList(buf);
2047        }
2048
2049        return buf.toString();
2050    }
2051    //////////////////////////////////////////////////////////////////////////
2052
// echo
2053
//////////////////////////////////////////////////////////////////////////
2054
protected static void appendEcho(StringBuilder JavaDoc buf) {
2055        appendIndent(buf, 1);
2056        buf.append("echo text <cr>");
2057        buf.append(nl);
2058        appendIndent(buf, 2);
2059        buf.append("echo text to standard out.");
2060    }
2061    protected String JavaDoc executeEcho(String JavaDoc mdxCmd) {
2062
2063        try {
2064            String JavaDoc resultString = (mdxCmd.length() == 4)
2065                ? "" : mdxCmd.substring(4);
2066            return resultString;
2067
2068        } catch (Exception JavaDoc ex) {
2069            setError(ex);
2070            //return error;
2071
return null;
2072        }
2073    }
2074    //////////////////////////////////////////////////////////////////////////
2075
// expr
2076
//////////////////////////////////////////////////////////////////////////
2077
protected static void appendExpr(StringBuilder JavaDoc buf) {
2078        appendIndent(buf, 1);
2079        buf.append("expr cubename expression<cr>");
2080        buf.append(nl);
2081        appendIndent(buf, 2);
2082        buf.append("evaluate an expression against a cube.");
2083        buf.append(nl);
2084        appendIndent(buf, 2);
2085        buf.append("where: ");
2086        buf.append(nl);
2087        appendIndent(buf, 3);
2088        buf.append("cubename is single word or string using [], '' or \"\"");
2089        buf.append(nl);
2090        appendIndent(buf, 3);
2091        buf.append("expression is string using \"\"");
2092    }
2093    protected String JavaDoc executeExpr(String JavaDoc mdxCmd) {
2094        StringBuilder JavaDoc buf = new StringBuilder JavaDoc(256);
2095
2096        mdxCmd = (mdxCmd.length() == 5)
2097                ? "" : mdxCmd.substring(5);
2098
2099        String JavaDoc regex = "(\"[^\"]+\"|'[^\']+'|\\[[^\\]]+\\]|[^\\s]+)\\s+.*";
2100        Pattern JavaDoc p = Pattern.compile(regex);
2101        Matcher JavaDoc m = p.matcher(mdxCmd);
2102        boolean b = m.matches();
2103
2104        if (! b) {
2105            buf.append("Could not parse into \"cubename expression\" command:");
2106            buf.append(nl);
2107            buf.append(mdxCmd);
2108            String JavaDoc msg = buf.toString();
2109            setError(msg);
2110            return msg;
2111        } else {
2112
2113            String JavaDoc cubeName = m.group(1);
2114            String JavaDoc expression = mdxCmd.substring(cubeName.length()+1);
2115
2116            if (cubeName.charAt(0) == '"') {
2117                cubeName = cubeName.substring(1, cubeName.length()-1);
2118            } else if (cubeName.charAt(0) == '\'') {
2119                cubeName = cubeName.substring(1, cubeName.length()-1);
2120            } else if (cubeName.charAt(0) == '[') {
2121                cubeName = cubeName.substring(1, cubeName.length()-1);
2122            }
2123
2124            int len = expression.length();
2125            if (expression.charAt(0) == '"') {
2126                if (expression.charAt(len-1) != '"') {
2127                    buf.append("Missing end '\"' in expression:");
2128                    buf.append(nl);
2129                    buf.append(expression);
2130                    String JavaDoc msg = buf.toString();
2131                    setError(msg);
2132                    return msg;
2133                }
2134                expression = expression.substring(1, len-1);
2135
2136            } else if (expression.charAt(0) == '\'') {
2137                if (expression.charAt(len-1) != '\'') {
2138                    buf.append("Missing end \"'\" in expression:");
2139                    buf.append(nl);
2140                    buf.append(expression);
2141                    String JavaDoc msg = buf.toString();
2142                    setError(msg);
2143                    return msg;
2144                }
2145                expression = expression.substring(1, len-1);
2146            }
2147
2148            Cube cube = getCube(cubeName);
2149            if (cube == null) {
2150                buf.append("No cube found with name \"");
2151                buf.append(cubeName);
2152                buf.append("\"");
2153                String JavaDoc msg = buf.toString();
2154                setError(msg);
2155                return msg;
2156
2157            } else {
2158                try {
2159                    if (cubeName.indexOf(' ') >= 0) {
2160                        if (cubeName.charAt(0) != '[') {
2161                            cubeName = Util.quoteMdxIdentifier(cubeName);
2162                        }
2163                    }
2164                    final char c = '\'';
2165                    if (expression.indexOf('\'') != -1) {
2166                        // make sure all "'" are escaped
2167
int start = 0;
2168                        int index = expression.indexOf('\'', start);
2169                        if (index == 0) {
2170                            // error: starts with "'"
2171
buf.append("Double \"''\" starting expression:");
2172                            buf.append(nl);
2173                            buf.append(expression);
2174                            String JavaDoc msg = buf.toString();
2175                            setError(msg);
2176                            return msg;
2177                        }
2178                        while (index != -1) {
2179                            if (expression.charAt(index-1) != '\\') {
2180                                // error
2181
buf.append("Non-escaped \"'\" in expression:");
2182                                buf.append(nl);
2183                                buf.append(expression);
2184                                String JavaDoc msg = buf.toString();
2185                                setError(msg);
2186                                return msg;
2187                            }
2188                            start = index+1;
2189                            index = expression.indexOf('\'', start);
2190                        }
2191                    }
2192
2193                    // taken from FoodMartTest code
2194
StringBuilder JavaDoc queryStringBuf = new StringBuilder JavaDoc(64);
2195                    queryStringBuf.append("with member [Measures].[Foo] as ");
2196                    queryStringBuf.append(c);
2197                    queryStringBuf.append(expression);
2198                    queryStringBuf.append(c);
2199                    queryStringBuf.append(" select {[Measures].[Foo]} on columns from ");
2200                    queryStringBuf.append(cubeName);
2201
2202                    String JavaDoc queryString = queryStringBuf.toString();
2203
2204                    Result result = runQuery(queryString, true);
2205                    String JavaDoc resultString =
2206                        result.getCell(new int[]{0}).getFormattedValue();
2207                    mdxResult = resultString;
2208                    clearError();
2209
2210                    buf.append(resultString);
2211
2212                } catch (Exception JavaDoc ex) {
2213                    setError(ex);
2214                    buf.append("Error: " +ex);
2215                }
2216            }
2217        }
2218        return buf.toString();
2219    }
2220    //////////////////////////////////////////////////////////////////////////
2221
// exit
2222
//////////////////////////////////////////////////////////////////////////
2223
protected static void appendExit(StringBuilder JavaDoc buf) {
2224        appendIndent(buf, 1);
2225        buf.append("exit <cr>");
2226        buf.append(nl);
2227        appendIndent(buf, 2);
2228        buf.append("Exit mdx command interpreter.");
2229    }
2230
2231
2232    protected String JavaDoc reExecuteMdxCmd() {
2233        if (this.mdxCmd == null) {
2234            return "No command to execute";
2235        } else {
2236            return executeMdxCmd(this.mdxCmd);
2237        }
2238    }
2239
2240    protected String JavaDoc executeMdxCmd(String JavaDoc mdxCmd) {
2241
2242        this.mdxCmd = mdxCmd;
2243        try {
2244
2245            String JavaDoc resultString = execute(mdxCmd);
2246            mdxResult = resultString;
2247            clearError();
2248            return resultString;
2249
2250        } catch (Exception JavaDoc ex) {
2251            setError(ex);
2252            //return error;
2253
return null;
2254        }
2255    }
2256
2257    /////////////////////////////////////////////////////////////////////////
2258
// helpers
2259
/////////////////////////////////////////////////////////////////////////
2260
protected static void loadPropertiesFromFile(String JavaDoc propFile)
2261                throws IOException {
2262
2263        MondrianProperties.instance().load(new FileInputStream(propFile));
2264    }
2265
2266    /////////////////////////////////////////////////////////////////////////
2267
// main
2268
/////////////////////////////////////////////////////////////////////////
2269

2270    /**
2271     * Prints a usage message.
2272     *
2273     * @param msg Prefix to the message
2274     * @param out Output stream
2275     */

2276    protected static void usage(String JavaDoc msg, PrintStream out) {
2277        StringBuilder JavaDoc buf = new StringBuilder JavaDoc(256);
2278        if (msg != null) {
2279            buf.append(msg);
2280            buf.append(nl);
2281        }
2282        buf.append("Usage: mondrian.tui.CmdRunner args");
2283        buf.append(nl);
2284        buf.append(" args:");
2285        buf.append(nl);
2286        buf.append(" -h : print this usage text");
2287        buf.append(nl);
2288        buf.append(" -d : enable local debugging");
2289        buf.append(nl);
2290        buf.append(" -t : time each mdx query");
2291        buf.append(nl);
2292        buf.append(" -nocache : turn off in-memory aggregate caching");
2293        buf.append(nl);
2294        buf.append(" for all cubes regardless of setting");
2295        buf.append(nl);
2296        buf.append(" in schema");
2297        buf.append(nl);
2298        buf.append(" -rc : do NOT reload connections each query");
2299        buf.append(nl);
2300        buf.append(" (default is to reload connections)");
2301        buf.append(nl);
2302        buf.append(" -p propertyfile : load mondrian properties");
2303        buf.append(nl);
2304        buf.append(" -f mdx_filename+ : execute mdx in one or more files");
2305        buf.append(nl);
2306        buf.append(" -x xmla_filename+: execute XMLA in one or more files");
2307        buf.append(" the XMLA request has no SOAP wrapper");
2308        buf.append(nl);
2309        buf.append(" -xs soap_xmla_filename+ ");
2310        buf.append(" : execute Soap XMLA in one or more files");
2311        buf.append(" the XMLA request has a SOAP wrapper");
2312        buf.append(nl);
2313        buf.append(" -vt : validate xmla response using transforms");
2314        buf.append(" only used with -x or -xs flags");
2315        buf.append(nl);
2316        buf.append(" -vx : validate xmla response using xpaths");
2317        buf.append(" only used with -x or -xs flags");
2318        buf.append(nl);
2319        buf.append(" mdx_cmd : execute mdx_cmd");
2320        buf.append(nl);
2321
2322        out.println(buf.toString());
2323    }
2324
2325    /**
2326     * Set the default comment delimiters for CmdRunner. These defaults are
2327     * # to end of line
2328     * plus all the comment delimiters in Scanner.
2329     */

2330    private static void setDefaultCommentState() {
2331        allowNestedComments = mondrian.olap.Scanner.getNestedCommentsState();
2332        String JavaDoc[][] scannerCommentsDelimiters = mondrian.olap.Scanner.getCommentDelimiters();
2333        commentDelim = new String JavaDoc[scannerCommentsDelimiters.length+1][2];
2334        commentStartChars = new char[scannerCommentsDelimiters.length+1];
2335
2336
2337        // CmdRunner has extra delimiter; # to end of line
2338
commentDelim[0][0] = "#";
2339        commentDelim[0][1] = null;
2340        commentStartChars[0] = commentDelim[0][0].charAt(0);
2341
2342
2343        // copy all the rest of the delimiters
2344
for (int x = 0; x < scannerCommentsDelimiters.length; x++) {
2345            commentDelim[x + 1][0] = scannerCommentsDelimiters[x][0];
2346            commentDelim[x + 1][1] = scannerCommentsDelimiters[x][1];
2347            commentStartChars[x + 1] = commentDelim[x+1][0].charAt(0);
2348        }
2349    }
2350
2351    private static final int DO_MDX = 1;
2352    private static final int DO_XMLA = 2;
2353    private static final int DO_SOAP_XMLA = 3;
2354
2355    private static final int VALIDATE_NONE = 1;
2356    private static final int VALIDATE_TRANSFORM = 2;
2357    private static final int VALIDATE_XPATH = 3;
2358
2359    protected static class Options {
2360        private boolean debug = false;
2361        private boolean timeQueries;
2362        private boolean noCache = false;
2363        private int validateXmlaResponse = VALIDATE_NONE;
2364        private final List JavaDoc<String JavaDoc> filenames = new ArrayList JavaDoc<String JavaDoc>();
2365        private int doingWhat = DO_MDX;
2366        private String JavaDoc singleMdxCmd;
2367    }
2368
2369    public static void main(String JavaDoc[] args) throws Exception JavaDoc {
2370
2371        Options options;
2372        try {
2373            options = parseOptions(args);
2374        } catch (BadOption badOption) {
2375            usage(badOption.getMessage(), System.out);
2376            return;
2377        }
2378
2379        CmdRunner cmdRunner =
2380                new CmdRunner(options, new PrintWriter(System.out));
2381        if (options.noCache) {
2382            cmdRunner.noCubeCaching();
2383        }
2384
2385        if (!options.filenames.isEmpty()) {
2386            for (String JavaDoc filename : options.filenames) {
2387                cmdRunner.filename = filename;
2388                switch (options.doingWhat) {
2389                case DO_MDX:
2390                    // its a file containing mdx
2391
cmdRunner.commandLoop(new File(filename));
2392                    break;
2393                case DO_XMLA:
2394                    // its a file containing XMLA
2395
cmdRunner.processXmla(
2396                        new File(filename),
2397                        options.validateXmlaResponse);
2398                    break;
2399                default:
2400                    // its a file containing SOAP XMLA
2401
cmdRunner.processSoapXmla(
2402                        new File(filename),
2403                        options.validateXmlaResponse);
2404                    break;
2405                }
2406                if (cmdRunner.error != null) {
2407                    System.err.println(filename);
2408                    System.err.println(cmdRunner.error);
2409                    if (cmdRunner.stack != null) {
2410                        System.err.println(cmdRunner.stack);
2411                    }
2412                    cmdRunner.printQueryTime();
2413                    cmdRunner.clearError();
2414                }
2415            }
2416        } else if (options.singleMdxCmd != null) {
2417            cmdRunner.commandLoop(options.singleMdxCmd, false);
2418            if (cmdRunner.error != null) {
2419                System.err.println(cmdRunner.error);
2420                if (cmdRunner.stack != null) {
2421                    System.err.println(cmdRunner.stack);
2422                }
2423            }
2424        } else {
2425            cmdRunner.commandLoop(true);
2426        }
2427        cmdRunner.printTotalQueryTime();
2428    }
2429
2430    private void printTotalQueryTime() {
2431        if (options.timeQueries) {
2432            // only print if different
2433
if (totalQueryTime != queryTime) {
2434                out.println("total[" + totalQueryTime + "ms]");
2435            }
2436        }
2437        out.flush();
2438    }
2439
2440    private static Options parseOptions(String JavaDoc[] args)
2441            throws BadOption, IOException {
2442        final Options options = new Options();
2443        for (int i = 0; i < args.length; i++) {
2444            String JavaDoc arg = args[i];
2445
2446            if (arg.equals("-h")) {
2447                throw new BadOption(null);
2448
2449            } else if (arg.equals("-d")) {
2450                options.debug = true;
2451
2452            } else if (arg.equals("-t")) {
2453                options.timeQueries = true;
2454
2455            } else if (arg.equals("-nocache")) {
2456                options.noCache = true;
2457
2458            } else if (arg.equals("-rc")) {
2459                CmdRunner.RELOAD_CONNECTION = false;
2460
2461            } else if (arg.equals("-vt")) {
2462                options.validateXmlaResponse = VALIDATE_TRANSFORM;
2463
2464            } else if (arg.equals("-vx")) {
2465                options.validateXmlaResponse = VALIDATE_XPATH;
2466
2467            } else if (arg.equals("-f")) {
2468                i++;
2469                if (i == args.length) {
2470                    throw new BadOption("no mdx filename given");
2471                }
2472                options.filenames.add(args[i]);
2473
2474            } else if (arg.equals("-x")) {
2475                i++;
2476                if (i == args.length) {
2477                    throw new BadOption("no XMLA filename given");
2478                }
2479                options.doingWhat = DO_XMLA;
2480                options.filenames.add(args[i]);
2481
2482            } else if (arg.equals("-xs")) {
2483                i++;
2484                if (i == args.length) {
2485                    throw new BadOption("no XMLA filename given");
2486                }
2487                options.doingWhat = DO_SOAP_XMLA;
2488                options.filenames.add(args[i]);
2489
2490            } else if (arg.equals("-p")) {
2491                i++;
2492                if (i == args.length) {
2493                    throw new BadOption("no mondrian properties file given");
2494                }
2495                String JavaDoc propFile = args[i];
2496                loadPropertiesFromFile(propFile);
2497
2498            } else if (!options.filenames.isEmpty()) {
2499                options.filenames.add(arg);
2500            } else {
2501                options.singleMdxCmd = arg;
2502            }
2503        }
2504        return options;
2505    }
2506
2507    private static class BadOption extends Exception JavaDoc {
2508        BadOption(String JavaDoc msg) {
2509            super(msg);
2510        }
2511    }
2512}
2513
2514// End CmdRunner.java
2515

2516
Popular Tags