View Javadoc

1   package org.apache.maven.plugins.scm.release;
2   
3   /* ====================================================================
4    *   Licensed to the Apache Software Foundation (ASF) under one or more
5    *   contributor license agreements.  See the NOTICE file distributed with
6    *   this work for additional information regarding copyright ownership.
7    *   The ASF licenses this file to You under the Apache License, Version 2.0
8    *   (the "License"); you may not use this file except in compliance with
9    *   the License.  You may obtain a copy of the License at
10   *
11   *       http://www.apache.org/licenses/LICENSE-2.0
12   *
13   *   Unless required by applicable law or agreed to in writing, software
14   *   distributed under the License is distributed on an "AS IS" BASIS,
15   *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   *   See the License for the specific language governing permissions and
17   *   limitations under the License.
18   * ====================================================================
19   */
20  
21  import java.io.File;
22  import java.io.FileOutputStream;
23  import java.io.OutputStream;
24  import java.io.PrintStream;
25  import java.util.ArrayList;
26  import java.util.Iterator;
27  import java.util.List;
28  import java.util.Map;
29  
30  import org.apache.commons.io.FileUtils;
31  import org.dom4j.Document;
32  import org.dom4j.Namespace;
33  import org.dom4j.Node;
34  import org.dom4j.io.OutputFormat;
35  import org.dom4j.io.SAXReader;
36  import org.dom4j.io.XMLWriter;
37  import org.jaxen.XPath;
38  import org.jaxen.dom4j.Dom4jXPath;
39  import org.xml.sax.Attributes;
40  import org.xml.sax.SAXException;
41  import org.xml.sax.helpers.XMLFilterImpl;
42  
43  /**
44   * This is the base class for any tool that attempts to transform fields
45   * in the POM. Currently we are using the XML form of the POM and using Jaxen
46   * but eventually we will be able to perform the same transformations on
47   * POM beans. Jaxen needs to be modified and some serious cleanup needs to
48   * go on in Maven internally, but this will serve as a start. An attempt is
49   * made to make this tool GUI friendly.
50   *
51   * @author <a href="mailto:jason@zenplex.com">Jason van Zyl</a>
52   *
53   * @version $Id: AbstractPomTransformer.java 521198 2007-03-22 10:39:43Z ltheussl $
54   */
55  public abstract class AbstractPomTransformer
56      implements PomTransformer
57  {
58      /** POM document */
59      private File project;
60  
61      /** Dom4j document. */
62      private Document document;
63  
64      /** Output file. */
65      private File outputFile;
66  
67      /** Properties used in transformNode */
68      private Map variables;
69  
70      /** Nodes selected for transformation using xpath. */
71      private List selectedNodes;
72  
73      private List transformations;
74  
75      // -------------------------------------------------------------------------
76      // Accessors
77      // -------------------------------------------------------------------------
78  
79      /**
80       *
81       * @return
82       */
83      public Map getVariables()
84      {
85          return variables;
86      }
87  
88      /**
89       *
90       * @param variables
91       */
92      public void setVariables( Map variables )
93      {
94          this.variables = variables;
95      }
96  
97      /**
98       *
99       * @param project
100      */
101     public void setProject( File project )
102     {
103         this.project = project;
104     }
105 
106     /**
107      *
108      * @return
109      */
110     public File getProject()
111     {
112         return project;
113     }
114 
115     /**
116      *
117      * @return
118      */
119     public Document getDocument()
120     {
121         return document;
122     }
123 
124     /**
125      *
126      * @param document
127      */
128     public void setDocument( Document document )
129     {
130         this.document = document;
131     }
132 
133     /**
134      *
135      * @return
136      */
137     public File getOutputFile()
138     {
139         return outputFile;
140     }
141 
142     /**
143      *
144      * @param outputFile
145      */
146     public void setOutputFile( File outputFile )
147     {
148         this.outputFile = outputFile;
149     }
150 
151     /**
152      *
153      * @return
154      */
155     public List getSelectedNodes()
156     {
157         if ( selectedNodes == null )
158         {
159             try
160             {
161                 selectNodes();
162             }
163             catch ( Exception e )
164             {
165                 // do nothing.
166             }
167         }
168         return selectedNodes;
169     }
170 
171     /**
172      *
173      * @param selectedNodes
174      */
175     public void setSelectedNodes( List selectedNodes )
176     {
177         this.selectedNodes = selectedNodes;
178     }
179 
180     /**
181      *
182      * @return
183      */
184     public int getSelectedNodeCount()
185     {
186         return getSelectedNodes().size();
187     }
188 
189     /**
190      *
191      * @return
192      */
193     public List getTransformations()
194     {
195         if ( transformations == null )
196         {
197             createTransformations();
198         }
199 
200         return transformations;
201     }
202 
203     /**
204      *
205      */
206     public void createTransformations()
207     {
208         transformations = new ArrayList();
209 
210         for ( Iterator i = getSelectedNodes().iterator(); i.hasNext(); )
211         {
212             Object o = i.next();
213 
214             if ( o instanceof Node )
215             {
216                 Transformation transformation = new Transformation( this );
217                 transformation.setNode( (Node) o );
218                 transformations.add( transformation );
219             }
220         }
221     }
222 
223     /**
224      * This is the automated way of transforming the nodes if there is
225      * no user interaction involved.
226      *
227      * @throws Exception If an error occurs while transforming the nodes.
228      */
229     public void transformNodes()
230         throws Exception
231     {
232         for ( Iterator i = getSelectedNodes().iterator(); i.hasNext(); )
233         {
234             Object o = i.next();
235 
236             if ( o instanceof Node )
237             {
238                 transformNode( (Node) o );
239             }
240         }
241     }
242 
243     // ----------------------------------------------------------------------
244     // Implementation
245     // ----------------------------------------------------------------------
246 
247     /**
248      *
249      * @return
250      */
251     public abstract String selectNodesXPathExpression();
252 
253     /**
254      *
255      * @param node
256      * @throws Exception
257      */
258     public abstract void transformNode( Node node )
259         throws Exception;
260 
261     /**
262      * Update the snapshot version identifiers with actual timestamp versions
263      * and write out the POM in its updated form.
264      *
265      * @throws Exception
266      */
267     public void selectNodes()
268         throws Exception
269     {
270         SAXReader reader = new SAXReader();
271 
272         // make xpath expressions worh with poms with or without namespace
273         reader.setXMLFilter( new XMLFilterImpl()
274         {
275 
276             public void endElement( String uri, String localName, String qName )
277                 throws SAXException
278             {
279                 super.endElement( "", localName, "" );
280             }
281 
282             public void startElement( String uri, String localName, String qName, Attributes atts )
283                 throws SAXException
284             {
285                 super.startElement( "", localName, "", atts );
286             }
287 
288         } );
289         setDocument( reader.read( getProject() ) );
290 
291         // The selecting nodes with the xpath expression will give us a list
292         // of dependencies elements where the version element is equal to 'SNAPSHOT'.
293         // So we can get any information we need, and alter anything we need to before writing
294         // the dom4j document back out.
295         XPath xpath = new Dom4jXPath( selectNodesXPathExpression() );
296         setSelectedNodes( xpath.selectNodes( getDocument() ) );
297     }
298 
299     /**
300      *
301      * @throws Exception
302      */
303     public void write()
304         throws Exception
305     {
306         write( null );
307     }
308 
309     /**
310      *
311      * @throws Exception
312      */
313     public void write( String encoding )
314         throws Exception
315     {
316         OutputStream os = null;
317 
318         if ( getOutputFile() != null )
319         {
320             // Backup the original first.
321             FileUtils.copyFile( getOutputFile(), new File( getOutputFile() + ".backup" ) );
322 
323             // Now hand of the os.
324             os = new FileOutputStream( getOutputFile() );
325         }
326         else
327         {
328             os = new PrintStream( System.out );
329         }
330 
331         OutputFormat format = new OutputFormat();
332         format.setIndentSize( 2 );
333         format.setNewlines( true );
334         format.setTrimText( true );
335         if ( encoding != null )
336         {
337             format.setEncoding( encoding );
338         }
339 
340         XMLWriter writer = new XMLWriter( format )
341         {
342             protected boolean isNamespaceDeclaration( Namespace ns )
343             {
344                 // this will filter out empty namespaces, only the correct POM ns is allowed
345                 return "http://maven.apache.org/POM/3.0.0".equals( ns.getURI() );
346             }
347         };
348 
349         writer.setOutputStream( os );
350         writer.write( getDocument() );
351         writer.flush();
352         writer.close();
353     }
354 }