/* * JasperReports - Free Java Reporting Library. * Copyright (C) 2001 - 2009 Jaspersoft Corporation. All rights reserved. * http://www.jaspersoft.com * * Unless you have purchased a commercial license agreement from Jaspersoft, * the following license terms apply: * * This program is part of JasperReports. * * JasperReports is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * JasperReports is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with JasperReports. If not, see <http://www.gnu.org/licenses/>. */ package net.sf.jasperreports.engine.util; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Enumeration; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Properties; import java.util.Set; import net.sf.jasperreports.engine.JRException; import net.sf.jasperreports.engine.JRPropertiesHolder; import net.sf.jasperreports.engine.JRPropertiesMap; import net.sf.jasperreports.engine.JRRuntimeException; /** * Class that provides static methods for loading, getting and setting properties. * <p> * The following actions are performed: * <ul> * <li>The default (hardcoded) properties are set.</li> * <li>If the system property "net.sf.jasperreports.properties" has been set * then the specified proprties file is loaded.</li> * <li>Otherwise "jasperreports.properties" is loaded if found in the classpath.</li> * <li>For backward compatibility, system properties like "jasper.reports.compile.xml.validation" * are checked and their values are used. This way of specifying properties is deprecated.</li> * </ul> * </p> * * @author Lucian Chirita (lucianc@users.sourceforge.net) * @version $Id: JRProperties.java 3712 2010-04-08 09:53:09Z teodord $ */ public final class JRProperties { /** * The default properties file. */ protected static final String DEFAULT_PROPERTIES_FILE = "jasperreports.properties"; /** * The prefix used by all properties. */ public static final String PROPERTY_PREFIX = "net.sf.jasperreports."; /** * The name of the system property that specifies the properties file name. */ public static final String PROPERTIES_FILE = PROPERTY_PREFIX + "properties"; /** * The name of the class to be used for report compilation. * <p> * No default value. * * @deprecated Replaced by {@link net.sf.jasperreports.engine.design.JRCompiler#COMPILER_PREFIX}. */ public static final String COMPILER_CLASS = PROPERTY_PREFIX + "compiler.class"; /** * Whether to validate the xml report when compiling. * <p> * Defaults to <code>true</code>. */ public static final String COMPILER_XML_VALIDATION = PROPERTY_PREFIX + "compiler.xml.validation"; /** * Whether to keep the java file generated when the report is compiled. * <p> * Defaults to <code>false</code>. */ public static final String COMPILER_KEEP_JAVA_FILE = PROPERTY_PREFIX + "compiler.keep.java.file"; /** * The temporary directory used by the report compiler. * <p> * Defaults to <code>System.getProperty("user.dir")</code>. */ public static final String COMPILER_TEMP_DIR = PROPERTY_PREFIX + "compiler.temp.dir"; /** * The classpath used by the report compiler. * <p> * Defaults to <code>System.getProperty("java.class.path")</code>. */ public static final String COMPILER_CLASSPATH = PROPERTY_PREFIX + "compiler.classpath"; /** * Validation flag used by the XML exporter. * <p> * Defaults to <code>true</code>. */ public static final String EXPORT_XML_VALIDATION = PROPERTY_PREFIX + "export.xml.validation"; /** * Prefix of properties that specify font files for the PDF exporter. */ public static final String PDF_FONT_FILES_PREFIX = PROPERTY_PREFIX + "export.pdf.font."; /** * Prefix of properties that specify font directories for the PDF exporter. */ public static final String PDF_FONT_DIRS_PREFIX = PROPERTY_PREFIX + "export.pdf.fontdir."; /** * @deprecated Replaced by {@link net.sf.jasperreports.engine.query#QUERY_EXECUTER_FACTORY_PREFIX}. */ public static final String QUERY_EXECUTER_FACTORY_PREFIX = PROPERTY_PREFIX + "query.executer.factory."; /** * @deprecated Replaced by {@link net.sf.jasperreports.engine.fill.JRSubreportRunnerFactory#SUBREPORT_RUNNER_FACTORY}. */ public static final String SUBREPORT_RUNNER_FACTORY = PROPERTY_PREFIX + "subreport.runner.factory"; /** * @deprecated Replaced by {@link net.sf.jasperreports.engine.export.JRPdfExporterParameter#PROPERTY_FORCE_LINEBREAK_POLICY}. */ public static final String PDF_FORCE_LINEBREAK_POLICY = PROPERTY_PREFIX + "export.pdf.force.linebreak.policy"; protected static Properties props; protected static Properties savedProps; static { initProperties(); } /** * Loads the properties. */ protected static void initProperties() { try { Properties defaults = getDefaults(); String propFile = getSystemProperty(PROPERTIES_FILE); if (propFile == null) { props = loadProperties(DEFAULT_PROPERTIES_FILE, defaults); if (props == null) { props = new Properties(defaults); } } else { props = loadProperties(propFile, defaults); if (props == null) { throw new JRRuntimeException("Could not load properties file \"" + propFile + "\""); } } loadSystemProperties(); } catch (JRException e) { throw new JRRuntimeException("Error loading the properties", e); } } protected static void loadSystemProperties() { loadSystemProperty("jasper.reports.compiler.class", COMPILER_CLASS); loadSystemProperty("jasper.reports.compile.xml.validation", COMPILER_XML_VALIDATION); loadSystemProperty("jasper.reports.export.xml.validation", EXPORT_XML_VALIDATION); loadSystemProperty("jasper.reports.compile.keep.java.file", COMPILER_KEEP_JAVA_FILE); loadSystemProperty("jasper.reports.compile.temp", COMPILER_TEMP_DIR); loadSystemProperty("jasper.reports.compile.class.path", COMPILER_CLASSPATH); } /** * Sets the default properties. * * @return the default properties */ protected static Properties getDefaults() throws JRException { Properties defaults = new Properties(); InputStream is = JRProperties.class.getResourceAsStream("/default.jasperreports.properties"); if (is == null) { throw new JRException("Default properties file not found."); } try { defaults.load(is); } catch (IOException e) { throw new JRException("Failed to load default properties.", e); } finally { try { is.close(); } catch (IOException e) { } } String userDir = getSystemProperty("user.dir"); if (userDir != null) { defaults.setProperty(COMPILER_TEMP_DIR, userDir); } String classPath = getSystemProperty("java.class.path"); if (classPath != null) { defaults.setProperty(COMPILER_CLASSPATH, classPath); } return defaults; } /** * */ protected static String getSystemProperty(String propertyName) { try { return System.getProperty(propertyName); } catch (SecurityException e) { // This could fail if we are in the applet viewer or some other // restrictive environment, but it should be safe to simply return null. // We cannot log this properly using a logging API, // as we want to keep applet JAR dependencies to a minimum. return null; } } protected static void loadSystemProperty(String sysKey, String propKey) { String val = getSystemProperty(sysKey); if (val != null) { props.setProperty(propKey, val); } } /** * Loads a properties file from the classpath. * * @param name the resource name * @param defaults the default properties * @return the loaded properties if the resource is found, <code>null</code> otherwise * @throws JRException */ public static Properties loadProperties (String name, Properties defaults) throws JRException { Properties properties = null; InputStream is = null; try { is = JRLoader.getLocationInputStream(name); } catch (SecurityException e) { // This could fail if we are in the applet viewer or some other // restrictive environment, but most of the time it should be safe to ignore. // We cannot log this properly using a logging API, // as we want to keep applet JAR dependencies to a minimum. } if (is != null) { properties = new Properties(defaults); try { properties.load(is); } catch (IOException e) { throw new JRException("Failed to load properties file \"" + name + "\"", e); } finally { try { is.close(); } catch (IOException e) { } } } return properties; } /** * Returns the value of the property. * * @param key the key * @return the property value */ public static String getProperty (String key) { return props.getProperty(key); } /** * Returns a property as a boolean value. * * @param key the key * @return the property value as a boolean */ public static boolean getBooleanProperty (String key) { return asBoolean(props.getProperty(key)); } /** * Returns a property as an integer value. * * @param key the key * @return the property value as an integer */ public static int getIntegerProperty (String key) { return asInteger(props.getProperty(key)); } /** * Returns a property as a float value. * * @param key the key * @return the property value as a float */ public static float getFloatProperty (String key) { return asFloat(props.getProperty(key)); } /** * Converts a <code>String</code> value into a <code>boolean</code>. * * @param value the value * @return the value as a <code>boolean</code> */ public static boolean asBoolean(String value) { return Boolean.valueOf(value).booleanValue(); } /** * Converts a <code>String</code> value into a <code>int</code>. * * @param value the value * @return the value as a <code>int</code> */ public static int asInteger(String value) { return Integer.parseInt(value); } /** * Converts a <code>String</code> value into a <code>float</code>. * * @param value the value * @return the value as a <code>float</code> */ public static float asFloat(String value) { return Float.parseFloat(value); } /** * Sets the value of a property. * * @param key the key * @param value the value */ public static void setProperty (String key, String value) { props.setProperty(key, value); } /** * Sets the value of a property. * * @param key the key * @param value the value */ public static void setProperty (String key, boolean value) { props.setProperty(key, String.valueOf(value)); } /** * Removes the value set for a property. * * <p> * This method removes values set in jasperreports.properties or via the * {@link #setProperty(String, String) setProperty} method. * Built-in default property values are not affected; if the property has * a default value it will be used after calling this method for the * property. * </p> * * @param key the property key */ public static void removePropertyValue (String key) { props.remove(key); } /** * Saves a copy of the current properties. * * @see #restoreProperties() */ public static void backupProperties () { savedProps = (Properties) props.clone(); } /** * Restores previously saved properties. * * @see #backupProperties() */ public static void restoreProperties () { if (savedProps != null) { try { props.clear(); props.putAll(savedProps); } finally { savedProps = null; } } } /** * Class used by {@link JRProperties#getProperties(String)}. * * @author Lucian Chirita */ public static class PropertySuffix { protected final String key; protected final String suffix; protected final String value; public PropertySuffix (String key, String suffix, String value) { this.key = key; this.suffix = suffix; this.value = value; } public String getKey() { return key; } public String getSuffix () { return suffix; } public String getValue () { return value; } } /** * Returns the list of all properties for a key prefix. * * @param prefix the key prefix * @return a list of {@link PropertySuffix PropertySuffix} objects containing the suffix of the key and the value */ public static List getProperties (String prefix) { int prefixLength = prefix.length(); List values = new ArrayList(); for (Enumeration names = props.propertyNames(); names.hasMoreElements();) { String name = (String) names.nextElement(); if (name.startsWith(prefix)) { String suffix = name.substring(prefixLength); String value = props.getProperty(name); values.add(new PropertySuffix(name, suffix, value)); } } return values; } /** * Returns the list of all properties for a key prefix. * * Only this holder's own properties are considered, and not global * properties. * * @param propertiesHolder the properties holder * @param prefix the key prefix * @return a list of {@link PropertySuffix PropertySuffix} objects containing the suffix of the key and the value * @see #getAllProperties(JRPropertiesHolder, String) */ public static List getProperties(JRPropertiesHolder propertiesHolder, String prefix) { return getProperties(getOwnProperties(propertiesHolder), prefix); } /** * Returns the list of all properties for a key prefix, including global * properties. * * @param propertiesHolder the properties holder * @param prefix the key prefix * @return a list of {@link PropertySuffix PropertySuffix} objects containing the suffix of the key and the value * @see #getProperties(JRPropertiesHolder, String) */ public static List getAllProperties(JRPropertiesHolder propertiesHolder, String prefix) { return getAllProperties(getOwnProperties(propertiesHolder), prefix); } /** * Returns the list of all properties for a key prefix. * * Only properties from <code>propertiesMap</code> are considered, and * not global properties. * * @param propertiesMap the properties map * @param prefix the key prefix * @return a list of {@link PropertySuffix PropertySuffix} objects containing the suffix of the key and the value * @see #getAllProperties(JRPropertiesMap, String) */ public static List getProperties(JRPropertiesMap propertiesMap, String prefix) { int prefixLength = prefix.length(); List values = new ArrayList(); if (propertiesMap != null) { String[] propertyNames = propertiesMap.getPropertyNames(); for (int i = 0; i < propertyNames.length; i++) { String name = propertyNames[i]; if (name.startsWith(prefix)) { String suffix = name.substring(prefixLength); String value = propertiesMap.getProperty(name); values.add(new PropertySuffix(name, suffix, value)); } } } return values; } /** * Returns the list of all properties for a key prefix, including global * properties. * * @param propertiesMap the properties map * @param prefix the key prefix * @return a list of {@link PropertySuffix PropertySuffix} objects containing the suffix of the key and the value * @see #getProperties(JRPropertiesMap, String) */ public static List getAllProperties(JRPropertiesMap propertiesMap, String prefix) { List own = getProperties(propertiesMap, prefix); List global = getProperties(prefix); List collected; if (own.isEmpty()) { collected = global; } else { if (!global.isEmpty()) { Set ownSuffixes = new HashSet(); for (Iterator it = own.iterator(); it.hasNext();) { PropertySuffix prop = (PropertySuffix) it.next(); ownSuffixes.add(prop.getSuffix()); } for (Iterator it = global.iterator(); it.hasNext();) { PropertySuffix prop = (PropertySuffix) it.next(); if (!ownSuffixes.contains(prop.getSuffix())) { own.add(prop); } } } collected = own; } return collected; } /** * Returns the value of a property, looking first in the supplied properties holder * and then in the system properties. * * @param propertiesHolder the properties holder * @param key the key * @return the property value */ public static String getProperty (JRPropertiesHolder propertiesHolder, String key) { String value = null; while (propertiesHolder != null && value == null) { if (propertiesHolder.hasProperties()) { value = propertiesHolder.getPropertiesMap().getProperty(key); } propertiesHolder = propertiesHolder.getParentProperties(); } if (value == null) { value = props.getProperty(key); } return value; } /** * Returns the value of a property, looking first in the supplied properties map * and then in the system properties. * * @param propertiesMap the properties map * @param key the key * @return the property value */ public static String getProperty (JRPropertiesMap propertiesMap, String key) { String value = null; if (propertiesMap != null) { value = propertiesMap.getProperty(key); } if (value == null) { value = props.getProperty(key); } return value; } /** * Returns the value of a property as a boolean, looking first in the supplied properties holder * and then in the system properties. * * @param propertiesHolder the properties holder * @param key the key * @param defaultValue the default value used if the property is not found * @return the property value */ public static boolean getBooleanProperty (JRPropertiesHolder propertiesHolder, String key, boolean defaultValue) { String value = getProperty(propertiesHolder, key); return value == null ? defaultValue : asBoolean(value); } /** * Returns the value of a property as a boolean, looking first in the supplied properties map * and then in the system properties. * * @param propertiesMap the properties map * @param key the key * @param defaultValue the default value used if the property is not found * @return the property value */ public static boolean getBooleanProperty (JRPropertiesMap propertiesMap, String key, boolean defaultValue) { String value = getProperty(propertiesMap, key); return value == null ? defaultValue : asBoolean(value); } /** * Returns the value of a property as an integer, looking first in the supplied properties holder * and then in the system properties. * * @param propertiesHolder the properties holder * @param key the key * @param defaultValue the default value used if the property is not found * @return the property value */ public static int getIntegerProperty (JRPropertiesHolder propertiesHolder, String key, int defaultValue) { String value = getProperty(propertiesHolder, key); return value == null ? defaultValue : asInteger(value); } /** * Returns the value of a property as an integer, looking first in the supplied properties map * and then in the system properties. * * @param propertiesMap the properties map * @param key the key * @param defaultValue the default value used if the property is not found * @return the property value */ public static int getIntegerProperty (JRPropertiesMap propertiesMap, String key, int defaultValue) { String value = getProperty(propertiesMap, key); return value == null ? defaultValue : asInteger(value); } /** * Returns the value of a property as an integer. * * @param key the key * @param defaultValue the default value used if the property is not found * @return the property value */ public static int getIntegerProperty (String key, int defaultValue) { String value = getProperty(key); return value == null ? defaultValue : asInteger(value); } /** * Returns the value of a property as a float, looking first in the supplied properties holder * and then in the system properties. * * @param propertiesHolder the properties holder * @param key the key * @param defaultValue the default value used if the property is not found * @return the property value */ public static float getFloatProperty (JRPropertiesHolder propertiesHolder, String key, float defaultValue) { String value = getProperty(propertiesHolder, key); return value == null ? defaultValue : asFloat(value); } /** * Returns the value of a property as a float, looking first in the supplied properties map * and then in the system properties. * * @param propertiesMap the properties map * @param key the key * @param defaultValue the default value used if the property is not found * @return the property value */ public static float getFloatProperty (JRPropertiesMap propertiesMap, String key, float defaultValue) { String value = getProperty(propertiesMap, key); return value == null ? defaultValue : asFloat(value); } /** * Returns the value of a property as a float. * * @param key the key * @param defaultValue the default value used if the property is not found * @return the property value */ public static float getFloatProperty (String key, float defaultValue) { String value = getProperty(key); return value == null ? defaultValue : asFloat(value); } /** * Converts a <code>String</code> value into a <code>long</code>. * * @param value the value * @return the value as a <code>long</code> */ public static long asLong(String value) { return Long.parseLong(value); } /** * Returns a property as a long value. * * @param key the key * @return the property value as a long */ public static long getLongProperty (String key) { return asLong(props.getProperty(key)); } /** * Returns the value of a property as a long, looking first in the supplied properties map * and then in the system properties. * * @param propertiesMap the properties map * @param key the key * @param defaultValue the default value used if the property is not found * @return the property value */ public static long getLongProperty (JRPropertiesMap propertiesMap, String key, int defaultValue) { String value = getProperty(propertiesMap, key); return value == null ? defaultValue : asLong(value); } /** * Returns the value of a property as a long, looking first in the supplied properties holder * and then in the system properties. * * @param propertiesHolder the properties holder * @param key the key * @param defaultValue the default value used if the property is not found * @return the property value */ public static long getLongProperty (JRPropertiesHolder propertiesHolder, String key, int defaultValue) { String value = getProperty(propertiesHolder, key); return value == null ? defaultValue : asLong(value); } protected static JRPropertiesMap getOwnProperties(JRPropertiesHolder propertiesHolder) { return propertiesHolder.hasProperties() ? propertiesHolder.getPropertiesMap() : null; } /** * Copies properties from one object to another. * * <p> * The properties to be copied are determined by one or more JasperReports * properties having a specified prefix. The values of these properties * are interpreted as prefixes of properties to copy. * </p> * * @param source the source properties holder * @param destination the destination properties holder * @param tranferPropertiesPrefix the prefix of the JasperReports properties * that specify the object properties to copy */ public static void transferProperties(JRPropertiesHolder source, JRPropertiesHolder destination, String tranferPropertiesPrefix) { if (!source.hasProperties()) { return; } transfer(source.getPropertiesMap(), destination, tranferPropertiesPrefix); } /** * Copies properties from one object to another. * * @param source the source properties * @param destination the destination properties holder * @param tranferPropertiesPrefix the prefix of the JasperReports properties * that specify the object properties to copy * @see #transferProperties(JRPropertiesHolder, JRPropertiesHolder, String) */ public static void transferProperties(JRPropertiesMap source, JRPropertiesHolder destination, String tranferPropertiesPrefix) { if (source == null || !source.hasProperties()) { return; } transfer(source, destination, tranferPropertiesPrefix); } protected static void transfer(JRPropertiesMap source, JRPropertiesHolder destination, String tranferPropertiesPrefix) { List transferPrefixProps = getProperties(tranferPropertiesPrefix); for (Iterator prefixIt = transferPrefixProps.iterator(); prefixIt.hasNext();) { JRProperties.PropertySuffix transferPrefixProp = (JRProperties.PropertySuffix) prefixIt.next(); String transferPrefix = transferPrefixProp.getValue(); if (transferPrefix != null && transferPrefix.length() > 0) { List transferProps = getProperties(source, transferPrefix); for (Iterator propIt = transferProps.iterator(); propIt.hasNext();) { JRProperties.PropertySuffix property = (JRProperties.PropertySuffix) propIt.next(); String value = property.getValue(); destination.getPropertiesMap().setProperty(property.getKey(), value); } } } } /** * Returns a property as a <code>Character</code> value. * * @param key the key * @return the property value as a <code>Character</code> * @see #asCharacter(String) */ public static Character getCharacterProperty(String key) { return asCharacter(props.getProperty(key)); } /** * Returns the value of a property as a <code>Character</code> value, * looking first in the supplied properties holder and then in the * system properties. * * @param propertiesMap the properties map * @param key the key * @return the property value as a <code>Character</code> */ public static Character getCharacterProperty(JRPropertiesMap propertiesMap, String key) { String value = getProperty(propertiesMap, key); return asCharacter(value); } /** * Converts a <code>String</code> into a <code>Character</code> value. * * <p> * If the <code>String</code> value is null or the empty string, * <code>null</code> is returned. Otherwise, the method returns * the first character in the string. * * @param value the <code>String</code> value * @return the value converted to <code>Character</code> */ public static Character asCharacter(String value) { return value == null || value.length() == 0 ? null : new Character(value.charAt(0)); } private JRProperties() { } }