1   
2   
3   
4   
5   
6   
7   
8   
9   
10  
11  
12  
13  
14  package org.apache.maven.plugin.eclipse.reader;
15  
16  import java.io.DataInputStream;
17  import java.io.File;
18  import java.io.FileInputStream;
19  import java.io.FileNotFoundException;
20  import java.io.FileReader;
21  import java.io.IOException;
22  import java.io.StringReader;
23  import java.net.URI;
24  import java.net.URISyntaxException;
25  import java.text.MessageFormat;
26  import java.util.ArrayList;
27  import java.util.HashMap;
28  import java.util.Iterator;
29  import java.util.Map;
30  import java.util.Properties;
31  import java.util.Set;
32  import java.util.jar.JarFile;
33  
34  import org.apache.maven.plugin.eclipse.Messages;
35  import org.apache.maven.plugin.eclipse.WorkspaceConfiguration;
36  import org.apache.maven.plugin.ide.IdeDependency;
37  import org.apache.maven.plugin.ide.IdeUtils;
38  import org.apache.maven.plugin.logging.Log;
39  import org.apache.maven.project.MavenProject;
40  import org.codehaus.plexus.util.IOUtil;
41  import org.codehaus.plexus.util.xml.Xpp3Dom;
42  import org.codehaus.plexus.util.xml.Xpp3DomBuilder;
43  import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
44  import org.eclipse.core.internal.localstore.SafeChunkyInputStream;
45  
46  
47  
48  
49  
50  
51  
52  public class ReadWorkspaceLocations
53  {
54  
55      public static final String BINARY_LOCATION_FILE = ".location";
56  
57      public static final String METADATA_PLUGINS_ORG_ECLIPSE_CORE_RESOURCES_PROJECTS =
58          ".metadata/.plugins/org.eclipse.core.resources/.projects";
59  
60      private static final String[] PARENT_VERSION = new String[] { "parent", "version" };
61  
62      private static final String[] PARENT_GROUP_ID = new String[] { "parent", "groupId" };
63  
64      private static final String[] PACKAGING = new String[] { "packaging" };
65  
66      private static final String[] VERSION = new String[] { "version" };
67  
68      private static final String[] GROUP_ID = new String[] { "groupId" };
69  
70      private static final String[] ARTEFACT_ID = new String[] { "artifactId" };
71  
72      private static final String METADATA_PLUGINS_ORG_ECLIPSE_CORE_RUNTIME_LAUNCHING_PREFS =
73          ".metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.jdt.launching.prefs";
74  
75      private static final String METADATA_PLUGINS_ORG_ECLIPSE_CORE_RUNTIME_PREFS_VM_KEY =
76          "org.eclipse.jdt.launching.PREF_VM_XML";
77  
78      private static final String METADATA_PLUGINS_ORG_ECLIPSE_CORE_RUNTIME_SERVER_PREFS =
79          ".metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.wst.server.core.prefs";
80  
81      private static final String METADATA_PLUGINS_ORG_ECLIPSE_CORE_RUNTIME_PREFS_RUNTIMES_KEY = "runtimes";
82  
83      private static final String CLASSPATHENTRY_DEFAULT = "org.eclipse.jdt.launching.JRE_CONTAINER";
84  
85      private static final String CLASSPATHENTRY_STANDARD =
86          CLASSPATHENTRY_DEFAULT + "/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/";
87  
88      private static final String CLASSPATHENTRY_FORMAT = ReadWorkspaceLocations.CLASSPATHENTRY_DEFAULT + "/{0}/{1}";
89  
90      public void init( Log log, WorkspaceConfiguration workspaceConfiguration, MavenProject project,
91                        String wtpDefaultServer )
92      {
93          detectDefaultJREContainer( workspaceConfiguration, project, log );
94          readWorkspace( workspaceConfiguration, log );
95          detectWTPDefaultServer( workspaceConfiguration, wtpDefaultServer, log );
96      }
97  
98      
99  
100 
101 
102 
103 
104 
105     private void detectWTPDefaultServer( WorkspaceConfiguration workspaceConfiguration, String wtpDefaultServer, Log log )
106     {
107         HashMap servers = readDefinedServers( workspaceConfiguration, log );
108         if ( servers == null || servers.isEmpty() )
109         {
110             return;
111         }
112         if ( wtpDefaultServer != null )
113         {
114             Set ids = servers.keySet();
115             
116             Iterator idIterator = ids.iterator();
117             while ( workspaceConfiguration.getDefaultDeployServerId() == null && idIterator.hasNext() )
118             {
119                 String id = (String) idIterator.next();
120                 String name = (String) servers.get( id );
121                 if ( wtpDefaultServer.equals( id ) || wtpDefaultServer.equals( name ) )
122                 {
123                     workspaceConfiguration.setDefaultDeployServerId( id );
124                     workspaceConfiguration.setDefaultDeployServerName( name );
125                 }
126             }
127             if ( workspaceConfiguration.getDefaultDeployServerId() == null )
128             {
129                 log.info( "no exact wtp server match." );
130                 
131                 idIterator = ids.iterator();
132                 while ( workspaceConfiguration.getDefaultDeployServerId() == null && idIterator.hasNext() )
133                 {
134                     String id = (String) idIterator.next();
135                     String name = (String) servers.get( id );
136                     if ( id.indexOf( wtpDefaultServer ) >= 0 || name.indexOf( wtpDefaultServer ) >= 0 )
137                     {
138                         workspaceConfiguration.setDefaultDeployServerId( id );
139                         workspaceConfiguration.setDefaultDeployServerName( name );
140                     }
141                 }
142             }
143         }
144         if ( workspaceConfiguration.getDefaultDeployServerId() == null && servers.size() > 0 )
145         {
146             
147             log.info( "no substring wtp server match." );
148             workspaceConfiguration.setDefaultDeployServerId( (String) servers.get( "" ) );
149             workspaceConfiguration.setDefaultDeployServerName( (String) servers.get( workspaceConfiguration.getDefaultDeployServerId() ) );
150         }
151         log.info( "Using as WTP server : " + workspaceConfiguration.getDefaultDeployServerName() );
152     }
153 
154     
155 
156 
157 
158 
159 
160 
161 
162     private String getContainerFromExecutable( String rawExecutable, Map jreMap, Log logger )
163     {
164         String foundContainer = null;
165         if ( rawExecutable != null )
166         {
167             String executable;
168             try
169             {
170                 executable = new File( rawExecutable ).getCanonicalPath();
171                 logger.debug( "detected executable: " + executable );
172             }
173             catch ( Exception e )
174             {
175                 return null;
176             }
177             File executableFile = new File( executable );
178             while ( executableFile != null )
179             {
180                 foundContainer = (String) jreMap.get( executableFile.getPath() );
181                 if ( foundContainer != null )
182                 {
183                     logger.debug( "detected classpathContainer from executable: " + foundContainer );
184                     return foundContainer;
185 
186                 }
187                 executableFile = executableFile.getParentFile();
188             }
189         }
190         return null;
191     }
192 
193     
194 
195 
196 
197 
198 
199 
200     private void detectDefaultJREContainer( WorkspaceConfiguration workspaceConfiguration, MavenProject project,
201                                             Log logger )
202     {
203         String defaultJREContainer = ReadWorkspaceLocations.CLASSPATHENTRY_DEFAULT;
204         if ( workspaceConfiguration.getWorkspaceDirectory() != null )
205         {
206             Map jreMap = readAvailableJREs( workspaceConfiguration.getWorkspaceDirectory(), logger );
207             if ( jreMap != null )
208             {
209                 String foundContainer =
210                     getContainerFromExecutable( System.getProperty( "maven.compiler.executable" ), jreMap, logger );
211                 if ( foundContainer == null )
212                 {
213                     foundContainer =
214                         getContainerFromExecutable( IdeUtils.getCompilerPluginSetting( project, "executable" ), jreMap,
215                                                     logger );
216                 }
217                 if ( foundContainer == null )
218                 {
219                     String sourceVersion = IdeUtils.getCompilerSourceVersion( project );
220                     foundContainer = (String) jreMap.get( sourceVersion );
221                     if ( foundContainer != null )
222                     {
223                         logger.debug( "detected classpathContainer from sourceVersion(" + sourceVersion + "): "
224                             + foundContainer );
225                     }
226                 }
227                 if ( foundContainer == null )
228                 {
229                     foundContainer = getContainerFromExecutable( System.getProperty( "java.home" ), jreMap, logger );
230                 }
231                 if ( foundContainer != null )
232                 {
233                     defaultJREContainer = foundContainer;
234                 }
235 
236             }
237         }
238         workspaceConfiguration.setDefaultClasspathContainer( defaultJREContainer );
239     }
240 
241     
242 
243 
244 
245 
246 
247 
248 
249 
250     
251         throws IOException, URISyntaxException
252     {
253         File location = new File( project, ReadWorkspaceLocations.BINARY_LOCATION_FILE );
254         if ( location.exists() )
255         {
256             SafeChunkyInputStream fileInputStream = null;
257             try
258             {
259                 fileInputStream = new SafeChunkyInputStream( location );
260                 DataInputStream dataInputStream = new DataInputStream( fileInputStream );
261                 String file = dataInputStream.readUTF().trim();
262 
263                 if ( file.length() > 0 )
264                 {
265                     if ( !file.startsWith( "URI//" ) )
266                     {
267                         throw new IOException( location.getAbsolutePath() + " contains unexpected data: " + file );
268                     }
269                     file = file.substring( "URI//".length() );
270                     return new File( new URI( file ) );
271                 }
272             }
273             finally
274             {
275                 IOUtil.close( fileInputStream );
276             }
277         }
278         File projectBase = new File( workspaceLocation, project.getName() );
279         if ( projectBase.isDirectory() )
280         {
281             return projectBase;
282         }
283 
284         return null;
285     }
286 
287     
288 
289 
290 
291 
292 
293 
294 
295     private String getValue( Xpp3Dom element, String[] elementNames, String defaultValue )
296     {
297         String value = null;
298         Xpp3Dom dom = element;
299         for ( int index = 0; dom != null && index < elementNames.length; index++ )
300         {
301             dom = dom.getChild( elementNames[index] );
302         }
303         if ( dom != null )
304         {
305             value = dom.getValue();
306         }
307         if ( value == null || value.trim().length() == 0 )
308         {
309             return defaultValue;
310         }
311         else
312         {
313             return value;
314         }
315     }
316 
317     
318 
319 
320 
321 
322 
323 
324 
325 
326 
327 
328     private IdeDependency readArtefact( File projectLocation, Log logger )
329         throws FileNotFoundException, XmlPullParserException, IOException
330     {
331         File projectFile = new File( projectLocation, ".project" );
332         String eclipseProjectName = projectLocation.getName();
333         if ( projectFile.exists() )
334         {
335             Xpp3Dom project = Xpp3DomBuilder.build( new FileReader( projectFile ) );
336             eclipseProjectName = getValue( project, new String[] { "name" }, eclipseProjectName );
337         }
338         File pomFile = new File( projectLocation, "pom.xml" );
339         if ( pomFile.exists() )
340         {
341             Xpp3Dom pom = Xpp3DomBuilder.build( new FileReader( pomFile ) );
342 
343             String artifact = getValue( pom, ReadWorkspaceLocations.ARTEFACT_ID, null );
344             String group =
345                 getValue( pom, ReadWorkspaceLocations.GROUP_ID, getValue( pom, ReadWorkspaceLocations.PARENT_GROUP_ID,
346                                                                           null ) );
347             String version =
348                 getValue( pom, ReadWorkspaceLocations.VERSION, getValue( pom, ReadWorkspaceLocations.PARENT_VERSION,
349                                                                          null ) );
350             String packaging = getValue( pom, ReadWorkspaceLocations.PACKAGING, "jar" );
351 
352             logger.debug( "found workspace artefact " + group + ":" + artifact + ":" + version + " " + packaging + " ("
353                 + eclipseProjectName + ")" + " -> " + projectLocation.getAbsolutePath() );
354             return new IdeDependency( group, artifact, version, packaging, true, false, false, false, false, null,
355                                       packaging, false, null, 0, eclipseProjectName );
356         }
357         else
358         {
359             logger.debug( "ignored workspace project NO pom available " + projectLocation.getAbsolutePath() );
360             return null;
361         }
362     }
363 
364     
365     {
366         HashMap detectedRuntimes = new HashMap();
367         if ( workspaceConfiguration.getWorkspaceDirectory() != null )
368         {
369             Xpp3Dom runtimesElement = null;
370             try
371             {
372                 File prefs =
373                     new File( workspaceConfiguration.getWorkspaceDirectory(),
374                               ReadWorkspaceLocations.METADATA_PLUGINS_ORG_ECLIPSE_CORE_RUNTIME_SERVER_PREFS );
375                 if ( prefs.exists() )
376                 {
377                     Properties properties = new Properties();
378                     properties.load( new FileInputStream( prefs ) );
379                     String runtimes = properties.getProperty( ReadWorkspaceLocations.METADATA_PLUGINS_ORG_ECLIPSE_CORE_RUNTIME_PREFS_RUNTIMES_KEY );
380                     if ( runtimes != null )
381                     {
382                         runtimesElement = Xpp3DomBuilder.build( new StringReader( runtimes ) );
383                     }
384                 }
385             }
386             catch ( Exception e )
387             {
388                 logger.error( "Could not read workspace wtp server runtimes preferences : " + e.getMessage() );
389             }
390 
391             if ( runtimesElement != null )
392             {
393                 Xpp3Dom[] runtimeArray = runtimesElement.getChildren( "runtime" );
394                 for ( int index = 0; runtimeArray != null && index < runtimeArray.length; index++ )
395                 {
396                     String id = runtimeArray[index].getAttribute( "id" );
397                     String name = runtimeArray[index].getAttribute( "name" );
398                     if ( detectedRuntimes.isEmpty() )
399                     {
400                         logger.debug( "Using WTP runtime with id: \"" + id + "\" as default runtime" );
401                         detectedRuntimes.put( "", id );
402                     }
403                     detectedRuntimes.put( id, name );
404                     logger.debug( "Detected WTP runtime with id: \"" + id + "\" and name: \"" + name + "\"" );
405                 }
406             }
407         }
408         return detectedRuntimes;
409     }
410 
411     
412 
413 
414 
415 
416 
417 
418 
419     private HashMap readAvailableJREs( File workspaceLocation, Log logger )
420     {
421         Xpp3Dom vms;
422         try
423         {
424             File prefs =
425                 new File( workspaceLocation,
426                           ReadWorkspaceLocations.METADATA_PLUGINS_ORG_ECLIPSE_CORE_RUNTIME_LAUNCHING_PREFS );
427             if ( !prefs.exists() )
428             {
429                 return null;
430             }
431             Properties properties = new Properties();
432             properties.load( new FileInputStream( prefs ) );
433             vms =
434                 Xpp3DomBuilder.build( new StringReader(
435                                                         properties.getProperty( ReadWorkspaceLocations.METADATA_PLUGINS_ORG_ECLIPSE_CORE_RUNTIME_PREFS_VM_KEY ) ) );
436         }
437         catch ( Exception e )
438         {
439             logger.error( "Could not read workspace JRE preferences", e );
440             return null;
441         }
442 
443         HashMap jreMap = new HashMap();
444         jreMap.put( "1.2", CLASSPATHENTRY_STANDARD + "J2SE-1.2" );
445         jreMap.put( "1.3", CLASSPATHENTRY_STANDARD + "J2SE-1.3" );
446         jreMap.put( "1.4", CLASSPATHENTRY_STANDARD + "J2SE-1.4" );
447         jreMap.put( "1.5", CLASSPATHENTRY_STANDARD + "J2SE-1.5" );
448         jreMap.put( "5", jreMap.get( "1.5" ) );
449         jreMap.put( "1.6", CLASSPATHENTRY_STANDARD + "JavaSE-1.6" );
450         jreMap.put( "6", jreMap.get( "1.6" ) );
451         String defaultJRE = vms.getAttribute( "defaultVM" ).trim();
452         Xpp3Dom[] vmTypes = vms.getChildren( "vmType" );
453         for ( int vmTypeIndex = 0; vmTypeIndex < vmTypes.length; vmTypeIndex++ )
454         {
455             String typeId = vmTypes[vmTypeIndex].getAttribute( "id" );
456             Xpp3Dom[] vm = vmTypes[vmTypeIndex].getChildren( "vm" );
457             for ( int vmIndex = 0; vmIndex < vm.length; vmIndex++ )
458             {
459                 try
460                 {
461                     String path = vm[vmIndex].getAttribute( "path" );
462                     String name = vm[vmIndex].getAttribute( "name" );
463                     String vmId = vm[vmIndex].getAttribute( "id" ).trim();
464                     String classpathEntry =
465                         MessageFormat.format( ReadWorkspaceLocations.CLASSPATHENTRY_FORMAT,
466                                               new Object[] { typeId, name } );
467                     String jrePath = new File( path ).getCanonicalPath();
468                     File rtJarFile = new File( new File( jrePath ), "jre/lib/rt.jar" );
469                     if ( !rtJarFile.exists() ) {
470                         logger.warn( Messages.getString( "EclipsePlugin.invalidvminworkspace", jrePath ) );
471                         continue;
472                     }
473                     JarFile rtJar = new JarFile( rtJarFile );
474                     String version = rtJar.getManifest().getMainAttributes().getValue( "Specification-Version" );
475                     if ( defaultJRE.endsWith( "," + vmId ) )
476                     {
477                         jreMap.put( jrePath, ReadWorkspaceLocations.CLASSPATHENTRY_DEFAULT );
478                         jreMap.put( version, ReadWorkspaceLocations.CLASSPATHENTRY_DEFAULT );
479                         logger.debug( "Default Classpath Container version: " + version + "  location: " + jrePath );
480                     }
481                     else if ( !jreMap.containsKey( jrePath ) )
482                     {
483                         if ( !jreMap.containsKey( version ) )
484                         {
485                             jreMap.put( version, classpathEntry );
486                         }
487                         jreMap.put( jrePath, classpathEntry );
488                         logger.debug( "Additional Classpath Container version: " + version + " " + classpathEntry
489                             + " location: " + jrePath );
490                     }
491                     else
492                     {
493                         logger.debug( "Ignored (duplicated) additional Classpath Container version: " + version + " "
494                             + classpathEntry + " location: " + jrePath );
495                     }
496                 }
497                 catch ( IOException e )
498                 {
499                     logger.warn( "Could not interpret entry: " + vm[vmIndex].toString() );
500                 }
501             }
502         }
503         return jreMap;
504     }
505 
506     
507 
508 
509 
510 
511 
512     private void readWorkspace( WorkspaceConfiguration workspaceConfiguration, Log logger )
513     {
514         ArrayList dependencies = new ArrayList();
515         if ( workspaceConfiguration.getWorkspaceDirectory() != null )
516         {
517             File workspace =
518                 new File( workspaceConfiguration.getWorkspaceDirectory(),
519                           ReadWorkspaceLocations.METADATA_PLUGINS_ORG_ECLIPSE_CORE_RESOURCES_PROJECTS );
520 
521             File[] directories = workspace.listFiles();
522             for ( int index = 0; directories != null && index < directories.length; index++ )
523             {
524                 File project = directories[index];
525                 if ( project.isDirectory() )
526                 {
527                     try
528                     {
529                         File projectLocation =
530                             getProjectLocation( workspaceConfiguration.getWorkspaceDirectory(), project );
531                         if ( projectLocation != null )
532                         {
533                             IdeDependency ideDependency = readArtefact( projectLocation, logger );
534                             if ( ideDependency != null )
535                             {
536                                 dependencies.add( ideDependency );
537                             }
538                         }
539                     }
540                     catch ( Exception e )
541                     {
542                         logger.warn( "could not read workspace project:" + project, e );
543                     }
544                 }
545             }
546         }
547         workspaceConfiguration.setWorkspaceArtefacts( (IdeDependency[]) dependencies.toArray( new IdeDependency[dependencies.size()] ) );
548     }
549 }