View Javadoc

1   /*
2    * Copyright 2010 - org.tinyjee.maven
3    *
4    *    Licensed under the Apache License, Version 2.0 (the "License");
5    *    you may not use this file except in compliance with the License.
6    *    You may obtain a copy of the License at
7    *
8    *        http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *    Unless required by applicable law or agreed to in writing, software
11   *    distributed under the License is distributed on an "AS IS" BASIS,
12   *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *    See the License for the specific language governing permissions and
14   *    limitations under the License.
15   */
16  
17  package org.tinyjee.maven.dim.extensions;
18  
19  import org.apache.maven.doxia.logging.Log;
20  import org.codehaus.plexus.util.FileUtils;
21  import org.tinyjee.maven.dim.spi.Globals;
22  import org.tinyjee.maven.dim.utils.AbstractAliasHandler;
23  import org.tinyjee.maven.dim.utils.SelectableArrayList;
24  
25  import java.io.File;
26  import java.io.IOException;
27  import java.net.URL;
28  import java.util.LinkedHashMap;
29  import java.util.Map;
30  import java.util.Properties;
31  import java.util.TreeSet;
32  
33  import static org.tinyjee.maven.dim.spi.ResourceResolver.findSource;
34  
35  /**
36   * PropertiesLoader is a 'source-class' compatible helper class that can load a properties file
37   * and add or overwrite the request properties by the properties contained in the file.
38   * <p/>
39   * <p/>
40   * <b>Usage:</b><div><code>
41   * %{include|source=template.vm|source-class=org.tinyjee.maven.dim.extensions.PropertiesLoader|properties=props.(xml|properties)}
42   * </code></div>
43   * or when using the alias:<div><code>
44   * %{include|source=template.vm|source-properties=props.(xml|properties)}
45   * </code></div>
46   *
47   * @author Juergen_Kellerer, 2010-09-08
48   * @version 1.0
49   */
50  public class PropertiesLoader extends LinkedHashMap<String, Object> {
51  
52  	private static final long serialVersionUID = 7451224247313497738L;
53  
54  	/**
55  	 * Implements the "{@link PropertiesLoader#PARAM_ALIAS}" alias functionality.
56  	 */
57  	public static class AliasHandler extends AbstractAliasHandler {
58  		/**
59  		 * Constructs the handler (Note: Is called by
60  		 * {@link org.tinyjee.maven.dim.spi.RequestParameterTransformer#TRANSFORMERS}).
61  		 */
62  		public AliasHandler() {
63  			super(PARAM_ALIAS, PARAM_PROPERTIES, PropertiesLoader.class.getName());
64  		}
65  	}
66  
67  	/**
68  	 * Defines a shortcut for the request properties '{@code source-class}' and '{@code properties}'.
69  	 * <p/>
70  	 * If this parameter is present inside the request parameters list, the system
71  	 * will effectively behave as if 'source-class' and 'properties' where set
72  	 * separately.
73  	 */
74  	public static final String PARAM_ALIAS = "source-properties";
75  
76  	/**
77  	 * Sets the path to the properties file to load inside the request parameters.
78  	 * <p/>
79  	 * The specified file is retrieved in exactly the same way as if the "{@code source}"
80  	 * parameter would have been used (see Macro reference).
81  	 * <p/>
82  	 * <i>Note:</i> Properties can use the traditional {@code .properties} or
83  	 * the newer {@code .xml} format. Format selection is performed by file extension.
84  	 */
85  	public static final String PARAM_PROPERTIES = "properties";
86  
87  	/**
88  	 * Is filled with the loaded {@link Properties} instance.
89  	 * <p/>
90  	 * Note: All loaded properties are exposed in the standard scope as request properties and are accessible
91  	 * like any other parameters specified with the macro call.
92  	 * <br/>
93  	 * This additional map based access allows to query properties whose names are not compatible with the variable naming
94  	 * scheme and it also allows to iterate all loaded properties using {@code $loadedProperties.entrySet()}.
95  	 */
96  	public static final String OUT_PARAM_LOADED_PROPERTIES = "loadedProperties";
97  
98  	/**
99  	 * Is filled with a sorted, regex-enabled list of property keys (=
100 	 * <code>new {@link SelectableArrayList}&lt;String&gt;(new TreeSet&lt;String&gt;(properties.keySet()));</code>).
101 	 */
102 	public static final String OUT_PARAM_LOADED_PROPERTY_KEYS = "loadedPropertyKeys";
103 
104 	/**
105 	 * Constructs a new properties loader searching for properties using the given base path.
106 	 *
107 	 * @param baseDir       the base dir to of the maven module.
108 	 * @param requestParams the request params of the macro call.
109 	 */
110 	@SuppressWarnings("unchecked")
111 	public PropertiesLoader(File baseDir, Map<String, Object> requestParams) {
112 		final Log log = Globals.getLog();
113 		final boolean debug = log.isDebugEnabled();
114 
115 		putAll(requestParams);
116 
117 		URL propertiesURL = findSource(baseDir, (String) requestParams.get(PARAM_PROPERTIES));
118 		try {
119 			Properties properties = new Properties();
120 			boolean isXml = "xml".equalsIgnoreCase(FileUtils.extension(propertiesURL.getFile()));
121 			if (debug) log.debug("About to load properties from '" + propertiesURL + "'. Used format: " + (isXml ? "xml" : "properties"));
122 			if (isXml)
123 				properties.loadFromXML(propertiesURL.openStream());
124 			else
125 				properties.load(propertiesURL.openStream());
126 
127 			put(OUT_PARAM_LOADED_PROPERTIES, properties);
128 			SelectableArrayList sortedKeys = new SelectableArrayList(new TreeSet(properties.keySet()));
129 			put(OUT_PARAM_LOADED_PROPERTY_KEYS, sortedKeys);
130 
131 			if (debug) log.debug("Loaded properties:");
132 			for (Object key : sortedKeys) {
133 				String propertyKey = key.toString(), propertyValue = properties.getProperty(propertyKey);
134 				put(propertyKey, propertyValue);
135 				if (debug) log.debug(propertyKey + "=" + propertyValue);
136 			}
137 		} catch (IOException e) {
138 			throw new RuntimeException(e);
139 		}
140 	}
141 }