1 13 14 package mondrian.olap; 15 16 import org.apache.log4j.Logger; 17 import org.eigenbase.xom.XOMUtil; 18 19 import java.io.File ; 20 import java.io.PrintWriter ; 21 import java.io.BufferedReader ; 22 import java.io.Reader ; 23 import java.io.IOException ; 24 import java.io.InputStreamReader ; 25 import java.io.StringWriter ; 26 import java.net.MalformedURLException ; 27 import java.net.URL ; 28 import java.util.*; 29 import java.util.regex.Matcher ; 30 import java.util.regex.Pattern ; 31 32 import mondrian.olap.fun.*; 33 import mondrian.olap.type.Type; 34 import mondrian.resource.MondrianResource; 35 import mondrian.mdx.*; 36 import mondrian.util.UtilCompatible; 37 38 45 public class Util extends XOMUtil { 46 47 public static final String nl = System.getProperty("line.separator"); 48 49 private static final Logger LOGGER = Logger.getLogger(Util.class); 50 51 54 public static final Object nullValue = new Double (FunUtil.DoubleNull); 55 56 59 public static final Object EmptyValue = new Double (FunUtil.DoubleEmpty); 60 61 64 private static long databaseMillis = 0; 65 66 70 private static final Random metaRandom = 71 createRandom(MondrianProperties.instance().TestSeed.get()); 72 73 79 public static final boolean PreJdk15 = 80 System.getProperty("java.version").startsWith("1.4"); 81 82 private static final UtilCompatible compatible; 83 static { 84 String className; 85 if (PreJdk15) { 86 className = "mondrian.util.UtilCompatibleJdk14"; 87 } else { 88 className = "mondrian.util.UtilCompatibleJdk15"; 89 } 90 try { 91 Class <UtilCompatible> clazz = 92 (Class <UtilCompatible>) Class.forName(className); 93 compatible = clazz.newInstance(); 94 } catch (ClassNotFoundException e) { 95 throw Util.newInternal(e, "Could not load '" + className + "'"); 96 } catch (InstantiationException e) { 97 throw Util.newInternal(e, "Could not load '" + className + "'"); 98 } catch (IllegalAccessException e) { 99 throw Util.newInternal(e, "Could not load '" + className + "'"); 100 } 101 } 102 103 public static boolean isNull(Object o) { 104 return o == null || o == nullValue; 105 } 106 107 113 public static <T> boolean isSorted(List<T> list) { 114 T prev = null; 115 for (T t : list) { 116 if (prev != null && 117 ((Comparable <T>) prev).compareTo(t) >= 0) { 118 return false; 119 } 120 prev = t; 121 } 122 return true; 123 } 124 125 128 public static String mdxEncodeString(String st) { 129 StringBuilder retString = new StringBuilder (st.length() + 20); 130 for (int i = 0; i < st.length(); i++) { 131 char c = st.charAt(i); 132 if ((c == ']') && 133 ((i+1) < st.length()) && 134 (st.charAt(i+1) != '.')) { 135 136 retString.append(']'); } 138 retString.append(c); 139 } 140 return retString.toString(); 141 } 142 143 146 public static String quoteForMdx(String val) { 147 StringBuilder buf = new StringBuilder (val.length()+20); 148 buf.append("\""); 149 150 String s0 = replace(val, "\"", "\"\""); 151 buf.append(s0); 152 153 buf.append("\""); 154 return buf.toString(); 155 } 156 157 162 public static String quoteMdxIdentifier(String id) { 163 StringBuilder buf = new StringBuilder (id.length() + 20); 164 quoteMdxIdentifier(id, buf); 165 return buf.toString(); 166 } 167 168 public static void quoteMdxIdentifier(String id, StringBuilder buf) { 169 buf.append('['); 170 int start = buf.length(); 171 buf.append(id); 172 replace(buf, start, "]", "]]"); 173 buf.append(']'); 174 } 175 176 180 public static String quoteMdxIdentifier(String [] ids) { 181 StringBuilder sb = new StringBuilder (64); 182 quoteMdxIdentifier(ids, sb); 183 return sb.toString(); 184 } 185 186 public static void quoteMdxIdentifier(String [] ids, StringBuilder sb) { 187 for (int i = 0; i < ids.length; i++) { 188 if (i > 0) { 189 sb.append('.'); 190 } 191 quoteMdxIdentifier(ids[i], sb); 192 } 193 } 194 195 198 public static boolean equals(Object s, Object t) { 199 return (s == null) ? (t == null) : s.equals(t); 200 } 201 202 209 public static boolean equals(String s, String t) { 210 return equals((Object ) s, (Object ) t); 211 } 212 213 219 public static boolean equalName(String s, String t) { 220 if (s == null) { 221 return t == null; 222 } 223 boolean caseSensitive = MondrianProperties.instance().CaseSensitive.get(); 224 return caseSensitive ? s.equals(t) : s.equalsIgnoreCase(t); 225 } 226 227 235 public static boolean equal(String s, String t, boolean matchCase) { 236 return matchCase ? s.equals(t) : s.equalsIgnoreCase(t); 237 } 238 239 245 public static int compareName(String s, String t) { 246 boolean caseSensitive = MondrianProperties.instance().CaseSensitive.get(); 247 return caseSensitive ? s.compareTo(t) : s.compareToIgnoreCase(t); 248 } 249 250 256 public static String normalizeName(String s) { 257 return MondrianProperties.instance().CaseSensitive.get() ? 258 s : 259 s.toUpperCase(); 260 } 261 262 269 public static int compareKey(Object k1, Object k2) { 270 if (k1 instanceof Boolean ) { 271 k1 = k1.toString(); 273 k2 = k2.toString(); 274 } 275 return ((Comparable ) k1).compareTo(k2); 276 } 277 278 282 public static String replace(String s, String find, String replace) { 283 int found = s.indexOf(find); 285 if (found == -1) { 286 return s; 287 } 288 StringBuilder sb = new StringBuilder (s.length() + 20); 289 int start = 0; 290 char[] chars = s.toCharArray(); 291 final int step = find.length(); 292 if (step == 0) { 293 sb.append(s); 295 replace(sb, 0, find, replace); 296 } else { 297 for (;;) { 298 sb.append(chars, start, found-start); 299 if (found == s.length()) { 300 break; 301 } 302 sb.append(replace); 303 start = found + step; 304 found = s.indexOf(find, start); 305 if (found == -1) { 306 found = s.length(); 307 } 308 } 309 } 310 return sb.toString(); 311 } 312 313 322 public static StringBuilder replace( 323 StringBuilder buf, 324 int start, 325 String find, String replace) { 326 int findLength = find.length(); 329 if (findLength == 0) { 330 for (int j = buf.length(); j >= 0; --j) { 332 buf.insert(j, replace); 333 } 334 return buf; 335 } 336 int k = buf.length(); 337 while (k > 0) { 338 int i = buf.lastIndexOf(find, k); 339 if (i < start) { 340 break; 341 } 342 buf.replace(i, i + find.length(), replace); 343 k = i - findLength; 346 } 347 return buf; 348 } 349 350 public static String [] explode(String s) { 351 if (!s.startsWith("[")) { 352 return new String []{s}; 353 } 354 355 List<String > list = new ArrayList<String >(); 356 int i = 0; 357 358 while (i < s.length()) { 359 if (s.charAt(i) != '[') { 360 throw MondrianResource.instance().MdxInvalidMember.ex(s); 361 } 362 363 int j = getEndIndex(s, i + 1); 364 if (j == -1) { 365 throw MondrianResource.instance().MdxInvalidMember.ex(s); 366 } 367 368 list.add(replace(s.substring(i + 1, j), "]]", "]")); 369 i = j + 2; 370 } 371 return list.toArray(new String [list.size()]); 372 } 373 374 private static int getEndIndex(String s, int i) { 375 while (i < s.length()) { 376 char ch = s.charAt(i); 377 if (ch == ']') { 378 if (i + 1 < s.length() && s.charAt(i + 1) == ']') { i += 2; 380 } else { 381 return i; 382 } 383 } else { 384 i++; 385 } 386 } 387 return -1; 388 } 389 390 394 public static String implode(String [] names) { 395 StringBuilder sb = new StringBuilder (64); 396 for (int i = 0; i < names.length; i++) { 397 if (i > 0) { 398 sb.append("."); 399 } 400 quoteMdxIdentifier(names[i], sb); 401 } 402 return sb.toString(); 403 } 404 405 public static String makeFqName(String name) { 406 return quoteMdxIdentifier(name); 407 } 408 409 public static String makeFqName(OlapElement parent, String name) { 410 if (parent == null) { 411 return Util.quoteMdxIdentifier(name); 412 } else { 413 StringBuilder buf = new StringBuilder (64); 414 buf.append(parent.getUniqueName()); 415 buf.append('.'); 416 Util.quoteMdxIdentifier(name, buf); 417 return buf.toString(); 418 } 419 } 420 421 public static String makeFqName(String parentUniqueName, String name) { 422 if (parentUniqueName == null) { 423 return quoteMdxIdentifier(name); 424 } else { 425 StringBuilder buf = new StringBuilder (64); 426 buf.append(parentUniqueName); 427 buf.append('.'); 428 Util.quoteMdxIdentifier(name, buf); 429 return buf.toString(); 430 } 431 } 432 433 public static OlapElement lookupCompound( 434 SchemaReader schemaReader, 435 OlapElement parent, 436 String [] names, 437 boolean failIfNotFound, 438 int category) 439 { 440 return lookupCompound( 441 schemaReader, parent, names, failIfNotFound, category, 442 MatchType.EXACT); 443 } 444 445 462 public static OlapElement lookupCompound( 463 SchemaReader schemaReader, 464 OlapElement parent, 465 String [] names, 466 boolean failIfNotFound, 467 int category, 468 MatchType matchType) 469 { 470 471 Util.assertPrecondition(parent != null, "parent != null"); 472 473 if (LOGGER.isDebugEnabled()) { 474 StringBuilder buf = new StringBuilder (64); 475 buf.append("Util.lookupCompound: "); 476 buf.append("parent.name="); 477 buf.append(parent.getName()); 478 buf.append(", category="); 479 buf.append(Category.instance.getName(category)); 480 buf.append(", names="); 481 quoteMdxIdentifier(names, buf); 482 LOGGER.debug(buf.toString()); 483 } 484 485 switch (category) { 488 case Category.Member: 489 case Category.Unknown: 490 Member member = schemaReader.getCalculatedMember(names); 491 if (member != null) { 492 return member; 493 } 494 } 495 switch (category) { 497 case Category.Set: 498 case Category.Unknown: 499 NamedSet namedSet = schemaReader.getNamedSet(names); 500 if (namedSet != null) { 501 return namedSet; 502 } 503 } 504 505 for (int i = 0; i < names.length; i++) { 507 String name = names[i]; 508 OlapElement child = 509 schemaReader.getElementChild(parent, name, matchType); 510 if (child != null && matchType != MatchType.EXACT && 515 !Util.equalName(child.getName(), name)) 516 { 517 Util.assertPrecondition(child instanceof Member); 518 Member bestChild = (Member) child; 519 for (int j = i + 1; j < names.length; j++) { 520 Member[] children = 521 schemaReader.getMemberChildren(bestChild); 522 List<Member> childrenList = Arrays.asList(children); 523 FunUtil.hierarchize(childrenList, false); 524 if (matchType == MatchType.AFTER) { 525 bestChild = childrenList.get(0); 526 } else { 527 bestChild = 528 childrenList.get(children.length - 1); 529 } 530 if (bestChild == null) { 531 child = null; 532 break; 533 } 534 } 535 parent = bestChild; 536 break; 537 } 538 if (child == null) { 539 if (LOGGER.isDebugEnabled()) { 540 StringBuilder buf = new StringBuilder (64); 541 buf.append("Util.lookupCompound: "); 542 buf.append("parent.name="); 543 buf.append(parent.getName()); 544 buf.append(" has no child with name="); 545 buf.append(name); 546 LOGGER.debug(buf.toString()); 547 } 548 549 if (failIfNotFound) { 550 throw MondrianResource.instance().MdxChildObjectNotFound.ex( 551 name, parent.getQualifiedName()); 552 } else { 553 return null; 554 } 555 } 556 parent = child; 557 } 558 if (LOGGER.isDebugEnabled()) { 559 StringBuilder buf = new StringBuilder (64); 560 buf.append("Util.lookupCompound: "); 561 buf.append("found child.name="); 562 buf.append(parent.getName()); 563 buf.append(", child.class="); 564 buf.append(parent.getClass().getName()); 565 LOGGER.debug(buf.toString()); 566 } 567 568 switch (category) { 569 case Category.Dimension: 570 if (parent instanceof Dimension) { 571 return parent; 572 } else if (parent instanceof Hierarchy) { 573 return parent.getDimension(); 574 } else if (failIfNotFound) { 575 throw Util.newError("Can not find dimension '" + implode(names) + "'"); 576 } else { 577 return null; 578 } 579 case Category.Hierarchy: 580 if (parent instanceof Hierarchy) { 581 return parent; 582 } else if (parent instanceof Dimension) { 583 return parent.getHierarchy(); 584 } else if (failIfNotFound) { 585 throw Util.newError("Can not find hierarchy '" + implode(names) + "'"); 586 } else { 587 return null; 588 } 589 case Category.Level: 590 if (parent instanceof Level) { 591 return parent; 592 } else if (failIfNotFound) { 593 throw Util.newError("Can not find level '" + implode(names) + "'"); 594 } else { 595 return null; 596 } 597 case Category.Member: 598 if (parent instanceof Member) { 599 return parent; 600 } else if (failIfNotFound) { 601 throw MondrianResource.instance().MdxCantFindMember.ex(implode(names)); 602 } else { 603 return null; 604 } 605 case Category.Unknown: 606 assertPostcondition(parent != null, "return != null"); 607 return parent; 608 default: 609 throw newInternal("Bad switch " + category); 610 } 611 } 612 613 public static OlapElement lookup(Query q, String [] nameParts) { 614 final Exp exp = lookup(q, nameParts, false); 615 if (exp instanceof MemberExpr) { 616 MemberExpr memberExpr = (MemberExpr) exp; 617 return memberExpr.getMember(); 618 } else if (exp instanceof LevelExpr) { 619 LevelExpr levelExpr = (LevelExpr) exp; 620 return levelExpr.getLevel(); 621 } else if (exp instanceof HierarchyExpr) { 622 HierarchyExpr hierarchyExpr = (HierarchyExpr) exp; 623 return hierarchyExpr.getHierarchy(); 624 } else if (exp instanceof DimensionExpr) { 625 DimensionExpr dimensionExpr = (DimensionExpr) exp; 626 return dimensionExpr.getDimension(); 627 } else { 628 throw Util.newInternal("Not an olap element: " + exp); 629 } 630 } 631 632 647 public static Exp lookup( 648 Query q, String [] nameParts, boolean allowProp) { 649 650 final String fullName = quoteMdxIdentifier(nameParts); 652 final SchemaReader schemaReader = q.getSchemaReader(false); 655 OlapElement olapElement = schemaReader.lookupCompound( 656 q.getCube(), nameParts, false, Category.Unknown); 657 if (olapElement != null) { 658 Role role = q.getConnection().getRole(); 659 if (!role.canAccess(olapElement)) { 660 olapElement = null; 661 } 662 } 663 if (olapElement == null) { 664 if (allowProp && 665 nameParts.length > 1) { 666 String [] namePartsButOne = new String [nameParts.length - 1]; 667 System.arraycopy(nameParts, 0, 668 namePartsButOne, 0, 669 nameParts.length - 1); 670 final String propertyName = nameParts[nameParts.length - 1]; 671 olapElement = schemaReader.lookupCompound( 672 q.getCube(), namePartsButOne, false, Category.Member); 673 if (olapElement != null && 674 isValidProperty((Member) olapElement, propertyName)) { 675 return new UnresolvedFunCall( 676 propertyName, Syntax.Property, new Exp[] { 677 createExpr(olapElement)}); 678 } 679 } 680 if (q.ignoreInvalidMembers()) { 686 int nameLen = nameParts.length - 1; 687 olapElement = null; 688 while (nameLen > 0 && olapElement == null) { 689 String [] partialName = new String [nameLen]; 690 System.arraycopy( 691 nameParts, 692 0, 693 partialName, 694 0, 695 nameLen); 696 olapElement = schemaReader.lookupCompound( 697 q.getCube(), partialName, false, Category.Unknown); 698 nameLen--; 699 } 700 if (olapElement != null) { 701 olapElement = olapElement.getHierarchy().getNullMember(); 702 } else { 703 throw MondrianResource.instance().MdxChildObjectNotFound.ex( 704 fullName, q.getCube().getQualifiedName()); 705 } 706 } else { 707 throw MondrianResource.instance().MdxChildObjectNotFound.ex( 708 fullName, q.getCube().getQualifiedName()); 709 } 710 } 711 q.addMeasuresMembers(olapElement); 715 return createExpr(olapElement); 716 } 717 718 722 public static Exp createExpr(OlapElement element) 723 { 724 if (element instanceof Member) { 725 Member member = (Member) element; 726 return new MemberExpr(member); 727 } else if (element instanceof Level) { 728 Level level = (Level) element; 729 return new LevelExpr(level); 730 } else if (element instanceof Hierarchy) { 731 Hierarchy hierarchy = (Hierarchy) element; 732 return new HierarchyExpr(hierarchy); 733 } else if (element instanceof Dimension) { 734 Dimension dimension = (Dimension) element; 735 return new DimensionExpr(dimension); 736 } else if (element instanceof NamedSet) { 737 NamedSet namedSet = (NamedSet) element; 738 return new NamedSetExpr(namedSet); 739 } else { 740 throw Util.newInternal("Unexpected element type: " + element); 741 } 742 } 743 744 public static Member lookupHierarchyRootMember( 745 SchemaReader reader, Hierarchy hierarchy, String memberName) 746 { 747 return lookupHierarchyRootMember( 748 reader, hierarchy, memberName, MatchType.EXACT); 749 } 750 751 758 public static Member lookupHierarchyRootMember( 759 SchemaReader reader, 760 Hierarchy hierarchy, 761 String memberName, 762 MatchType matchType) 763 { 764 Member[] rootMembers = reader.getHierarchyRootMembers(hierarchy); 766 767 Member searchMember = null; 771 if (matchType != MatchType.EXACT && !hierarchy.hasAll() && 772 rootMembers.length > 0) 773 { 774 searchMember = 775 hierarchy.createMember( 776 null, 777 rootMembers[0].getLevel(), 778 memberName, 779 null); 780 } 781 782 int bestMatch = -1; 783 for (int i = 0; i < rootMembers.length; i++) { 784 int rc; 785 if (matchType == MatchType.EXACT || hierarchy.hasAll()) { 787 rc = rootMembers[i].getName().compareToIgnoreCase(memberName); 788 } else { 789 rc = FunUtil.compareSiblingMembers( 790 rootMembers[i], 791 searchMember); 792 } 793 if (rc == 0) { 794 return rootMembers[i]; 795 } 796 if (!hierarchy.hasAll()) { 797 if (matchType == MatchType.BEFORE) { 798 if (rc < 0 && 799 (bestMatch == -1 || 800 FunUtil.compareSiblingMembers( 801 rootMembers[i], 802 rootMembers[bestMatch]) > 0)) 803 { 804 bestMatch = i; 805 } 806 } else if (matchType == MatchType.AFTER) { 807 if (rc > 0 && 808 (bestMatch == -1 || 809 FunUtil.compareSiblingMembers( 810 rootMembers[i], 811 rootMembers[bestMatch]) < 0)) 812 { 813 bestMatch = i; 814 } 815 } 816 } 817 } 818 if (matchType != MatchType.EXACT && bestMatch != -1) { 819 return rootMembers[bestMatch]; 820 } 821 return (rootMembers.length == 1 && rootMembers[0].isAll()) 825 ? reader.lookupMemberChildByName( 826 rootMembers[0], 827 memberName, 828 matchType) 829 : null; 830 } 831 832 836 public static Level lookupHierarchyLevel(Hierarchy hierarchy, String s) { 837 final Level[] levels = hierarchy.getLevels(); 838 for (Level level : levels) { 839 if (level.getName().equalsIgnoreCase(s)) { 840 return level; 841 } 842 } 843 return null; 844 } 845 846 847 848 851 public static int getMemberOrdinalInParent(SchemaReader reader, 852 Member member) { 853 Member parent = member.getParentMember(); 854 Member[] siblings = (parent == null) 855 ? reader.getHierarchyRootMembers(member.getHierarchy()) 856 : reader.getMemberChildren(parent); 857 858 for (int i = 0; i < siblings.length; i++) { 859 if (siblings[i] == member) { 860 return i; 861 } 862 } 863 throw Util.newInternal( 864 "could not find member " + member + " amongst its siblings"); 865 } 866 867 872 public static Member getFirstDescendantOnLevel( 873 SchemaReader reader, 874 Member parent, 875 Level level) 876 { 877 Member m = parent; 878 while (m.getLevel() != level) { 879 Member[] children = reader.getMemberChildren(m); 880 m = children[0]; 881 } 882 return m; 883 } 884 885 888 public static boolean isEmpty(String s) { 889 return (s == null) || (s.length() == 0); 890 } 891 892 897 public static String singleQuoteString(String val) { 898 StringBuilder buf = new StringBuilder (64); 899 singleQuoteString(val, buf); 900 return buf.toString(); 901 } 902 903 908 public static void singleQuoteString(String val, StringBuilder buf) { 909 buf.append('\''); 910 911 String s0 = replace(val, "'", "''"); 912 buf.append(s0); 913 914 buf.append('\''); 915 } 916 917 929 public static Random createRandom(long seed) { 930 if (seed == 0) { 931 seed = new Random().nextLong(); 932 System.out.println("random: seed=" + seed); 933 } else if (seed == -1 && metaRandom != null) { 934 seed = metaRandom.nextLong(); 935 } 936 return new Random(seed); 937 } 938 939 949 public static boolean isValidProperty( 950 Member member, String propertyName) { 951 return lookupProperty(member.getLevel(), propertyName) != null; 952 } 953 954 958 protected static Property lookupProperty(Level level, String propertyName) { 959 do { 960 Property[] properties = level.getProperties(); 961 for (Property property : properties) { 962 if (property.getName().equals(propertyName)) { 963 return property; 964 } 965 } 966 level = level.getParentLevel(); 967 } while (level != null); 968 boolean caseSensitive = 970 MondrianProperties.instance().CaseSensitive.get(); 971 final Property property = Property.lookup(propertyName, caseSensitive); 972 if (property != null && 973 property.isMemberProperty() && 974 property.isStandard()) { 975 return property; 976 } 977 return null; 978 } 979 980 986 public static void deprecated(String reason) { 987 throw new UnsupportedOperationException (reason); 988 } 989 990 public static Member[] addLevelCalculatedMembers( 991 SchemaReader reader, 992 Level level, 993 Member[] members) { 994 List<Member> calcMembers = 995 reader.getCalculatedMembers(level.getHierarchy()); 996 List<Member> calcMembersInThisLevel = new ArrayList<Member>(); 997 for (Member calcMember : calcMembers) { 998 if (calcMember.getLevel().equals(level)) { 999 calcMembersInThisLevel.add(calcMember); 1000 } 1001 } 1002 if (!calcMembersInThisLevel.isEmpty()) { 1003 List<Member> newMemberList = 1004 new ArrayList<Member>(Arrays.asList(members)); 1005 newMemberList.addAll(calcMembersInThisLevel); 1006 members = newMemberList.toArray(new Member[newMemberList.size()]); 1007 } 1008 return members; 1009 } 1010 1011 1015 public static RuntimeException needToImplement(Object o) { 1016 throw new UnsupportedOperationException ("need to implement " + o); 1017 } 1018 1019 1023 public static <T extends Enum <T>> RuntimeException badValue( 1024 Enum <T> anEnum) 1025 { 1026 return Util.newInternal("Was not expecting value '" + anEnum + 1027 "' for enumeration '" + anEnum.getDeclaringClass().getName() + 1028 "' in this context"); 1029 } 1030 1031 1038 public static String maskVersion(String str) { 1039 MondrianServer.MondrianVersion mondrianVersion = 1040 MondrianServer.forConnection(null).getVersion(); 1041 String versionString = mondrianVersion.getVersionString(); 1042 return replace(str, versionString, "${mondrianVersion}"); 1043 } 1044 1045 public static class ErrorCellValue { 1046 public String toString() { 1047 return "#ERR"; 1048 } 1049 } 1050 1051 1055 public static void assertTrue(boolean b) { 1056 if (!b) { 1057 throw newInternal("assert failed"); 1058 } 1059 } 1060 1061 1066 public static void assertTrue(boolean b, String message) { 1067 if (!b) { 1068 throw newInternal("assert failed: " + message); 1069 } 1070 } 1071 1072 1075 public static RuntimeException newInternal(String message) { 1076 return MondrianResource.instance().Internal.ex(message); 1077 } 1078 1079 1082 public static RuntimeException newInternal(Throwable e, String message) { 1083 return MondrianResource.instance().Internal.ex(message, e); 1084 } 1085 1086 1090 public static RuntimeException newError(String message) { 1091 return newInternal(message); 1092 } 1093 1094 1098 public static RuntimeException newError(Throwable e, String message) { 1099 return newInternal(e, message); 1100 } 1101 1102 1108 public static void assertPrecondition(boolean b) { 1109 assertTrue(b); 1110 } 1111 1112 1124 public static void assertPrecondition(boolean b, String condition) { 1125 assertTrue(b, condition); 1126 } 1127 1128 1134 public static void assertPostcondition(boolean b) { 1135 assertTrue(b); 1136 } 1137 1138 1144 public static void assertPostcondition(boolean b, String condition) { 1145 assertTrue(b, condition); 1146 } 1147 1148 1154 public static String [] convertStackToString(Throwable e) { 1155 List<String > list = new ArrayList<String >(); 1156 while (e != null) { 1157 String sMsg = getErrorMessage(e); 1158 list.add(sMsg); 1159 e = e.getCause(); 1160 } 1161 return list.toArray(new String [list.size()]); 1162 } 1163 1164 1171 public static String getErrorMessage(Throwable err) { 1172 boolean prependClassName = 1173 !(err instanceof java.sql.SQLException || 1174 err.getClass() == java.lang.Exception .class); 1175 return getErrorMessage(err, prependClassName); 1176 } 1177 1178 1188 public static String getErrorMessage( 1189 Throwable err, 1190 boolean prependClassName) 1191 { 1192 String errMsg = err.getMessage(); 1193 if ((errMsg == null) || (err instanceof RuntimeException )) { 1194 StringWriter sw = new StringWriter (); 1195 PrintWriter pw = new PrintWriter (sw); 1196 err.printStackTrace(pw); 1197 return sw.toString(); 1198 } else { 1199 return (prependClassName) 1200 ? err.getClass().getName() + ": " + errMsg 1201 : errMsg; 1202 1203 } 1204 } 1205 1206 1209 public static String unparse(Exp exp) { 1210 StringWriter sw = new StringWriter (); 1211 PrintWriter pw = new PrintWriter (sw); 1212 exp.unparse(pw); 1213 return sw.toString(); 1214 } 1215 1216 1219 public static String unparse(Query query) { 1220 StringWriter sw = new StringWriter (); 1221 PrintWriter pw = new QueryPrintWriter(sw); 1222 query.unparse(pw); 1223 return sw.toString(); 1224 } 1225 1226 1229 public static URL toURL(File file) throws MalformedURLException { 1230 String path = file.getAbsolutePath(); 1231 String fs = System.getProperty("file.separator"); 1235 if (fs.length() == 1) { 1236 char sep = fs.charAt(0); 1237 if (sep != '/') { 1238 path = path.replace(sep, '/'); 1239 } 1240 if (path.charAt(0) != '/') { 1241 path = '/' + path; 1242 } 1243 } 1244 path = "file://" + path; 1245 return new URL (path); 1246 } 1247 1248 1252 public static class PropertyList { 1253 List<String []> list = new ArrayList<String []>(); 1254 1255 public String get(String key) { 1256 return get(key, null); 1257 } 1258 1259 public String get(String key, String defaultValue) { 1260 for (int i = 0, n = list.size(); i < n; i++) { 1261 String [] pair = list.get(i); 1262 if (pair[0].equalsIgnoreCase(key)) { 1263 return pair[1]; 1264 } 1265 } 1266 return defaultValue; 1267 } 1268 1269 public String put(String key, String value) { 1270 for (int i = 0, n = list.size(); i < n; i++) { 1271 String [] pair = list.get(i); 1272 if (pair[0].equalsIgnoreCase(key)) { 1273 String old = pair[1]; 1274 if (key.equalsIgnoreCase("Provider")) { 1275 } else { 1278 pair[1] = value; 1279 } 1280 return old; 1281 } 1282 } 1283 list.add(new String [] {key, value}); 1284 return null; 1285 } 1286 1287 public String toString() { 1288 StringBuilder sb = new StringBuilder (64); 1289 for (int i = 0, n = list.size(); i < n; i++) { 1290 String [] pair = list.get(i); 1291 if (i > 0) { 1292 sb.append("; "); 1293 } 1294 sb.append(pair[0]); 1295 sb.append('='); 1296 1297 if (pair[1] == null) { 1298 sb.append("'null'"); 1299 } else { 1300 1304 if (pair[1].indexOf(';') >= 0 && pair[1].charAt(0) != '\'') { 1305 sb.append("'"); 1306 } 1307 1308 sb.append(pair[1]); 1309 1310 if (pair[1].indexOf(';') >= 0 && pair[1].charAt(pair[1].length() - 1) != '\'') { 1311 sb.append("'"); 1312 } 1313 } 1314 1315 } 1316 return sb.toString(); 1317 } 1318 1319 public Iterator<String []> iterator() { 1320 return list.iterator(); 1321 } 1322 } 1323 1324 1339 public static PropertyList parseConnectString(String s) { 1340 return new ConnectStringParser(s).parse(); 1341 } 1342 1343 private static class ConnectStringParser { 1344 private final String s; 1345 private final int n; 1346 private int i; 1347 private final StringBuilder nameBuf; 1348 private final StringBuilder valueBuf; 1349 1350 private ConnectStringParser(String s) { 1351 this.s = s; 1352 this.i = 0; 1353 this.n = s.length(); 1354 this.nameBuf = new StringBuilder (64); 1355 this.valueBuf = new StringBuilder (64); 1356 } 1357 1358 PropertyList parse() { 1359 PropertyList list = new PropertyList(); 1360 while (i < n) { 1361 parsePair(list); 1362 } 1363 return list; 1364 } 1365 1368 void parsePair(PropertyList list) { 1369 String name = parseName(); 1370 String value; 1371 if (i >= n) { 1372 value = ""; 1373 } else if (s.charAt(i) == ';') { 1374 i++; 1375 value = ""; 1376 } else { 1377 value = parseValue(); 1378 } 1379 list.put(name, value); 1380 } 1381 1385 String parseName() { 1386 nameBuf.setLength(0); 1387 while (true) { 1388 char c = s.charAt(i); 1389 switch (c) { 1390 case '=': 1391 i++; 1392 if (i < n && (c = s.charAt(i)) == '=') { 1393 i++; 1395 nameBuf.append(c); 1396 break; 1397 } 1398 String name = nameBuf.toString(); 1399 name = name.trim(); 1400 return name; 1401 case ' ': 1402 if (nameBuf.length() == 0) { 1403 i++; 1405 break; 1406 } else { 1407 } 1409 default: 1410 nameBuf.append(c); 1411 i++; 1412 if (i >= n) { 1413 return nameBuf.toString().trim(); 1414 } 1415 } 1416 } 1417 } 1418 1421 String parseValue() { 1422 char c; 1423 while ((c = s.charAt(i)) == ' ') { 1425 i++; 1426 if (i >= n) { 1427 return ""; 1428 } 1429 } 1430 if (c == '"' || c == '\'') { 1431 String value = parseQuoted(c); 1432 while (i < n && (c = s.charAt(i)) == ' ') { 1434 i++; 1435 } 1436 if (i >= n) { 1437 return value; 1438 } else if (s.charAt(i) == ';') { 1439 i++; 1440 return value; 1441 } else { 1442 throw new RuntimeException ( 1443 "quoted value ended too soon, at position " + i + 1444 " in '" + s + "'"); 1445 } 1446 } else { 1447 String value; 1448 int semi = s.indexOf(';', i); 1449 if (semi >= 0) { 1450 value = s.substring(i, semi); 1451 i = semi + 1; 1452 } else { 1453 value = s.substring(i); 1454 i = n; 1455 } 1456 return value.trim(); 1457 } 1458 } 1459 1465 String parseQuoted(char q) { 1466 char c = s.charAt(i++); 1467 Util.assertTrue(c == q); 1468 valueBuf.setLength(0); 1469 while (i < n) { 1470 c = s.charAt(i); 1471 if (c == q) { 1472 i++; 1473 if (i < n) { 1474 c = s.charAt(i); 1475 if (c == q) { 1476 valueBuf.append(c); 1477 i++; 1478 continue; 1479 } 1480 } 1481 return valueBuf.toString(); 1482 } else { 1483 valueBuf.append(c); 1484 i++; 1485 } 1486 } 1487 throw new RuntimeException ( 1488 "Connect string '" + s + 1489 "' contains unterminated quoted value '" + 1490 valueBuf.toString() + "'"); 1491 } 1492 } 1493 1494 1497 public static int hash(int i, int j) { 1498 return (i << 4) ^ j; 1499 } 1500 1501 1505 public static int hash(int h, Object o) { 1506 int k = (o == null) ? 0 : o.hashCode(); 1507 return ((h << 4) | h) ^ k; 1508 } 1509 1510 1514 public static int hashArray(int h, Object [] a) { 1515 if (a == null) { 1518 return hash(h, 19690429); 1519 } 1520 if (a.length == 0) { 1521 return hash(h, 19690721); 1522 } 1523 for (Object anA : a) { 1524 h = hash(h, anA); 1525 } 1526 return h; 1527 } 1528 1529 1532 public static long dbTimeMillis() { 1533 return databaseMillis; 1534 } 1535 1536 1539 public static void addDatabaseTime(long millis) { 1540 databaseMillis += millis; 1541 } 1542 1543 1549 public static long nonDbTimeMillis() { 1550 final long systemMillis = System.currentTimeMillis(); 1551 return systemMillis - databaseMillis; 1552 } 1553 1554 1558 public static Validator createSimpleValidator(final FunTable funTable) { 1559 return new Validator() { 1560 public Query getQuery() { 1561 return null; 1562 } 1563 1564 public Exp validate(Exp exp, boolean scalar) { 1565 return exp; 1566 } 1567 1568 public void validate(ParameterExpr parameterExpr) { 1569 } 1570 1571 public void validate(MemberProperty memberProperty) { 1572 } 1573 1574 public void validate(QueryAxis axis) { 1575 } 1576 1577 public void validate(Formula formula) { 1578 } 1579 1580 public boolean canConvert(Exp fromExp, int to, int[] conversionCount) { 1581 return true; 1582 } 1583 1584 public boolean requiresExpression() { 1585 return false; 1586 } 1587 1588 public FunTable getFunTable() { 1589 return funTable; 1590 } 1591 1592 public Parameter createOrLookupParam( 1593 boolean definition, 1594 String name, 1595 Type type, 1596 Exp defaultExp, 1597 String description) { 1598 return null; 1599 } 1600 }; 1601 } 1602 1603 1612 public static String readFully(final Reader rdr, final int bufferSize) 1613 throws IOException { 1614 1615 if (bufferSize <= 0) { 1616 throw new IllegalArgumentException ( 1617 "Buffer size must be greater than 0"); 1618 } 1619 1620 final char[] buffer = new char[bufferSize]; 1621 final StringBuilder buf = new StringBuilder (bufferSize); 1622 1623 int len = rdr.read(buffer); 1624 while (len != -1) { 1625 buf.append(buffer, 0, len); 1626 len = rdr.read(buffer); 1627 } 1628 1629 final String s = buf.toString(); 1630 return (s.length() == 0) ? null : s; 1631 } 1632 1633 1634 1642 public static String readURL(final String urlStr) 1643 throws MalformedURLException , IOException { 1644 return readURL(urlStr, null); 1645 } 1646 1647 1658 public static String readURL(final String urlStr, Map map) 1659 throws MalformedURLException , IOException { 1660 final URL url = new URL (urlStr); 1661 return readURL(url, map); 1662 } 1663 1664 1671 public static String readURL(final URL url) throws IOException { 1672 return readURL(url, null); 1673 } 1674 1675 1685 public static String readURL(final URL url, Map<String , String > map) throws IOException { 1686 final Reader r = 1687 new BufferedReader (new InputStreamReader (url.openStream())); 1688 final int BUF_SIZE = 8096; 1689 try { 1690 String xmlCatalog = readFully(r, BUF_SIZE); 1691 if (map != null) { 1692 xmlCatalog = Util.replaceProperties(xmlCatalog, map); 1693 } 1694 return xmlCatalog; 1695 } finally { 1696 r.close(); 1697 } 1698 } 1699 1700 public static Map<String , String > toMap(final Properties properties) { 1701 return new AbstractMap<String , String >() { 1702 public Set<Entry<String , String >> entrySet() { 1703 return (Set) properties.entrySet(); 1704 } 1705 }; 1706 } 1707 1717 public static String replaceProperties( 1718 String text, 1719 Map<String , String > env) 1720 { 1721 StringBuffer buf = new StringBuffer (text.length() + 200); 1724 1725 Pattern pattern = Pattern.compile("\\$\\{([^${}]+)\\}"); 1726 Matcher matcher = pattern.matcher(text); 1727 while (matcher.find()) { 1728 String varName = matcher.group(1); 1729 String varValue = env.get(varName); 1730 if (varValue != null) { 1731 matcher.appendReplacement(buf, varValue); 1732 } else { 1733 matcher.appendReplacement(buf, "\\${$1}"); 1734 } 1735 } 1736 matcher.appendTail(buf); 1737 1738 return buf.toString(); 1739 } 1740 1741 public static String printMemory() { 1742 return printMemory(null); 1743 } 1744 1745 public static String printMemory(String msg) { 1746 final Runtime rt = Runtime.getRuntime(); 1747 final long freeMemory = rt.freeMemory(); 1748 final long totalMemory = rt.totalMemory(); 1749 final StringBuilder buf = new StringBuilder (64); 1750 1751 buf.append("FREE_MEMORY:"); 1752 if (msg != null) { 1753 buf.append(msg); 1754 buf.append(':'); 1755 } 1756 buf.append(' '); 1757 buf.append(freeMemory / 1024); 1758 buf.append("kb "); 1759 1760 long hundredths = (freeMemory * 10000) / totalMemory; 1761 1762 buf.append(hundredths / 100); 1763 hundredths %= 100; 1764 if (hundredths >= 10) { 1765 buf.append('.'); 1766 } else { 1767 buf.append(".0"); 1768 } 1769 buf.append(hundredths); 1770 buf.append('%'); 1771 1772 return buf.toString(); 1773 } 1774 1775 1783 public static <E extends Enum <E>> boolean isValid(Class <E> clazz, E e) { 1784 E[] enumConstants = clazz.getEnumConstants(); 1785 for (E enumConstant : enumConstants) { 1786 if (e == enumConstant) { 1787 return true; 1788 } 1789 } 1790 return false; 1791 } 1792 1793 1796 public static <E extends Enum <E>> E lookup(Class <E> clazz, String name) { 1797 try { 1798 return Enum.valueOf(clazz, name); 1799 } catch (IllegalArgumentException e) { 1800 return null; 1801 } 1802 } 1803 1804 1814 public static <E extends Enum <E>> Set<E> enumSetOf(E first, E... rest) { 1815 return compatible.enumSetOf(first, rest); 1816 } 1817 1818 1825 public static <E extends Enum <E>> Set<E> enumSetNoneOf(Class <E> elementType) { 1826 return compatible.enumSetNoneOf(elementType); 1827 } 1828 1829 1836 public static <E extends Enum <E>> Set<E> enumSetAllOf(Class <E> elementType) { 1837 return compatible.enumSetAllOf(elementType); 1838 } 1839} 1840 1841 | Popular Tags |