diff --git a/_ext/eclipse-base/CHANGES.md b/_ext/eclipse-base/CHANGES.md
index 5e28d4bd59..815f29e320 100644
--- a/_ext/eclipse-base/CHANGES.md
+++ b/_ext/eclipse-base/CHANGES.md
@@ -1,5 +1,9 @@
# spotless-eclipse-base
+### Version 3.2.0 - June 30th 2019 ([artifact]([jcenter](https://bintray.com/diffplug/opensource/spotless-eclipse-base)))
+
+* Added support of Eclipse 4.12 framework wiring. ([#413](https://github.com/diffplug/spotless/issues/413))
+
### Version 3.1.1 - June 4th 2019 ([artifact]([jcenter](https://bintray.com/diffplug/opensource/spotless-eclipse-base)))
* Fixed problem handling URL escaped characters in JAR file location. ([#401](https://github.com/diffplug/spotless/issues/401))
diff --git a/_ext/eclipse-base/gradle.properties b/_ext/eclipse-base/gradle.properties
index 3c42ae3abe..6737e08912 100644
--- a/_ext/eclipse-base/gradle.properties
+++ b/_ext/eclipse-base/gradle.properties
@@ -1,7 +1,7 @@
# Mayor versions correspond to the supported Eclipse core version.
# Minor version is incremented for features or incompatible changes (including changes to supported dependency versions).
# Patch version is incremented for backward compatible patches of this library.
-ext_version=3.1.1
+ext_version=3.2.0
ext_artifactId=spotless-eclipse-base
ext_description=Eclipse bundle controller and services for Spotless
@@ -12,7 +12,7 @@ ext_group=com.diffplug.spotless
ext_VER_JAVA=1.8
# Compile dependencies
-VER_ECLIPSE_CORE_RESOURCES=[3.11.1,4.0.0[
+VER_ECLIPSE_CORE_RESOURCES=[3.13.400,4.0.0[
# Provided dependencies
VER_SLF4J=[1.6,2.0[
\ No newline at end of file
diff --git a/_ext/eclipse-base/src/main/java/com/diffplug/spotless/extra/eclipse/base/SpotlessEclipseFramework.java b/_ext/eclipse-base/src/main/java/com/diffplug/spotless/extra/eclipse/base/SpotlessEclipseFramework.java
index 03e8c37d95..2a7a59b79b 100644
--- a/_ext/eclipse-base/src/main/java/com/diffplug/spotless/extra/eclipse/base/SpotlessEclipseFramework.java
+++ b/_ext/eclipse-base/src/main/java/com/diffplug/spotless/extra/eclipse/base/SpotlessEclipseFramework.java
@@ -25,6 +25,7 @@
import javax.xml.parsers.SAXParserFactory;
+import org.eclipse.core.internal.runtime.InternalPlatform;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
@@ -226,6 +227,13 @@ private void addPlugin(int state, BundleActivator plugin) throws BundleException
if (!coreConfigStarted) {
//The SAXParserFactory.class is required for parsing the plugin XML files
addMandatoryServiceIfMissing(SAXParserFactory.class, SAXParserFactory.newInstance());
+ /*
+ * Since org.eclipse.core.runtime version 3.15.300, the Eclipse bundle look-up is accomplished
+ * via the wiring framework, which requires a stat of the InternalPlatform.
+ * The internal platform initialization is customized by the services
+ * registered to the controller.
+ */
+ InternalPlatform.getDefault().start(controller);
startFrameworkBundles();
coreConfigStarted = true;
}
diff --git a/_ext/eclipse-base/src/main/java/com/diffplug/spotless/extra/eclipse/base/osgi/BundleController.java b/_ext/eclipse-base/src/main/java/com/diffplug/spotless/extra/eclipse/base/osgi/BundleController.java
index 8ee9b8c7be..3956b2d30c 100644
--- a/_ext/eclipse-base/src/main/java/com/diffplug/spotless/extra/eclipse/base/osgi/BundleController.java
+++ b/_ext/eclipse-base/src/main/java/com/diffplug/spotless/extra/eclipse/base/osgi/BundleController.java
@@ -28,6 +28,7 @@
import org.osgi.framework.Filter;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
+import org.osgi.framework.wiring.FrameworkWiring;
/**
* OSGi bundle controller allowing a minimal Eclipse platform setup
@@ -63,8 +64,11 @@ public BundleController() throws BundleException {
bundles.add(systemBundle);
services = new ServiceCollection(systemBundle, properties);
+
//Eclipse core (InternalPlatform) still uses PackageAdmin for looking up bundles
- services.add(org.osgi.service.packageadmin.PackageAdmin.class, new EclipseBundleLookup(bundles));
+ EclipseBundleLookup bundleLookup = new EclipseBundleLookup(systemBundle, bundles);
+ services.add(org.osgi.service.packageadmin.PackageAdmin.class, bundleLookup);
+ services.add(FrameworkWiring.class, bundleLookup);
//Redirect framework activator requests to the the org.eclipse.osgi bundle to this instance.
bundles.add(new SimpleBundle(systemBundle, ECLIPSE_LAUNCHER_SYMBOLIC_NAME, Bundle.ACTIVE));
diff --git a/_ext/eclipse-base/src/main/java/com/diffplug/spotless/extra/eclipse/base/osgi/EclipseBundleLookup.java b/_ext/eclipse-base/src/main/java/com/diffplug/spotless/extra/eclipse/base/osgi/EclipseBundleLookup.java
index 601825bbfd..0ec091a58b 100644
--- a/_ext/eclipse-base/src/main/java/com/diffplug/spotless/extra/eclipse/base/osgi/EclipseBundleLookup.java
+++ b/_ext/eclipse-base/src/main/java/com/diffplug/spotless/extra/eclipse/base/osgi/EclipseBundleLookup.java
@@ -15,26 +15,48 @@
*/
package com.diffplug.spotless.extra.eclipse.base.osgi;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import org.eclipse.osgi.internal.framework.FilterImpl;
import org.osgi.framework.Bundle;
+import org.osgi.framework.FrameworkListener;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.namespace.IdentityNamespace;
+import org.osgi.framework.wiring.BundleCapability;
+import org.osgi.framework.wiring.FrameworkWiring;
+import org.osgi.resource.Namespace;
+import org.osgi.resource.Requirement;
import org.osgi.service.packageadmin.ExportedPackage;
import org.osgi.service.packageadmin.PackageAdmin;
import org.osgi.service.packageadmin.RequiredBundle;
/**
- * {@link PackageAdmin} service for bundle look-up and bypassing wiring.
+ *
+ * {@link PackageAdmin} and {@link FrameworkWiring} service for bundle look-up.
*
- * The wiring information will always claim that all required bundles are present.
- * Other functionality is not supported.
- * Unsupported methods are marked as deprecated and throw an {@link UnsupportedOperationException}.
+ * The wiring information will always claim that all required bundles are present, since
+ * Spotlss does on purpose not provide all dependencies requested by plugins, since
+ * only small parts of the plugins are used.
+ * Removal and addition requests for bundles will always claim that there is nothing to do.
*
- * Interface is deprecated, but for example the InternalPlatform still uses PackageAdmin.
+ * PackageAdmin interface is deprecated, but might still be used by bundles.
+ * It is kept for backward compatibility until removed from Eclipse.
*/
@SuppressWarnings("deprecation")
-class EclipseBundleLookup implements PackageAdmin {
+class EclipseBundleLookup implements FrameworkWiring, PackageAdmin {
+ private static final Set OSGI_KEYS_FOR_SYMBOLIC_NAMES = Collections.unmodifiableSet(Stream.of(IdentityNamespace.IDENTITY_NAMESPACE, IdentityNamespace.TYPE_BUNDLE).collect(Collectors.toSet()));
+ private final Bundle systemBundle;
private final BundleSet bundles;
- EclipseBundleLookup(final BundleSet bundles) {
+ EclipseBundleLookup(final Bundle systemBundle, final BundleSet bundles) {
+ this.systemBundle = systemBundle;
this.bundles = bundles;
}
@@ -97,4 +119,64 @@ public int getBundleType(Bundle bundle) {
return 0; //No fragments
}
+ @Override
+ public Bundle getBundle() {
+ return systemBundle;
+ }
+
+ @Override
+ public void refreshBundles(Collection bundles, FrameworkListener... listeners) {
+ //Spotless bundles cannot be loaded dynamically
+ }
+
+ @Override
+ public boolean resolveBundles(Collection bundles) {
+ return true;
+ }
+
+ @Override
+ public Collection getRemovalPendingBundles() {
+ return Collections.emptyList(); //Nothing to remove
+ }
+
+ @Override
+ public Collection getDependencyClosure(Collection bundles) {
+ return Collections.emptyList(); //No dependencies
+ }
+
+ @Override
+ public Collection findProviders(Requirement requirement) {
+ // requirement must not be null (according to interface description)!
+ String filterSpec = requirement.getDirectives().get(Namespace.REQUIREMENT_FILTER_DIRECTIVE);
+ if (null == filterSpec) {
+ throw new IllegalArgumentException("Requirement filter diretive '" + Namespace.REQUIREMENT_FILTER_DIRECTIVE + "' not found.");
+ }
+ try {
+ FilterImpl requirementFilter = FilterImpl.newInstance(filterSpec);
+ Collection requiredSymbolicNames = getRequestedSymbolicNames(requirementFilter);
+ Collection capabilities = new ArrayList(requiredSymbolicNames.size());
+ requiredSymbolicNames.forEach(symbolicName -> {
+ Bundle bundle = bundles.get(symbolicName);
+ if (bundle != null) {
+ capabilities.add(new SimpleBundleCapability(bundle));
+ }
+ });
+ return capabilities;
+ } catch (InvalidSyntaxException e) {
+ throw new IllegalArgumentException("Filter specifiation invalid:\n" + filterSpec, e);
+ }
+ }
+
+ /**
+ * Simplified parser irgnoreing the version.
+ * Parser is incomplete since it ignores the filter operation.
+ * It basicall implements the bespoke way Eclipse maps its old style bundle handling to OSGI.
+ */
+ private static Collection getRequestedSymbolicNames(FilterImpl filter) {
+ List symbolicNames = filter.getStandardOSGiAttributes().entrySet().stream().filter(entry -> OSGI_KEYS_FOR_SYMBOLIC_NAMES.contains(entry.getKey())).map(entry -> entry.getValue()).collect(Collectors.toList());
+ filter.getChildren().forEach(childFilter -> {
+ symbolicNames.addAll(getRequestedSymbolicNames(childFilter));
+ });
+ return symbolicNames;
+ }
}
diff --git a/_ext/eclipse-base/src/main/java/com/diffplug/spotless/extra/eclipse/base/osgi/SimpleBundle.java b/_ext/eclipse-base/src/main/java/com/diffplug/spotless/extra/eclipse/base/osgi/SimpleBundle.java
index 3a7e305975..5234855dc5 100644
--- a/_ext/eclipse-base/src/main/java/com/diffplug/spotless/extra/eclipse/base/osgi/SimpleBundle.java
+++ b/_ext/eclipse-base/src/main/java/com/diffplug/spotless/extra/eclipse/base/osgi/SimpleBundle.java
@@ -69,6 +69,35 @@ private SimpleBundle(BundleContext context, int state, ResourceAccessor resource
name = master.name;
}
+ @Override
+ public A adapt(Class type) {
+ /*
+ * The adaptation is currently used by the InternalPlugin to get the framework wiring
+ * implementation from the system bundle.
+ * The original purpose to provide more specialized access to the Bundle object,
+ * seems not be used by Eclipse at all.
+ * Hence the call is mapped to old-style Eclipse services.
+ */
+ try {
+
+ ServiceReference>[] references = context.getAllServiceReferences(type.getName(), "");
+ if ((null != references) && (0 != references.length)) {
+ if (1 != references.length) {
+ throw new IllegalArgumentException("Multiple services found for " + type.getName()); //In Spotless services should always be unique
+ }
+ Object obj = context.getService(references[0]);
+ try {
+ return type.cast(obj);
+ } catch (ClassCastException e) {
+ throw new IllegalArgumentException("Received unexpected class for reference filter " + type.getName(), e);
+ }
+ }
+ return null;
+ } catch (InvalidSyntaxException e) {
+ throw new IllegalArgumentException("Unexpected syntax exception", e); //Should never be thrown by Spotless bundle controller
+ }
+ }
+
@Override
public int getState() {
return state;
diff --git a/_ext/eclipse-base/src/main/java/com/diffplug/spotless/extra/eclipse/base/osgi/SimpleBundleCapability.java b/_ext/eclipse-base/src/main/java/com/diffplug/spotless/extra/eclipse/base/osgi/SimpleBundleCapability.java
new file mode 100644
index 0000000000..66f331807d
--- /dev/null
+++ b/_ext/eclipse-base/src/main/java/com/diffplug/spotless/extra/eclipse/base/osgi/SimpleBundleCapability.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2016 DiffPlug
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.diffplug.spotless.extra.eclipse.base.osgi;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Version;
+import org.osgi.framework.wiring.BundleCapability;
+import org.osgi.framework.wiring.BundleRequirement;
+import org.osgi.framework.wiring.BundleRevision;
+import org.osgi.framework.wiring.BundleWiring;
+import org.osgi.resource.Capability;
+import org.osgi.resource.Requirement;
+
+/**
+ * Simplified bundle capability ignoring internal wiring and versions
+ *
+ * Since multiple versions/implementations of bundles for the same
+ * capability is not supported a split of bundle capability and revision is not required.
+ */
+class SimpleBundleCapability implements BundleCapability, BundleRevision {
+ private final Bundle bundle;
+
+ SimpleBundleCapability(Bundle bundle) {
+ this.bundle = bundle;
+ }
+
+ @Override
+ public BundleRevision getRevision() {
+ return this;
+ }
+
+ @Override
+ public String getNamespace() {
+ return this.getClass().getName(); //All bundles live in th same namespace
+ }
+
+ @Override
+ public Map getDirectives() {
+ return Collections.emptyMap();
+ }
+
+ @Override
+ public Map getAttributes() {
+ return Collections.emptyMap();
+ }
+
+ @Override
+ public BundleRevision getResource() {
+ return this;
+ }
+
+ @Override
+ public Bundle getBundle() {
+ return bundle;
+ }
+
+ @Override
+ public String getSymbolicName() {
+ return bundle.getSymbolicName();
+ }
+
+ @Override
+ public Version getVersion() {
+ return bundle.getVersion();
+ }
+
+ @Override
+ public List getDeclaredCapabilities(String namespace) {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public List getDeclaredRequirements(String namespace) {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public int getTypes() {
+ return 0; //It does not matter whether this bunddle is a fragment of not since all bundles are initially provided
+ }
+
+ @Override
+ public BundleWiring getWiring() {
+ return null; //No wiring information
+ }
+
+ @Override
+ public List getCapabilities(String namespace) {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public List getRequirements(String namespace) {
+ return Collections.emptyList();
+ }
+
+}