1 13 14 package mondrian.rolap; 15 import mondrian.olap.*; 16 import mondrian.olap.fun.FunUtil; 17 import mondrian.resource.MondrianResource; 18 19 import org.apache.log4j.Logger; 20 import org.eigenbase.util.property.StringProperty; 21 import java.io.*; 22 import java.lang.reflect.Array ; 23 import java.sql.SQLException ; 24 import java.util.ArrayList ; 25 import java.util.HashSet ; 26 import java.util.List ; 27 import java.util.StringTokenizer ; 28 29 import mondrian.calc.ExpCompiler; 30 31 import javax.sql.DataSource ; 32 33 40 public class RolapUtil { 41 42 static final Logger LOGGER = Logger.getLogger(RolapUtil.class); 43 static final RolapMember[] emptyMemberArray = new RolapMember[0]; 44 private static PrintWriter traceOut = null; 45 private static boolean checkedTracing = false; 46 private static boolean traceEnabled; 47 private static Semaphore querySemaphore; 48 49 52 public static final Object valueNotReadyException = new Double (0); 53 54 57 static final ThreadLocal <ExecuteQueryHook> threadHooks = 58 new ThreadLocal <ExecuteQueryHook>(); 59 60 63 public static final Comparable sqlNullValue = new Comparable () { 64 public boolean equals(Object o) { 65 return o == this; 66 } 67 public int hashCode() { 68 return super.hashCode(); 69 } 70 public String toString() { 71 return "#null"; 72 } 73 74 public int compareTo(Object o) { 75 return o == this ? 0 : -1; 76 } 77 }; 78 79 public static final String mdxNullLiteral = "#null"; 80 public static final String sqlNullLiteral = "null"; 81 82 86 private static final HashSet <String > loadedDrivers = new HashSet <String >(); 87 88 static RolapMember[] toArray(List <RolapMember> v) { 89 return v.isEmpty() 90 ? emptyMemberArray 91 : v.toArray(new RolapMember[v.size()]); 92 } 93 94 static RolapMember lookupMember( 95 MemberReader reader, 96 String [] uniqueNameParts, 97 boolean failIfNotFound) { 98 RolapMember member = 99 lookupMemberInternal( 100 uniqueNameParts, null, reader, failIfNotFound); 101 if (member != null) { 102 return member; 103 } 104 105 final List <RolapMember> rootMembers = reader.getRootMembers(); 109 if (rootMembers.size() == 1) { 110 final RolapMember rootMember = rootMembers.get(0); 111 if (rootMember.isAll()) { 112 member = 113 lookupMemberInternal( 114 uniqueNameParts, rootMember, reader, failIfNotFound); 115 } 116 } 117 return member; 118 } 119 120 private static RolapMember lookupMemberInternal( 121 String [] uniqueNameParts, 122 RolapMember member, 123 MemberReader reader, 124 boolean failIfNotFound) 125 { 126 for (String name : uniqueNameParts) { 127 List <RolapMember> children; 128 if (member == null) { 129 children = reader.getRootMembers(); 130 } else { 131 children = new ArrayList <RolapMember>(); 132 reader.getMemberChildren(member, children); 133 member = null; 134 } 135 for (RolapMember child : children) { 136 if (child.getName().equals(name)) { 137 member = child; 138 break; 139 } 140 } 141 if (member == null) { 142 break; 143 } 144 } 145 if (member == null && failIfNotFound) { 146 throw MondrianResource.instance().MdxCantFindMember.ex( 147 Util.implode(uniqueNameParts)); 148 } 149 return member; 150 } 151 152 156 static <T> T[] addElement(T[] a, T o) { 157 Class clazz = a.getClass().getComponentType(); 158 T[] a2 = (T[]) Array.newInstance(clazz, a.length + 1); 159 System.arraycopy(a, 0, a2, 0, a.length); 160 a2[a.length] = o; 161 return a2; 162 } 163 164 168 static <T> T[] addElements(T[] a, T[] b) { 169 Class clazz = a.getClass().getComponentType(); 170 T[] c = (T[]) Array.newInstance(clazz, a.length + b.length); 171 System.arraycopy(a, 0, c, 0, a.length); 172 System.arraycopy(b, 0, c, a.length, b.length); 173 return c; 174 } 175 176 188 public static synchronized PrintWriter checkTracing() { 189 if (!checkedTracing) { 190 int trace = MondrianProperties.instance().TraceLevel.get(); 191 if (trace > 0) { 192 String debugOutFile = 193 MondrianProperties.instance().DebugOutFile.get(); 194 if (debugOutFile != null) { 195 File f; 196 try { 197 f = new File(debugOutFile); 198 setDebugOut(new PrintWriter(new FileOutputStream(f), true)); 199 } catch (Exception e) { 200 setDebugOut(new PrintWriter(System.out, true)); 201 } 202 } else { 203 setDebugOut(new PrintWriter(System.out, true)); 204 } 205 traceEnabled = true; 206 } else { 207 traceEnabled = false; 208 } 209 checkedTracing = true; 210 } 211 return traceEnabled ? traceOut : null; 212 } 213 214 218 static public void setDebugOut(PrintWriter pw) { 219 traceOut = pw; 220 } 221 222 240 public static SqlStatement executeQuery( 241 DataSource dataSource, 242 String sql, 243 String component, 244 String message) 245 { 246 return executeQuery( 247 dataSource, sql, -1, component, message, -1, -1); 248 } 249 250 271 public static SqlStatement executeQuery( 272 DataSource dataSource, 273 String sql, 274 int maxRows, 275 String component, 276 String message, 277 int resultSetType, 278 int resultSetConcurrency) 279 { 280 SqlStatement stmt = 281 new SqlStatement( 282 dataSource, sql, maxRows, component, message, 283 resultSetType, resultSetConcurrency); 284 try { 285 stmt.execute(); 286 return stmt; 287 } catch (SQLException e) { 288 throw stmt.handle(e); 289 } 290 } 291 292 304 public static void alertNonNative( 305 String functionName, String reason) 306 throws NativeEvaluationUnsupportedException { 307 308 String alertMsg = 310 "Unable to use native SQL evaluation for '" + functionName 311 + "'; reason: " + reason; 312 313 StringProperty alertProperty = 314 MondrianProperties.instance().AlertNativeEvaluationUnsupported; 315 String alertValue = alertProperty.get(); 316 317 if (alertValue.equalsIgnoreCase( 318 org.apache.log4j.Level.WARN.toString())) { 319 LOGGER.warn(alertMsg); 320 } else if (alertValue.equalsIgnoreCase( 321 org.apache.log4j.Level.ERROR.toString())) { 322 LOGGER.error(alertMsg); 323 throw MondrianResource.instance().NativeEvaluationUnsupported.ex( 324 functionName); 325 } 326 } 327 328 335 public static synchronized void loadDrivers(String jdbcDrivers) { 336 StringTokenizer tok = new StringTokenizer (jdbcDrivers, ","); 337 while (tok.hasMoreTokens()) { 338 String jdbcDriver = tok.nextToken(); 339 if (loadedDrivers.add(jdbcDriver)) { 340 try { 341 Class.forName(jdbcDriver); 342 LOGGER.info("Mondrian: JDBC driver " 343 + jdbcDriver + " loaded successfully"); 344 } catch (ClassNotFoundException e) { 345 LOGGER.warn("Mondrian: Warning: JDBC driver " 346 + jdbcDriver + " not found"); 347 } 348 } 349 } 350 } 351 352 358 public static ExpCompiler createDependencyTestingCompiler( 359 ExpCompiler compiler) { 360 return new RolapDependencyTestingEvaluator.DteCompiler(compiler); 361 } 362 363 380 public static Member findBestMemberMatch( 381 List <? extends Member> members, 382 RolapMember parent, 383 RolapLevel level, 384 String searchName, 385 MatchType matchType, 386 boolean caseInsensitive) 387 { 388 RolapMember searchMember = new RolapMember(parent, level, searchName); 392 Member bestMatch = null; 393 for (Member member : members) { 394 int rc; 395 if (matchType == MatchType.EXACT) { 396 if (caseInsensitive) { 397 rc = Util.compareName(member.getName(), searchName); 398 } else { 399 rc = member.getName().compareTo(searchName); 400 } 401 } else { 402 rc = 403 FunUtil.compareSiblingMembers( 404 member, 405 searchMember); 406 } 407 if (rc == 0) { 408 return member; 409 } 410 if (matchType == MatchType.BEFORE) { 411 if (rc < 0 && 412 (bestMatch == null || 413 FunUtil.compareSiblingMembers(member, bestMatch) > 0)) { 414 bestMatch = member; 415 } 416 } else if (matchType == MatchType.AFTER) { 417 if (rc > 0 && 418 (bestMatch == null || 419 FunUtil.compareSiblingMembers(member, bestMatch) < 0)) { 420 bestMatch = member; 421 } 422 } 423 } 424 if (matchType == MatchType.EXACT) { 425 return null; 426 } 427 return bestMatch; 428 } 429 430 433 public static class TeeWriter extends FilterWriter { 434 StringWriter buf = new StringWriter(); 435 public TeeWriter(Writer out) { 436 super(out); 437 } 438 439 442 public String toString() { 443 return buf.toString(); 444 } 445 446 449 public Writer getWriter() { 450 return out; 451 } 452 453 public void write(int c) throws IOException { 454 super.write(c); 455 buf.write(c); 456 } 457 458 public void write(char cbuf[]) throws IOException { 459 super.write(cbuf); 460 buf.write(cbuf); 461 } 462 463 public void write(char cbuf[], int off, int len) throws IOException { 464 super.write(cbuf, off, len); 465 buf.write(cbuf, off, len); 466 } 467 468 public void write(String str) throws IOException { 469 super.write(str); 470 buf.write(str); 471 } 472 473 public void write(String str, int off, int len) throws IOException { 474 super.write(str, off, len); 475 buf.write(str, off, len); 476 } 477 } 478 479 482 private static class NullWriter extends Writer { 483 public void write(char cbuf[], int off, int len) throws IOException { 484 } 485 486 public void flush() throws IOException { 487 } 488 489 public void close() throws IOException { 490 } 491 } 492 493 497 public static synchronized TeeWriter startTracing() { 498 TeeWriter tw; 499 if (traceOut == null) { 500 tw = new TeeWriter(new NullWriter()); 501 } else { 502 tw = new TeeWriter(RolapUtil.traceOut); 503 } 504 traceOut = new PrintWriter(tw); 505 return tw; 506 } 507 508 512 static synchronized Semaphore getQuerySemaphore() { 513 if (querySemaphore == null) { 514 int queryCount = MondrianProperties.instance().QueryLimit.get(); 515 querySemaphore = new Semaphore(queryCount); 516 } 517 return querySemaphore; 518 } 519 520 523 public static Evaluator createEvaluator(Query query) { 524 final RolapResult result = new RolapResult(query, false); 525 return result.getRootEvaluator(); 526 } 527 528 536 static class Semaphore { 537 private int count; 538 Semaphore(int count) { 539 if (count < 0) { 540 count = Integer.MAX_VALUE; 541 } 542 this.count = count; 543 } 544 synchronized void enter() { 545 if (count == Integer.MAX_VALUE) { 546 return; 547 } 548 if (count == 0) { 549 try { 550 wait(); 551 } catch (InterruptedException e) { 552 throw Util.newInternal(e, "while waiting for semaphore"); 553 } 554 } 555 Util.assertTrue(count > 0); 556 count--; 557 } 558 synchronized void leave() { 559 if (count == Integer.MAX_VALUE) { 560 return; 561 } 562 count++; 563 notify(); 564 } 565 } 566 567 static interface ExecuteQueryHook { 568 void onExecuteQuery(String sql); 569 } 570 571 } 572 573 | Popular Tags |