1 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 ; 25 import java.text.ParseException ; 26 import java.util.ArrayList ; 27 import java.util.Enumeration ; 28 import java.util.Iterator ; 29 import java.util.List ; 30 import java.util.HashMap ; 31 import java.util.Map ; 32 import java.util.regex.Matcher ; 33 import java.util.regex.Pattern ; 34 import java.lang.reflect.Field ; 35 import java.lang.reflect.Modifier ; 36 37 45 public class CmdRunner { 46 47 private static final String nl = Util.nl; 48 49 private static boolean RELOAD_CONNECTION = true; 50 private static String CATALOG_NAME = "FoodMart"; 51 52 private static final Map <Object , String > paraNameValues = 53 new HashMap <Object , String >(); 54 55 private static String [][] 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 filename; 63 private String mdxCmd; 64 private String mdxResult; 65 private String error; 66 private String stack; 67 private String connectString; 68 private Connection connection; 69 private final PrintWriter out; 70 71 static { 72 setDefaultCommentState(); 73 } 74 75 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 s) { 121 this.error = s; 122 } 123 124 void setError(Throwable 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 formatError(Throwable mex) { 139 String 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 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 buf) { 159 PropertyInfo propertyInfo = 160 new PropertyInfo(MondrianProperties.instance()); 161 for (int i = 0; i < propertyInfo.size(); i++) { 162 String propertyName = propertyInfo.getPropertyName(i); 163 String propertyValue = propertyInfo.getProperty(i).getString(); 164 buf.append(propertyName); 165 buf.append('='); 166 buf.append(propertyValue); 167 buf.append(nl); 168 } 169 } 170 171 174 private static String getPropertyValue(String 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 propertyName, StringBuilder buf) { 184 buf.append(getPropertyValue(propertyName)); 185 } 186 187 public static boolean isProperty(String propertyName) { 188 final Property property = PropertyInfo.lookupProperty( 189 MondrianProperties.instance(), 190 propertyName); 191 return property != null; 192 } 193 194 public static boolean setProperty(String name, String value) { 195 final Property property = PropertyInfo.lookupProperty( 196 MondrianProperties.instance(), 197 name); 198 String 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 217 private static class PropertyInfo { 218 private final List <Property> propertyList = new ArrayList <Property>(); 219 private final List <String > propertyNameList = new ArrayList <String >(); 220 221 PropertyInfo(MondrianProperties properties) { 222 final Class <? extends Object > clazz = properties.getClass(); 223 final Field [] fields = clazz.getFields(); 224 for (Field 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 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 getPropertyName(int i) { 251 return propertyNameList.get(i); 252 } 253 254 257 public static Property lookupProperty( 258 MondrianProperties properties, 259 String propertyName) 260 { 261 final Class <? extends Object > clazz = properties.getClass(); 262 final Field field; 263 try { 264 field = clazz.getField(propertyName); 265 } catch (NoSuchFieldException 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 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 value; 289 final Type type; 290 Expr(Object 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 name = param.getName(); 299 String 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 switch (category) { 311 case Category.Numeric: 312 if (type != Expr.Type.NUMERIC) { 313 String msg = "For parameter named \"" 314 + name 315 + "\" of Catetory.Numeric, " 316 + "the value was type \"" 317 + type 318 + "\""; 319 throw new IllegalArgumentException (msg); 320 } 321 break; 322 case Category.String: 323 if (type != Expr.Type.STRING) { 324 String msg = "For parameter named \"" 325 + name 326 + "\" of Catetory.String, " 327 + "the value was type \"" 328 + type 329 + "\""; 330 throw new IllegalArgumentException (msg); 331 } 332 break; 333 334 case Category.Member: 335 if (type != Expr.Type.MEMBER) { 336 String msg = "For parameter named \"" 337 + name 338 + "\" of Catetory.Member, " 339 + "the value was type \"" 340 + type 341 + "\""; 342 throw new IllegalArgumentException (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 nf = NumberFormat.getInstance(); 353 354 public Expr parseParameter(String value) { 356 String 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 Number number = null; 374 try { 375 number = nf.parse(trimmed); 376 } catch (ParseException pex) { 377 } 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 389 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 buf) { 412 for (Map.Entry <Object , String > 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 name, StringBuilder buf) { 421 String v = CmdRunner.paraNameValues.get(name); 422 buf.append(v); 423 } 424 425 public static boolean isParam(String name) { 426 String v = CmdRunner.paraNameValues.get(name); 427 return (v != null); 428 } 429 430 public static void setParameter(String name, String 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 public Cube[] getCubes() { 447 Connection conn = getConnection(); 448 return conn.getSchemaReader().getCubes(); 449 } 450 451 public Cube getCube(String 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 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 name, StringBuilder 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 cubename, 488 String command, 489 StringBuilder 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 cubename, 511 String name, 512 String value, 513 StringBuilder 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 536 542 public String execute(String queryString) { 543 Result result = runQuery(queryString, true); 544 return toString(result); 545 } 546 547 553 public Result runQuery(String 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 581 public String 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 connectString = CmdRunner.getConnectStringProperty(); 592 debug("CmdRunner.makeConnectString: connectString="+connectString); 593 594 Util.PropertyList connectProperties; 595 if (connectString == null || connectString.equals("")) { 596 connectProperties = new Util.PropertyList(); 598 connectProperties.put(RolapConnectionProperties.Provider.name(),"mondrian"); 599 } else { 600 connectProperties = Util.parseConnectString(connectString); 602 } 603 604 String jdbcURL = CmdRunner.getJdbcURLProperty(); 606 607 debug("CmdRunner.makeConnectString: jdbcURL="+jdbcURL); 608 609 if (jdbcURL != null) { 610 connectProperties.put(RolapConnectionProperties.Jdbc.name(), jdbcURL); 612 } 613 614 String jdbcDrivers = CmdRunner.getJdbcDriversProperty(); 616 617 debug("CmdRunner.makeConnectString: jdbcDrivers="+jdbcDrivers); 618 if (jdbcDrivers != null) { 619 connectProperties.put(RolapConnectionProperties.JdbcDrivers.name(), jdbcDrivers); 621 } 622 623 String catalogURL = CmdRunner.getCatalogURLProperty(); 625 626 debug("CmdRunner.makeConnectString: catalogURL="+catalogURL); 627 628 if (catalogURL != null) { 629 connectProperties.put(RolapConnectionProperties.Catalog.name(), catalogURL); 631 } 632 633 String jdbcUser = CmdRunner.getJdbcUserProperty(); 635 636 debug("CmdRunner.makeConnectString: jdbcUser="+jdbcUser); 637 638 if (jdbcUser != null) { 639 connectProperties.put(RolapConnectionProperties.JdbcUser.name(), jdbcUser); 641 } 642 643 String jdbcPassword = CmdRunner.getJdbcPasswordProperty(); 645 646 debug("CmdRunner.makeConnectString: jdbcPassword="+jdbcPassword); 647 648 if (jdbcPassword != null) { 649 connectProperties.put(RolapConnectionProperties.JdbcPassword.name(), jdbcPassword); 651 } 652 653 debug("CmdRunner.makeConnectString: connectProperties="+connectProperties); 654 655 this.connectString = connectProperties.toString(); 656 } 657 658 663 public Connection getConnection() { 664 return getConnection(CmdRunner.RELOAD_CONNECTION); 665 } 666 667 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 getConnectString() { 685 return getConnectString(CmdRunner.RELOAD_CONNECTION); 686 } 687 public synchronized String getConnectString(boolean fresh) { 688 if (this.connectString == null) { 689 makeConnectString(); 690 } 691 return this.connectString; 692 } 693 694 702 protected void debug(String msg) { 703 if (options.debug) { 704 out.println(msg); 705 } 706 } 707 708 protected static String getConnectStringProperty() { 712 return MondrianProperties.instance().TestConnectString.get(); 713 } 714 protected static String getJdbcURLProperty() { 715 return MondrianProperties.instance().TestJdbcURL.get(); 716 } 717 718 protected static String getJdbcUserProperty() { 719 return MondrianProperties.instance().TestJdbcUser.get(); 720 } 721 722 protected static String getJdbcPasswordProperty() { 723 return MondrianProperties.instance().TestJdbcPassword.get(); 724 } 725 protected static String getCatalogURLProperty() { 726 return MondrianProperties.instance().CatalogURL.get(); 727 } 728 protected static String getJdbcDriversProperty() { 729 return MondrianProperties.instance().JdbcDrivers.get(); 730 } 731 732 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 FileReader in = new FileReader(file); 746 try { 747 commandLoop(new BufferedReader(in), false); 748 } finally { 749 try { 750 in.close(); 751 } catch (Exception ex) { 752 } 754 } 755 } 756 757 protected void commandLoop(String mdxCmd, boolean interactive) 758 throws IOException { 759 760 StringReader is = new StringReader(mdxCmd); 761 commandLoop(is, interactive); 762 } 763 764 private static final String COMMAND_PROMPT_START = "> "; 765 private static final String COMMAND_PROMPT_MID = "? "; 766 767 774 protected void commandLoop(Reader in, boolean interactive) { 775 776 StringBuilder buf = new StringBuilder (2048); 777 boolean inMdxCmd = false; 778 String 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 line; 802 try { 803 line = readLine(in, inMdxCmd); 804 } catch (IOException e) { 805 throw new RuntimeException ( 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 (line == null) { 817 return; 818 } 819 } 820 821 if (! inMdxCmd) { 824 String 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 if ((line == null) || 860 ((line.length() == 1) && 861 ((line.charAt(0) == EXECUTE_CHAR) || 862 (line.charAt(0) == CANCEL_CHAR)) )) { 863 864 if ((line == null) || (line.charAt(0) == EXECUTE_CHAR)) { 867 String 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 inMdxCmd = true; 878 879 if (line.endsWith(SEMI_COLON_STRING)) { 880 buf.append(line.substring(0, line.length() - 1)); 882 String mdxCmd = buf.toString().trim(); 883 debug("mdxCmd=\"" + mdxCmd + "\""); 884 resultString = executeMdxCmd(mdxCmd); 885 inMdxCmd = false; 886 } else { 887 buf.append(line); 888 buf.append(nl); 890 } 891 } 892 } 893 } 894 895 protected void printResults(String 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 924 protected static String readLine(Reader reader, boolean inMdxCmd) 925 throws IOException { 926 927 StringBuilder buf = new StringBuilder (128); 928 StringBuilder line = new StringBuilder (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 for (int x = 0; x < commentDelim.length; x++) { 954 if (c != commentStartChars[x]) { 955 continue; 956 } 957 String 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 if (offset == 0) { 971 commentType = x; 972 break; 973 } 974 } else { 975 commentType = x; 976 break; 977 } 978 } 979 } 980 } 981 982 if (commentType == -1) { 984 buf.append(c); 985 } else { 986 if (commentDelim[commentType][1] == null) { 988 break; 989 } else { 990 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 1013 protected static int getLine(Reader reader, StringBuilder 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 1037 protected static int readString( 1038 Reader reader, 1039 StringBuilder line, 1040 int offset, 1041 StringBuilder buf, 1042 int i) 1043 throws IOException { 1044 1045 String delim=line.substring(offset, offset + 1); 1046 return readBlock(reader, line, offset, delim, delim, true, true, buf, i); 1047 } 1048 1049 1056 protected static int readBlock( 1057 Reader reader, 1058 StringBuilder line, 1059 int offset, 1060 final String startDelim, 1061 final String endDelim, 1062 final boolean allowEscape, 1063 final boolean addToBuf, 1064 StringBuilder 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 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 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 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 if (i == -1) { 1116 break; 1117 } 1118 i = getLine(reader, line); 1119 1120 offset = 0; 1122 if (line.length() == 0) { 1123 break; 1124 } 1125 } 1126 } 1127 1128 if (offset > 0) { 1130 line.delete(0, offset - 1); 1131 } 1132 1133 return i; 1134 } 1135 1136 1140 1145 protected void processSoapXmla(File file, int validateXmlaResponse) 1146 throws Exception { 1147 1148 1149 String catalogURL = CmdRunner.getCatalogURLProperty(); 1150 String [][] catalogNameUrls = new String [][] { 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 response = new String (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 1189 protected void processXmla(File file, int validateXmlaResponce) 1190 throws Exception { 1191 1192 1193 String catalogURL = CmdRunner.getCatalogURLProperty(); 1194 String [][] catalogNameUrls = new String [][] { 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 response = new String (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 private static final String 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 SEMI_COLON_STRING = ";"; 1271 1272 protected static String executeHelp(String mdxCmd) { 1276 StringBuilder buf = new StringBuilder (200); 1277 1278 String [] 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 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 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 buf.append(nl); 1336 appendSet(buf); 1337 } 1338 1339 if ((cmd & LOG_CMD) != 0) { 1340 buf.append(nl); 1342 appendLog(buf); 1343 } 1344 1345 if ((cmd & FILE_CMD) != 0) { 1346 buf.append(nl); 1348 appendFile(buf); 1349 1350 } 1351 if ((cmd & LIST_CMD) != 0) { 1352 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 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 buf.append(nl); 1454 appendExit(buf); 1455 } 1456 1457 1458 return buf.toString(); 1459 } 1460 1461 protected static void appendIndent(StringBuilder buf, int i) { 1462 while (i-- > 0) { 1463 buf.append(CmdRunner.INDENT); 1464 } 1465 } 1466 1467 protected static void appendSet(StringBuilder 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 executeSet(String mdxCmd) { 1485 StringBuilder buf = new StringBuilder (400); 1486 1487 String [] tokens = mdxCmd.split("\\s+"); 1488 1489 if (tokens.length == 1) { 1490 listPropertiesAll(buf); 1492 1493 } else if (tokens.length == 2) { 1494 String arg = tokens[1]; 1495 int index = arg.indexOf('='); 1496 if (index == -1) { 1497 listProperty(arg, buf); 1498 } else { 1499 String [] nv = arg.split("="); 1500 String name = nv[0]; 1501 String value = nv[1]; 1502 if (isProperty(name)) { 1503 try { 1504 if (setProperty(name, value)) { 1505 this.connectString = null; 1506 } 1507 } catch (Exception 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 protected static void appendLog(StringBuilder 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 executeLog(String mdxCmd) { 1546 StringBuilder buf = new StringBuilder (200); 1547 1548 String [] tokens = mdxCmd.split("\\s+"); 1549 1550 if (tokens.length == 1) { 1551 Enumeration 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 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 [] nv = arg.split("="); 1577 String classname = nv[0]; 1578 String 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 protected static void appendFile(StringBuilder 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 executeFile(String mdxCmd) { 1627 StringBuilder buf = new StringBuilder (512); 1628 String [] 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 token = tokens[1]; 1637 String nameOfFile = null; 1638 if ((token.length() == 1) && (token.charAt(0) == EXECUTE_CHAR)) { 1639 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 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 protected static void appendList(StringBuilder 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 executeList(String mdxCmd) { 1693 StringBuilder buf = new StringBuilder (200); 1694 1695 String [] 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 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 protected static void appendFunc(StringBuilder 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 executeFunc(String mdxCmd) { 1752 StringBuilder buf = new StringBuilder (200); 1753 1754 String [] tokens = mdxCmd.split("\\s+"); 1755 1756 final FunTable funTable = getConnection().getSchema().getFunTable(); 1757 if (tokens.length == 1) { 1758 List <FunInfo> funInfoList = funTable.getFunInfoList(); 1760 Iterator <FunInfo> it = funInfoList.iterator(); 1761 String prevName = null; 1762 while (it.hasNext()) { 1763 FunInfo fi = it.next(); 1764 String 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 funcname = tokens[1]; 1774 List <FunInfo> funInfoList = funTable.getFunInfoList(); 1775 List <FunInfo> matches = new ArrayList <FunInfo>(); 1776 1777 Iterator <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 [] 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 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 protected static void appendParam(StringBuilder 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 executeParam(String mdxCmd) { 1886 StringBuilder buf = new StringBuilder (200); 1887 1888 String [] tokens = mdxCmd.split("\\s+"); 1889 1890 if (tokens.length == 1) { 1891 listParameterNameValues(buf); 1893 1894 } else if (tokens.length == 2) { 1895 String arg = tokens[1]; 1896 int index = arg.indexOf('='); 1897 if (index == -1) { 1898 String 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 [] nv = arg.split("="); 1908 String name = (nv.length == 0) ? null : nv[0]; 1909 String 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 protected static void appendCube(StringBuilder 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 executeCube(String mdxCmd) { 1956 StringBuilder buf = new StringBuilder (200); 1957 1958 String [] tokens = mdxCmd.split("\\s+"); 1959 1960 if (tokens.length == 1) { 1961 listCubeName(buf); 1963 } else if (tokens.length == 2) { 1964 String cubename = tokens[1]; 1965 listCubeAttribues(cubename, buf); 1966 1967 } else if (tokens.length == 3) { 1968 String cubename = tokens[1]; 1969 String arg = tokens[2]; 1970 int index = arg.indexOf('='); 1971 if (index == -1) { 1972 String command = arg; 1974 executeCubeCommand(cubename, command, buf); 1975 } else { 1976 String [] nv = arg.split("="); 1977 String name = (nv.length == 0) ? null : nv[0]; 1978 String 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 protected static void appendError(StringBuilder 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 executeError(String mdxCmd) { 2010 StringBuilder buf = new StringBuilder (200); 2011 2012 String [] 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 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 protected static void appendEcho(StringBuilder 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 executeEcho(String mdxCmd) { 2062 2063 try { 2064 String resultString = (mdxCmd.length() == 4) 2065 ? "" : mdxCmd.substring(4); 2066 return resultString; 2067 2068 } catch (Exception ex) { 2069 setError(ex); 2070 return null; 2072 } 2073 } 2074 protected static void appendExpr(StringBuilder 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 executeExpr(String mdxCmd) { 2094 StringBuilder buf = new StringBuilder (256); 2095 2096 mdxCmd = (mdxCmd.length() == 5) 2097 ? "" : mdxCmd.substring(5); 2098 2099 String regex = "(\"[^\"]+\"|'[^\']+'|\\[[^\\]]+\\]|[^\\s]+)\\s+.*"; 2100 Pattern p = Pattern.compile(regex); 2101 Matcher 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 msg = buf.toString(); 2109 setError(msg); 2110 return msg; 2111 } else { 2112 2113 String cubeName = m.group(1); 2114 String 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 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 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 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 int start = 0; 2168 int index = expression.indexOf('\'', start); 2169 if (index == 0) { 2170 buf.append("Double \"''\" starting expression:"); 2172 buf.append(nl); 2173 buf.append(expression); 2174 String msg = buf.toString(); 2175 setError(msg); 2176 return msg; 2177 } 2178 while (index != -1) { 2179 if (expression.charAt(index-1) != '\\') { 2180 buf.append("Non-escaped \"'\" in expression:"); 2182 buf.append(nl); 2183 buf.append(expression); 2184 String msg = buf.toString(); 2185 setError(msg); 2186 return msg; 2187 } 2188 start = index+1; 2189 index = expression.indexOf('\'', start); 2190 } 2191 } 2192 2193 StringBuilder queryStringBuf = new StringBuilder (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 queryString = queryStringBuf.toString(); 2203 2204 Result result = runQuery(queryString, true); 2205 String resultString = 2206 result.getCell(new int[]{0}).getFormattedValue(); 2207 mdxResult = resultString; 2208 clearError(); 2209 2210 buf.append(resultString); 2211 2212 } catch (Exception ex) { 2213 setError(ex); 2214 buf.append("Error: " +ex); 2215 } 2216 } 2217 } 2218 return buf.toString(); 2219 } 2220 protected static void appendExit(StringBuilder 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 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 executeMdxCmd(String mdxCmd) { 2241 2242 this.mdxCmd = mdxCmd; 2243 try { 2244 2245 String resultString = execute(mdxCmd); 2246 mdxResult = resultString; 2247 clearError(); 2248 return resultString; 2249 2250 } catch (Exception ex) { 2251 setError(ex); 2252 return null; 2254 } 2255 } 2256 2257 protected static void loadPropertiesFromFile(String propFile) 2261 throws IOException { 2262 2263 MondrianProperties.instance().load(new FileInputStream(propFile)); 2264 } 2265 2266 2270 2276 protected static void usage(String msg, PrintStream out) { 2277 StringBuilder buf = new StringBuilder (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 2330 private static void setDefaultCommentState() { 2331 allowNestedComments = mondrian.olap.Scanner.getNestedCommentsState(); 2332 String [][] scannerCommentsDelimiters = mondrian.olap.Scanner.getCommentDelimiters(); 2333 commentDelim = new String [scannerCommentsDelimiters.length+1][2]; 2334 commentStartChars = new char[scannerCommentsDelimiters.length+1]; 2335 2336 2337 commentDelim[0][0] = "#"; 2339 commentDelim[0][1] = null; 2340 commentStartChars[0] = commentDelim[0][0].charAt(0); 2341 2342 2343 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 <String > filenames = new ArrayList <String >(); 2365 private int doingWhat = DO_MDX; 2366 private String singleMdxCmd; 2367 } 2368 2369 public static void main(String [] args) throws Exception { 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 filename : options.filenames) { 2387 cmdRunner.filename = filename; 2388 switch (options.doingWhat) { 2389 case DO_MDX: 2390 cmdRunner.commandLoop(new File(filename)); 2392 break; 2393 case DO_XMLA: 2394 cmdRunner.processXmla( 2396 new File(filename), 2397 options.validateXmlaResponse); 2398 break; 2399 default: 2400 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 if (totalQueryTime != queryTime) { 2434 out.println("total[" + totalQueryTime + "ms]"); 2435 } 2436 } 2437 out.flush(); 2438 } 2439 2440 private static Options parseOptions(String [] args) 2441 throws BadOption, IOException { 2442 final Options options = new Options(); 2443 for (int i = 0; i < args.length; i++) { 2444 String 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 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 { 2508 BadOption(String msg) { 2509 super(msg); 2510 } 2511 } 2512} 2513 2514 2516 | Popular Tags |