1 package org.codehaus.mojo.jaxb2.shared.environment.sysprops;
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 org.apache.maven.plugin.logging.Log;
23 import org.codehaus.mojo.jaxb2.AbstractJaxbMojo;
24 import org.codehaus.mojo.jaxb2.shared.Validate;
25 import org.codehaus.mojo.jaxb2.shared.environment.AbstractLogAwareFacet;
26
27 import java.util.ArrayList;
28 import java.util.List;
29
30 /**
31 * EnvironmentFacet which changes
32 * system property key and two values (original and new values).
33 *
34 * @author <a href="mailto:lj@jguru.se">Lennart Jörelid</a>, jGuru Europe AB
35 * @since 2.1
36 */
37 public class SystemPropertyChangeEnvironmentFacet extends AbstractLogAwareFacet {
38
39 /**
40 * Operation definitions indicating how a System property should be changed by this EnvironmentFacet.
41 */
42 public enum ChangeType {
43
44 /**
45 * Indicates that a System property should be added during {@code setup()}
46 * and removed during {@code restore()}. If the property was already present,
47 * this behaves like {@code #CHANGE}.
48 */
49 ADD,
50
51 /**
52 * Indicates that a System property should be removed during {@code setup()}
53 * and restored/re-added during {@code restore()}
54 */
55 REMOVE,
56
57 /**
58 * Indicates that a System property should be altered during {@code setup()}
59 * and restored during {@code restore()}
60 */
61 CHANGE
62 }
63
64 // Internal state
65 private ChangeType type;
66 private String key;
67 private String newValue;
68 private String originalValue;
69
70 /**
71 * Creates a SystemPropertyChange which will remove the supplied system property for the
72 * duration of this SystemPropertyChange. No exception will be thrown if the supplied System property
73 * key is not found in the present System.properties.
74 *
75 * @param log The active Maven Log.
76 * @param key A non-null key.
77 * @see SystemPropertyChangeEnvironmentFacet.ChangeType#REMOVE
78 */
79 private SystemPropertyChangeEnvironmentFacet(final Log log, final String key) {
80
81 // Delegate
82 super(log);
83
84 // Assign internal state
85 this.key = key;
86 this.type = ChangeType.REMOVE;
87 }
88
89 /**
90 * Creates a SystemPropertyChange which stores the current
91 *
92 * @param log The active Maven Log.
93 * @param key The key of the System property managed by this SystemPropertyChange.
94 * @param newValue The new value of this SystemPropertyChange.
95 */
96 private SystemPropertyChangeEnvironmentFacet(final Log log, final String key, final String newValue) {
97
98 // Delegate
99 super(log);
100
101 // Assign internal state
102 this.key = key;
103 this.originalValue = System.getProperty(key);
104 this.newValue = newValue;
105 this.type = existsAsSystemProperty(key) ? ChangeType.CHANGE : ChangeType.ADD;
106 }
107
108 /**
109 * {@inheritDoc}
110 */
111 @Override
112 public void setup() {
113
114 if (type == ChangeType.REMOVE) {
115 System.clearProperty(key);
116 } else {
117 System.setProperty(key, newValue);
118 }
119
120 if(log.isDebugEnabled()) {
121 log.debug("Setup " + toString());
122 }
123 }
124
125 /**
126 * {@inheritDoc}
127 */
128 @Override
129 public void restore() {
130
131 if (type == ChangeType.ADD) {
132 System.clearProperty(key);
133 } else {
134 System.setProperty(key, originalValue);
135 }
136
137 if(log.isDebugEnabled()) {
138 log.debug("Restored " + toString());
139 }
140 }
141
142 /**
143 * @return A Debug string representation of this SystemPropertyChangeEnvironmentFacet.
144 */
145 @Override
146 public String toString() {
147 final String toReturn = "SysProp key [" + key + "]\n"
148 + " ... Original value: [" + originalValue + "]\n"
149 + " ... Changed value : [" + newValue + "]";
150 return toReturn.replace("\n", AbstractJaxbMojo.NEWLINE);
151 }
152
153 /**
154 * Creates a SystemPropertyChangesBuilder which uses the supplied active Maven Log.
155 *
156 * @param mavenLog The active Maven Log to be used by all SystemPropertyChange objects created
157 * by this SystemPropertyChangesBuilder.
158 * @return A SystemPropertyChangesBuilder ready for use.
159 */
160 public static SystemPropertyChangesBuilder getBuilder(final Log mavenLog) {
161 return new SystemPropertyChangesBuilder(mavenLog);
162 }
163
164 /**
165 * Builder class intended to simplify creating SystemPropertyChange EnvironmentFacets.
166 */
167 public static class SystemPropertyChangesBuilder {
168
169 // Internal state
170 private List<SystemPropertyChangeEnvironmentFacet> toReturn;
171 private Log mavenLog;
172
173 private SystemPropertyChangesBuilder(final Log mavenLog) {
174
175 // Check sanity
176 Validate.notNull(mavenLog, "mavenLog");
177
178 // Assign internal state
179 this.toReturn = new ArrayList<SystemPropertyChangeEnvironmentFacet>();
180 this.mavenLog = mavenLog;
181 }
182
183 /**
184 * Adds a SystemPropertyChange which removes the named System property.
185 *
186 * @param propertyName The name of the system property for which to create a REMOVE-type SystemPropertyChange.
187 * @return This builder, for chaining.
188 * @see SystemPropertyChangeEnvironmentFacet.ChangeType#REMOVE
189 */
190 public SystemPropertyChangesBuilder remove(final String propertyName) {
191
192 // Check sanity
193 checkSanity(propertyName);
194
195 // Add the SystemPropertyChange.
196 toReturn.add(new SystemPropertyChangeEnvironmentFacet(mavenLog, propertyName));
197
198 // All done.
199 return this;
200 }
201
202 /**
203 * Adds a SystemPropertyChange which adds or changes the named System property.
204 *
205 * @param propertyName The name of the system property for which to create an
206 * ADD- or CREATE-type SystemPropertyChange.
207 * @return This builder, for chaining.
208 * @see SystemPropertyChangeEnvironmentFacet.ChangeType#ADD
209 * @see SystemPropertyChangeEnvironmentFacet.ChangeType#CHANGE
210 */
211 public SystemPropertyChangesBuilder addOrChange(final String propertyName, final String value) {
212
213 // Check sanity
214 checkSanity(propertyName);
215
216 // Add the SystemPropertyChange.
217 toReturn.add(new SystemPropertyChangeEnvironmentFacet(mavenLog, propertyName, value));
218
219 // All done.
220 return this;
221
222 }
223
224 /**
225 * @return A List of SystemPropertyChange EnvironmentFacets which can be included as required into the
226 * ToolExecutionEnvironment.
227 */
228 public List<SystemPropertyChangeEnvironmentFacet> build() {
229 return toReturn;
230 }
231
232 //
233 // Private helpers
234 //
235
236 private void checkSanity(final String propertyName) {
237
238 // Check sanity
239 Validate.notEmpty(propertyName, "propertyName");
240
241 // Validate that the property name is not already present as a SystemPropertyChange.
242 for (SystemPropertyChangeEnvironmentFacet current : toReturn) {
243 if (current.key.equals(propertyName)) {
244 throw new IllegalArgumentException("A SystemPropertyChange for propertyName '" + propertyName +
245 "' is already present. Only one SystemPropertyChange per propertyName should be supplied.");
246 }
247 }
248 }
249 }
250
251 //
252 // Private helpers
253 //
254
255 private boolean existsAsSystemProperty(final String key) {
256 return System.getProperties().keySet().contains(key);
257 }
258 }