001: /*
002: * ============================================================================
003: * GNU Lesser General Public License
004: * ============================================================================
005: *
006: * JasperReports - Free Java report-generating library.
007: * Copyright (C) 2001-2006 JasperSoft Corporation http://www.jaspersoft.com
008: *
009: * This library is free software; you can redistribute it and/or
010: * modify it under the terms of the GNU Lesser General Public
011: * License as published by the Free Software Foundation; either
012: * version 2.1 of the License, or (at your option) any later version.
013: *
014: * This library is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
017: * Lesser General Public License for more details.
018: *
019: * You should have received a copy of the GNU Lesser General Public
020: * License along with this library; if not, write to the Free Software
021: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
022: *
023: * JasperSoft Corporation
024: * 303 Second Street, Suite 450 North
025: * San Francisco, CA 94107
026: * http://www.jaspersoft.com
027: */
028: package net.sf.jasperreports.engine.util;
029:
030: import java.io.IOException;
031: import java.io.InputStream;
032: import java.util.ArrayList;
033: import java.util.Enumeration;
034: import java.util.List;
035: import java.util.Properties;
036:
037: import net.sf.jasperreports.engine.JRException;
038: import net.sf.jasperreports.engine.JRPropertiesMap;
039: import net.sf.jasperreports.engine.JRRuntimeException;
040:
041: /**
042: * Class that provides static methods for loading, getting and setting properties.
043: * <p>
044: * The following actions are performed:
045: * <ul>
046: * <li>The default (hardcoded) properties are set.</li>
047: * <li>If the system property "net.sf.jasperreports.properties" has been set
048: * then the specified proprties file is loaded.</li>
049: * <li>Otherwise "jasperreports.properties" is loaded if found in the classpath.</li>
050: * <li>For backward compatibility, system properties like "jasper.reports.compile.xml.validation"
051: * are checked and their values are used. This way of specifying properties is deprecated.</li>
052: *
053: * @author Lucian Chirita (lucianc@users.sourceforge.net)
054: * @version $Id: JRProperties.java 1828 2007-08-24 13:58:43Z teodord $
055: */
056: public class JRProperties {
057: /**
058: * The default properties file.
059: */
060: protected static final String DEFAULT_PROPERTIES_FILE = "jasperreports.properties";
061:
062: /**
063: * The prefix used by all properties.
064: */
065: public static final String PROPERTY_PREFIX = "net.sf.jasperreports.";
066:
067: /**
068: * The name of the system property that specifies the properties file name.
069: */
070: public static final String PROPERTIES_FILE = PROPERTY_PREFIX
071: + "properties";
072:
073: /**
074: * The name of the class to be used for report compilation.
075: * <p>
076: * No default value.
077: *
078: * @deprecated Replaced by {@link net.sf.jasperreports.engine.design#COMPILER_PREFIX}.
079: */
080: public static final String COMPILER_CLASS = PROPERTY_PREFIX
081: + "compiler.class";
082:
083: /**
084: * Whether to validate the xml report when compiling.
085: * <p>
086: * Defaults to <code>true</code>.
087: */
088: public static final String COMPILER_XML_VALIDATION = PROPERTY_PREFIX
089: + "compiler.xml.validation";
090:
091: /**
092: * Whether to keep the java file generated when the report is compiled.
093: * <p>
094: * Defaults to <code>false</code>.
095: */
096: public static final String COMPILER_KEEP_JAVA_FILE = PROPERTY_PREFIX
097: + "compiler.keep.java.file";
098:
099: /**
100: * The temporary directory used by the report compiler.
101: * <p>
102: * Defaults to <code>System.getProperty("user.dir")</code>.
103: */
104: public static final String COMPILER_TEMP_DIR = PROPERTY_PREFIX
105: + "compiler.temp.dir";
106:
107: /**
108: * The classpath used by the report compiler.
109: * <p>
110: * Defaults to <code>System.getProperty("java.class.path")</code>.
111: */
112: public static final String COMPILER_CLASSPATH = PROPERTY_PREFIX
113: + "compiler.classpath";
114:
115: /**
116: * Validation flag used by the XML exporter.
117: * <p>
118: * Defaults to <code>true</code>.
119: */
120: public static final String EXPORT_XML_VALIDATION = PROPERTY_PREFIX
121: + "export.xml.validation";
122:
123: /**
124: * Prefix of properties that specify font files for the PDF exporter.
125: */
126: public static final String PDF_FONT_FILES_PREFIX = PROPERTY_PREFIX
127: + "export.pdf.font.";
128:
129: /**
130: * Prefix of properties that specify font directories for the PDF exporter.
131: */
132: public static final String PDF_FONT_DIRS_PREFIX = PROPERTY_PREFIX
133: + "export.pdf.fontdir.";
134:
135: /**
136: * @deprecated Replaced by {@link net.sf.jasperreports.engine.query#QUERY_EXECUTER_FACTORY_PREFIX}.
137: */
138: public static final String QUERY_EXECUTER_FACTORY_PREFIX = PROPERTY_PREFIX
139: + "query.executer.factory.";
140:
141: /**
142: * @deprecated Replaced by {@link net.sf.jasperreports.engine.fill.JRSubreportRunnerFactory#SUBREPORT_RUNNER_FACTORY}.
143: */
144: public static final String SUBREPORT_RUNNER_FACTORY = PROPERTY_PREFIX
145: + "subreport.runner.factory";
146:
147: /**
148: * @deprecated Replaced by {@link net.sf.jasperreports.engine.export.JRPdfExporterParameter#PROPERTY_FORCE_LINEBREAK_POLICY}.
149: */
150: public static final String PDF_FORCE_LINEBREAK_POLICY = PROPERTY_PREFIX
151: + "export.pdf.force.linebreak.policy";
152:
153: protected static Properties props;
154:
155: protected static Properties savedProps;
156:
157: static {
158: initProperties();
159: }
160:
161: /**
162: * Loads the properties.
163: */
164: protected static void initProperties() {
165: try {
166: Properties defaults = getDefaults();
167: String propFile = getSystemProperty(PROPERTIES_FILE);
168: if (propFile == null) {
169: props = loadProperties(DEFAULT_PROPERTIES_FILE,
170: defaults);
171: if (props == null) {
172: props = new Properties(defaults);
173: }
174: } else {
175: props = loadProperties(propFile, defaults);
176: if (props == null) {
177: throw new JRRuntimeException(
178: "Could not load properties file \""
179: + propFile + "\"");
180: }
181: }
182:
183: loadSystemProperties();
184: } catch (JRException e) {
185: throw new JRRuntimeException(
186: "Error loading the properties", e);
187: }
188: }
189:
190: protected static void loadSystemProperties() {
191: loadSystemProperty("jasper.reports.compiler.class",
192: COMPILER_CLASS);
193: loadSystemProperty("jasper.reports.compile.xml.validation",
194: COMPILER_XML_VALIDATION);
195: loadSystemProperty("jasper.reports.export.xml.validation",
196: EXPORT_XML_VALIDATION);
197: loadSystemProperty("jasper.reports.compile.keep.java.file",
198: COMPILER_KEEP_JAVA_FILE);
199: loadSystemProperty("jasper.reports.compile.temp",
200: COMPILER_TEMP_DIR);
201: loadSystemProperty("jasper.reports.compile.class.path",
202: COMPILER_CLASSPATH);
203: }
204:
205: /**
206: * Sets the default properties.
207: *
208: * @return the default properties
209: */
210: protected static Properties getDefaults() throws JRException {
211: Properties defaults = new Properties();
212:
213: InputStream is = JRProperties.class
214: .getResourceAsStream("/default.jasperreports.properties");
215:
216: if (is == null) {
217: throw new JRException("Default properties file not found.");
218: }
219:
220: try {
221: defaults.load(is);
222: } catch (IOException e) {
223: throw new JRException("Failed to load default properties.",
224: e);
225: } finally {
226: try {
227: is.close();
228: } catch (IOException e) {
229: }
230: }
231:
232: String userDir = getSystemProperty("user.dir");
233: if (userDir != null) {
234: defaults.setProperty(COMPILER_TEMP_DIR, userDir);
235: }
236:
237: String classPath = getSystemProperty("java.class.path");
238: if (classPath != null) {
239: defaults.setProperty(COMPILER_CLASSPATH, classPath);
240: }
241:
242: return defaults;
243: }
244:
245: /**
246: *
247: */
248: protected static String getSystemProperty(String propertyName) {
249: try {
250: return System.getProperty(propertyName);
251: } catch (SecurityException e) {
252: // This could fail if we are in the applet viewer or some other
253: // restrictive environment, but it should be safe to simply return null.
254: // We cannot log this properly using a logging API,
255: // as we want to keep applet JAR dependencies to a minimum.
256: return null;
257: }
258: }
259:
260: protected static void loadSystemProperty(String sysKey,
261: String propKey) {
262: String val = getSystemProperty(sysKey);
263: if (val != null) {
264: props.setProperty(propKey, val);
265: }
266: }
267:
268: /**
269: * Loads a properties file from the classpath.
270: *
271: * @param name the resource name
272: * @param defaults the default properties
273: * @return the loaded properties if the resource is found, <code>null</code> otherwise
274: * @throws JRException
275: */
276: public static Properties loadProperties(String name,
277: Properties defaults) throws JRException {
278: Properties properties = null;
279:
280: InputStream is = null;
281:
282: try {
283: is = JRLoader.getLocationInputStream(name);
284: } catch (SecurityException e) {
285: // This could fail if we are in the applet viewer or some other
286: // restrictive environment, but most of the time it should be safe to ignore.
287: // We cannot log this properly using a logging API,
288: // as we want to keep applet JAR dependencies to a minimum.
289: }
290:
291: if (is != null) {
292: properties = new Properties(defaults);
293: try {
294: properties.load(is);
295: } catch (IOException e) {
296: throw new JRException(
297: "Failed to load properties file \"" + name
298: + "\"", e);
299: } finally {
300: try {
301: is.close();
302: } catch (IOException e) {
303: }
304: }
305: }
306:
307: return properties;
308: }
309:
310: /**
311: * Returns the value of the property.
312: *
313: * @param key the key
314: * @return the property value
315: */
316: public static String getProperty(String key) {
317: return props.getProperty(key);
318: }
319:
320: /**
321: * Returns a property as a boolean value.
322: *
323: * @param key the key
324: * @return the property value as a boolean
325: */
326: public static boolean getBooleanProperty(String key) {
327: return asBoolean(props.getProperty(key));
328: }
329:
330: /**
331: * Returns a property as an integer value.
332: *
333: * @param key the key
334: * @return the property value as an integer
335: */
336: public static int getIntegerProperty(String key) {
337: return asInteger(props.getProperty(key));
338: }
339:
340: /**
341: * Converts a <code>String</code> value into a <code>boolean</code>.
342: *
343: * @param value the value
344: * @return the value as a <code>boolean</code>
345: */
346: public static boolean asBoolean(String value) {
347: return Boolean.valueOf(value).booleanValue();
348: }
349:
350: /**
351: * Converts a <code>String</code> value into a <code>int</code>.
352: *
353: * @param value the value
354: * @return the value as a <code>int</code>
355: */
356: public static int asInteger(String value) {
357: return Integer.parseInt(value);
358: }
359:
360: /**
361: * Sets the value of a property.
362: *
363: * @param key the key
364: * @param value the value
365: */
366: public static void setProperty(String key, String value) {
367: props.setProperty(key, value);
368: }
369:
370: /**
371: * Sets the value of a property.
372: *
373: * @param key the key
374: * @param value the value
375: */
376: public static void setProperty(String key, boolean value) {
377: props.setProperty(key, String.valueOf(value));
378: }
379:
380: /**
381: * Saves a copy of the current properties.
382: *
383: * @see #restoreProperties()
384: */
385: public static void backupProperties() {
386: savedProps = (Properties) props.clone();
387: }
388:
389: /**
390: * Restores previously saved properties.
391: *
392: * @see #backupProperties()
393: */
394: public static void restoreProperties() {
395: if (savedProps != null) {
396: try {
397: props.clear();
398: props.putAll(savedProps);
399: } finally {
400: savedProps = null;
401: }
402: }
403: }
404:
405: /**
406: * Class used by {@link JRProperties#getProperties(String)}.
407: *
408: * @author Lucian Chirita
409: */
410: public static class PropertySuffix {
411: protected final String key;
412: protected final String suffix;
413: protected final String value;
414:
415: public PropertySuffix(String key, String suffix, String value) {
416: this .key = key;
417: this .suffix = suffix;
418: this .value = value;
419: }
420:
421: public String getKey() {
422: return key;
423: }
424:
425: public String getSuffix() {
426: return suffix;
427: }
428:
429: public String getValue() {
430: return value;
431: }
432: }
433:
434: /**
435: * Returns the list of all properties for a key prefix.
436: *
437: * @param prefix the key prefix
438: * @return a list of {@link PropertySuffix PropertySuffix} objects containing the suffix of the key and the value
439: */
440: public static List getProperties(String prefix) {
441: int prefixLength = prefix.length();
442: List values = new ArrayList();
443: for (Enumeration names = props.propertyNames(); names
444: .hasMoreElements();) {
445: String name = (String) names.nextElement();
446: if (name.startsWith(prefix)) {
447: String suffix = name.substring(prefixLength);
448: String value = props.getProperty(name);
449: values.add(new PropertySuffix(name, suffix, value));
450: }
451: }
452: return values;
453: }
454:
455: /**
456: * Returns the list of all properties for a key prefix.
457: *
458: * @param propertiesMap the properties map
459: * @param prefix the key prefix
460: * @return a list of {@link PropertySuffix PropertySuffix} objects containing the suffix of the key and the value
461: */
462: public static List getProperties(JRPropertiesMap propertiesMap,
463: String prefix) {
464: int prefixLength = prefix.length();
465: List values = new ArrayList();
466: String[] propertyNames = propertiesMap.getPropertyNames();
467: if (propertyNames != null) {
468: for (int i = 0; i < propertyNames.length; i++) {
469: String name = propertyNames[i];
470: if (name.startsWith(prefix)) {
471: String suffix = name.substring(prefixLength);
472: String value = propertiesMap.getProperty(name);
473: values.add(new PropertySuffix(name, suffix, value));
474: }
475: }
476: }
477: return values;
478: }
479:
480: /**
481: * Returns the value of a property, looking first in the supplied properties map
482: * and then in the system properties.
483: *
484: * @param propertiesMap the properties map
485: * @param key the key
486: * @return the property value
487: */
488: public static String getProperty(JRPropertiesMap propertiesMap,
489: String key) {
490: String value = null;
491: if (propertiesMap != null) {
492: value = propertiesMap.getProperty(key);
493: }
494:
495: if (value == null) {
496: value = props.getProperty(key);
497: }
498:
499: return value;
500: }
501:
502: /**
503: * Returns the value of a property as a boolean, looking first in the supplied properties map
504: * and then in the system properties.
505: *
506: * @param propertiesMap the properties map
507: * @param key the key
508: * @param defaultValue the default value used if the property is not found
509: * @return the property value
510: */
511: public static boolean getBooleanProperty(
512: JRPropertiesMap propertiesMap, String key,
513: boolean defaultValue) {
514: String value = getProperty(propertiesMap, key);
515:
516: return value == null ? defaultValue : asBoolean(value);
517: }
518:
519: /**
520: * Returns the value of a property as an integer, looking first in the supplied properties map
521: * and then in the system properties.
522: *
523: * @param propertiesMap the properties map
524: * @param key the key
525: * @param defaultValue the default value used if the property is not found
526: * @return the property value
527: */
528: public static int getIntegerProperty(JRPropertiesMap propertiesMap,
529: String key, int defaultValue) {
530: String value = getProperty(propertiesMap, key);
531:
532: return value == null ? defaultValue : asInteger(value);
533: }
534:
535: /**
536: * Returns the value of a property as an integer.
537: *
538: * @param key the key
539: * @param defaultValue the default value used if the property is not found
540: * @return the property value
541: */
542: public static int getIntegerProperty(String key, int defaultValue) {
543: String value = getProperty(key);
544:
545: return value == null ? defaultValue : asInteger(value);
546: }
547:
548: /**
549: * Converts a <code>String</code> value into a <code>long</code>.
550: *
551: * @param value the value
552: * @return the value as a <code>long</code>
553: */
554: public static long asLong(String value) {
555: return Long.parseLong(value);
556: }
557:
558: /**
559: * Returns a property as a long value.
560: *
561: * @param key the key
562: * @return the property value as a long
563: */
564: public static long getLongProperty(String key) {
565: return asLong(props.getProperty(key));
566: }
567:
568: /**
569: * Returns the value of a property as a long, looking first in the supplied properties map
570: * and then in the system properties.
571: *
572: * @param propertiesMap the properties map
573: * @param key the key
574: * @param defaultValue the default value used if the property is not found
575: * @return the property value
576: */
577: public static long getLongProperty(JRPropertiesMap propertiesMap,
578: String key, int defaultValue) {
579: String value = getProperty(propertiesMap, key);
580:
581: return value == null ? defaultValue : asLong(value);
582: }
583: }
|