1
1
/*******************************************************************************
2
- * Copyright (c) 2004, 2021 IBM Corporation and others.
2
+ * Copyright (c) 2004, 2023 IBM Corporation and others.
3
3
*
4
4
* This program and the accompanying materials
5
5
* are made available under the terms of the Eclipse Public License 2.0
10
10
*
11
11
* Contributors:
12
12
* IBM Corporation - initial API and implementation
13
+ * Hannes Wellmann - Enhance computation of system-package provided by a ExecutionEnvironment
13
14
*******************************************************************************/
14
15
package org .eclipse .pde .internal .build .site ;
15
16
28
29
import java .util .Hashtable ;
29
30
import java .util .List ;
30
31
import java .util .Map ;
32
+ import java .util .Optional ;
31
33
import java .util .Properties ;
32
34
import java .util .Set ;
33
35
import java .util .TreeSet ;
36
+ import java .util .function .Function ;
34
37
import java .util .jar .JarFile ;
38
+ import java .util .regex .Pattern ;
39
+ import java .util .stream .Stream ;
35
40
import java .util .zip .ZipEntry ;
36
41
import java .util .zip .ZipFile ;
37
42
44
49
import org .eclipse .jdt .core .JavaCore ;
45
50
import org .eclipse .jdt .launching .IVMInstall ;
46
51
import org .eclipse .jdt .launching .JavaRuntime ;
52
+ import org .eclipse .jdt .launching .LibraryLocation ;
47
53
import org .eclipse .jdt .launching .environments .IExecutionEnvironment ;
48
54
import org .eclipse .osgi .service .resolver .BundleDescription ;
49
55
import org .eclipse .osgi .service .resolver .ExportPackageDescription ;
@@ -388,7 +394,6 @@ public void resolveState() {
388
394
389
395
// initialize profileManager and get the JRE profiles
390
396
String [] javaProfiles = getJavaProfiles ();
391
- String systemPackages = null ;
392
397
String ee = null ;
393
398
394
399
for (Config aConfig : configs ) {
@@ -435,7 +440,8 @@ public void resolveState() {
435
440
if (profileProps != null ) {
436
441
String profileName = profileProps .getProperty (ProfileManager .PROFILE_NAME );
437
442
if (AbstractScriptGenerator .getImmutableAntProperty (profileName ) != null || (j == 0 && !added )) {
438
- systemPackages = profileProps .getProperty (ProfileManager .SYSTEM_PACKAGES );
443
+ IExecutionEnvironment env = JavaRuntime .getExecutionEnvironmentsManager ().getEnvironment (javaProfiles [j ]);
444
+ String systemPackages = getSystemPackages (env , profileProps );
439
445
ee = profileProps .getProperty (Constants .FRAMEWORK_EXECUTIONENVIRONMENT );
440
446
441
447
prop = new Hashtable <>();
@@ -459,7 +465,7 @@ public void resolveState() {
459
465
for (String execEnvID : eeJava10AndBeyond ) {
460
466
prop = new Hashtable <>();
461
467
IExecutionEnvironment env = JavaRuntime .getExecutionEnvironmentsManager ().getEnvironment (execEnvID );
462
- systemPackages = querySystemPackages (env );
468
+ String systemPackages = querySystemPackages (env , null );
463
469
String currentEE = previousEE + "," + execEnvID ; //$NON-NLS-1$
464
470
if (systemPackages == null ) {
465
471
previousEE = currentEE ;
@@ -480,13 +486,178 @@ public void resolveState() {
480
486
}
481
487
}
482
488
483
- public static String querySystemPackages (IExecutionEnvironment environment ) {
484
- // Copy of org.eclipse.pde.internal.core.TargetPlatformHelper.querySystemPackages()
485
- IVMInstall vm = bestVmInstallFor (environment );
486
- if (vm == null || !JavaRuntime .isModularJava (vm )) {
489
+ public static String getSystemPackages (IExecutionEnvironment environment , Properties profileProperties ) {
490
+ // The pre-defined lists of system-packages are incomplete. Always overwrite, if we have a more up-to-date one.
491
+ String systemPackages = querySystemPackages (environment , profileProperties );
492
+ if (systemPackages == null && profileProperties != null ) {
493
+ // Unable to compute system-packages, probably OSGi specific EE, use the those its profile
494
+ systemPackages = profileProperties .getProperty (Constants .FRAMEWORK_SYSTEMPACKAGES );
495
+ }
496
+ return systemPackages ;
497
+ }
498
+
499
+ private static final Pattern COMMA = Pattern .compile ("," ); //$NON-NLS-1$
500
+
501
+ public static String querySystemPackages (IExecutionEnvironment environment , Properties preJava9ProfileProperties ) {
502
+ if (environment == null ) {
503
+ return null ;
504
+ }
505
+ String eeId = environment .getId ();
506
+ Integer releaseVersion = readJavaReleaseVersion (eeId );
507
+ if (releaseVersion == null ) {
487
508
return null ;
488
509
}
489
- String release = environment .getProfileProperties ().getProperty (JavaCore .COMPILER_COMPLIANCE );
510
+ Collection <String > systemPackages ;
511
+ if (releaseVersion <= 8 ) {
512
+ IVMInstall eeVM = bestVmInstallFor (environment , vms -> null ); // Use selected VM or a perfect match
513
+ if (eeVM != null ) {
514
+ // In case a VM is selected for an EE, query that VM and use its system-packages
515
+ systemPackages = querySystemPackages (eeVM , null );
516
+ } else {
517
+ // No VM selected for the non-modular EE:
518
+ // Compose list of available system-packages from the java.* packages in the predefined profiles in o.e.osgi respectively the hard-coded lists of java-packages in this class
519
+ // plus the non-java packages of this workspace's default VM.
520
+ // The reasoning for this is, that the OSGi standard only requires the java.* packages of an EE to be present, everything else is optional.
521
+ // Therefore the Workspaces default VM (which can also be set as target VM in the active target-definition) is the best guess for them.
522
+ // See also OSGi 8.0 specification chapter 3.4 Execution Environment
523
+
524
+ List <String > javaPackages = PRE_JAVA_9_SYSTEM_PACKAGES .get (eeId );
525
+ if (javaPackages == null ) {
526
+ String profileSystemPackages = preJava9ProfileProperties .getProperty (Constants .FRAMEWORK_SYSTEMPACKAGES , "" ); //$NON-NLS-1$
527
+ if (profileSystemPackages .isBlank ()) {
528
+ return null ;
529
+ }
530
+ javaPackages = COMMA .splitAsStream (profileSystemPackages ).filter (p -> p .startsWith ("java." )).toList (); //$NON-NLS-1$
531
+ }
532
+ IVMInstall targetVM = JavaRuntime .getDefaultVMInstall (); // Set by the Target-Definition if specified there
533
+ Collection <String > targetVMSystemPackages = querySystemPackages (targetVM , null );
534
+ if (targetVMSystemPackages == null ) {
535
+ return null ;
536
+ }
537
+ Stream <String > targetVMNonJavaPackages = targetVMSystemPackages .stream ().filter (p -> !p .startsWith ("java." )); //$NON-NLS-1$
538
+
539
+ systemPackages = Stream .concat (javaPackages .stream (), targetVMNonJavaPackages ).sorted ().toList ();
540
+ }
541
+ } else {
542
+ IVMInstall vm = bestVmInstallFor (environment , vms -> vms [0 ]);
543
+ if (vm == null ) {
544
+ return null ;
545
+ }
546
+ systemPackages = querySystemPackages (vm , environment );
547
+ }
548
+ return String .join ("," , systemPackages ); //$NON-NLS-1$
549
+ }
550
+
551
+ @ SuppressWarnings ("nls" )
552
+ private static Integer readJavaReleaseVersion (String eeId ) {
553
+ if (eeId .startsWith ("JavaSE-" )) { //$NON-NLS-1$
554
+ try {
555
+ return Integer .parseInt (eeId .substring ("JavaSE-" .length ())); //$NON-NLS-1$
556
+ } catch (NumberFormatException e ) { // Another EE
557
+ }
558
+ }
559
+ return switch (eeId ) {
560
+ // There is no EE for Java 1.0 in OSGi
561
+ case "JRE-1.1" -> 1 ;
562
+ case "J2SE-1.2" -> 2 ;
563
+ case "J2SE-1.3" -> 3 ;
564
+ case "J2SE-1.4" -> 4 ;
565
+ case "J2SE-1.5" -> 5 ;
566
+ case "JavaSE-1.6" -> 6 ;
567
+ case "JavaSE-1.7" -> 7 ;
568
+ case "JavaSE-1.8" -> 8 ;
569
+ default -> null ;
570
+ };
571
+ }
572
+
573
+ // Old JDKs can for example be obtained from https://www.oracle.com/java/technologies/downloads/archive/
574
+ @ SuppressWarnings ("nls" )
575
+ private static final Map <String , List <String >> PRE_JAVA_9_SYSTEM_PACKAGES = Map .of (//
576
+ "JRE-1.1" , List .of ("java.applet" , //
577
+ "java.awt" , //
578
+ "java.awt.datatransfer" , //
579
+ "java.awt.event" , //
580
+ "java.awt.image" , //
581
+ "java.awt.peer" , //
582
+ "java.beans" , //
583
+ "java.io" , //
584
+ "java.lang" , //
585
+ "java.lang.reflect" , //
586
+ "java.math" , //
587
+ "java.net" , //
588
+ "java.rmi" , //
589
+ "java.rmi.dgc" , //
590
+ "java.rmi.registry" , //
591
+ "java.rmi.server" , //
592
+ "java.security" , //
593
+ "java.security.acl" , //
594
+ "java.security.interfaces" , //
595
+ "java.sql" , //
596
+ "java.text" , //
597
+ "java.text.resources" , //
598
+ "java.util" , //
599
+ "java.util.zip" ),
600
+ "J2SE-1.2" , List .of ("java.applet" , //
601
+ "java.awt" , //
602
+ "java.awt.color" , //
603
+ "java.awt.datatransfer" , //
604
+ "java.awt.dnd" , //
605
+ "java.awt.dnd.peer" , //
606
+ "java.awt.event" , //
607
+ "java.awt.font" , //
608
+ "java.awt.geom" , //
609
+ "java.awt.im" , //
610
+ "java.awt.image" , //
611
+ "java.awt.image.renderable" , //
612
+ "java.awt.peer" , //
613
+ "java.awt.print" , //
614
+ "java.awt.resources" , //
615
+ "java.beans" , //
616
+ "java.beans.beancontext" , //
617
+ "java.io" , //
618
+ "java.lang" , //
619
+ "java.lang.ref" , //
620
+ "java.lang.reflect" , //
621
+ "java.math" , //
622
+ "java.net" , //
623
+ "java.rmi" , //
624
+ "java.rmi.activation" , //
625
+ "java.rmi.dgc" , //
626
+ "java.rmi.registry" , //
627
+ "java.rmi.server" , //
628
+ "java.security" , //
629
+ "java.security.acl" , //
630
+ "java.security.cert" , //
631
+ "java.security.interfaces" , //
632
+ "java.security.spec" , //
633
+ "java.sql" , //
634
+ "java.text" , //
635
+ "java.text.resources" , //
636
+ "java.util" , //
637
+ "java.util.jar" , //
638
+ "java.util.zip" ));
639
+
640
+ private static Collection <String > querySystemPackages (IVMInstall vm , IExecutionEnvironment environment ) {
641
+ if (!JavaRuntime .isModularJava (vm )) {
642
+ Set <String > classFileDirectories = new HashSet <>();
643
+ for (LibraryLocation libLocation : JavaRuntime .getLibraryLocations (vm )) {
644
+ IPath path = libLocation .getSystemLibraryPath ();
645
+ if (path != null ) {
646
+ try (ZipFile zip = new ZipFile (path .toFile ())) {
647
+ // Collect names of all directories that contain a .class file
648
+ zip .stream ().filter (e -> !e .isDirectory ()).map (ZipEntry ::getName ) //
649
+ .filter (n -> n .endsWith (".class" )) //$NON-NLS-1$
650
+ .map (n -> n .substring (0 , n .lastIndexOf ('/' ))) //
651
+ .forEach (classFileDirectories ::add );
652
+ } catch (IOException e ) {
653
+ ILog .get ().error ("Failed to read packages in JVM library for " + vm + ", at " + path , e ); //$NON-NLS-1$ //$NON-NLS-2$
654
+ }
655
+ }
656
+ }
657
+ return classFileDirectories .stream ().map (n -> n .replace ('/' , '.' )).sorted ().toList ();
658
+ }
659
+
660
+ String release = environment != null ? environment .getProfileProperties ().getProperty (JavaCore .COMPILER_COMPLIANCE ) : null ;
490
661
try {
491
662
Collection <String > packages = new TreeSet <>();
492
663
String jrtPath = "lib/" + org .eclipse .jdt .internal .compiler .util .JRTUtil .JRT_FS_JAR ; //$NON-NLS-1$
@@ -503,17 +674,14 @@ public static String querySystemPackages(IExecutionEnvironment environment) {
503
674
}
504
675
}
505
676
}
506
- return String . join ( "," , packages ); //$NON-NLS-1$
677
+ return packages ;
507
678
} catch (CoreException e ) {
508
- ILog .of (PDEState .class ).log (Status .error ("failed to read system packages for " + environment , e )); //$NON-NLS-1$
679
+ ILog .of (PDEState .class ).log (Status .error ("Failed to read system packages for " + environment , e )); //$NON-NLS-1$
509
680
}
510
681
return null ;
511
682
}
512
683
513
- private static IVMInstall bestVmInstallFor (IExecutionEnvironment environment ) {
514
- if (environment == null ) {
515
- return null ;
516
- }
684
+ private static IVMInstall bestVmInstallFor (IExecutionEnvironment environment , Function <IVMInstall [], IVMInstall > nonStrictDefaultSelector ) {
517
685
IVMInstall defaultVM = environment .getDefaultVM ();
518
686
if (defaultVM != null ) {
519
687
return defaultVM ;
@@ -522,12 +690,8 @@ private static IVMInstall bestVmInstallFor(IExecutionEnvironment environment) {
522
690
if (compatible .length == 0 ) {
523
691
return null ;
524
692
}
525
- for (IVMInstall vm : compatible ) {
526
- if (environment .isStrictlyCompatible (vm )) {
527
- return vm ;
528
- }
529
- }
530
- return compatible [0 ];
693
+ Optional <IVMInstall > vm = Arrays .stream (compatible ).filter (environment ::isStrictlyCompatible ).findFirst ();
694
+ return vm .isPresent () ? vm .get () : nonStrictDefaultSelector .apply (compatible );
531
695
}
532
696
533
697
public State getState () {
0 commit comments