View Javadoc
1   package org.apache.maven.model;
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.io.IOException;
23  import java.io.InputStream;
24  import java.io.OutputStream;
25  import java.io.PrintStream;
26  import java.io.PrintWriter;
27  import java.io.Reader;
28  import java.io.Writer;
29  import java.util.Collection;
30  import java.util.Collections;
31  import java.util.Enumeration;
32  import java.util.InvalidPropertiesFormatException;
33  import java.util.Map;
34  import java.util.Properties;
35  import java.util.Set;
36  import java.util.function.BiConsumer;
37  import java.util.function.BiFunction;
38  import java.util.function.Consumer;
39  import java.util.function.Function;
40  import java.util.function.Supplier;
41  
42  class WrapperProperties extends Properties
43  {
44  
45      final Supplier<Map<String, String>> getter;
46      final Consumer<Properties> setter;
47  
48      WrapperProperties( Supplier<Map<String, String>> getter, Consumer<Properties> setter )
49      {
50          this.getter = getter;
51          this.setter = setter;
52      }
53  
54      @Override
55      public String getProperty( String key )
56      {
57          return getter.get().get( key );
58      }
59  
60      @Override
61      public String getProperty( String key, String defaultValue )
62      {
63          return getter.get().getOrDefault( key, defaultValue );
64      }
65  
66      @Override
67      public Enumeration<?> propertyNames()
68      {
69          return Collections.enumeration( getter.get().keySet() );
70      }
71  
72      @Override
73      public Set<String> stringPropertyNames()
74      {
75          return getter.get().keySet();
76      }
77  
78      @Override
79      public void list( PrintStream out )
80      {
81          throw new UnsupportedOperationException();
82      }
83  
84      @Override
85      public void list( PrintWriter out )
86      {
87          throw new UnsupportedOperationException();
88      }
89  
90      @Override
91      public int size()
92      {
93          return getter.get().size();
94      }
95  
96      @Override
97      public boolean isEmpty()
98      {
99          return getter.get().isEmpty();
100     }
101 
102     @Override
103     public Enumeration<Object> keys()
104     {
105         return Collections.enumeration( (Set) getter.get().keySet() );
106     }
107 
108     @Override
109     public Enumeration<Object> elements()
110     {
111         return Collections.enumeration( (Collection) getter.get().values() );
112     }
113 
114     @Override
115     public boolean contains( Object value )
116     {
117         return getter.get().containsKey( value != null ? value.toString() : null );
118     }
119 
120     @Override
121     public boolean containsValue( Object value )
122     {
123         return getter.get().containsValue( value );
124     }
125 
126     @Override
127     public boolean containsKey( Object key )
128     {
129         return getter.get().containsKey( key );
130     }
131 
132     @Override
133     public Object get( Object key )
134     {
135         return getter.get().get( key );
136     }
137 
138     @Override
139     public synchronized String toString()
140     {
141         return getter.get().toString();
142     }
143 
144     @Override
145     public Set<Object> keySet()
146     {
147         return (Set) getter.get().keySet();
148     }
149 
150     @Override
151     public Collection<Object> values()
152     {
153         return (Collection) getter.get().values();
154     }
155 
156     @Override
157     public Set<Map.Entry<Object, Object>> entrySet()
158     {
159         return (Set) getter.get().entrySet();
160     }
161 
162     @Override
163     public synchronized boolean equals( Object o )
164     {
165         if ( o instanceof WrapperProperties )
166         {
167             o = ( (WrapperProperties) o ).getter.get();
168         }
169         return getter.get().equals( o );
170     }
171 
172     @Override
173     public synchronized int hashCode()
174     {
175         return getter.get().hashCode();
176     }
177 
178     @Override
179     public Object getOrDefault( Object key, Object defaultValue )
180     {
181         return getter.get().getOrDefault( key, defaultValue != null ? defaultValue.toString() : null );
182     }
183 
184     @Override
185     public synchronized void forEach( BiConsumer<? super Object, ? super Object> action )
186     {
187         getter.get().forEach( action );
188     }
189 
190     interface WriteOp<T>
191     {
192         T perform( Properties props );
193     }
194 
195     interface WriteOpVoid
196     {
197         void perform( Properties props );
198     }
199 
200     private <T> T writeOperation( WriteOp<T> runner )
201     {
202         Properties props = new Properties();
203         props.putAll( getter.get() );
204         T ret = runner.perform( props );
205         if ( ! props.equals( getter.get() ) )
206         {
207             setter.accept( props );
208         }
209         return ret;
210     }
211 
212     private void writeOperationVoid( WriteOpVoid runner )
213     {
214         Properties props = new Properties();
215         props.putAll( getter.get() );
216         runner.perform( props );
217         if ( ! props.equals( getter.get() ) )
218         {
219             setter.accept( props );
220         }
221     }
222 
223     @Override
224     public synchronized Object setProperty( String key, String value )
225     {
226         return writeOperation( p -> p.setProperty( key, value ) );
227     }
228 
229     @Override
230     public synchronized Object put( Object key, Object value )
231     {
232         return writeOperation( p -> p.put( key, value ) );
233     }
234 
235     @Override
236     public synchronized Object remove( Object key )
237     {
238         return writeOperation( p -> p.remove( key ) );
239     }
240 
241     @Override
242     public synchronized void putAll( Map<?, ?> t )
243     {
244         writeOperationVoid( p -> p.putAll( t ) );
245     }
246 
247     @Override
248     public synchronized void clear()
249     {
250         writeOperationVoid( Properties::clear );
251     }
252 
253     @Override
254     public synchronized void replaceAll( BiFunction<? super Object, ? super Object, ?> function )
255     {
256         writeOperationVoid( p -> p.replaceAll( function ) );
257     }
258 
259     @Override
260     public synchronized Object putIfAbsent( Object key, Object value )
261     {
262         return writeOperation( p -> p.putIfAbsent( key, value ) );
263     }
264 
265     @Override
266     public synchronized boolean remove( Object key, Object value )
267     {
268         return writeOperation( p -> p.remove( key, value ) );
269     }
270 
271     @Override
272     public synchronized boolean replace( Object key, Object oldValue, Object newValue )
273     {
274         return writeOperation( p -> p.replace( key, oldValue, newValue ) );
275     }
276 
277     @Override
278     public synchronized Object replace( Object key, Object value )
279     {
280         return writeOperation( p -> p.replace( key, value ) );
281     }
282 
283     @Override
284     public synchronized Object computeIfAbsent( Object key, Function<? super Object, ?> mappingFunction )
285     {
286         return writeOperation( p -> p.computeIfAbsent( key, mappingFunction ) );
287     }
288 
289     @Override
290     public synchronized Object computeIfPresent( Object key,
291                                                  BiFunction<? super Object, ? super Object, ?> remappingFunction )
292     {
293         return writeOperation( p -> p.computeIfPresent( key, remappingFunction ) );
294     }
295 
296     @Override
297     public synchronized Object compute( Object key, BiFunction<? super Object, ? super Object, ?> remappingFunction )
298     {
299         return writeOperation( p -> p.compute( key, remappingFunction ) );
300     }
301 
302     @Override
303     public synchronized Object merge( Object key, Object value,
304                                       BiFunction<? super Object, ? super Object, ?> remappingFunction )
305     {
306         return writeOperation( p -> p.merge( key, value, remappingFunction ) );
307     }
308 
309     @Override
310     public synchronized void load( Reader reader ) throws IOException
311     {
312         throw new UnsupportedOperationException();
313     }
314 
315     @Override
316     public synchronized void load( InputStream inStream ) throws IOException
317     {
318         throw new UnsupportedOperationException();
319     }
320 
321     @Override
322     public void save( OutputStream out, String comments )
323     {
324         Properties props = new Properties();
325         props.putAll( getter.get() );
326         props.save( out, comments );
327     }
328 
329     @Override
330     public void store( Writer writer, String comments ) throws IOException
331     {
332         Properties props = new Properties();
333         props.putAll( getter.get() );
334         props.store( writer, comments );
335     }
336 
337     @Override
338     public void store( OutputStream out, String comments ) throws IOException
339     {
340         Properties props = new Properties();
341         props.putAll( getter.get() );
342         props.store( out, comments );
343     }
344 
345     @Override
346     public synchronized void loadFromXML( InputStream in ) throws IOException, InvalidPropertiesFormatException
347     {
348         throw new UnsupportedOperationException();
349     }
350 
351     @Override
352     public void storeToXML( OutputStream os, String comment ) throws IOException
353     {
354         Properties props = new Properties();
355         props.putAll( getter.get() );
356         props.storeToXML( os, comment );
357     }
358 
359     @Override
360     public void storeToXML( OutputStream os, String comment, String encoding ) throws IOException
361     {
362         Properties props = new Properties();
363         props.putAll( getter.get() );
364         props.storeToXML( os, comment, encoding );
365     }
366 
367 }