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