CF client config message, modifiable CF client config
Cleanup
This commit is contained in:
@@ -56,7 +56,8 @@ public class CFCallableContext {
|
||||
Throwable deepestCause = ExceptionUtil.getDeepestCause(e);
|
||||
|
||||
if (deepestCause instanceof UaaException || deepestCause instanceof AbortedException
|
||||
|| deepestCause instanceof SocketException || deepestCause instanceof UnknownHostException) {
|
||||
|| deepestCause instanceof SocketException || deepestCause instanceof UnknownHostException
|
||||
&& this.paramsProviderMessages != null) {
|
||||
return new ConnectionException(this.paramsProviderMessages.noNetworkConnection());
|
||||
}
|
||||
return null;
|
||||
|
||||
@@ -12,6 +12,7 @@ package org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@@ -25,24 +26,28 @@ import com.google.common.cache.LoadingCache;
|
||||
|
||||
public class CFTargetCache {
|
||||
|
||||
private final ClientParamsProvider paramsProvider;
|
||||
private final CfClientConfig cfClientConfig;
|
||||
private final CloudFoundryClientFactory clientFactory;
|
||||
private final ClientTimeouts timeouts;
|
||||
private final LoadingCache<ClientParamsCacheKey, CFTarget> cache;
|
||||
private final CFCallableContext cacheCallableContext;
|
||||
private LoadingCache<ClientParamsCacheKey, CFTarget> cache;
|
||||
private CFCallableContext cacheCallableContext;
|
||||
|
||||
public static final Duration SERVICES_EXPIRATION = Duration.ofSeconds(10);
|
||||
public static final Duration TARGET_EXPIRATION = Duration.ofHours(1);
|
||||
public static final Duration ERROR_EXPIRATION = Duration.ofSeconds(10);
|
||||
|
||||
public CFTargetCache(ClientParamsProvider paramsProvider, CloudFoundryClientFactory clientFactory,
|
||||
public CFTargetCache(CfClientConfig cfClientConfig, CloudFoundryClientFactory clientFactory,
|
||||
ClientTimeouts timeouts) {
|
||||
Assert.isLegal(paramsProvider != null,
|
||||
Assert.isLegal(cfClientConfig != null,
|
||||
"A Cloud Foundry client parameters provider must be set when creating a target cache.");
|
||||
this.paramsProvider = paramsProvider;
|
||||
this.cfClientConfig = cfClientConfig;
|
||||
this.clientFactory = clientFactory;
|
||||
this.timeouts = timeouts;
|
||||
this.cacheCallableContext = new CFCallableContext(paramsProvider.getMessages());
|
||||
cfClientConfig.addClientParamsProviderChangedListener((newProvider, oldProvider) -> initCache());
|
||||
initCache();
|
||||
}
|
||||
|
||||
private void initCache() {
|
||||
CacheLoader<ClientParamsCacheKey, CFTarget> loader = new CacheLoader<ClientParamsCacheKey, CFTarget>() {
|
||||
|
||||
@Override
|
||||
@@ -53,6 +58,7 @@ public class CFTargetCache {
|
||||
};
|
||||
cache = CacheBuilder.newBuilder().maximumSize(1).expireAfterAccess(TARGET_EXPIRATION.toMillis(), TimeUnit.MILLISECONDS)
|
||||
.build(loader);
|
||||
this.cacheCallableContext = new CFCallableContext(cfClientConfig.getClientParamsProvider().getMessages());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -68,7 +74,7 @@ public class CFTargetCache {
|
||||
|
||||
protected synchronized List<CFTarget> doGetOrCreate() throws NoTargetsException, Exception {
|
||||
|
||||
List<CFClientParams> allParams = paramsProvider.getParams();
|
||||
Collection<CFClientParams> allParams = cfClientConfig.getClientParamsProvider().getParams();
|
||||
List<CFTarget> targets = new ArrayList<>();
|
||||
if (allParams != null) {
|
||||
for (CFClientParams params : allParams) {
|
||||
@@ -84,10 +90,10 @@ public class CFTargetCache {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return targets;
|
||||
}
|
||||
|
||||
|
||||
protected CFTarget create(CFClientParams params) throws Exception {
|
||||
/*
|
||||
* Must pass a NEW callable context. Cannot be
|
||||
@@ -95,7 +101,7 @@ public class CFTargetCache {
|
||||
* contexts may contain error state
|
||||
*/
|
||||
return new CFTarget(getTargetName(params), params, clientFactory.getClient(params, timeouts),
|
||||
new CFCallableContext(paramsProvider.getMessages()));
|
||||
new CFCallableContext(cfClientConfig.getClientParamsProvider().getMessages()));
|
||||
}
|
||||
|
||||
protected static String getTargetName(CFClientParams params) {
|
||||
|
||||
@@ -29,7 +29,6 @@ import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
*/
|
||||
public class CfCliParamsProvider implements ClientParamsProvider {
|
||||
|
||||
|
||||
public static final String TARGET = "Target";
|
||||
public static final String REFRESH_TOKEN = "RefreshToken";
|
||||
public static final String ORGANIZATION_FIELDS = "OrganizationFields";
|
||||
@@ -37,14 +36,27 @@ public class CfCliParamsProvider implements ClientParamsProvider {
|
||||
public static final String NAME = "Name";
|
||||
public static final String SSL_DISABLED = "SSLDisabled";
|
||||
private CfCliProviderMessages cfCliProviderMessages = new CfCliProviderMessages();
|
||||
|
||||
private static CfCliParamsProvider instance;
|
||||
|
||||
public static final CfCliParamsProvider getInstance() {
|
||||
if (instance == null) {
|
||||
instance= new CfCliParamsProvider();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
|
||||
private CfCliParamsProvider() {
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.
|
||||
* ClientParamsProvider#getParams()
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public List<CFClientParams> getParams() throws NoTargetsException, ExecutionException {
|
||||
List<CFClientParams> params = new ArrayList<>();
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2017 Pivotal, Inc.
|
||||
* 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:
|
||||
* Pivotal, Inc. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget;
|
||||
|
||||
/**
|
||||
* CF Client configuration
|
||||
*
|
||||
* @author Alex Boyko
|
||||
*
|
||||
*/
|
||||
public interface CfClientConfig {
|
||||
|
||||
/**
|
||||
* Listener to changes in parameters provider
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface ClientParamsProviderChangedListener {
|
||||
void clientParamsProviderChanged(ClientParamsProvider newProvider, ClientParamsProvider oldProvider);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns CF client parameters provider
|
||||
* @return parameters provider
|
||||
*/
|
||||
ClientParamsProvider getClientParamsProvider();
|
||||
|
||||
/**
|
||||
* Sets CF client parameters provider
|
||||
* @param provider
|
||||
*/
|
||||
void setClientParamsProvider(ClientParamsProvider provider);
|
||||
|
||||
/**
|
||||
* Adds listener to listen to CF parameter provider changes
|
||||
* @param listener
|
||||
*/
|
||||
void addClientParamsProviderChangedListener(ClientParamsProviderChangedListener listener);
|
||||
|
||||
/**
|
||||
* Removes CF parameter provider change listener
|
||||
* @param listener
|
||||
*/
|
||||
void removeClientParamsProviderChangedListener(ClientParamsProviderChangedListener listener);
|
||||
|
||||
/**
|
||||
* Default CF Client configuration
|
||||
*/
|
||||
final static CfClientConfig DEFAULT = new CfClientConfigImpl();
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2017 Pivotal, Inc.
|
||||
* 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:
|
||||
* Pivotal, Inc. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget;
|
||||
|
||||
import org.springframework.ide.vscode.commons.util.ListenerList;
|
||||
|
||||
/**
|
||||
* Default CF client configuration implementation
|
||||
*
|
||||
* @author Alex Boyko
|
||||
*
|
||||
*/
|
||||
class CfClientConfigImpl implements CfClientConfig {
|
||||
|
||||
private ClientParamsProvider clientParamsProvider;
|
||||
private ListenerList<ClientParamsProviderChangedListener> listeners = new ListenerList<>();
|
||||
|
||||
@Override
|
||||
public ClientParamsProvider getClientParamsProvider() {
|
||||
return clientParamsProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setClientParamsProvider(ClientParamsProvider provider) {
|
||||
ClientParamsProvider oldParamsProvider = this.clientParamsProvider;
|
||||
this.clientParamsProvider = provider;
|
||||
listeners.forEach(l -> l.clientParamsProviderChanged(clientParamsProvider, oldParamsProvider));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addClientParamsProviderChangedListener(ClientParamsProviderChangedListener listener) {
|
||||
listeners.add(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeClientParamsProviderChangedListener(ClientParamsProviderChangedListener listener) {
|
||||
listeners.remove(listener);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2017 Pivotal, Inc.
|
||||
* 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:
|
||||
* Pivotal, Inc. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.ide.vscode.commons.util.StringUtil;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.base.Suppliers;
|
||||
|
||||
/**
|
||||
* CF Client parameter provider based on the JSON data. the JSON data is
|
||||
* cosidered to be data from the from config changed message defined in the LSP
|
||||
* spec
|
||||
* {@link https://github.com/Microsoft/language-server-protocol/blob/master/protocol.md#workspace_didChangeConfiguration}
|
||||
*
|
||||
* @author Alex Boyko
|
||||
*
|
||||
*/
|
||||
public class CfJsonParamsProvider implements ClientParamsProvider {
|
||||
|
||||
private static final String NO_TARGETS_FOUND_MESSAGE = "No targets found";
|
||||
private static final String NO_NETWORK_CONNECTION = "No connection to Cloud Foundry";
|
||||
private static final String NO_ORG_SPACE = "No org/space selected";
|
||||
|
||||
private static final String TARGET = "Target";
|
||||
private static final String REFRESH_TOKEN = "RefreshToken";
|
||||
private static final String SSL_DISABLED = "SSLDisabled";
|
||||
private static final String ORG_NAME = "OrgName";
|
||||
private static final String SPACE_NAME = "SpaceName";
|
||||
|
||||
private Supplier<Collection<CFClientParams>> paramsSupplier;
|
||||
|
||||
public CfJsonParamsProvider(List<?> json) {
|
||||
this.paramsSupplier = Suppliers.memoize(() -> json
|
||||
.stream()
|
||||
.filter(o -> o instanceof Map<?, ?>)
|
||||
.map(m -> parseCfClientParams((Map<?,?>)m))
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<CFClientParams> getParams() throws NoTargetsException, ExecutionException {
|
||||
return paramsSupplier.get();
|
||||
}
|
||||
|
||||
private static CFClientParams parseCfClientParams(Map<?, ?> userData) {
|
||||
String refreshToken = (String) userData.get(REFRESH_TOKEN);
|
||||
// Only support connecting to CF via refresh token for now
|
||||
if (StringUtil.hasText(refreshToken)) {
|
||||
CFCredentials credentials = CFCredentials.fromRefreshToken(refreshToken);
|
||||
boolean sslDisabled = (Boolean) userData.get(SSL_DISABLED);
|
||||
String target = (String) userData.get(TARGET);
|
||||
String orgName = (String) userData.get(ORG_NAME);
|
||||
String spaceName = (String) userData.get(SPACE_NAME);
|
||||
if (target != null && StringUtil.hasText(orgName) && StringUtil.hasText(spaceName)) {
|
||||
return new CFClientParams(target, null, credentials, orgName, spaceName, sslDisabled);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public CFParamsProviderMessages getMessages() {
|
||||
return new CFParamsProviderMessages() {
|
||||
|
||||
@Override
|
||||
public String noTargetsFound() {
|
||||
return NO_TARGETS_FOUND_MESSAGE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String unauthorised() {
|
||||
return NO_NETWORK_CONNECTION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String noNetworkConnection() {
|
||||
return NO_NETWORK_CONNECTION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String noOrgSpace() {
|
||||
return NO_ORG_SPACE;
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -10,18 +10,19 @@
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
public interface ClientParamsProvider {
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @return non-null list of VALID params to connect to Cloud Foundry
|
||||
* @throws NoTargetsException if failure to resolve any params for Cloud Foundry
|
||||
* @throws ExecutionException if failure occurs while resolving params
|
||||
*/
|
||||
List<CFClientParams> getParams() throws NoTargetsException, ExecutionException;
|
||||
Collection<CFClientParams> getParams() throws NoTargetsException, ExecutionException;
|
||||
|
||||
CFParamsProviderMessages getMessages();
|
||||
|
||||
}
|
||||
@@ -40,7 +40,7 @@ public class CFClientTest {
|
||||
|
||||
@Before
|
||||
public void setup() throws Exception {
|
||||
targetCache = new CFTargetCache(cloudfoundry.paramsProvider, cloudfoundry.factory, timeouts);
|
||||
targetCache = new CFTargetCache(cloudfoundry.cfClientConfig, cloudfoundry.factory, timeouts);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -20,6 +20,7 @@ import org.springframework.ide.vscode.commons.cloudfoundry.client.CloudFoundryCl
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.CFClientParams;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.CFCredentials;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.CfCliProviderMessages;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.CfClientConfig;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.ClientParamsProvider;
|
||||
import org.springframework.ide.vscode.commons.util.ExceptionUtil;
|
||||
|
||||
@@ -32,11 +33,13 @@ public class MockCfCli {
|
||||
|
||||
public final CloudFoundryClientFactory factory = mock(CloudFoundryClientFactory.class);
|
||||
public final ClientRequests client = mock(ClientRequests.class);
|
||||
public final CfClientConfig cfClientConfig = CfClientConfig.DEFAULT;
|
||||
public final ClientParamsProvider paramsProvider = mock(ClientParamsProvider.class);
|
||||
public final CfCliProviderMessages actualCfCliMessages = new CfCliProviderMessages();
|
||||
|
||||
public MockCfCli() {
|
||||
try {
|
||||
cfClientConfig.setClientParamsProvider(paramsProvider);
|
||||
//program some default behavior into mocks... most tests will use this.
|
||||
//other tests should 'reset' the mocks and reprogram them as needed.
|
||||
when(factory.getClient(any(), any())).thenReturn(client);
|
||||
|
||||
Reference in New Issue
Block a user