View Javadoc

1   package org.apache.maven.plugin.idea;
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.artifact.factory.ArtifactFactory;
23  import org.apache.maven.artifact.repository.ArtifactRepository;
24  import org.apache.maven.artifact.resolver.ArtifactResolver;
25  import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
26  import org.apache.maven.plugin.MojoExecutionException;
27  import org.apache.maven.plugin.logging.Log;
28  import org.apache.maven.project.MavenProject;
29  import org.codehaus.plexus.util.StringUtils;
30  import org.dom4j.Element;
31  import org.dom4j.Document;
32  import org.dom4j.DocumentException;
33  
34  import java.io.File;
35  import java.io.IOException;
36  import java.util.Iterator;
37  import java.util.Set;
38  import java.util.StringTokenizer;
39  
40  /**
41   * Creates the project file (*.ipr) for IntelliJ IDEA.
42   *
43   * @author Edwin Punzalan
44   * @goal project
45   * @execute phase="generate-sources"
46   */
47  public class IdeaProjectMojo
48      extends AbstractIdeaMojo
49  {
50      /**
51       * Specify the name of the registered IDEA JDK to use
52       * for the project.
53       *
54       * @parameter expression="${jdkName}"
55       */
56      private String jdkName;
57  
58      /**
59       * Specify the version of the JDK to use for the project for the purpose of
60       * enabled assertions and Java 5.0 language features.
61       * The default value is the specification version of the executing JVM.
62       *
63       * @parameter expression="${jdkLevel}"
64       * @todo would be good to use the compilation source if possible
65       */
66      private String jdkLevel;
67  
68      /**
69       * Specify the resource pattern in wildcard format, for example "?*.xml;?*.properties".
70       * Currently supports 4.x and 5.x.
71       * Because IDEA doesn't distinguish between source and resources directories, this is needed.
72       * The default value corresponds to any file without a java extension.
73       * Please note that the default value includes package.html files as it's not possible to exclude those.
74       *
75       * @parameter expression="${wildcardResourcePatterns}" default-value="!?*.java"
76       */
77      private String wildcardResourcePatterns;
78  
79      /**
80       * Specify the version of IDEA to target.  This is needed to identify the default formatting of
81       * project-jdk-name used by IDEA.  Currently supports 4.x and 5.x.
82       * <p/>
83       * This will only be used when parameter jdkName is not set.
84       *
85       * @parameter expression="${ideaVersion}" default-value="5.x"
86       */
87      private String ideaVersion;
88  
89      private Set macros;
90  
91      public void initParam( MavenProject project, ArtifactFactory artifactFactory, ArtifactRepository localRepo,
92                             ArtifactResolver artifactResolver, ArtifactMetadataSource artifactMetadataSource, Log log,
93                             boolean overwrite, String jdkName, String jdkLevel, String wildcardResourcePatterns,
94                             String ideaVersion, Set macros )
95      {
96          super.initParam( project, artifactFactory, localRepo, artifactResolver, artifactMetadataSource, log,
97                           overwrite );
98  
99          this.jdkName = jdkName;
100 
101         this.jdkLevel = jdkLevel;
102 
103         this.wildcardResourcePatterns = wildcardResourcePatterns;
104 
105         this.ideaVersion = ideaVersion;
106 
107         this.macros = macros;
108     }
109 
110     /**
111      * Create IDEA (.ipr) project files.
112      *
113      * @throws org.apache.maven.plugin.MojoExecutionException
114      *
115      */
116     public void execute()
117         throws MojoExecutionException
118     {
119         try
120         {
121             doDependencyResolution( executedProject, localRepo );
122         }
123         catch ( Exception e )
124         {
125             throw new MojoExecutionException( "Unable to build project dependencies.", e );
126         }
127 
128         rewriteProject();
129     }
130 
131     public void rewriteProject()
132         throws MojoExecutionException
133     {
134         File projectFile = new File( executedProject.getBasedir(), executedProject.getArtifactId() + ".ipr" );
135 
136         try
137         {
138             Document document = readXmlDocument( projectFile, "project.xml" );
139 
140             Element module = document.getRootElement();
141 
142             // Set the jdk name if set
143             if ( jdkName != null )
144             {
145                 setJdkName( module, jdkName );
146             }
147             else
148             {
149                 String javaVersion = System.getProperty( "java.version" );
150                 String defaultJdkName;
151 
152                 if ( ideaVersion.startsWith( "4" ) )
153                 {
154                     defaultJdkName = "java version &quot;" + javaVersion + "&quot;";
155                 }
156                 else
157                 {
158                     defaultJdkName = javaVersion.substring( 0, 3 );
159                 }
160                 getLog().info( "jdkName is not set, using [java version" + javaVersion + "] as default." );
161                 setJdkName( module, defaultJdkName );
162             }
163 
164             setWildcardResourcePatterns( module, wildcardResourcePatterns );
165 
166             Element component = findComponent( module, "ProjectModuleManager" );
167             Element modules = findElement( component, "modules" );
168 
169             removeOldElements( modules, "module" );
170 
171             if ( executedProject.getCollectedProjects().size() > 0 )
172             {
173                 Element m = createElement( modules, "module" );
174                 String projectPath =
175                     new File( executedProject.getBasedir(),
176                               executedProject.getArtifactId() + ".iml" ).getAbsolutePath();
177                 m.addAttribute( "filepath",
178                                 "$PROJECT_DIR$/" + toRelative( executedProject.getBasedir().getAbsolutePath(),
179                                                                projectPath ) );
180 
181                 for ( Iterator i = executedProject.getCollectedProjects().iterator(); i.hasNext(); )
182                 {
183                     MavenProject p = (MavenProject) i.next();
184 
185                     m = createElement( modules, "module" );
186                     String modulePath = new File( p.getBasedir(), p.getArtifactId() + ".iml" ).getAbsolutePath();
187                     m.addAttribute( "filepath",
188                                     "$PROJECT_DIR$/" + toRelative( executedProject.getBasedir().getAbsolutePath(),
189                                                                    modulePath ) );
190                 }
191             }
192             else
193             {
194                 Element m = createElement( modules, "module" );
195                 String modulePath =
196                     new File( executedProject.getBasedir(),
197                               executedProject.getArtifactId() + ".iml" ).getAbsolutePath();
198                 m.addAttribute( "filepath",
199                                 "$PROJECT_DIR$/" + toRelative( executedProject.getBasedir().getAbsolutePath(),
200                                                                modulePath ) );
201             }
202 
203             // add any PathMacros we've come across
204             if ( macros != null && module.elements( "UsedPathMacros" ).size() > 0 )
205             {
206                 Element usedPathMacros = (Element) module.elements( "UsedPathMacros" ).get( 0 );
207                 removeOldElements( usedPathMacros, "macro" );
208                 for ( Iterator iterator = macros.iterator(); iterator.hasNext(); )
209                 {
210                     String macro = (String) iterator.next();
211                     Element macroElement = createElement( usedPathMacros, "macro" );
212                     macroElement.addAttribute( "name", macro );
213                 }
214             }
215 
216             writeXmlDocument( projectFile, document );
217         }
218         catch ( DocumentException e )
219         {
220             throw new MojoExecutionException( "Error parsing existing IPR file: " + projectFile.getAbsolutePath(), e );
221         }
222         catch ( IOException e )
223         {
224             throw new MojoExecutionException( "Error parsing existing IPR file: " + projectFile.getAbsolutePath(), e );
225         }
226     }
227 
228     /**
229      * Sets the name of the JDK to use.
230      *
231      * @param content Xpp3Dom element.
232      * @param jdkName Name of the JDK to use.
233      */
234     private void setJdkName( Element content, String jdkName )
235     {
236         Element component = findComponent( content, "ProjectRootManager" );
237         component.addAttribute( "project-jdk-name", jdkName );
238 
239         String jdkLevel = this.jdkLevel;
240         if ( jdkLevel == null )
241         {
242             jdkLevel = System.getProperty( "java.specification.version" );
243         }
244 
245         if ( jdkLevel.startsWith( "1.4" ) )
246         {
247             component.addAttribute( "assert-keyword", "true" );
248             component.addAttribute( "jdk-15", "false" );
249         }
250         else if ( jdkLevel.compareTo( "1.5" ) >= 0 )
251         {
252             component.addAttribute( "assert-keyword", "true" );
253             component.addAttribute( "jdk-15", "true" );
254         }
255         else
256         {
257             component.addAttribute( "assert-keyword", "false" );
258         }
259     }
260 
261     /**
262      * Sets the wilcard resource patterns.
263      *
264      * @param content                  Xpp3Dom element.
265      * @param wildcardResourcePatterns The wilcard resource patterns.
266      */
267     private void setWildcardResourcePatterns( Element content, String wildcardResourcePatterns )
268     {
269         Element compilerConfigurationElement = findComponent( content, "CompilerConfiguration" );
270         if ( !StringUtils.isEmpty( wildcardResourcePatterns ) )
271         {
272             removeOldElements( compilerConfigurationElement, "wildcardResourcePatterns" );
273             Element wildcardResourcePatternsElement =
274                 createElement( compilerConfigurationElement, "wildcardResourcePatterns" );
275             StringTokenizer wildcardResourcePatternsTokenizer = new StringTokenizer( wildcardResourcePatterns, ";" );
276             while ( wildcardResourcePatternsTokenizer.hasMoreTokens() )
277             {
278                 String wildcardResourcePattern = wildcardResourcePatternsTokenizer.nextToken();
279                 Element entryElement = createElement( wildcardResourcePatternsElement, "entry" );
280                 entryElement.addAttribute( "name", wildcardResourcePattern );
281             }
282         }
283     }
284 }