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