KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > mondrian > olap > MondrianProperties


1 /*
2 // $Id: //open/mondrian/src/main/mondrian/olap/MondrianProperties.java#71 $
3 // This software is subject to the terms of the Common Public License
4 // Agreement, available at the following URL:
5 // http://www.opensource.org/licenses/cpl.html.
6 // Copyright (C) 2001-2002 Kana Software, Inc.
7 // Copyright (C) 2001-2007 Julian Hyde and others
8 // All Rights Reserved.
9 // You must accept the terms of that agreement to use this software.
10 //
11 // jhyde, 22 December, 2002
12 */

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 JavaDoc;
21 import java.net.URL JavaDoc;
22 import java.net.URLConnection JavaDoc;
23 import java.util.Enumeration JavaDoc;
24 import java.util.Properties JavaDoc;
25 import java.util.List JavaDoc;
26 import java.util.ArrayList JavaDoc;
27 import java.lang.reflect.Field JavaDoc;
28 import java.lang.reflect.Modifier JavaDoc;
29
30 /**
31  * <code>MondrianProperties</code> contains the properties which determine the
32  * behavior of a mondrian instance.
33  *
34  * <p>There is a method for property valid in a
35  * <code>mondrian.properties</code> file. Although it is possible to retrieve
36  * properties using the inherited {@link Properties#getProperty(String)}
37  * method, we recommend that you use methods in this class.
38  *
39  * <h2>Note to developers</h2>
40  *
41  * If you add a property, you must:<ul>
42  *
43  * <li>Add a property definition to this class</li>
44  *
45  * <li>Modify the default <code>mondrian.properties</code> file checked into
46  * source control, with a description of the property and its default
47  * value.</li>
48  *
49  * <li>Modify the
50  * <a target="_top" HREF="{@docRoot}/../configuration.html#Property_list">
51  * Configuration Specification</a>.</li>
52  * </ul>
53  *
54  * <p>Similarly if you update or delete a property.
55  *
56  * @author jhyde
57  * @since 22 December, 2002
58  * @version $Id: //open/mondrian/src/main/mondrian/olap/MondrianProperties.java#71 $
59  */

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     /**
70      * Properties, drawn from {@link System#getProperties}, plus the contents
71      * of "mondrian.properties" if it exists. A singleton.
72      */

73     private static MondrianProperties instance;
74     private static final String JavaDoc mondrianDotProperties = "mondrian.properties";
75
76     /**
77      * Returns the singleton.
78      *
79      * @return Singleton instance
80      */

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     /**
97      * Represents a place that properties can be read from, and remembers the
98      * timestamp that we last read them.
99      */

100     public interface PropertySource {
101         /**
102          * Opens an input stream from the source.
103          *
104          * <p>Also checks the 'last modified' time, which will determine whether
105          * {@link #isStale()} returns true.
106          *
107          * @return input stream
108          */

109         InputStream openStream();
110
111         /**
112          * Returns true if the source exists and has been modified since last
113          * time we called {@link #openStream()}.
114          *
115          * @return whether source has changed since it was last read
116          */

117         boolean isStale();
118
119         /**
120          * Returns the description of this source, such as a filename or URL.
121          * @return description of this PropertySource
122          */

123         String JavaDoc getDescription();
124     }
125
126     /**
127      * Implementation of {@link PropertySource} which reads from a
128      * {@link File}.
129      */

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 JavaDoc getDescription() {
156             return "file=" + file.getAbsolutePath() +
157                 " (exists=" + file.exists() + ")";
158         }
159     }
160
161     /**
162      * Implementation of {@link PropertySource} which reads from a {@link URL}.
163      */

164     static class UrlPropertySource implements PropertySource {
165         private final URL JavaDoc url;
166         private long lastModified;
167
168         UrlPropertySource(URL JavaDoc url) {
169             this.url = url;
170         }
171
172         private URLConnection JavaDoc 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 JavaDoc 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 JavaDoc getDescription() {
200             return url.toExternalForm();
201         }
202     }
203
204     /**
205      * Loads this property set from: the file "$PWD/mondrian.properties" (if it
206      * exists); the "mondrian.properties" in the CLASSPATH; and from the system
207      * properties.
208      */

