View Javadoc
1   package org.codehaus.mojo.aspectj;
2   
3   /**
4    * The MIT License
5    *
6    * Copyright 2005-2006 The Codehaus.
7    *
8    * Permission is hereby granted, free of charge, to any person obtaining a copy of
9    * this software and associated documentation files (the "Software"), to deal in
10   * the Software without restriction, including without limitation the rights to
11   * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
12   * of the Software, and to permit persons to whom the Software is furnished to do
13   * so, subject to the following conditions:
14   *
15   * The above copyright notice and this permission notice shall be included in all
16   * copies or substantial portions of the Software.
17   *
18   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24   * SOFTWARE.
25   */
26  
27  import org.apache.maven.artifact.Artifact;
28  import org.apache.maven.plugin.MojoExecutionException;
29  import org.apache.maven.plugins.annotations.Mojo;
30  import org.apache.maven.plugins.annotations.ResolutionScope;
31  import org.codehaus.plexus.util.StringUtils;
32  import org.w3c.dom.Document;
33  import org.w3c.dom.Element;
34  import org.w3c.dom.NodeList;
35  import org.xml.sax.SAXException;
36  
37  import javax.xml.parsers.DocumentBuilder;
38  import javax.xml.parsers.DocumentBuilderFactory;
39  import javax.xml.parsers.ParserConfigurationException;
40  import javax.xml.transform.OutputKeys;
41  import javax.xml.transform.Transformer;
42  import javax.xml.transform.TransformerException;
43  import javax.xml.transform.TransformerFactory;
44  import javax.xml.transform.dom.DOMSource;
45  import javax.xml.transform.stream.StreamResult;
46  import java.io.File;
47  import java.io.FileNotFoundException;
48  import java.io.FileOutputStream;
49  import java.io.IOException;
50  import java.io.PrintWriter;
51  import java.util.Date;
52  import java.util.Set;
53  
54  /**
55   * Create eclipse configuration of aspectJ
56   *
57   * @author Juraj Burian
58   */
59  @Mojo( name="EclipseAjcMojo", requiresDependencyResolution = ResolutionScope.COMPILE )
60  public class EclipseAjcMojo
61      extends AbstractAjcMojo
62  {
63      public static final String FILE_SEPARATOR = System.getProperty( "file.separator" );
64  
65      private final String[] ASPECT_LIBRARIES_KEYS = //
66          new String[]{ "org.eclipse.ajdt.ui.aspectPath.contentKind",
67              "org.eclipse.ajdt.ui.aspectPath.entryKind",
68              "org.eclipse.ajdt.ui.aspectPath" };
69  
70      private final String[] WEAVE_DEPENDENCIES_KEYS = //
71          new String[]{ "org.eclipse.ajdt.ui.inPath.contentKind",
72              "org.eclipse.ajdt.ui.inPath.entryKind",
73              "org.eclipse.ajdt.ui.inPath" };
74  
75      private static final String AJ_BUILDER = "org.eclipse.ajdt.core.ajbuilder";
76  
77      private static final String M2_BUILDER = "org.maven.ide.eclipse.maven2Builder";
78  
79      private static final String AJ_NATURE = "org.eclipse.ajdt.ui.ajnature";
80  
81      public void execute()
82          throws MojoExecutionException
83      {
84          // exclude this :
85          if ( "pom".endsWith( project.getPackaging() ) || "ear".endsWith( project.getPackaging() ) )
86          {
87              return;
88          }
89  
90          // write file
91          File prefs = new File( basedir, ".settings" + FILE_SEPARATOR + "org.eclipse.ajdt.ui.prefs" );
92          try
93          {
94              prefs.getParentFile().mkdirs();
95              prefs.createNewFile();
96          }
97          catch ( IOException e )
98          {
99              throw new MojoExecutionException( "Can't create file: " + prefs.getPath() );
100         }
101 
102         PrintWriter out = null;
103         try
104         {
105             out = new PrintWriter( new FileOutputStream( prefs ) );
106         }
107         catch ( FileNotFoundException e )
108         {
109             // can't happen
110         }
111         out.println( "#" + new Date() );
112         out.println( "eclipse.preferences.version=1" );
113         writePaths( out, aspectLibraries, ASPECT_LIBRARIES_KEYS );
114         writePaths( out, weaveDependencies, WEAVE_DEPENDENCIES_KEYS );
115         if ( xmlConfigured != null )
116         {
117             String xmlPath;
118             if ( xmlConfigured.isAbsolute() )
119             {
120                 xmlPath = xmlConfigured.getAbsolutePath();
121             }
122             else
123             {
124                 // Note: Eclipse always use '/' here, not FILE_SEPARATOR
125                 xmlPath = "/" + project.getName() + "/" + xmlConfigured;
126             }
127             out.println( "org.eclipse.ajdt.aopxml=" + xmlPath );
128         }
129         out.flush();
130         out.close();
131 
132         // merge .project file if exists
133         File dotProject = new File( basedir, ".project" );
134         if ( dotProject.exists() )
135         {
136             mergeProject( dotProject );
137         }
138     }
139 
140     private final void writePaths( PrintWriter out, Module[] modules, String[] keys )
141         throws MojoExecutionException
142     {
143         if ( modules == null || modules.length == 0 )
144         {
145             return;
146         }
147         String[] paths = new String[modules.length];
148         for ( int i = 0; i < modules.length; i++ )
149         {
150             Module module = modules[i];
151             // String key = ArtifactUtils.versionlessKey( module.getGroupId(), module.getArtifactId() );
152             // Artifact artifact = (Artifact) project.getArtifactMap().get( key );
153             Artifact artifact = null;
154             @SuppressWarnings("unchecked") Set<Artifact> allArtifacts = project.getArtifacts();
155             for ( Artifact art : allArtifacts )
156             {
157                 if ( art.getGroupId().equals( module.getGroupId() )
158                     && art.getArtifactId().equals( module.getArtifactId() )
159                     && StringUtils.equals( module.getClassifier(), art.getClassifier() )
160                     && StringUtils.equals( module.getType(), module.getType() ) )
161                 {
162                     artifact = art;
163                     break;
164                 }
165 
166             }
167             if ( artifact == null )
168             {
169                 throw new MojoExecutionException( "The artifact " + module.toString()
170                                                       + " referenced in aspectj plugin as an aspect library, is not found the project dependencies" );
171 
172             }
173             paths[i] = artifact.getFile().getPath();
174         }
175         for ( int i = 1; i <= paths.length; i++ )
176         {
177             out.println( "org.eclipse.ajdt.ui.aspectPath.contentKind" + i + "=BINARY" );
178         }
179         for ( int i = 1; i <= paths.length; i++ )
180         {
181             out.println( "org.eclipse.ajdt.ui.aspectPath.entryKind" + i + "=LIBRARY" );
182         }
183         for ( int i = 0; i < paths.length; i++ )
184         {
185             out.print( "org.eclipse.ajdt.ui.aspectPath" + i + "=" );
186             String path = paths[i];
187             path = StringUtils.replace( path, "\\", "/" );
188             path = StringUtils.replace( path, ":", "\\:" );
189             out.println( path );
190         }
191     }
192 
193     /**
194      * @throws
195      */
196     private void mergeProject( File file )
197         throws MojoExecutionException
198     {
199         try
200         {
201             DocumentBuilder builder = //
202                 DocumentBuilderFactory.newInstance().newDocumentBuilder();
203             Document document = builder.parse( file );
204             boolean builderMerged = mergeBuilders( document );
205             boolean natureMerged = mergeNatures( document );
206             if ( builderMerged || natureMerged )
207             {
208                 writeDocument( document, file );
209             }
210 
211         }
212         catch ( ParserConfigurationException ex )
213         {
214             throw new MojoExecutionException( "Can't create doom parser configuration", ex );
215 
216         }
217         catch ( SAXException ex )
218         {
219             throw new MojoExecutionException( "Can't parse .project file", ex );
220 
221         }
222         catch ( Exception ex )
223         {
224             throw new MojoExecutionException( "Can't merge .project file", ex );
225         }
226     }
227 
228     /**
229      * @param document
230      * @return true if document need be saved
231      */
232     // TODO remove javac builder if aspectJ builder is used
233     private boolean mergeBuilders( Document document )
234         throws MojoExecutionException
235     {
236         NodeList buildCommandList = document.getElementsByTagName( "buildCommand" );
237         for ( int i = 0; i < buildCommandList.getLength(); i++ )
238         {
239             Element buildCommand = (Element) buildCommandList.item( i );
240             NodeList nameList = buildCommand.getElementsByTagName( "name" );
241             for ( int j = 0; j < nameList.getLength(); j++ )
242             {
243                 Element name = (Element) nameList.item( j );
244                 if ( name.getNodeValue().equals( AJ_BUILDER ) )
245                 {
246                     return false;
247                 }
248                 // if maven2 builder is used we don't need
249                 // use aspectJ builder
250                 if ( name.getNodeValue().equals( M2_BUILDER ) )
251                 {
252                     return false;
253                 }
254             }
255         }
256         // we need add aspectJ builder node
257         NodeList buildSpecList = document.getElementsByTagName( "buildSpec" );
258         if ( 0 == buildSpecList.getLength() )
259         {
260             NodeList nodes = document.getElementsByTagName( "natures" );
261             if ( 0 == nodes.getLength() )
262             {
263                 throw new MojoExecutionException( "At least one nature must be specified in .project file!" );
264             }
265             Element buildSpec = document.createElement( "buildSpec" );
266             document.insertBefore( buildSpec, nodes.item( 0 ) );
267             buildSpecList = document.getElementsByTagName( "buildSpec" );
268         }
269         Element buildSpec = (Element) buildSpecList.item( 0 );
270         Element buildCommand = document.createElement( "buildCommand" );
271 
272         // create & append <name/>
273         Element name = document.createElement( "name" );
274         name.setNodeValue( AJ_BUILDER );
275         buildCommand.appendChild( name );
276 
277         // create & append <arguments/>
278         buildCommand.appendChild( document.createElement( "arguments" ) );
279 
280         buildSpec.insertBefore( buildCommand, buildSpec.getFirstChild() );
281 
282         return true;
283     }
284 
285     private boolean mergeNatures( Document document )
286         throws MojoExecutionException
287     {
288         NodeList naturesList = document.getElementsByTagName( "natures" );
289         for ( int i = 0; i < naturesList.getLength(); i++ )
290         {
291             Element natures = (Element) naturesList.item( i );
292             NodeList natureList = natures.getElementsByTagName( "nature" );
293             for ( int j = 0; j < natureList.getLength(); j++ )
294             {
295                 Element nature = (Element) natureList.item( j );
296                 if ( nature.getNodeValue().equals( AJ_NATURE ) )
297                 {
298                     return false;
299                 }
300             }
301         }
302         Element natures = (Element) naturesList.item( 0 );
303         Element nature = document.createElement( "nature" );
304         nature.setNodeValue( AJ_NATURE );
305         natures.appendChild( nature );
306         return true;
307     }
308 
309     /**
310      * write document to the file
311      *
312      * @param document
313      * @param file
314      * @throws TransformerException
315      * @throws FileNotFoundException
316      */
317     private void writeDocument( Document document, File file )
318         throws TransformerException, FileNotFoundException
319     {
320         document.normalize();
321         DOMSource source = new DOMSource( document );
322         StreamResult result = new StreamResult( new FileOutputStream( file ) );
323         Transformer transformer = TransformerFactory.newInstance().newTransformer();
324         transformer.setOutputProperty( OutputKeys.INDENT, "yes" );
325         transformer.transform( source, result );
326     }
327 }