View Javadoc
1   package org.apache.maven.plugin.eclipse.writers.rad;
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.File;
23  import java.io.FileInputStream;
24  import java.io.FileNotFoundException;
25  import java.io.FileOutputStream;
26  import java.io.IOException;
27  import java.io.InputStreamReader;
28  import java.io.OutputStreamWriter;
29  import java.io.Reader;
30  import java.io.Writer;
31  import java.util.Arrays;
32  import java.util.Comparator;
33  
34  import org.apache.maven.plugin.MojoExecutionException;
35  import org.apache.maven.plugin.eclipse.Constants;
36  import org.apache.maven.plugin.eclipse.Messages;
37  import org.apache.maven.plugin.eclipse.writers.AbstractEclipseWriter;
38  import org.codehaus.plexus.util.IOUtil;
39  import org.codehaus.plexus.util.xml.PrettyPrintXMLWriter;
40  import org.codehaus.plexus.util.xml.XMLWriter;
41  import org.codehaus.plexus.util.xml.Xpp3Dom;
42  import org.codehaus.plexus.util.xml.Xpp3DomBuilder;
43  import org.codehaus.plexus.util.xml.Xpp3DomWriter;
44  
45  /**
46   * Adapts the .classpath file for RAD6 for now write hardcoded: target/websphere/classes future releases could make this
47   * varriable.
48   * 
49   * @author <a href="mailto:nir@cfc.at">Richard van Nieuwenhoven </a>
50   */
51  public class RadEjbClasspathWriter
52      extends AbstractEclipseWriter
53  {
54  
55      private static final String CLASSPATH = "classpath";
56  
57      private static final String CLASSPATH_FILE = ".classpath";
58  
59      private static final String CLASSPATHENTRY = "classpathentry";
60  
61      private static final String CON = "con";
62  
63      private static final String KIND = "kind";
64  
65      private static final String LIB = "lib";
66  
67      private static final String OUTPUT = "output";
68  
69      private static final String PATH = "path";
70  
71      private static final String SRC = "src";
72  
73      private static final String TARGET_WEBSPHERE_CLASSES = "target/websphere/generated-classes";
74  
75      private static final String VAR = "var";
76  
77      private static final String WEBSPHERE6CONTAINER =
78          "com.ibm.wtp.server.java.core.container/com.ibm.ws.ast.st.runtime.core.runtimeTarget.v60/was.base.v6";
79  
80      /**
81       * write the .classpath file to the project root directory.
82       * 
83       * @param sourceDirs all eclipse source directorys
84       * @param localRepository the local reposetory
85       * @param buildOutputDirectory build output directory (target)
86       * @throws MojoExecutionException when writing the config files was not possible
87       */
88      public void write()
89          throws MojoExecutionException
90      {
91          String packaging = config.getPackaging();
92          if ( Constants.PROJECT_PACKAGING_EJB.equalsIgnoreCase( packaging ) )
93          {
94              new File( config.getEclipseProjectDirectory(), TARGET_WEBSPHERE_CLASSES ).mkdirs();
95              File classpathFile = new File( config.getEclipseProjectDirectory(), CLASSPATH_FILE );
96  
97              if ( !classpathFile.exists() )
98              {
99                  return;
100             }
101             Xpp3Dom classpath = readXMLFile( classpathFile );
102             Xpp3Dom[] children = classpath.getChildren();
103             for ( Xpp3Dom aChildren : children )
104             {
105                 if ( LIB.equals( aChildren.getAttribute( KIND ) )
106                     && TARGET_WEBSPHERE_CLASSES.equals( aChildren.getAttribute( "path" ) ) )
107                 {
108                     return; // nothing to do!
109                 }
110             }
111 
112             Xpp3Dom newEntry = new Xpp3Dom( CLASSPATHENTRY );
113             newEntry.setAttribute( KIND, LIB );
114             newEntry.setAttribute( PATH, TARGET_WEBSPHERE_CLASSES );
115             classpath.addChild( newEntry );
116 
117             newEntry = new Xpp3Dom( CLASSPATHENTRY );
118             newEntry.setAttribute( KIND, CON );
119             newEntry.setAttribute( PATH, WEBSPHERE6CONTAINER );
120             classpath.addChild( newEntry );
121 
122             children = classpath.getChildren();
123             for ( int index = children.length - 1; index >= 0; index-- )
124             {
125                 if ( children[index].getValue() == null )
126                 {
127                     children[index].setValue( "" );
128                 }
129             }
130 
131             removeDupicateWAS6Libs( classpath );
132             classpath = orderClasspath( classpath );
133 
134             Writer w;
135             try
136             {
137                 w = new OutputStreamWriter( new FileOutputStream( classpathFile ), "UTF-8" );
138             }
139             catch ( IOException ex )
140             {
141                 throw new MojoExecutionException( Messages.getString( "EclipsePlugin.erroropeningfile" ), ex );
142             }
143             XMLWriter writer = new PrettyPrintXMLWriter( w, "UTF-8", null );
144             Xpp3DomWriter.write( writer, classpath );
145             IOUtil.close( w );
146         }
147     }
148 
149     /**
150      * determinate of witch type this classpath entry is. this is used for sorting them.
151      * 
152      * @param classpathentry the classpath entry to sort
153      * @return an integer identifieing the type
154      * @see RadEjbClasspathWriter#orderClasspath(Xpp3Dom)
155      */
156     private int detectClasspathEntryType( Xpp3Dom classpathentry )
157     {
158         String kind = classpathentry.getAttribute( KIND );
159         String path = classpathentry.getAttribute( PATH );
160 
161         if ( kind == null || path == null )
162         {
163             return 6;
164         }
165 
166         boolean absolutePath = path.startsWith( "\\" ) || path.startsWith( "/" );
167         boolean windowsAbsolutePath = path.indexOf( ':' ) >= 0;
168         boolean anyAbsolutePath = absolutePath || windowsAbsolutePath;
169 
170         if ( kind.equals( SRC ) && !absolutePath )
171         {
172             return 1;
173         }
174         else if ( kind.equals( LIB ) && !anyAbsolutePath )
175         {
176             return 2;
177         }
178         else if ( kind.equals( SRC ) )
179         {
180             return 3;
181         }
182         else if ( kind.equals( VAR ) )
183         {
184             return 4;
185         }
186         else if ( kind.equals( LIB ) )
187         {
188             return 5;
189         }
190         else if ( kind.equals( OUTPUT ) )
191         {
192             return 7;
193         }
194         else
195         {
196             return 6;
197         }
198     }
199 
200     /**
201      * Order of classpath this is nessesary for the ejb's the generated classes are elsewise not found. 1 - kind=src
202      * ohne starting '/' oder '\' 2 - kind=lib kein ':' und kein start mit '/' oder '\' 3 - kind=src mit ohne starting
203      * '/' oder '\' 4 - kind=var 5 - kind=lib ein ':' oder start mit '/' oder '\' 6 - rest 7 - kind=output
204      * 
205      * @param classpath the classpath to sort
206      * @return dom-tree representing ordered classpath
207      */
208     private Xpp3Dom orderClasspath( Xpp3Dom classpath )
209     {
210         Xpp3Dom[] children = classpath.getChildren();
211         Arrays.sort( children, new Comparator()
212         {
213             public int compare( Object o1, Object o2 )
214             {
215                 return detectClasspathEntryType( (Xpp3Dom) o1 ) - detectClasspathEntryType( (Xpp3Dom) o2 );
216             }
217         } );
218         Xpp3Dom resultClasspath = new Xpp3Dom( CLASSPATH );
219         for ( Xpp3Dom aChildren : children )
220         {
221             resultClasspath.addChild( aChildren );
222         }
223         return resultClasspath;
224     }
225 
226     /**
227      * read an xml file (application.xml or .modulemaps).
228      * 
229      * @param xmlFile an xmlfile
230      * @return dom-tree representing the file contents
231      */
232     private Xpp3Dom readXMLFile( File xmlFile )
233     {
234         try
235         {
236             Reader reader = new InputStreamReader( new FileInputStream( xmlFile ), "UTF-8" );
237             Xpp3Dom applicationXmlDom = Xpp3DomBuilder.build( reader );
238             return applicationXmlDom;
239         }
240         catch ( FileNotFoundException e )
241         {
242             return null;
243         }
244         catch ( Exception e )
245         {
246             log.error( Messages.getString( "EclipsePlugin.cantreadfile", xmlFile.getAbsolutePath() ) );
247             // this will trigger creating a new file
248             return null;
249         }
250     }
251 
252     /**
253      * Losche alle pfade die nach was6 zeigen diese sind erkennbar an den parrent runtimes/base_v6/lib.
254      * 
255      * @param classpath classpath to remove was6 libraries
256      */
257     private void removeDupicateWAS6Libs( Xpp3Dom classpath )
258     {
259         Xpp3Dom[] children;
260         children = classpath.getChildren();
261         for ( int index = children.length - 1; index >= 0; index-- )
262         {
263             try
264             {
265                 File path = new File( children[index].getAttribute( PATH ) );
266 
267                 if ( path.exists() && path.getParentFile().getName().equals( LIB )
268                     && path.getParentFile().getParentFile().getName().equals( "base_v6" )
269                     && path.getParentFile().getParentFile().getParentFile().getName().equals( "runtimes" ) )
270                 {
271                     Xpp3Dom[] currentChildren = classpath.getChildren();
272                     for ( int deleteIndex = currentChildren.length - 1; deleteIndex >= 0; deleteIndex-- )
273                     {
274                         if ( currentChildren[deleteIndex] == children[index] )
275                         {
276                             classpath.removeChild( deleteIndex );
277                             break;
278                         }
279                     }
280                 }
281             }
282             catch ( Exception e )
283             {
284                 log.debug( e );
285             }
286         }
287     }
288 
289 }