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