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}<String>(new TreeSet<String>(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 }