209     public void populate() {
210         // Read properties file "mondrian.properties", if it exists. If we have
211
// read the file before, only read it if it is newer.
212
loadIfStale(mondrianDotPropertiesSource);
213
214         URL JavaDoc url = null;
215         File file = new File(mondrianDotProperties);
216         if (file.exists() && file.isFile()) {
217             // Read properties file "mondrian.properties" from PWD, if it
218
// exists.
219
try {
220                 url = file.toURI().toURL();
221             } catch (MalformedURLException JavaDoc e) {
222                 LOGGER.warn("Mondrian: file '"
223                     + file.getAbsolutePath()
224                     + "' could not be loaded" , e);
225             }
226         } else {
227             // Then try load it from classloader
228
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         // copy in all system properties which start with "mondrian."
241
int count = 0;
242         for (Enumeration JavaDoc keys = System.getProperties().keys();
243              keys.hasMoreElements(); ) {
244             String JavaDoc key = (String JavaDoc) keys.nextElement();
245             String JavaDoc value = System.getProperty(key);
246             if (key.startsWith("mondrian.")) {
247                 // NOTE: the super allows us to bybase calling triggers
248
// Is this the correct behavior?
249
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     /**
264      * Reads properties from a source.
265      * If the source does not exist, or has not changed since we last read it,
266      * does nothing.
267      *
268      * @param source Source of properties
269      */

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     /**
280      * Tries to load properties from a URL. Does not fail, just prints success
281      * or failure to log.
282      *
283      * @param source Source to read properties from
284      */

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     /**
304      * Returns a list of every {@link org.eigenbase.util.property.Property}.
305      *
306      * <p>todo: Move to base class, {@link TriggerableProperties}, and rename
307      * base method {@link TriggerableProperties#getProperties()}}.
308      *
309      * @return List of properties
310      */

311     public List JavaDoc<Property> getPropertyList() {
312         Field JavaDoc[] fields = getClass().getFields();
313         List JavaDoc<Property> list = new ArrayList JavaDoc<Property>();
314         for (Field JavaDoc 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 JavaDoc e) {
321                     throw Util.newInternal(
322                         e,
323                         "While accessing property '" + field.getName() + "'");
324                 }
325             }
326         }
327         return list;
328     }
329
330     /**
331      * Returns the definition of a named property, or null if there is no
332      * such property.
333      *
334      * <p>todo: Move to base class, {@link TriggerableProperties}.
335      *
336      * @param path Name of the property
337      * @return Definition of property, or null if there is no property with this
338      * name
339      */

340     public Property getPropertyDefinition(String JavaDoc path) {
341         final List JavaDoc<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     /**
351      * Maximum number of simultaneous queries the system will allow.
352      *
353      * <p>Oracle fails if you try to run more than the 'processes' parameter in
354      * init.ora, typically 150. The throughput of Oracle and other databases
355      * will probably reduce long before you get to their limit.</p>
356      */

357     public final IntegerProperty QueryLimit = new IntegerProperty(
358             this, "mondrian.query.limit", 40);
359
360     /**
361      * Property which controls the amount of tracing displayed.
362      *
363      * <p>If trace level is above 0, SQL tracing will be enabled and logged as
364      * per the <code>{@link #DebugOutFile mondrian.debug.out.file}</code>
365      * property below. This is separate from Log4j logging.
366      */

367     public final IntegerProperty TraceLevel = new IntegerProperty(
368             this, "mondrian.trace.level");
369
370     /**
371      * Property containing the name of the file to which tracing is to be
372      * written. If empty (the default), prints to stdout.
373      */

374     public final StringProperty DebugOutFile = new StringProperty(
375             this, "mondrian.debug.out.file", null);
376
377     /**
378      * Property containing a list of JDBC drivers to load automatically.
379      * Must be a comma-separated list of class names, and the classes must be
380      * on the class path.
381      */

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     /**
391      * Property which, if set to a value greater than zero, limits the maximum
392      * size of a result set.
393      */

394     public final IntegerProperty ResultLimit = new IntegerProperty(
395             this, "mondrian.result.limit", 0);
396
397     /** @deprecated obsolete */
398     public final IntegerProperty CachePoolCostLimit = new IntegerProperty(
399             this, "mondrian.rolap.CachePool.costLimit", 10000);
400
401     /** @deprecated obsolete */
402     public final BooleanProperty PrintCacheablesAfterQuery =
403             new BooleanProperty(
404                     this, "mondrian.rolap.RolapResult.printCacheables");
405
406     /** @deprecated obsolete */
407     public final BooleanProperty FlushAfterQuery = new BooleanProperty(
408             this, "mondrian.rolap.RolapResult.flushAfterEachQuery");
409
410     // mondrian.test properties
411

412     /**
413      * Property which determines which tests are run.
414      * This is a regular expression as defined by
415      * {@link java.util.regex.Pattern}.
416      * If this property is specified, only tests whose names match the pattern
417      * in its entirety will be run.
418      *
419      * @see #TestClass
420      */

421     public final StringProperty TestName = new StringProperty(
422             this, "mondrian.test.Name", null);
423
424     /**
425      * Property which determines which test class to run.
426      * This is the name of the class which either implements
427      * <code>junit.framework.Test</code> or has a method
428      * <code>public [static] junit.framework.Test suite()</code>.
429      *
430      * <p>Example:
431      * <blockquote><code>mondrian.test.Class=mondrian.test.FoodMartTestCase</code></blockquote>
432      * </p>
433      *
434      * @see #TestName
435      */

436     public final StringProperty TestClass = new StringProperty(
437             this, "mondrian.test.Class", null);
438
439     /**
440      * Property containing the connect string which regresssion tests should
441      * use to connect to the database.
442      * Format is specified in {@link Util#parseConnectString(String)}.
443      */

444     public final StringProperty TestConnectString = new StringProperty(
445             this, "mondrian.test.connectString", null);
446
447
448     // miscellaneous
449

450     /**
451      * Property containing the JDBC URL of the FoodMart database.
452      * The default value is to connect to an ODBC data source called
453      * "MondrianFoodMart".
454      */

455     public final StringProperty FoodmartJdbcURL = new StringProperty(
456             this, "mondrian.foodmart.jdbcURL", "jdbc:odbc:MondrianFoodMart");
457
458     /**
459      * Property containing the JDBC URL of a test database.
460      * It does not default.
461      */

462     public final StringProperty TestJdbcURL = new StringProperty(
463             this, "mondrian.test.jdbcURL", null);
464
465     /**
466      * Property containing the JDBC user of a test database.
467      * The default value is null, to cope with DBMSs that don't need this.
468      */

469     public final StringProperty TestJdbcUser = new StringProperty(
470             this, "mondrian.test.jdbcUser", null);
471
472     /**
473      * Property containing the JDBC password of a test database.
474      * The default value is null, to cope with DBMSs that don't need this.
475      */

476     public final StringProperty TestJdbcPassword = new StringProperty(
477             this, "mondrian.test.jdbcPassword", null);
478
479     /**
480      * Property which determines when a dimension is considered "large".
481      * If a dimension has more than this number of members, Mondrian uses a
482      * {@link mondrian.rolap.SmartMemberReader smart member reader}.
483      */

484     public final IntegerProperty LargeDimensionThreshold = new IntegerProperty(
485             this, "mondrian.rolap.LargeDimensionThreshold", 100);
486
487     /**
488      * Property which, with {@link #SparseSegmentDensityThreshold}, determines
489      * whether to choose a sparse or dense representation when storing
490      * collections of cell values in memory.
491      *
492      * <p>When storing collections of cell values, Mondrian has to choose
493      * between a sparse and a dense representation, based upon the
494      * <code>possible</code> and <code>actual</code> number of values.
495      * The <code>density</code> is <code>actual / possible</code>.
496      *
497      * <p>We use a sparse representation if
498      * <code>(possible -
499      * {@link #SparseSegmentCountThreshold countThreshold}) *
500      * {@link #SparseSegmentDensityThreshold densityThreshold} &gt;
501      * actual</code>
502      *
503      * <p>For example, at the default values
504      * ({@link #SparseSegmentCountThreshold countThreshold} = 1000,
505      * {@link #SparseSegmentDensityThreshold} = 0.5),
506      * we use a dense representation for<ul>
507      * <li>(1000 possible, 0 actual), or
508      * <li>(2000 possible, 500 actual), or
509      * <li>(3000 possible, 1000 actual).
510      * </ul>
511      * Any fewer actual values, or any more
512      * possible values, and Mondrian will use a sparse representation.
513      */

514     public final IntegerProperty SparseSegmentCountThreshold =
515             new IntegerProperty(
516                     this, "mondrian.rolap.SparseSegmentValueThreshold", 1000);
517
518     /**
519      * Property which, with {@link #SparseSegmentCountThreshold},
520      * determines whether to choose a sparse or dense representation when
521      * storing collections of cell values in memory.
522      */

523     public final DoubleProperty SparseSegmentDensityThreshold =
524             new DoubleProperty(
525                     this, "mondrian.rolap.SparseSegmentDensityThreshold", 0.5);
526
527     /**
528      * Property which defines
529      * a pattern for which test XML files to run. Pattern has to
530      * match a file name of the form:
531      * <code>query<i>whatever</i>.xml</code> in the directory.
532      *
533      * <p>Example:
534      * <blockquote><code>mondrian.test.QueryFilePattern=queryTest_fec[A-Za-z0-9_]*.xml</code></blockquote>
535      * </p>
536      */

537     public final StringProperty QueryFilePattern = new StringProperty(
538             this, "mondrian.test.QueryFilePattern", null);
539
540     /**
541      * Property defining
542      * where the test XML files are.
543      */

544     public final StringProperty QueryFileDirectory = new StringProperty(
545             this, "mondrian.test.QueryFileDirectory", null);
546
547     /**
548      * todo:
549      */

550     public final IntegerProperty Iterations = new IntegerProperty(
551             this, "mondrian.test.Iterations", 1);
552
553     /**
554      * todo:
555      */

556     public final IntegerProperty VUsers = new IntegerProperty(
557             this, "mondrian.test.VUsers", 1);
558
559     /**
560      * Property which returns the time limit for the test run in seconds.
561      * If the test is running after that time, it is terminated.
562      */

563     public final IntegerProperty TimeLimit = new IntegerProperty(
564             this, "mondrian.test.TimeLimit", 0);
565
566     /**
567      * Property which indicates whether this is a "warmup test".
568      */

569     public final BooleanProperty Warmup = new BooleanProperty(
570             this, "mondrian.test.Warmup", false);
571
572     /**
573      * Property which contains the URL of the catalog to be used by
574      * {@link mondrian.tui.CmdRunner} and XML/A Test.
575      */

576     public final StringProperty CatalogURL = new StringProperty(
577             this, "mondrian.catalogURL", null);
578
579     //////////////////////////////////////////////////////////////////////////
580
//
581
// properties relating to aggregates
582
//
583

584     /**
585      * Boolean property that controls whether Mondrian uses aggregate tables.
586      *
587      * <p>If true, then Mondrian uses aggregate tables. This property is
588      * queried prior to each aggregate query so that changing the value of this
589      * property dynamically (not just at startup) is meaningful.
590      *
591      * <p>Aggregates can be read from the database using the
592      * {@link #ReadAggregates} property but will not be used unless this
593      * property is set to true.
594      */

595     public final BooleanProperty UseAggregates = new BooleanProperty(
596             this, "mondrian.rolap.aggregates.Use", false);
597
598     /**
599      * Boolean property which determines whether Mondrian should read aggregate
600      * tables.
601      *
602      * <p>If set to true, then Mondrian scans the database for aggregate tables.
603      * Unless mondrian.rolap.aggregates.Use is set to true, the aggregates
604      * found will not be used.
605      */

606     public final BooleanProperty ReadAggregates = new BooleanProperty(
607             this, "mondrian.rolap.aggregates.Read", false);
608
609
610     /**
611      * Boolean property that controls whether aggregate tables
612      * are ordered by their volume or row count.
613      *
614      * <p>If true, Mondrian uses the aggregate table with the smallest volume
615      * (number of rows multiplied by number of columns); if false, Mondrian
616      * uses the aggregate table with the fewest rows.
617      */

618     public final BooleanProperty ChooseAggregateByVolume = new BooleanProperty(
619             this, "mondrian.rolap.aggregates.ChooseByVolume", false);
620
621     /**
622      * String property containing the name of the file which defines the rules
623      * for recognizing an aggregate table. Can be either a resource in the
624      * Mondrian jar or a URL.
625      *
626      * <p>The default value is "/DefaultRules.xml", which is in the
627      * mondrian.rolap.aggmatcher package in Mondrian.jar.
628      *
629      * <p>Normally, this property is not set by a user.
630      */

631     public final StringProperty AggregateRules = new StringProperty(
632             this, "mondrian.rolap.aggregates.rules", "/DefaultRules.xml");
633
634     /**
635      * String property which is the AggRule element's tag value.
636      *
637      * <p>Normally, this property is not set by a user.
638      */

639     public final StringProperty AggregateRuleTag = new StringProperty(
640             this, "mondrian.rolap.aggregates.rule.tag", "default");
641
642     /**
643      * Boolean property which controls whether to print the SQL code
644      * generated for aggregate tables.
645      *
646      * <p>If set, then as each aggregate request is processed, both the lost
647      * and collapsed dimension create and insert sql code is printed.
648      * This is for use in the CmdRunner allowing one to create aggregate table
649      * generation sql.
650      */

651     public final BooleanProperty GenerateAggregateSql = new BooleanProperty(
652             this, "mondrian.rolap.aggregates.generateSql", false);
653
654     //
655
//////////////////////////////////////////////////////////////////////////
656

657     /**
658      * Boolean property that controls whether a RolapStar's
659      * aggregate data cache is cleared after each query.
660      * If true, no RolapStar will cache aggregate data from one
661      * query to the next (the cache is cleared after each query).
662      */

663     public final BooleanProperty DisableCaching = new BooleanProperty(
664             this, "mondrian.rolap.star.disableCaching", false);
665
666     /**
667      * Boolean property that controls whether to notify the Mondrian system
668      * when a {@link MondrianProperties property value} changes.
669      *
670      * <p>This allows objects dependent on Mondrian properties to react (that
671      * is, reload), when a given property changes via, say,
672      * <code>MondrianProperties.instance().populate(null)</code> or
673      * <code>MondrianProperties.instance().QueryLimit.set(50)</code>.
674
675      */

676     public final BooleanProperty EnableTriggers = new BooleanProperty(
677             this, "mondrian.olap.triggers.enable", true);
678
679     /**
680      * Boolean property which controls pretty-print mode.
681      * If set to true, the all SqlQuery SQL strings
682      * will be generated in pretty-print mode, formatted for ease of reading.
683      */

684     public final BooleanProperty GenerateFormattedSql = new BooleanProperty(
685             this, "mondrian.rolap.generate.formatted.sql", false);
686
687     /**
688      * Boolean property which controls whether each query axis implicit has the
689      * NON EMPTY option set. The default is false.
690      */

691     public final BooleanProperty EnableNonEmptyOnAllAxis = new BooleanProperty(
692             this, "mondrian.rolap.nonempty", false);
693
694     /**
695      * Boolean property which controls whether sibling members are
696      * compared according to order key value fetched from their ordinal
697      * expression. The default is false (only database ORDER BY is used).
698      */

699     public final BooleanProperty CompareSiblingsByOrderKey =
700         new BooleanProperty(
701             this, "mondrian.rolap.compareSiblingsByOrderKey",
702             false);
703
704     /**
705      * Boolean property which controls whether to use a cache for frequently
706      * evaluated expressions. With the cache disabled, an expression like
707      * <code>Rank([Product].CurrentMember,
708      * Order([Product].MEMBERS, [Measures].[Unit Sales]))</code> would perform
709      * many redundant sorts. The default is true.
710      */

711     public final BooleanProperty EnableExpCache = new BooleanProperty(
712             this, "mondrian.expCache.enable", true);
713
714
715     /**
716      * Integer property which controls whether to test operators' dependencies,
717      * and how much time to spend doing it.
718      *
719      * <p>If this property is positive, Mondrian's test framework allocates an
720      * expression evaluator which evaluates each expression several times, and
721      * makes sure that the results of the expression are independent of
722      * dimensions which the expression claims to be independent of.
723      *
724      * <p>The default is 0.
725      */

726     public final IntegerProperty TestExpDependencies = new IntegerProperty(
727             this, "mondrian.test.ExpDependencies", 0);
728
729     /**
730      * Seed for random number generator used by some of the tests.
731      *
732      * <p>
733      * Any value besides 0 or -1 gives deterministic behavior.
734      * The default value is 1234: most users should use this.
735      * Setting the seed to a different value can increase coverage, and
736      * therefore may uncover new bugs.
737      *
738      * <p>If you set the value to 0, the system will generate its own
739      * pseudo-random seed.
740      *
741      * <p>If you set the value to -1, Mondrian uses the next seed from an
742      * internal random-number generator. This is a little more deterministic
743      * than setting the value to 0.
744      */

745     public final IntegerProperty TestSeed = new IntegerProperty(
746             this, "mondrian.test.random.seed", 1234);
747
748     /**
749      * Name of locale property file.
750      *
751      * <p>Used for the {@link mondrian.rolap.DynamicSchemaProcessor
752      * LocalizingDynamicSchemaProcessor}; see
753      * <a HREF="{@docRoot}/../schema.html#I18n">Internationalization</a>
754      * for more details.</td>
755      *
756      * <p>Default value is null.
757      */

758     public final StringProperty LocalePropFile = new StringProperty(
759             this, "mondrian.rolap.localePropFile", null);
760
761     /**
762      * if enabled some NON EMPTY CrossJoin will be computed in SQL
763      */

764     public final BooleanProperty EnableNativeCrossJoin = new BooleanProperty(
765         this, "mondrian.native.crossjoin.enable", true);
766
767     /**
768      * if enabled some TopCount will be computed in SQL
769      */

770     public final BooleanProperty EnableNativeTopCount = new BooleanProperty(
771         this, "mondrian.native.topcount.enable", true);
772
773     /**
774      * if enabled some Filter() will be computed in SQL
775      */

776     public final BooleanProperty EnableNativeFilter = new BooleanProperty(
777         this, "mondrian.native.filter.enable", true);
778
779     /**
780      * some NON EMPTY set operations like member.children, level.members and
781      * member descendants will be computed in SQL
782      */

783     public final BooleanProperty EnableNativeNonEmpty = new BooleanProperty(
784         this, "mondrian.native.nonempty.enable", true);
785
786     /**
787      * Alerting action to take in case native evaluation of a function is
788      * enabled but not supported for that function's usage in a particular
789      * query. (No alert is ever raised in cases where native evaluation would
790      * definitely have been wasted effort.)
791      *
792      *<p>
793      *
794      * Recognized actions:
795      *
796      *<ul>
797      *
798      *<li><code>OFF</code>: do nothing (default action, also used if
799      * unrecognized action is specified)
800      *
801      *<li><code>WARN</code>: log a warning to RolapUtil logger
802      *
803      *<li><code>ERROR</code>: throw an instance of
804      * {@link NativeEvaluationUnsupportedException}
805      *
806      *</ul>
807      */

808     public final StringProperty AlertNativeEvaluationUnsupported =
809         new StringProperty(this, "mondrian.native.unsupported.alert", "OFF");
810
811     /**
812      * If enabled, first row in the result of an XML/A drill-through request
813      * will be filled with the total count of rows in underlying database.
814      */

815     public final BooleanProperty EnableTotalCount = new BooleanProperty(
816         this, "mondrian.xmla.drillthroughTotalCount.enable", true);
817
818     /**
819      * Boolean property which controls whether the MDX parser resolves uses
820      * case-sensitive matching when looking up identifiers. The default is
821      * false.
822      */

823     public final BooleanProperty CaseSensitive = new BooleanProperty(
824             this, "mondrian.olap.case.sensitive", false);
825
826
827     /**
828      * Property which defines
829      * limit on the number of rows returned by XML/A drill through request.
830      */

831     public final IntegerProperty MaxRows = new IntegerProperty(
832         this, "mondrian.xmla.drillthroughMaxRows", 1000);
833
834     /**
835      * Max number of constraints in a single `IN' SQL clause.
836      *
837      * <p>This value may be variant among database prodcuts and their runtime
838      * settings. Oracle, for example, gives the error "ORA-01795: maximum
839      * number of expressions in a list is 1000".
840      *
841      * <p>Recommended values:<ul>
842      * <li>Oracle: 1,000
843      * <li>DB2: 2,500
844      * <li>Other: 10,000</ul>
845      */

846     public final IntegerProperty MaxConstraints = new IntegerProperty(
847         this, "mondrian.rolap.maxConstraints", 1000);
848
849     /**
850      * Property which defines the
851      * maximum number of passes allowable while evaluating an MDX expression.
852      * If evaluation exceeds this depth (for example, while evaluating a
853      * very complex calculated member), Mondrian will throw an error.
854      */

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     /**
863      * Timeout value (in seconds) for queries; 0 indicates no timeout
864      */

865     public final IntegerProperty QueryTimeout = new IntegerProperty(
866         this, "mondrian.rolap.queryTimeout", 0);
867
868
869     /**
870      * Whether non-existent member errors should be ignored during schema
871      * load
872      */

873     public final BooleanProperty IgnoreInvalidMembers = new BooleanProperty(
874         this, "mondrian.rolap.ignoreInvalidMembers", false);
875
876     /**
877      * Iteration limit when computing an aggregate; 0 indicates unlimited
878      */

879     public final IntegerProperty IterationLimit = new IntegerProperty(
880         this, "mondrian.rolap.iterationLimit", 0);
881
882     /**
883      * Whether the <code>MemoryMonitor</code> should be enabled. By
884      * default for Java5 and above it is not enabled.
885      */

886     public final BooleanProperty MemoryMonitor = new BooleanProperty(
887         this, "mondrian.util.memoryMonitor.enable", false);
888
889     /**
890      * The default <code>MemoryMonitor</code> percentage threshold.
891      */

892     public final IntegerProperty MemoryMonitorThreshold = new IntegerProperty(
893         this, "mondrian.util.memoryMonitor.percentage.threshold", 90);
894
895     /**
896      * The <code>MemoryMonitor</code> class property. If the value is
897      * non-null, it is used by the <code>MemoryMonitorFactory</code>
898      * to create the implementation.
899      */

900     public final StringProperty MemoryMonitorClass = new StringProperty(
901             this, "mondrian.util.MemoryMonitor.class", null);
902
903     /**
904      * The <code>ExpCompiler</code> class property. If the value is
905      * non-null, it is used by the <code>ExpCompiler.Factory</code>
906      * to create the implementation.
907      */

908     public final StringProperty ExpCompilerClass = new StringProperty(
909             this, "mondrian.calc.ExpCompiler.class", null);
910
911     /**
912      * If a crossjoin input list's size is larger than this property's
913      * value and the axis has the "NON EMPTY" qualifier, then
914      * the crossjoin non-empty optimizer is applied.
915      * Setting this value to '0' means that for all crossjoin
916      * input lists in non-empty axes will have the optimizer applied.
917      * On the other hand, if the value is set larger than any possible
918      * list, say <code>Integer.MAX_VALUE</code>, then the optimizer
919      * will never be applied.
920      */

921     public final IntegerProperty CrossJoinOptimizerSize = new IntegerProperty(
922             this, "mondrian.olap.fun.crossjoin.optimizer.size", 0);
923
924 }
925
926 // End MondrianProperties.java
927
Popular Tags