1 13 package mondrian.olap; 14 15 import org.apache.log4j.Logger; 16 import org.eigenbase.util.property.*; 17 import org.eigenbase.util.property.Property; 18 19 import java.io.*; 20 import java.net.MalformedURLException ; 21 import java.net.URL ; 22 import java.net.URLConnection ; 23 import java.util.Enumeration ; 24 import java.util.Properties ; 25 import java.util.List ; 26 import java.util.ArrayList ; 27 import java.lang.reflect.Field ; 28 import java.lang.reflect.Modifier ; 29 30 60 public class MondrianProperties extends TriggerableProperties { 61 62 private final FilePropertySource mondrianDotPropertiesSource = 63 new FilePropertySource(new File(mondrianDotProperties)); 64 private int populateCount; 65 66 private static final Logger LOGGER = 67 Logger.getLogger(MondrianProperties.class); 68 69 73 private static MondrianProperties instance; 74 private static final String mondrianDotProperties = "mondrian.properties"; 75 76 81 public static synchronized MondrianProperties instance() { 82 if (instance == null) { 83 instance = new MondrianProperties(); 84 instance.populate(); 85 } 86 return instance; 87 } 88 89 public MondrianProperties() { 90 } 91 92 public boolean triggersAreEnabled() { 93 return EnableTriggers.get(); 94 } 95 96 100 public interface PropertySource { 101 109 InputStream openStream(); 110 111 117 boolean isStale(); 118 119 123 String getDescription(); 124 } 125 126 130 static class FilePropertySource implements PropertySource { 131 private final File file; 132 private long lastModified; 133 134 FilePropertySource(File file) { 135 this.file = file; 136 this.lastModified = 0; 137 } 138 139 public InputStream openStream() { 140 try { 141 this.lastModified = file.lastModified(); 142 return new FileInputStream(file); 143 } catch (FileNotFoundException e) { 144 throw Util.newInternal( 145 e, 146 "Error while opening properties file '" + file + "'"); 147 } 148 } 149 150 public boolean isStale() { 151 return file.exists() && 152 file.lastModified() > this.lastModified; 153 } 154 155 public String getDescription() { 156 return "file=" + file.getAbsolutePath() + 157 " (exists=" + file.exists() + ")"; 158 } 159 } 160 161 164 static class UrlPropertySource implements PropertySource { 165 private final URL url; 166 private long lastModified; 167 168 UrlPropertySource(URL url) { 169 this.url = url; 170 } 171 172 private URLConnection getConnection() { 173 try { 174 return url.openConnection(); 175 } catch (IOException e) { 176 throw Util.newInternal( 177 e, 178 "Error while opening properties file '" + url + "'"); 179 } 180 } 181 182 public InputStream openStream() { 183 try { 184 final URLConnection connection = getConnection(); 185 this.lastModified = connection.getLastModified(); 186 return connection.getInputStream(); 187 } catch (IOException e) { 188 throw Util.newInternal( 189 e, 190 "Error while opening properties file '" + url + "'"); 191 } 192 } 193 194 public boolean isStale() { 195 final long lastModified = getConnection().getLastModified(); 196 return lastModified > this.lastModified; 197 } 198 199 public String getDescription() { 200 return url.toExternalForm(); 201 } 202 } 203 204 209 public void populate() { 210 loadIfStale(mondrianDotPropertiesSource); 213 214 URL url = null; 215 File file = new File(mondrianDotProperties); 216 if (file.exists() && file.isFile()) { 217 try { 220 url = file.toURI().toURL(); 221 } catch (MalformedURLException e) { 222 LOGGER.warn("Mondrian: file '" 223 + file.getAbsolutePath() 224 + "' could not be loaded" , e); 225 } 226 } else { 227 url = 229 MondrianProperties.class.getClassLoader().getResource( 230 mondrianDotProperties); 231 } 232 233 if (url != null) { 234 load(new UrlPropertySource(url)); 235 } else { 236 LOGGER.warn("mondrian.properties can't be found under '" 237 + new File(".").getAbsolutePath() + "' or classloader"); 238 } 239 240 int count = 0; 242 for (Enumeration keys = System.getProperties().keys(); 243 keys.hasMoreElements(); ) { 244 String key = (String ) keys.nextElement(); 245 String value = System.getProperty(key); 246 if (key.startsWith("mondrian.")) { 247 if (LOGGER.isDebugEnabled()) { 250 LOGGER.debug("populate: key=" + key + ", value=" + value); 251 } 252 super.setProperty(key, value); 253 count++; 254 } 255 } 256 if (populateCount++ == 0) { 257 LOGGER.info("Mondrian: loaded " 258 + count 259 + " system properties"); 260 } 261 } 262 263 270 private void loadIfStale(PropertySource source) { 271 if (source.isStale()) { 272 if (LOGGER.isDebugEnabled()) { 273 LOGGER.debug("Mondrian: loading " + source.getDescription()); 274 } 275 load(source); 276 } 277 } 278 279 285 private void load(final PropertySource source) { 286 try { 287 load(source.openStream()); 288 if (populateCount == 0) { 289 LOGGER.info("Mondrian: properties loaded from '" 290 + source.getDescription() 291 + "'"); 292 } 293 } catch (IOException e) { 294 LOGGER.error("Mondrian: error while loading properties " 295 + "from '" 296 + source.getDescription() 297 + "' (" 298 + e 299 + ")"); 300 } 301 } 302 303 311 public List <Property> getPropertyList() { 312 Field [] fields = getClass().getFields(); 313 List <Property> list = new ArrayList <Property>(); 314 for (Field field : fields) { 315 if (!Modifier.isStatic(field.getModifiers()) && 316 Property.class.isAssignableFrom( 317 field.getType())) { 318 try { 319 list.add((Property) field.get(this)); 320 } catch (IllegalAccessException e) { 321 throw Util.newInternal( 322 e, 323 "While accessing property '" + field.getName() + "'"); 324 } 325 } 326 } 327 return list; 328 } 329 330 340 public Property getPropertyDefinition(String path) { 341 final List <Property> propertyList = getPropertyList(); 342 for (Property property : propertyList) { 343 if (property.getPath().equals(path)) { 344 return property; 345 } 346 } 347 return null; 348 } 349 350 357 public final IntegerProperty QueryLimit = new IntegerProperty( 358 this, "mondrian.query.limit", 40); 359 360 367 public final IntegerProperty TraceLevel = new IntegerProperty( 368 this, "mondrian.trace.level"); 369 370 374 public final StringProperty DebugOutFile = new StringProperty( 375 this, "mondrian.debug.out.file", null); 376 377 382 public final StringProperty JdbcDrivers = new StringProperty( 383 this, 384 "mondrian.jdbcDrivers", 385 "sun.jdbc.odbc.JdbcOdbcDriver," + 386 "org.hsqldb.jdbcDriver," + 387 "oracle.jdbc.OracleDriver," + 388 "com.mysql.jdbc.Driver"); 389 390 394 public final IntegerProperty ResultLimit = new IntegerProperty( 395 this, "mondrian.result.limit", 0); 396 397 398 public final IntegerProperty CachePoolCostLimit = new IntegerProperty( 399 this, "mondrian.rolap.CachePool.costLimit", 10000); 400 401 402 public final BooleanProperty PrintCacheablesAfterQuery = 403 new BooleanProperty( 404 this, "mondrian.rolap.RolapResult.printCacheables"); 405 406 407 public final BooleanProperty FlushAfterQuery = new BooleanProperty( 408 this, "mondrian.rolap.RolapResult.flushAfterEachQuery"); 409 410 412 421 public final StringProperty TestName = new StringProperty( 422 this, "mondrian.test.Name", null); 423 424 436 public final StringProperty TestClass = new StringProperty( 437 this, "mondrian.test.Class", null); 438 439 444 public final StringProperty TestConnectString = new StringProperty( 445 this, "mondrian.test.connectString", null); 446 447 448 450 455 public final StringProperty FoodmartJdbcURL = new StringProperty( 456 this, "mondrian.foodmart.jdbcURL", "jdbc:odbc:MondrianFoodMart"); 457 458 462 public final StringProperty TestJdbcURL = new StringProperty( 463 this, "mondrian.test.jdbcURL", null); 464 465 469 public final StringProperty TestJdbcUser = new StringProperty( 470 this, "mondrian.test.jdbcUser", null); 471 472 476 public final StringProperty TestJdbcPassword = new StringProperty( 477 this, "mondrian.test.jdbcPassword", null); 478 479 484 public final IntegerProperty LargeDimensionThreshold = new IntegerProperty( 485 this, "mondrian.rolap.LargeDimensionThreshold", 100); 486 487 514 public final IntegerProperty SparseSegmentCountThreshold = 515 new IntegerProperty( 516 this, "mondrian.rolap.SparseSegmentValueThreshold", 1000); 517 518 523 public final DoubleProperty SparseSegmentDensityThreshold = 524 new DoubleProperty( 525 this, "mondrian.rolap.SparseSegmentDensityThreshold", 0.5); 526 527 537 public final StringProperty QueryFilePattern = new StringProperty( 538 this, "mondrian.test.QueryFilePattern", null); 539 540 544 public final StringProperty QueryFileDirectory = new StringProperty( 545 this, "mondrian.test.QueryFileDirectory", null); 546 547 550 public final IntegerProperty Iterations = new IntegerProperty( 551 this, "mondrian.test.Iterations", 1); 552 553 556 public final IntegerProperty VUsers = new IntegerProperty( 557 this, "mondrian.test.VUsers", 1); 558 559 563 public final IntegerProperty TimeLimit = new IntegerProperty( 564 this, "mondrian.test.TimeLimit", 0); 565 566 569 public final BooleanProperty Warmup = new BooleanProperty( 570 this, "mondrian.test.Warmup", false); 571 572 576 public final StringProperty CatalogURL = new StringProperty( 577 this, "mondrian.catalogURL", null); 578 579 584 595 public final BooleanProperty UseAggregates = new BooleanProperty( 596 this, "mondrian.rolap.aggregates.Use", false); 597 598 606 public final BooleanProperty ReadAggregates = new BooleanProperty( 607 this, "mondrian.rolap.aggregates.Read", false); 608 609 610 618 public final BooleanProperty ChooseAggregateByVolume = new BooleanProperty( 619 this, "mondrian.rolap.aggregates.ChooseByVolume", false); 620 621 631 public final StringProperty AggregateRules = new StringProperty( 632 this, "mondrian.rolap.aggregates.rules", "/DefaultRules.xml"); 633 634 639 public final StringProperty AggregateRuleTag = new StringProperty( 640 this, "mondrian.rolap.aggregates.rule.tag", "default"); 641 642 651 public final BooleanProperty GenerateAggregateSql = new BooleanProperty( 652 this, "mondrian.rolap.aggregates.generateSql", false); 653 654 657 663 public final BooleanProperty DisableCaching = new BooleanProperty( 664 this, "mondrian.rolap.star.disableCaching", false); 665 666 676 public final BooleanProperty EnableTriggers = new BooleanProperty( 677 this, "mondrian.olap.triggers.enable", true); 678 679 684 public final BooleanProperty GenerateFormattedSql = new BooleanProperty( 685 this, "mondrian.rolap.generate.formatted.sql", false); 686 687 691 public final BooleanProperty EnableNonEmptyOnAllAxis = new BooleanProperty( 692 this, "mondrian.rolap.nonempty", false); 693 694 699 public final BooleanProperty CompareSiblingsByOrderKey = 700 new BooleanProperty( 701 this, "mondrian.rolap.compareSiblingsByOrderKey", 702 false); 703 704 711 public final BooleanProperty EnableExpCache = new BooleanProperty( 712 this, "mondrian.expCache.enable", true); 713 714 715 726 public final IntegerProperty TestExpDependencies = new IntegerProperty( 727 this, "mondrian.test.ExpDependencies", 0); 728 729 745 public final IntegerProperty TestSeed = new IntegerProperty( 746 this, "mondrian.test.random.seed", 1234); 747 748 758 public final StringProperty LocalePropFile = new StringProperty( 759 this, "mondrian.rolap.localePropFile", null); 760 761 764 public final BooleanProperty EnableNativeCrossJoin = new BooleanProperty( 765 this, "mondrian.native.crossjoin.enable", true); 766 767 770 public final BooleanProperty EnableNativeTopCount = new BooleanProperty( 771 this, "mondrian.native.topcount.enable", true); 772 773 776 public final BooleanProperty EnableNativeFilter = new BooleanProperty( 777 this, "mondrian.native.filter.enable", true); 778 779 783 public final BooleanProperty EnableNativeNonEmpty = new BooleanProperty( 784 this, "mondrian.native.nonempty.enable", true); 785 786 808 public final StringProperty AlertNativeEvaluationUnsupported = 809 new StringProperty(this, "mondrian.native.unsupported.alert", "OFF"); 810 811 815 public final BooleanProperty EnableTotalCount = new BooleanProperty( 816 this, "mondrian.xmla.drillthroughTotalCount.enable", true); 817 818 823 public final BooleanProperty CaseSensitive = new BooleanProperty( 824 this, "mondrian.olap.case.sensitive", false); 825 826 827 831 public final IntegerProperty MaxRows = new IntegerProperty( 832 this, "mondrian.xmla.drillthroughMaxRows", 1000); 833 834 846 public final IntegerProperty MaxConstraints = new IntegerProperty( 847 this, "mondrian.rolap.maxConstraints", 1000); 848 849 855 public final IntegerProperty MaxEvalDepth = new IntegerProperty( 856 this, "mondrian.rolap.evaluate.MaxEvalDepth", 10); 857 858 859 public final StringProperty JdbcFactoryClass = new StringProperty( 860 this, "mondrian.rolap.aggregates.jdbcFactoryClass", null); 861 862 865 public final IntegerProperty QueryTimeout = new IntegerProperty( 866 this, "mondrian.rolap.queryTimeout", 0); 867 868 869 873 public final BooleanProperty IgnoreInvalidMembers = new BooleanProperty( 874 this, "mondrian.rolap.ignoreInvalidMembers", false); 875 876 879 public final IntegerProperty IterationLimit = new IntegerProperty( 880 this, "mondrian.rolap.iterationLimit", 0); 881 882 886 public final BooleanProperty MemoryMonitor = new BooleanProperty( 887 this, "mondrian.util.memoryMonitor.enable", false); 888 889 892 public final IntegerProperty MemoryMonitorThreshold = new IntegerProperty( 893 this, "mondrian.util.memoryMonitor.percentage.threshold", 90); 894 895 900 public final StringProperty MemoryMonitorClass = new StringProperty( 901 this, "mondrian.util.MemoryMonitor.class", null); 902 903 908 public final StringProperty ExpCompilerClass = new StringProperty( 909 this, "mondrian.calc.ExpCompiler.class", null); 910 911 921 public final IntegerProperty CrossJoinOptimizerSize = new IntegerProperty( 922 this, "mondrian.olap.fun.crossjoin.optimizer.size", 0); 923 924 } 925 926 | Popular Tags |