View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.plugin.eclipse.writers.rad;
20  
21  import java.io.File;
22  import java.io.FileInputStream;
23  import java.io.FileNotFoundException;
24  import java.io.FileOutputStream;
25  import java.io.IOException;
26  import java.io.InputStreamReader;
27  import java.io.OutputStreamWriter;
28  import java.io.Reader;
29  import java.io.Writer;
30  import java.util.Arrays;
31  import java.util.Comparator;
32  
33  import org.apache.maven.artifact.repository.ArtifactRepository;
34  import org.apache.maven.plugin.MojoExecutionException;
35  import org.apache.maven.plugin.eclipse.Constants;
36  import org.apache.maven.plugin.eclipse.EclipseSourceDir;
37  import org.apache.maven.plugin.eclipse.Messages;
38  import org.apache.maven.plugin.eclipse.writers.AbstractEclipseWriter;
39  import org.apache.maven.plugin.eclipse.writers.wtp.AbstractWtpResourceWriter;
40  import org.codehaus.plexus.util.IOUtil;
41  import org.codehaus.plexus.util.xml.PrettyPrintXMLWriter;
42  import org.codehaus.plexus.util.xml.XMLWriter;
43  import org.codehaus.plexus.util.xml.Xpp3Dom;
44  import org.codehaus.plexus.util.xml.Xpp3DomBuilder;
45  import org.codehaus.plexus.util.xml.Xpp3DomWriter;
46  
47  /**
48   * Adapts the .classpath file for RAD6 for now write hardcoded: target/websphere/classes future releases could make this
49   * varriable.
50   * 
51   * @author <a href="mailto:nir@cfc.at">Richard van Nieuwenhoven </a>
52   */
53  public class RadEjbClasspathWriter
54      extends AbstractEclipseWriter
55  {
56  
57      private static final String CLASSPATH = "classpath";
58  
59      private static final String CLASSPATH_FILE = ".classpath";
60  
61      private static final String CLASSPATHENTRY = "classpathentry";
62  
63      private static final String CON = "con";
64  
65      private static final String KIND = "kind";
66  
67      private static final String LIB = "lib";
68  
69      private static final String OUTPUT = "output";
70  
71      private static final String PATH = "path";
72  
73      private static final String SRC = "src";
74  
75      private static final String TARGET_WEBSPHERE_CLASSES = "target/websphere/generated-classes";
76  
77      private static final String VAR = "var";
78  
79      private static final String WEBSPHERE6CONTAINER =
80          "com.ibm.wtp.server.java.core.container/com.ibm.ws.ast.st.runtime.core.runtimeTarget.v60/was.base.v6";
81  
82      /**
83       * write the .classpath file to the project root directory.
84       * 
85       * @see AbstractWtpResourceWriter#write(EclipseSourceDir[], ArtifactRepository, File)
86       * @param sourceDirs all eclipse source directorys
87       * @param localRepository the local reposetory
88       * @param buildOutputDirectory build output directory (target)
89       * @throws MojoExecutionException when writing the config files was not possible
90       */
91      public void write()
92          throws MojoExecutionException
93      {
94          String packaging = config.getPackaging();
95          if ( Constants.PROJECT_PACKAGING_EJB.equalsIgnoreCase( packaging ) )
96          {
97              new File( config.getEclipseProjectDirectory(), TARGET_WEBSPHERE_CLASSES ).mkdirs();
98              File classpathFile = new File( config.getEclipseProjectDirectory(), CLASSPATH_FILE );
99  
100             if ( !classpathFile.exists() )
101             {
102                 return;
103             }
104             Xpp3Dom classpath = readXMLFile( classpathFile );
105             Xpp3Dom[] children = classpath.getChildren();
106             for (Xpp3Dom aChildren : children) {
107                 if (LIB.equals(aChildren.getAttribute(KIND))
108                         && TARGET_WEBSPHERE_CLASSES.equals(aChildren.getAttribute("path"))) {
109                     return; // nothing to do!
110                 }
111             }
112 
113             Xpp3Dom newEntry = new Xpp3Dom( CLASSPATHENTRY );
114             newEntry.setAttribute( KIND, LIB );
115             newEntry.setAttribute( PATH, TARGET_WEBSPHERE_CLASSES );
116             classpath.addChild( newEntry );
117 
118             newEntry = new Xpp3Dom( CLASSPATHENTRY );
119             newEntry.setAttribute( KIND, CON );
120             newEntry.setAttribute( PATH, WEBSPHERE6CONTAINER );
121             classpath.addChild( newEntry );
122 
123             children = classpath.getChildren();
124             for ( int index = children.length - 1; index >= 0; index-- )
125             {
126                 if ( children[index].getValue() == null )
127                 {
128                     children[index].setValue( "" );
129                 }
130             }
131 
132             removeDupicateWAS6Libs( classpath );
133             classpath = orderClasspath( classpath );
134 
135             Writer w;
136             try
137             {
138                 w = new OutputStreamWriter( new FileOutputStream( classpathFile ), "UTF-8" );
139             }
140             catch ( IOException ex )
141             {
142                 throw new MojoExecutionException( Messages.getString( "EclipsePlugin.erroropeningfile" ), ex ); //$NON-NLS-1$
143             }
144             XMLWriter writer = new PrettyPrintXMLWriter( w, "UTF-8", null );
145             Xpp3DomWriter.write( writer, classpath );
146             IOUtil.close( w );
147         }
148     }
149 
150     /**
151      * determinate of witch type this classpath entry is. this is used for sorting them.
152      * 
153      * @param classpathentry the classpath entry to sort
154      * @return an integer identifieing the type
155      * @see RadEjbClasspathWriter#orderClasspath(Xpp3Dom)
156      */
157     private int detectClasspathEntryType( Xpp3Dom classpathentry )
158     {
159         String kind = classpathentry.getAttribute( KIND );
160         String path = classpathentry.getAttribute( PATH );
161 
162         if ( kind == null || path == null )
163         {
164             return 6;
165         }
166 
167         boolean absolutePath = path.startsWith( "\\" ) || path.startsWith( "/" );
168         boolean windowsAbsolutePath = path.indexOf( ':' ) >= 0;
169         boolean anyAbsolutePath = absolutePath || windowsAbsolutePath;
170 
171         if ( kind.equals( SRC ) && !absolutePath )
172         {
173             return 1;
174         }
175         else if ( kind.equals( LIB ) && !anyAbsolutePath )
176         {
177             return 2;
178         }
179         else if ( kind.equals( SRC ) )
180         {
181             return 3;
182         }
183         else if ( kind.equals( VAR ) )
184         {
185             return 4;
186         }
187         else if ( kind.equals( LIB ) )
188         {
189             return 5;
190         }
191         else if ( kind.equals( OUTPUT ) )
192         {
193             return 7;
194         }
195         else
196         {
197             return 6;
198         }
199     }
200 
201     /**
202      * Order of classpath this is nessesary for the ejb's the generated classes are elsewise not found. 1 - kind=src
203      * ohne starting '/' oder '\' 2 - kind=lib kein ':' und kein start mit '/' oder '\' 3 - kind=src mit ohne starting
204      * '/' oder '\' 4 - kind=var 5 - kind=lib ein ':' oder start mit '/' oder '\' 6 - rest 7 - kind=output
205      * 
206      * @param classpath the classpath to sort
207      * @return dom-tree representing ordered classpath
208      */
209     private Xpp3Dom orderClasspath( Xpp3Dom classpath )
210     {
211         Xpp3Dom[] children = classpath.getChildren();
212         Arrays.sort( children, new Comparator()
213         {
214             public int compare( Object o1, Object o2 )
215             {
216                 return detectClasspathEntryType( (Xpp3Dom) o1 ) - detectClasspathEntryType( (Xpp3Dom) o2 );
217             }
218         } );
219         Xpp3Dom resultClasspath = new Xpp3Dom( CLASSPATH );
220         for (Xpp3Dom aChildren : children) {
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 }