Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCarsten Reckord2017-03-15 12:54:06 +0000
committerCarsten Reckord2017-03-15 19:24:28 +0000
commitb5202d198f4ea9e2432ec92035aeb233e8290290 (patch)
tree1905768f5ccfcd0316254a55ae318d58ef2dc4cd
parentb79322844c8d0112e13329b25f919b25d4853315 (diff)
downloadorg.eclipse.epp.mpc-b5202d198f4ea9e2432ec92035aeb233e8290290.tar.gz
org.eclipse.epp.mpc-b5202d198f4ea9e2432ec92035aeb233e8290290.tar.xz
org.eclipse.epp.mpc-b5202d198f4ea9e2432ec92035aeb233e8290290.zip
511216: Support central USS OAuth login in MPC
Support USS 1.0.1 with regular login and USS 1.1 with OAuth This reverts parts of the following commits, until all clients have updated to USS 1.1: - 1ca5fe5 Bug 499930 - MPC will need a client_id and client_secret for Eclipse USS SDK - 09b7551 499930: MPC will need a client_id and client_secret for Eclipse USS SDK Bug: 511216 Task-Url: https://bugs.eclipse.org/bugs/show_bug.cgi?id=511216
-rw-r--r--org.eclipse.epp.mpc-target/oxygen.target8
-rw-r--r--org.eclipse.epp.mpc.core/META-INF/MANIFEST.MF6
-rw-r--r--org.eclipse.epp.mpc.core/src/org/eclipse/epp/internal/mpc/core/service/MPCOAuthParameters.java53
-rw-r--r--org.eclipse.epp.mpc.core/src/org/eclipse/epp/internal/mpc/core/service/MarketplaceStorageService.java22
-rw-r--r--org.eclipse.epp.mpc.core/src/org/eclipse/epp/internal/mpc/core/service/StorageConfigurer.java131
-rw-r--r--org.eclipse.epp.mpc.core/src/org/eclipse/epp/internal/mpc/core/service/USS10StorageConfigurer.java51
-rw-r--r--org.eclipse.epp.mpc.core/src/org/eclipse/epp/internal/mpc/core/service/USS11ExtendedOAuthStorageConfigurer.java125
-rw-r--r--org.eclipse.epp.mpc.core/src/org/eclipse/epp/internal/mpc/core/service/USS11NonInteractiveOAuthCredentialsProvider.java82
-rw-r--r--org.eclipse.epp.mpc.core/src/org/eclipse/epp/internal/mpc/core/service/USS11OAuthStorageConfigurer.java146
-rw-r--r--org.eclipse.epp.mpc.tests/src/org/eclipse/epp/mpc/tests/service/MarketplaceStorageServiceRegistrationTest.java87
-rw-r--r--org.eclipse.epp.mpc.tests/src/org/eclipse/epp/mpc/tests/service/SolutionCompatibilityFilterTest.java2
-rw-r--r--org.eclipse.epp.mpc.tests/src/org/eclipse/epp/mpc/tests/util/PropertyStub.java65
-rw-r--r--org.eclipse.epp.mpc.ui/META-INF/MANIFEST.MF4
13 files changed, 712 insertions, 70 deletions
diff --git a/org.eclipse.epp.mpc-target/oxygen.target b/org.eclipse.epp.mpc-target/oxygen.target
index da5aca98..2ed38776 100644
--- a/org.eclipse.epp.mpc-target/oxygen.target
+++ b/org.eclipse.epp.mpc-target/oxygen.target
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<?pde version="3.8"?><target name="MPC Target Platform - Oxygen" sequenceNumber="27">
+<?pde version="3.8"?><target name="MPC Target Platform - Oxygen" sequenceNumber="6">
<locations>
<location includeAllPlatforms="false" includeConfigurePhase="true" includeMode="planner" includeSource="true" type="InstallableUnit">
<unit id="org.eclipse.equinox.p2.sdk.feature.group" version="0.0.0"/>
@@ -9,14 +9,14 @@
<repository location="http://download.eclipse.org/releases/oxygen"/>
</location>
<location includeAllPlatforms="false" includeConfigurePhase="true" includeMode="planner" includeSource="true" type="InstallableUnit">
-<unit id="org.apache.httpcomponents.httpclient" version="4.3.6.v201511171540"/>
-<unit id="org.apache.httpcomponents.httpcore" version="4.3.3.v201411290715"/>
+<unit id="org.apache.httpcomponents.httpclient" version="4.5.2.v20170210-0925"/>
+<unit id="org.apache.httpcomponents.httpcore" version="4.4.6.v20170210-0925"/>
<unit id="org.junit" version="0.0.0"/>
<unit id="org.hamcrest" version="0.0.0"/>
<unit id="org.hamcrest.core" version="0.0.0"/>
<unit id="org.hamcrest.library" version="0.0.0"/>
<unit id="org.mockito" version="0.0.0"/>
-<repository location="http://download.eclipse.org/tools/orbit/downloads/drops/S20160916162009/repository/"/>
+<repository location="http://download.eclipse.org/tools/orbit/downloads/drops/S20170306214312/repository/"/>
</location>
<location includeAllPlatforms="false" includeConfigurePhase="true" includeMode="planner" includeSource="true" type="InstallableUnit">
<unit id="org.eclipse.license.feature.group" version="0.0.0"/>
diff --git a/org.eclipse.epp.mpc.core/META-INF/MANIFEST.MF b/org.eclipse.epp.mpc.core/META-INF/MANIFEST.MF
index 851632b7..720e783a 100644
--- a/org.eclipse.epp.mpc.core/META-INF/MANIFEST.MF
+++ b/org.eclipse.epp.mpc.core/META-INF/MANIFEST.MF
@@ -13,9 +13,9 @@ Require-Bundle: org.eclipse.osgi;bundle-version="3.6.0",
org.eclipse.equinox.ds;bundle-version="1.4.100",
org.eclipse.osgi.services;bundle-version="3.3.100",
org.eclipse.equinox.util;bundle-version="1.0.500",
- org.eclipse.equinox.security,
- org.eclipse.userstorage;bundle-version="[1.1.0,2.0.0)",
- org.eclipse.userstorage.oauth;bundle-version="[1.0.0,2.0.0)"
+ org.eclipse.userstorage;bundle-version="[1.0.1,1.2.0)",
+ org.eclipse.userstorage.oauth;bundle-version="[1.0.0,1.2.0)";resolution:=optional,
+ org.eclipse.equinox.security
Export-Package: org.eclipse.epp.internal.mpc.core;x-friends:="org.eclipse.epp.mpc.ui",
org.eclipse.epp.internal.mpc.core.model;x-friends:="org.eclipse.epp.mpc.ui",
org.eclipse.epp.internal.mpc.core.service;x-friends:="org.eclipse.epp.mpc.ui",
diff --git a/org.eclipse.epp.mpc.core/src/org/eclipse/epp/internal/mpc/core/service/MPCOAuthParameters.java b/org.eclipse.epp.mpc.core/src/org/eclipse/epp/internal/mpc/core/service/MPCOAuthParameters.java
deleted file mode 100644
index 174b95d0..00000000
--- a/org.eclipse.epp.mpc.core/src/org/eclipse/epp/internal/mpc/core/service/MPCOAuthParameters.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010 The Eclipse Foundation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * The Eclipse Foundation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.epp.internal.mpc.core.service;
-
-import org.eclipse.userstorage.oauth.OAuthParameters;
-
-public class MPCOAuthParameters extends OAuthParameters {
-
- private static final String SERVICE_NAME = "mpc"; //$NON-NLS-1$
-
- private static final String CLIENT_ID = "1e8b68d6e5015c2bcf8e03d44dd97fc431f17e394860f08f1a05978c"; //$NON-NLS-1$
-
- private static final String CLIENT_SECRET = "26e9f81e5d02d4a019e042d012a861f34a446c35cb84070e80278d8e"; //$NON-NLS-1$
-
- private static final String CLIENT_KEY = "9d08c11f742f53a2cd6348d373fd1fa0b079694199f760b315a12a"; //$NON-NLS-1$
-
- // FIXME: these should be the uss_project_* alternatives
- //private static final String[] DEFAULT_MPC_SCOPES = { "profile", "uss_project_retrieve", "uss_project_update", "uss_project_delete" };
- private static final String[] DEFAULT_MPC_SCOPES = { "profile", "uss_retrieve", "uss_update" }; //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
-
- @Override
- protected String getServiceName() {
- return SERVICE_NAME;
- }
-
- @Override
- protected String getDefaultClientId() {
- return CLIENT_ID;
- }
-
- @Override
- protected String getDefaultClientSecret() {
- return CLIENT_SECRET;
- }
-
- @Override
- protected String getDefaultClientKey() {
- return CLIENT_KEY;
- }
-
- @Override
- protected String[] getDefaultScopes() {
- return DEFAULT_MPC_SCOPES;
- }
-}
diff --git a/org.eclipse.epp.mpc.core/src/org/eclipse/epp/internal/mpc/core/service/MarketplaceStorageService.java b/org.eclipse.epp.mpc.core/src/org/eclipse/epp/internal/mpc/core/service/MarketplaceStorageService.java
index a9054a71..2a19721f 100644
--- a/org.eclipse.epp.mpc.core/src/org/eclipse/epp/internal/mpc/core/service/MarketplaceStorageService.java
+++ b/org.eclipse.epp.mpc.core/src/org/eclipse/epp/internal/mpc/core/service/MarketplaceStorageService.java
@@ -22,6 +22,7 @@ import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.CopyOnWriteArrayList;
+import org.eclipse.core.runtime.CoreException;
import org.eclipse.epp.internal.mpc.core.MarketplaceClientCore;
import org.eclipse.epp.internal.mpc.core.util.ServiceUtil;
import org.eclipse.epp.mpc.core.service.IMarketplaceStorageService;
@@ -64,6 +65,8 @@ public class MarketplaceStorageService implements IMarketplaceStorageService {
private EclipseOAuthCredentialsProvider credentialsProvider;
+ private StorageConfigurer configurer;
+
public URI getServiceUri() {
return serviceUri;
}
@@ -101,9 +104,14 @@ public class MarketplaceStorageService implements IMarketplaceStorageService {
protected IStorage createStorage() {
IStorage storage = getStorageFactory().create(applicationToken,
new FileStorageCache.SingleApplication(this.applicationToken));
- credentialsProvider = new EclipseOAuthCredentialsProvider(new MPCOAuthParameters());
- credentialsProvider.setInteractive(false);
- storage.setCredentialsProvider(credentialsProvider);
+ try {
+ configurer = StorageConfigurer.get();
+ configurer.configure(storage);
+ configurer.setInteractive(storage, false);
+ } catch (CoreException e) {
+ configurer = null;
+ MarketplaceClientCore.error(e);
+ }
return storage;
}
@@ -129,13 +137,10 @@ public class MarketplaceStorageService implements IMarketplaceStorageService {
public <T> T runWithLogin(Callable<T> c) throws Exception {
String oldUser = getCurrentUser();
- boolean wasInteractive = credentialsProvider.isInteractive();
- credentialsProvider.setInteractive(true);
try {
- T result = c.call();
+ T result = configurer != null ? configurer.runWithLogin(storage, c) : c.call();
return result;
} finally {
- credentialsProvider.setInteractive(wasInteractive);
String newUser = getCurrentUser();//TODO the OAuth token might change with the user staying the same - this would cause an unnecessary refresh event
notifyLoginChanged(oldUser, newUser);
}
@@ -181,7 +186,8 @@ public class MarketplaceStorageService implements IMarketplaceStorageService {
return null;
}
IStorageService service = getStorage().getService();
- return provider.hasCredentials(service) ? provider.getCredentials(service) : null;
+ //return provider.hasCredentials(service) ? provider.getCredentials(service) : null;
+ return ((StorageService) service).getCredentials();
}
public void activate(BundleContext context, Map<?, ?> properties) {
diff --git a/org.eclipse.epp.mpc.core/src/org/eclipse/epp/internal/mpc/core/service/StorageConfigurer.java b/org.eclipse.epp.mpc.core/src/org/eclipse/epp/internal/mpc/core/service/StorageConfigurer.java
new file mode 100644
index 00000000..c9a551c5
--- /dev/null
+++ b/org.eclipse.epp.mpc.core/src/org/eclipse/epp/internal/mpc/core/service/StorageConfigurer.java
@@ -0,0 +1,131 @@
+/*******************************************************************************
+ * Copyright (c) 2010 The Eclipse Foundation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * The Eclipse Foundation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.epp.internal.mpc.core.service;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.Callable;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.MultiStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.epp.internal.mpc.core.MarketplaceClientCore;
+import org.eclipse.userstorage.IStorage;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.Version;
+
+public abstract class StorageConfigurer {
+
+ public static final String PROP_FACTORIES = StorageConfigurer.class.getName() + ".factories";
+ private static final String[] DEFAULT_FACTORIES = { "org.eclipse.epp.internal.mpc.core.service.USS11ExtendedOAuthStorageConfigurer$Factory",
+ "org.eclipse.epp.internal.mpc.core.service.USS11OAuthStorageConfigurer$Factory",
+ "org.eclipse.epp.internal.mpc.core.service.USS10StorageConfigurer$Factory" };
+
+ abstract static class Factory {
+ abstract boolean isApplicable();
+
+ abstract StorageConfigurer doCreate();
+
+ public StorageConfigurer create() {
+ if (isApplicable()) {
+ return doCreate();
+ }
+ return null;
+ }
+ }
+
+ static Version getUSSVersion() {
+ Bundle bundle = FrameworkUtil.getBundle(IStorage.class);
+ return bundle.getVersion();
+ }
+
+ private static StorageConfigurer instance;
+
+ private static StorageConfigurer create() throws CoreException {
+ String[] factories = getFactories();
+
+ MultiStatus errors = new MultiStatus(MarketplaceClientCore.BUNDLE_ID, 0,
+ "Failed to create user storage configurer", null);
+ for (String factoryName : factories) {
+ try {
+ Class<? extends Factory> factoryClass = Class.forName(factoryName).asSubclass(Factory.class);
+ Factory factory = factoryClass.newInstance();
+ StorageConfigurer configurer = factory.create();
+ if (configurer != null) {
+ return configurer;
+ }
+ } catch (Exception e) {
+ errors.add(new Status(IStatus.ERROR, MarketplaceClientCore.BUNDLE_ID, factoryName, e));
+ }
+ }
+ try {
+ return new USS10StorageConfigurer();
+ } catch (Throwable t) {
+ errors.add(new Status(IStatus.ERROR, MarketplaceClientCore.BUNDLE_ID, "Fallback", t));
+ }
+ throw new CoreException(errors);
+ }
+
+ private static String[] getFactories() {
+ String[] factories = DEFAULT_FACTORIES;
+ String factoriesValue = System.getProperty(PROP_FACTORIES);
+ if (factoriesValue != null && !factoriesValue.isEmpty()) {
+ String[] givenFactories = factoriesValue.split("\\s+"); //$NON-NLS-1$
+ List<String> givenFactoriesList = new ArrayList<String>(Arrays.asList(givenFactories));
+ Set<String> supportedFactories = new HashSet<String>(Arrays.asList(DEFAULT_FACTORIES));
+ givenFactoriesList.retainAll(supportedFactories);
+ factories = givenFactoriesList.toArray(new String[givenFactoriesList.size()]);
+ }
+ return factories;
+ }
+
+ public static synchronized StorageConfigurer get() throws CoreException {
+ if (instance == null) {
+ instance = create();
+ }
+ return instance;
+ }
+
+ public static synchronized StorageConfigurer reset() throws CoreException {
+ StorageConfigurer oldInstance = instance;
+ instance = null;
+ StorageConfigurer newInstance = get();
+ if (oldInstance != null && newInstance.getClass() == oldInstance.getClass()) {
+ instance = oldInstance;
+ }
+ return instance;
+ }
+
+ public static synchronized void unset() {
+ instance = null;
+ }
+
+ public abstract void configure(IStorage storage) throws CoreException;
+
+ public abstract Object setInteractive(IStorage storage, boolean interactive) throws CoreException;
+
+ abstract void restoreInteractive(IStorage storage, Object restoreValue) throws CoreException;
+
+ public <T> T runWithLogin(IStorage storage, Callable<T> c) throws Exception {
+ final Object restoreValue = setInteractive(storage, true);
+ try {
+ T result = c.call();
+ return result;
+ } finally {
+ restoreInteractive(storage, restoreValue);
+ }
+ }
+}
diff --git a/org.eclipse.epp.mpc.core/src/org/eclipse/epp/internal/mpc/core/service/USS10StorageConfigurer.java b/org.eclipse.epp.mpc.core/src/org/eclipse/epp/internal/mpc/core/service/USS10StorageConfigurer.java
new file mode 100644
index 00000000..e6c4cd9e
--- /dev/null
+++ b/org.eclipse.epp.mpc.core/src/org/eclipse/epp/internal/mpc/core/service/USS10StorageConfigurer.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright (c) 2010 The Eclipse Foundation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * The Eclipse Foundation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.epp.internal.mpc.core.service;
+
+import org.eclipse.userstorage.IStorage;
+import org.eclipse.userstorage.spi.ICredentialsProvider;
+import org.osgi.framework.Version;
+
+class USS10StorageConfigurer extends StorageConfigurer {
+ static class Factory extends StorageConfigurer.Factory {
+
+ @Override
+ boolean isApplicable() {
+ Version ussVersion = getUSSVersion();
+ return ussVersion.getMajor() == 1 && ussVersion.getMinor() == 0;
+ }
+
+ @Override
+ StorageConfigurer doCreate() {
+ return new USS10StorageConfigurer();
+ }
+
+ }
+
+ @Override
+ public void configure(IStorage storage) {
+ storage.setCredentialsProvider(ICredentialsProvider.CANCEL);
+ }
+
+ @Override
+ public Object setInteractive(IStorage storage, boolean interactive) {
+ ICredentialsProvider credentialsProvider = storage.getCredentialsProvider();
+ //Use default credentials provider for interactive mode
+ storage.setCredentialsProvider(interactive ? null : ICredentialsProvider.CANCEL);
+ return credentialsProvider;
+ }
+
+ @Override
+ void restoreInteractive(IStorage storage, Object restoreValue) {
+ storage.setCredentialsProvider((ICredentialsProvider) restoreValue);
+ }
+
+}
diff --git a/org.eclipse.epp.mpc.core/src/org/eclipse/epp/internal/mpc/core/service/USS11ExtendedOAuthStorageConfigurer.java b/org.eclipse.epp.mpc.core/src/org/eclipse/epp/internal/mpc/core/service/USS11ExtendedOAuthStorageConfigurer.java
new file mode 100644
index 00000000..2789c719
--- /dev/null
+++ b/org.eclipse.epp.mpc.core/src/org/eclipse/epp/internal/mpc/core/service/USS11ExtendedOAuthStorageConfigurer.java
@@ -0,0 +1,125 @@
+/*******************************************************************************
+ * Copyright (c) 2010 The Eclipse Foundation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * The Eclipse Foundation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.epp.internal.mpc.core.service;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.epp.internal.mpc.core.MarketplaceClientCore;
+import org.eclipse.userstorage.IStorage;
+import org.eclipse.userstorage.oauth.EclipseOAuthCredentialsProvider;
+import org.eclipse.userstorage.spi.ICredentialsProvider;
+
+class USS11ExtendedOAuthStorageConfigurer extends USS11OAuthStorageConfigurer {
+
+ static class Factory extends USS11OAuthStorageConfigurer.Factory {
+ static Boolean hasInteractiveMethods = null;
+
+ static Method setInteractiveMethod = null;
+
+ static Method isInteractiveMethod = null;
+
+ @Override
+ boolean isApplicable() {
+ if (!super.isApplicable()) {
+ return false;
+ }
+ synchronized (Factory.class) {
+ if (hasInteractiveMethods != null) {
+ return hasInteractiveMethods;
+ }
+ try {
+ Class<?> providerClass = Class
+ .forName("org.eclipse.userstorage.oauth.EclipseOAuthCredentialsProvider");
+ Method setInteractiveMethod = providerClass.getMethod("setInteractive", boolean.class);
+ Method isInteractiveMethod = providerClass.getMethod("isInteractive");
+ hasInteractiveMethods = true;
+ Factory.setInteractiveMethod = setInteractiveMethod;
+ Factory.isInteractiveMethod = isInteractiveMethod;
+ return true;
+ } catch (Exception ex) {
+ disable();
+ return false;
+ }
+ }
+ }
+
+ @Override
+ StorageConfigurer doCreate() {
+ return new USS11ExtendedOAuthStorageConfigurer();
+ }
+
+ static void disable() {
+ synchronized (Factory.class) {
+ hasInteractiveMethods = false;
+ Factory.setInteractiveMethod = null;
+ Factory.isInteractiveMethod = null;
+ }
+ }
+ }
+
+ @Override
+ ICredentialsProvider createCredentialsProvider() {
+ return createOAuthCredentialsProvider();
+ }
+
+ @Override
+ public Object setInteractive(IStorage storage, boolean interactive) throws CoreException {
+ try {
+ return super.setInteractive(storage, interactive);
+ } catch (RuntimeException ex) {
+ StorageConfigurer configurer = StorageConfigurer.reset();
+ if (configurer != this) {
+ configurer.configure(storage);
+ return configurer.setInteractive(storage, interactive);
+ }
+ throw new CoreException(new Status(IStatus.ERROR, MarketplaceClientCore.BUNDLE_ID,
+ "Failed to change interactive authentication mode", ex));
+ }
+ }
+
+ @Override
+ boolean setInteractive(ICredentialsProvider credentialsProvider, boolean interactive) {
+ EclipseOAuthCredentialsProvider oauthProvider = (EclipseOAuthCredentialsProvider) credentialsProvider;
+ Method setInteractiveMethod;
+ Method isInteractiveMethod;
+ synchronized (Factory.class) {
+ if (!Boolean.TRUE.equals(Factory.hasInteractiveMethods)) {
+ throw new UnsupportedOperationException();
+ }
+ setInteractiveMethod = Factory.setInteractiveMethod;
+ isInteractiveMethod = Factory.isInteractiveMethod;
+ }
+ boolean oldInteractive = invoke(oauthProvider, isInteractiveMethod, Boolean.class);
+ invoke(oauthProvider, setInteractiveMethod, Void.class, interactive);
+ return oldInteractive;
+ }
+
+ private static <T> T invoke(Object target, Method method, Class<T> returnType, Object... parameters) {
+ try {
+ Object result = method.invoke(target, parameters);
+ return returnType.cast(result);
+ } catch (IllegalAccessException e) {
+ Factory.disable();
+ throw new RuntimeException(e);
+ } catch (InvocationTargetException e) {
+ Factory.disable();
+ Throwable cause = e.getCause();
+ if (cause instanceof RuntimeException) {
+ throw (RuntimeException) cause;
+ }
+ throw new RuntimeException(cause);
+ }
+ }
+}
diff --git a/org.eclipse.epp.mpc.core/src/org/eclipse/epp/internal/mpc/core/service/USS11NonInteractiveOAuthCredentialsProvider.java b/org.eclipse.epp.mpc.core/src/org/eclipse/epp/internal/mpc/core/service/USS11NonInteractiveOAuthCredentialsProvider.java
new file mode 100644
index 00000000..d05a64e9
--- /dev/null
+++ b/org.eclipse.epp.mpc.core/src/org/eclipse/epp/internal/mpc/core/service/USS11NonInteractiveOAuthCredentialsProvider.java
@@ -0,0 +1,82 @@
+/*******************************************************************************
+ * Copyright (c) 2010 The Eclipse Foundation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * The Eclipse Foundation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.epp.internal.mpc.core.service;
+
+import java.net.URI;
+
+import org.apache.http.client.fluent.Request;
+import org.eclipse.userstorage.IStorageService;
+import org.eclipse.userstorage.oauth.OAuthCredentialsProvider;
+import org.eclipse.userstorage.spi.Credentials;
+
+class USS11NonInteractiveOAuthCredentialsProvider extends OAuthCredentialsProvider
+implements USS11OAuthStorageConfigurer.ToggleInteractive {
+
+ private final OAuthCredentialsProvider delegate;
+
+ private boolean interactive;
+
+ USS11NonInteractiveOAuthCredentialsProvider(OAuthCredentialsProvider delegate, URI authService, String clientId,
+ String clientSecret, String[] scopes, URI expectedCallback) {
+ super(authService, clientId, clientSecret, scopes, expectedCallback);
+ this.delegate = delegate;
+ }
+
+ protected boolean canProvideCredentialsNonInteractively() {
+ return false;
+ }
+
+ public Credentials provideCredentials(IStorageService service, boolean reauthentication) {
+ if (!isInteractive() && !canProvideCredentialsNonInteractively()) {
+ return null;
+ }
+ return delegate.provideCredentials(service, reauthentication);
+ }
+
+ @Override
+ public Credentials getCredentials(IStorageService service) {
+ return delegate.getCredentials(service);
+ }
+
+ @Override
+ public boolean hasCredentials(IStorageService service) {
+ return delegate.hasCredentials(service);
+ }
+
+ @Override
+ public boolean isValid(Credentials credentials) {
+ return delegate.isValid(credentials);
+ }
+
+ @Override
+ public boolean updateCredentials(IStorageService service, Credentials credential) {
+ return delegate.updateCredentials(service, credential);
+ }
+
+ @Override
+ public Request configureRequest(Request request, URI uri, Credentials credentials) {
+ return delegate.configureRequest(request, uri, credentials);
+ }
+
+ @Override
+ public void setStateCode(String stateCode) {
+ super.setStateCode(stateCode);
+ delegate.setStateCode(stateCode);
+ }
+
+ public void setInteractive(boolean interactive) {
+ this.interactive = interactive;
+ }
+
+ public boolean isInteractive() {
+ return interactive;
+ }
+}
diff --git a/org.eclipse.epp.mpc.core/src/org/eclipse/epp/internal/mpc/core/service/USS11OAuthStorageConfigurer.java b/org.eclipse.epp.mpc.core/src/org/eclipse/epp/internal/mpc/core/service/USS11OAuthStorageConfigurer.java
new file mode 100644
index 00000000..329f9a7d
--- /dev/null
+++ b/org.eclipse.epp.mpc.core/src/org/eclipse/epp/internal/mpc/core/service/USS11OAuthStorageConfigurer.java
@@ -0,0 +1,146 @@
+/*******************************************************************************
+ * Copyright (c) 2010 The Eclipse Foundation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * The Eclipse Foundation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.epp.internal.mpc.core.service;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.userstorage.IStorage;
+import org.eclipse.userstorage.oauth.EclipseOAuthCredentialsProvider;
+import org.eclipse.userstorage.oauth.OAuthCredentialsProvider;
+import org.eclipse.userstorage.spi.ICredentialsProvider;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Version;
+
+class USS11OAuthStorageConfigurer extends StorageConfigurer {
+
+ private static final String CLIENT_ID = "1e8b68d6e5015c2bcf8e03d44dd97fc431f17e394860f08f1a05978c"; //$NON-NLS-1$
+
+ private static final String CLIENT_SECRET = "26e9f81e5d02d4a019e042d012a861f34a446c35cb84070e80278d8e"; //$NON-NLS-1$
+
+ private static final String CLIENT_KEY = "9d08c11f742f53a2cd6348d373fd1fa0b079694199f760b315a12a"; //$NON-NLS-1$
+
+ // FIXME: these should be the uss_project_* alternatives
+ //private static final String[] DEFAULT_MPC_SCOPES = { "profile", "uss_project_retrieve", "uss_project_update", "uss_project_delete" };
+ private static final String[] DEFAULT_MPC_SCOPES = { "profile", "uss_retrieve", "uss_update" }; //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
+
+ static class Factory extends StorageConfigurer.Factory {
+
+ @Override
+ boolean isApplicable() {
+ Version ussVersion = getUSSVersion();
+ if (ussVersion.getMajor() > 1 || (ussVersion.getMajor() == 1 && ussVersion.getMinor() >= 1)) {
+ Bundle oauthBundle = Platform.getBundle("org.eclipse.userstorage.oauth"); //$NON-NLS-1$
+ if (oauthBundle == null) {
+ return false;
+ }
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ StorageConfigurer doCreate() {
+ return new USS11OAuthStorageConfigurer();
+ }
+
+ }
+
+ @Override
+ public void configure(IStorage storage) throws CoreException {
+ ICredentialsProvider provider = createCredentialsProvider();
+ storage.setCredentialsProvider(provider);
+ }
+
+ ICredentialsProvider createCredentialsProvider() {
+ return new USS11NonInteractiveOAuthCredentialsProvider(createOAuthCredentialsProvider(),
+ URI.create("https://accounts.eclipse.org/"), //$NON-NLS-1$
+ decrypt(CLIENT_ID, CLIENT_KEY), decrypt(CLIENT_SECRET, CLIENT_KEY), DEFAULT_MPC_SCOPES,
+ URI.create("http://localhost/")); //$NON-NLS-1$
+ }
+
+ OAuthCredentialsProvider createOAuthCredentialsProvider() {
+ EclipseOAuthCredentialsProvider oauthProvider = new EclipseOAuthCredentialsProvider(URI.create("https://accounts.eclipse.org/"), //$NON-NLS-1$
+ decrypt(CLIENT_ID, CLIENT_KEY), decrypt(CLIENT_SECRET, CLIENT_KEY), DEFAULT_MPC_SCOPES,
+ URI.create("http://localhost/")); //$NON-NLS-1$
+ //oauthProvider.setShell(null);
+ return oauthProvider;
+ }
+
+ @Override
+ public Object setInteractive(IStorage storage, boolean interactive) throws CoreException {
+ ICredentialsProvider credentialsProvider = storage.getCredentialsProvider();
+ boolean oldInteractive = setInteractive(credentialsProvider, interactive);
+ return oldInteractive;
+ }
+
+ boolean setInteractive(ICredentialsProvider credentialsProvider, boolean interactive) {
+ ToggleInteractive uss11Provider = (ToggleInteractive) credentialsProvider;
+ boolean oldInteractive = uss11Provider.isInteractive();
+ uss11Provider.setInteractive(interactive);
+ return oldInteractive;
+ }
+
+ @Override
+ void restoreInteractive(IStorage storage, Object restoreValue) throws CoreException {
+ setInteractive(storage, Boolean.TRUE.equals(restoreValue));
+ }
+
+ private static String decrypt(String str, String key) {
+ byte[] keyBytes = hexToBytes(key);
+ byte[] bytes = hexToBytes(str);
+ byte[] result = new byte[bytes.length - 1];
+
+ int j = bytes[result.length] - Byte.MIN_VALUE;
+ crypt(bytes, result, keyBytes, result.length, j);
+ try {
+ return new String(result, "UTF-8"); //$NON-NLS-1$
+ } catch (UnsupportedEncodingException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ private static byte[] hexToBytes(String hexStr) {
+ int hexStrLen = hexStr.length();
+ if ((hexStrLen & 1) == 1) {
+ hexStr = '0' + hexStr;
+ hexStrLen++;
+ }
+ byte[] out = new byte[hexStrLen / 2];
+
+ // Safe to assume the string is even length
+ byte b1, b2;
+ for (int i = 0; i < hexStrLen; i += 2) {
+ b1 = (byte) Character.digit(hexStr.charAt(i), 16);
+ b2 = (byte) Character.digit(hexStr.charAt(i + 1), 16);
+ if (b1 < 0 || b2 < 0) {
+ throw new NumberFormatException(hexStr);
+ }
+
+ out[i / 2] = (byte) (b1 << 4 | b2 & 0xff);
+ }
+ return out;
+ }
+
+ private static void crypt(byte[] bytes, byte[] result, byte[] key, int length, int j) {
+ for (int i = 0; i < length; i++) {
+ result[i] = (byte) (bytes[i] ^ key[j++ % key.length]);
+ }
+ }
+
+ static interface ToggleInteractive {
+ void setInteractive(boolean interactive);
+
+ boolean isInteractive();
+ }
+}
diff --git a/org.eclipse.epp.mpc.tests/src/org/eclipse/epp/mpc/tests/service/MarketplaceStorageServiceRegistrationTest.java b/org.eclipse.epp.mpc.tests/src/org/eclipse/epp/mpc/tests/service/MarketplaceStorageServiceRegistrationTest.java
index c70d2ef7..cac9b195 100644
--- a/org.eclipse.epp.mpc.tests/src/org/eclipse/epp/mpc/tests/service/MarketplaceStorageServiceRegistrationTest.java
+++ b/org.eclipse.epp.mpc.tests/src/org/eclipse/epp/mpc/tests/service/MarketplaceStorageServiceRegistrationTest.java
@@ -12,21 +12,30 @@ package org.eclipse.epp.mpc.tests.service;
import static org.junit.Assert.*;
+import java.lang.reflect.Method;
import java.net.URI;
import java.util.LinkedHashSet;
import java.util.Set;
+import org.eclipse.core.runtime.CoreException;
import org.eclipse.epp.internal.mpc.core.ServiceLocator;
import org.eclipse.epp.internal.mpc.core.service.DefaultMarketplaceService;
+import org.eclipse.epp.internal.mpc.core.service.StorageConfigurer;
import org.eclipse.epp.mpc.core.service.IMarketplaceStorageService;
import org.eclipse.epp.mpc.core.service.ServiceHelper;
+import org.eclipse.epp.mpc.tests.util.PropertyStub;
+import org.eclipse.userstorage.IStorage;
import org.eclipse.userstorage.IStorageService;
import org.eclipse.userstorage.IStorageService.Dynamic;
import org.eclipse.userstorage.internal.StorageService;
+import org.eclipse.userstorage.spi.ICredentialsProvider;
+import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExternalResource;
+import org.mockito.Matchers;
+import org.mockito.Mockito;
public class MarketplaceStorageServiceRegistrationTest {
@@ -92,6 +101,11 @@ public class MarketplaceStorageServiceRegistrationTest {
storageServices.cleanup("https://api-test.example.org");
}
+ @After
+ public void cleanUp() {
+ setCustomConfigurers((String[]) null);
+ }
+
@Test
public void testRegisterNewStorageServiceWithSlash() {
IMarketplaceStorageService registered = serviceLocator.registerStorageService(
@@ -174,4 +188,77 @@ public class MarketplaceStorageServiceRegistrationTest {
withoutSlash = IStorageService.Registry.INSTANCE.getService(URI.create("https://api.eclipse.org"));
assertNull(withoutSlash);
}
+
+ @Test
+ public void testDefaultConfigurer() throws Exception {
+ testConfigurer((String[]) null);
+ }
+
+ @Test
+ public void testUSS10Configurer() throws Exception {
+ //"org.eclipse.epp.internal.mpc.core.service.USS11ExtendedOAuthStorageConfigurer$Factory"
+ //"org.eclipse.epp.internal.mpc.core.service.USS11OAuthStorageConfigurer$Factory"
+ //"org.eclipse.epp.internal.mpc.core.service.USS10StorageConfigurer$Factory"
+ testConfigurer("org.eclipse.epp.internal.mpc.core.service.USS10StorageConfigurer$Factory");
+ }
+
+ @Test
+ public void testUSS11Configurer() throws Exception {
+ testConfigurer("org.eclipse.epp.internal.mpc.core.service.USS11OAuthStorageConfigurer$Factory");
+ }
+
+ @Test
+ public void testUSS11ExtendedConfigurer() throws Exception {
+ testConfigurer("org.eclipse.epp.internal.mpc.core.service.USS11ExtendedOAuthStorageConfigurer$Factory");
+ }
+
+ protected void testConfigurer(String... factories) throws CoreException {
+ setCustomConfigurers(factories);
+ StorageConfigurer configurer = StorageConfigurer.get();//FIXME this might return the fallback configurer
+ assertNotNull(configurer);
+ IStorage storageMock = Mockito.mock(IStorage.class);
+ PropertyStub.mock(storageMock, ICredentialsProvider.class, storageMock.getCredentialsProvider())
+ .setCredentialsProvider(Matchers.any());
+
+ configurer.configure(storageMock);
+ configurer.setInteractive(storageMock, false);
+ assertNotNull(storageMock.getCredentialsProvider());
+ assertFalse(isInteractive(storageMock.getCredentialsProvider()));
+ configurer.setInteractive(storageMock, true);
+ assertTrue(isInteractive(storageMock.getCredentialsProvider()));
+ }
+
+ private static void setCustomConfigurers(String... factories) {
+ if (factories == null || (factories.length == 1 && factories[0] == null)) {
+ System.getProperties().remove(StorageConfigurer.PROP_FACTORIES);
+ } else if (factories.length == 0) {
+ System.setProperty(StorageConfigurer.PROP_FACTORIES, "");
+ } else {
+ StringBuilder b = new StringBuilder();
+ for (int i = 0; i < factories.length; i++) {
+ if (i > 0) {
+ b.append(" ");
+ }
+ b.append(factories[i]);
+ }
+ System.setProperty(StorageConfigurer.PROP_FACTORIES, b.toString());
+ }
+ StorageConfigurer.unset();
+ }
+
+ private static boolean isInteractive(ICredentialsProvider credentialsProvider) {
+ if (credentialsProvider == null) {
+ return true;
+ }
+ if (credentialsProvider.getClass() == ICredentialsProvider.CANCEL.getClass()) {
+ return false;
+ }
+ try {
+ Method method = credentialsProvider.getClass().getMethod("isInteractive");
+ method.setAccessible(true);
+ return (boolean) method.invoke(credentialsProvider);
+ } catch (Throwable t) {
+ return false;
+ }
+ }
}
diff --git a/org.eclipse.epp.mpc.tests/src/org/eclipse/epp/mpc/tests/service/SolutionCompatibilityFilterTest.java b/org.eclipse.epp.mpc.tests/src/org/eclipse/epp/mpc/tests/service/SolutionCompatibilityFilterTest.java
index 4d023bac..39051761 100644
--- a/org.eclipse.epp.mpc.tests/src/org/eclipse/epp/mpc/tests/service/SolutionCompatibilityFilterTest.java
+++ b/org.eclipse.epp.mpc.tests/src/org/eclipse/epp/mpc/tests/service/SolutionCompatibilityFilterTest.java
@@ -59,6 +59,7 @@ import org.junit.Assert;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.ComparisonFailure;
+import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.experimental.categories.Category;
@@ -75,6 +76,7 @@ import org.osgi.framework.ServiceRegistration;
@RunWith(Parameterized.class)
@Category(RemoteTests.class)
+@Ignore("Disabled until test data on marketplace-staging.eclipse.org can be recreated")
public class SolutionCompatibilityFilterTest {
private static final String BASE_URL = "http://marketplace-staging.eclipse.org";
diff --git a/org.eclipse.epp.mpc.tests/src/org/eclipse/epp/mpc/tests/util/PropertyStub.java b/org.eclipse.epp.mpc.tests/src/org/eclipse/epp/mpc/tests/util/PropertyStub.java
new file mode 100644
index 00000000..57bff98c
--- /dev/null
+++ b/org.eclipse.epp.mpc.tests/src/org/eclipse/epp/mpc/tests/util/PropertyStub.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright (c) 2010 The Eclipse Foundation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * The Eclipse Foundation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.epp.mpc.tests.util;
+
+import org.mockito.Mockito;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+public class PropertyStub<T> {
+ private final Class<T> type;
+
+ private T value;
+
+ public PropertyStub(Class<T> type) {
+ super();
+ this.type = type;
+ }
+
+ private final Answer<Void> setterAnswer = new Answer<Void>() {
+
+ @Override
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ value = type.cast(invocation.getArguments()[0]);
+ return null;
+ }
+ };
+
+ private final Answer<T> getterAnswer = new Answer<T>() {
+
+ @Override
+ public T answer(InvocationOnMock invocation) throws Throwable {
+ return value;
+ }
+ };
+
+ public T getValue() {
+ return value;
+ }
+
+ public void setValue(T value) {
+ this.value = value;
+ }
+
+ public Answer<Void> getSetterAnswer() {
+ return setterAnswer;
+ }
+
+ public Answer<T> getGetterAnswer() {
+ return getterAnswer;
+ }
+
+ public static <X, T> X mock(X mock, Class<T> type, T getterCall) {
+ PropertyStub<T> propertyStub = new PropertyStub<>(type);
+ Mockito.when(getterCall).thenAnswer(propertyStub.getGetterAnswer());
+ return Mockito.doAnswer(propertyStub.getSetterAnswer()).when(mock);
+ }
+}
diff --git a/org.eclipse.epp.mpc.ui/META-INF/MANIFEST.MF b/org.eclipse.epp.mpc.ui/META-INF/MANIFEST.MF
index 538887a8..931997f3 100644
--- a/org.eclipse.epp.mpc.ui/META-INF/MANIFEST.MF
+++ b/org.eclipse.epp.mpc.ui/META-INF/MANIFEST.MF
@@ -22,8 +22,8 @@ Require-Bundle: org.eclipse.core.runtime;bundle-version="3.6.0",
org.eclipse.equinox.p2.director,
org.eclipse.osgi.services;bundle-version="3.3.100",
org.eclipse.equinox.ds;bundle-version="1.4.100",
- org.eclipse.userstorage;bundle-version="[1.1.0,2.0.0)",
- org.eclipse.userstorage.ui;bundle-version="[1.0.0,2.0.0)",
+ org.eclipse.userstorage;bundle-version="[1.0.1,1.2.0)",
+ org.eclipse.userstorage.ui;bundle-version="[1.0.0,1.2.0)",
org.eclipse.ui.ide;bundle-version="3.12.0"
Export-Package: org.eclipse.epp.internal.mpc.ui;x-internal:=true,
org.eclipse.epp.internal.mpc.ui.actions;x-internal:=true,

Back to the top