2020import java .util .ArrayList ;
2121import java .util .Arrays ;
2222import java .util .Collection ;
23+ import java .util .List ;
2324import java .util .Objects ;
2425import java .util .Optional ;
2526import java .util .stream .Stream ;
3334import org .eclipse .jdt .core .IClasspathEntry ;
3435import org .eclipse .jdt .core .IJavaProject ;
3536import org .eclipse .jdt .core .JavaCore ;
37+ import org .eclipse .osgi .service .resolver .BundleDescription ;
3638import org .eclipse .pde .core .build .IBuild ;
3739import org .eclipse .pde .core .build .IBuildModel ;
3840import org .eclipse .pde .core .plugin .IFragment ;
5052import org .eclipse .pde .internal .core .plugin .Fragment ;
5153import org .eclipse .pde .internal .core .plugin .Plugin ;
5254import org .eclipse .pde .internal .core .plugin .PluginBase ;
55+ import org .osgi .framework .Bundle ;
56+ import org .osgi .framework .namespace .PackageNamespace ;
57+ import org .osgi .framework .wiring .BundleWire ;
58+ import org .osgi .framework .wiring .BundleWiring ;
5359import org .osgi .resource .Resource ;
5460
5561public class ClasspathUtilCore {
@@ -87,34 +93,92 @@ private static Collection<ClasspathLibrary> collectLibraryEntries(IPluginModelBa
8793 }
8894
8995 public static Stream <IClasspathEntry > classpathEntriesForBundle (String id ) {
96+ return classpathEntriesForBundle (id , false , new IClasspathAttribute [0 ]);
97+ }
98+
99+ public static Stream <IClasspathEntry > classpathEntriesForBundle (String id , boolean includeRequired ,
100+ IClasspathAttribute [] extra ) {
90101 // first look if we have something in the workspace...
91102 IPluginModelBase model = PluginRegistry .findModel (id );
92103 if (model != null && model .isEnabled ()) {
93- IResource resource = model .getUnderlyingResource ();
94- if (resource != null && PluginProject .isJavaProject (resource .getProject ())) {
95- IJavaProject javaProject = JavaCore .create (resource .getProject ());
96- return Stream .of (JavaCore .newProjectEntry (javaProject .getPath ()));
97- }
98- String location = model .getInstallLocation ();
99- if (location == null ) {
100- return Stream .empty ();
104+ Stream <IClasspathEntry > modelBundleClasspath = classpathEntriesForModelBundle (model , extra );
105+ if (includeRequired ) {
106+ return Stream .concat (modelBundleClasspath ,
107+ getRequiredByDescription (model .getBundleDescription (), extra ));
101108 }
102- boolean isJarShape = new File (location ).isFile ();
103- IPluginLibrary [] libraries = model .getPluginBase ().getLibraries ();
104- if (isJarShape || libraries .length == 0 ) {
105- return Stream .of (getEntryForPath (IPath .fromOSString (location )));
106- }
107- return Arrays .stream (libraries ).filter (library -> !IPluginLibrary .RESOURCE .equals (library .getType ()))
108- .map (library -> {
109- String name = library .getName ();
110- String expandedName = ClasspathUtilCore .expandLibraryName (name );
111- return ClasspathUtilCore .getPath (model , expandedName , isJarShape );
112- }).filter (Objects ::nonNull ).map (ClasspathUtilCore ::getEntryForPath );
109+ return modelBundleClasspath ;
113110 }
114111 // if not found in the models, try to use one from the running eclipse
115- return Optional .ofNullable (Platform .getBundle (id )).map (bundle -> bundle .adapt (File .class )).filter (File ::exists )
112+ Bundle runtimeBundle = Platform .getBundle (id );
113+ if (runtimeBundle == null ) {
114+ return Stream .empty ();
115+ }
116+ Stream <IClasspathEntry > bundleClasspath = classpathEntriesForRuntimeBundle (runtimeBundle , extra ).stream ();
117+ if (includeRequired ) {
118+ return Stream .concat (bundleClasspath , getRequiredByWire (runtimeBundle , extra ));
119+ }
120+ return bundleClasspath ;
121+ }
122+
123+ private static Stream <IClasspathEntry > getRequiredByDescription (BundleDescription description ,
124+ IClasspathAttribute [] extra ) {
125+ BundleWiring wiring = description .getWiring ();
126+ if (wiring == null ) {
127+ return Stream .empty ();
128+ }
129+
130+ List <BundleWire > wires = wiring .getRequiredWires (PackageNamespace .PACKAGE_NAMESPACE );
131+ return wires .stream ().map (wire -> {
132+ return wire .getProvider ();
133+ }).distinct ().flatMap (provider -> {
134+ IPluginModelBase model = PluginRegistry .findModel (provider );
135+ if (model != null && model .isEnabled ()) {
136+ return classpathEntriesForModelBundle (model , extra );
137+ }
138+ return Stream .empty ();
139+ });
140+ }
141+
142+ protected static Stream <IClasspathEntry > classpathEntriesForModelBundle (IPluginModelBase model ,
143+ IClasspathAttribute [] extra ) {
144+ IResource resource = model .getUnderlyingResource ();
145+ if (resource != null && PluginProject .isJavaProject (resource .getProject ())) {
146+ IJavaProject javaProject = JavaCore .create (resource .getProject ());
147+ return Stream .of (JavaCore .newProjectEntry (javaProject .getPath ()));
148+ }
149+ String location = model .getInstallLocation ();
150+ if (location == null ) {
151+ return Stream .empty ();
152+ }
153+ boolean isJarShape = new File (location ).isFile ();
154+ IPluginLibrary [] libraries = model .getPluginBase ().getLibraries ();
155+ if (isJarShape || libraries .length == 0 ) {
156+ return Stream .of (getEntryForPath (IPath .fromOSString (location ), extra ));
157+ }
158+ return Arrays .stream (libraries ).filter (library -> !IPluginLibrary .RESOURCE .equals (library .getType ()))
159+ .map (library -> {
160+ String name = library .getName ();
161+ String expandedName = ClasspathUtilCore .expandLibraryName (name );
162+ return ClasspathUtilCore .getPath (model , expandedName , isJarShape );
163+ }).filter (Objects ::nonNull ).map (entry -> getEntryForPath (entry , extra ));
164+ }
165+
166+ public static Stream <IClasspathEntry > getRequiredByWire (Bundle bundle , IClasspathAttribute [] extra ) {
167+ BundleWiring wiring = bundle .adapt (BundleWiring .class );
168+ if (wiring == null ) {
169+ return Stream .empty ();
170+ }
171+ List <BundleWire > wires = wiring .getRequiredWires (PackageNamespace .PACKAGE_NAMESPACE );
172+ return wires .stream ().map (wire -> wire .getProviderWiring ().getBundle ()).distinct ()
173+ .filter (b -> b .getBundleId () != 0 )
174+ .flatMap (b -> classpathEntriesForRuntimeBundle (b , extra ).stream ());
175+ }
176+
177+ private static Optional <IClasspathEntry > classpathEntriesForRuntimeBundle (Bundle bundle ,
178+ IClasspathAttribute [] extra ) {
179+ return Optional .ofNullable (bundle .adapt (File .class )).filter (File ::exists )
116180 .map (File ::toPath ).map (Path ::normalize ).map (path -> IPath .fromOSString (path .toString ()))
117- .map (ClasspathUtilCore :: getEntryForPath ). stream ( );
181+ .map (entry -> getEntryForPath ( entry , extra ) );
118182 }
119183
120184 public static boolean isEntryForModel (IClasspathEntry entry , IPluginModelBase projectModel ) {
@@ -127,8 +191,8 @@ public static boolean isEntryForModel(IClasspathEntry entry, IPluginModelBase pr
127191 return false ;
128192 }
129193
130- private static IClasspathEntry getEntryForPath (IPath path ) {
131- return JavaCore .newLibraryEntry (path , path , IPath .ROOT , new IAccessRule [0 ], new IClasspathAttribute [ 0 ] , false );
194+ private static IClasspathEntry getEntryForPath (IPath path , IClasspathAttribute [] extra ) {
195+ return JavaCore .newLibraryEntry (path , path , IPath .ROOT , new IAccessRule [0 ], extra , false );
132196 }
133197
134198 private static void addLibraryEntry (IPluginLibrary library , Collection <ClasspathLibrary > entries ) {
0 commit comments