1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19 package org.apache.maven.plugins.invoker;
20
21 /*
22 * Licensed to the Apache Software Foundation (ASF) under one
23 * or more contributor license agreements. See the NOTICE file
24 * distributed with this work for additional information
25 * regarding copyright ownership. The ASF licenses this file
26 * to you under the Apache License, Version 2.0 (the
27 * "License"); you may not use this file except in compliance
28 * with the License. You may obtain a copy of the License at
29 *
30 * http://www.apache.org/licenses/LICENSE-2.0
31 *
32 * Unless required by applicable law or agreed to in writing,
33 * software distributed under the License is distributed on an
34 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
35 * KIND, either express or implied. See the License for the
36 * specific language governing permissions and limitations
37 * under the License.
38 */
39
40 import java.util.Collection;
41 import java.util.HashMap;
42 import java.util.Map;
43 import java.util.Set;
44
45 import org.apache.maven.project.MavenProject;
46 import org.codehaus.plexus.util.introspection.ReflectionValueExtractor;
47
48 /**
49 * A map-like source to interpolate expressions.
50 *
51 * @author Olivier Lamy
52 * @since 1.1
53 */
54 class CompositeMap implements Map<String, Object> {
55
56 /**
57 * The Maven project from which to extract interpolated values, never <code>null</code>.
58 */
59 private MavenProject mavenProject;
60
61 /**
62 * The set of additional properties from which to extract interpolated values, never <code>null</code>.
63 */
64 private Map<String, Object> properties;
65
66 /**
67 * Flag indicating to escape XML special characters.
68 */
69 private final boolean escapeXml;
70
71 /**
72 * Creates a new interpolation source backed by the specified Maven project and some user-specified properties.
73 *
74 * @param mavenProject The Maven project from which to extract interpolated values, must not be <code>null</code>.
75 * @param properties The set of additional properties from which to extract interpolated values, may be
76 * <code>null</code>.
77 * @param escapeXml {@code true}, to escape any XML special characters; {@code false}, to not perform any escaping.
78 */
79 protected CompositeMap(MavenProject mavenProject, Map<String, Object> properties, boolean escapeXml) {
80 if (mavenProject == null) {
81 throw new IllegalArgumentException("no project specified");
82 }
83 this.mavenProject = mavenProject;
84 this.properties = properties == null ? new HashMap<String, Object>() : properties;
85 this.escapeXml = escapeXml;
86 }
87
88 /**
89 * {@inheritDoc}
90 *
91 * @see java.util.Map#clear()
92 */
93 public void clear() {
94 // nothing here
95 }
96
97 /**
98 * {@inheritDoc}
99 *
100 * @see java.util.Map#containsKey(java.lang.Object)
101 */
102 public boolean containsKey(Object key) {
103 if (!(key instanceof String)) {
104 return false;
105 }
106
107 String expression = (String) key;
108 if (expression.startsWith("project.") || expression.startsWith("pom.")) {
109 try {
110 Object evaluated = ReflectionValueExtractor.evaluate(expression, this.mavenProject);
111 if (evaluated != null) {
112 return true;
113 }
114 } catch (Exception e) {
115 // uhm do we have to throw a RuntimeException here ?
116 }
117 }
118
119 return properties.containsKey(key) || mavenProject.getProperties().containsKey(key);
120 }
121
122 /**
123 * {@inheritDoc}
124 *
125 * @see java.util.Map#containsValue(java.lang.Object)
126 */
127 public boolean containsValue(Object value) {
128 throw new UnsupportedOperationException();
129 }
130
131 /**
132 * {@inheritDoc}
133 *
134 * @see java.util.Map#entrySet()
135 */
136 public Set<Entry<String, Object>> entrySet() {
137 throw new UnsupportedOperationException();
138 }
139
140 /**
141 * {@inheritDoc}
142 *
143 * @see java.util.Map#get(java.lang.Object)
144 */
145 public Object get(Object key) {
146 if (!(key instanceof String)) {
147 return null;
148 }
149
150 Object value = null;
151 String expression = (String) key;
152 if (expression.startsWith("project.") || expression.startsWith("pom.")) {
153 try {
154 Object evaluated = ReflectionValueExtractor.evaluate(expression, this.mavenProject);
155 if (evaluated != null) {
156 value = evaluated;
157 }
158 } catch (Exception e) {
159 // uhm do we have to throw a RuntimeException here ?
160 }
161 }
162
163 if (value == null) {
164 value = properties.get(key);
165 }
166
167 if (value == null) {
168 value = this.mavenProject.getProperties().get(key);
169 }
170
171 if (value != null && this.escapeXml) {
172 value = value.toString()
173 .replaceAll("\"", """)
174 .replaceAll("<", "<")
175 .replaceAll(">", ">")
176 .replaceAll("&", "&");
177 }
178
179 return value;
180 }
181
182 /**
183 * {@inheritDoc}
184 *
185 * @see java.util.Map#isEmpty()
186 */
187 public boolean isEmpty() {
188 return this.mavenProject.getProperties().isEmpty() && this.properties.isEmpty();
189 }
190
191 /**
192 * {@inheritDoc}
193 *
194 * @see java.util.Map#keySet()
195 */
196 public Set<String> keySet() {
197 throw new UnsupportedOperationException();
198 }
199
200 /**
201 * {@inheritDoc}
202 *
203 * @see java.util.Map#put(java.lang.Object, java.lang.Object)
204 */
205 public Object put(String key, Object value) {
206 throw new UnsupportedOperationException();
207 }
208
209 /**
210 * {@inheritDoc}
211 *
212 * @see java.util.Map#putAll(java.util.Map)
213 */
214 public void putAll(Map<? extends String, ? extends Object> t) {
215 throw new UnsupportedOperationException();
216 }
217
218 /**
219 * {@inheritDoc}
220 *
221 * @see java.util.Map#remove(java.lang.Object)
222 */
223 public Object remove(Object key) {
224 throw new UnsupportedOperationException();
225 }
226
227 /**
228 * {@inheritDoc}
229 *
230 * @see java.util.Map#size()
231 */
232 public int size() {
233 throw new UnsupportedOperationException();
234 }
235
236 /**
237 * {@inheritDoc}
238 *
239 * @see java.util.Map#values()
240 */
241 public Collection<Object> values() {
242 throw new UnsupportedOperationException();
243 }
244 }