Skip to content
Browse files

Various fixes and changes: removed operations abstraction and merged

with Request abstraction. Refactored Request (now ClientRequest) out of
the server behaviour and added a LocalServerRequest subclass that is
aware of the local server instance. The base request only operates on
the CF Java client. Updated junits with further harness changes, fixing
several failing test cases. Additional bug fixes, including bugs in URL
domain and org and spaces lookups.
  • Loading branch information...
1 parent ccc8641 commit 259a6cb8d8345f687aa7f7a75ad1b6a84f2dbc5c nierajsingh committed
Showing with 1,376 additions and 1,243 deletions.
  1. +27 −13 .../eclipse/internal/server/core/{CloudApplicationUrlLookup.java → ApplicationUrlLookupService.java}
  2. +7 −15 ...ide.eclipse.server.core/src/org/cloudfoundry/ide/eclipse/internal/server/core/CloudErrorUtil.java
  3. +15 −0 ...lipse.server.core/src/org/cloudfoundry/ide/eclipse/internal/server/core/CloudFoundryCallback.java
  4. +6 −3 ...r.core/src/org/cloudfoundry/ide/eclipse/internal/server/core/application/ApplicationDelegate.java
  5. +2 −2 ....core/src/org/cloudfoundry/ide/eclipse/internal/server/core/application/IApplicationDelegate.java
  6. +14 −15 ...src/org/cloudfoundry/ide/eclipse/internal/server/core/application/JavaWebApplicationDelegate.java
  7. +50 −31 ...server.core/src/org/cloudfoundry/ide/eclipse/internal/server/core/application/ManifestParser.java
  8. +235 −0 ...lipse.server.core/src/org/cloudfoundry/ide/eclipse/internal/server/core/client/ClientRequest.java
  9. +0 −147 ...ver.core/src/org/cloudfoundry/ide/eclipse/internal/server/core/client/ClientRequestOperation.java
  10. +9 −5 ...e/src/org/cloudfoundry/ide/eclipse/internal/server/core/client/CloudFoundryApplicationModule.java
  11. +15 −2 ....core/src/org/cloudfoundry/ide/eclipse/internal/server/core/client/CloudFoundryClientFactory.java
  12. +274 −295 ...ore/src/org/cloudfoundry/ide/eclipse/internal/server/core/client/CloudFoundryServerBehaviour.java
  13. +35 −0 ...r.core/src/org/cloudfoundry/ide/eclipse/internal/server/core/client/CloudOperationsConstants.java
  14. +13 −2 ....core/src/org/cloudfoundry/ide/eclipse/internal/server/core/client/DeploymentInfoWorkingCopy.java
  15. +92 −0 ....server.core/src/org/cloudfoundry/ide/eclipse/internal/server/core/client/LocalServerRequest.java
  16. +0 −37 ...src/org/cloudfoundry/ide/eclipse/internal/server/core/client/RetryAppInStoppedStateOperation.java
  17. +0 −45 ...rc/org/cloudfoundry/ide/eclipse/internal/server/core/client/RetryNotFinishedStagingOperation.java
  18. +8 −3 ...pse.server.core/src/org/cloudfoundry/ide/eclipse/internal/server/core/client/TunnelBehaviour.java
  19. +0 −238 ...ver.core/src/org/cloudfoundry/ide/eclipse/internal/server/core/spaces/CloudSpaceServerLookup.java
  20. +3 −3 ...andalone/src/org/cloudfoundry/ide/eclipse/server/standalone/internal/ui/StandaloneAppUrlPart.java
  21. +3 −3 ...g/cloudfoundry/ide/eclipse/server/standalone/internal/ui/StandaloneApplicationWizardDelegate.java
  22. +4 −4 ...rc/org/cloudfoundry/ide/eclipse/server/standalone/internal/ui/StandaloneDeploymentWizardPage.java
  23. +2 −2 ...tests/src/org/cloudfoundry/ide/eclipse/internal/server/core/AbstractCloudFoundryServicesTest.java
  24. +40 −21 ....server.tests/src/org/cloudfoundry/ide/eclipse/internal/server/core/AbstractCloudFoundryTest.java
  25. +2 −2 ...lipse.server.tests/src/org/cloudfoundry/ide/eclipse/internal/server/core/CaldecottTunnelTest.java
  26. +170 −0 ...tests/src/org/cloudfoundry/ide/eclipse/internal/server/core/CloudFoundryClientConnectionTest.java
  27. +0 −115 ...se.server.tests/src/org/cloudfoundry/ide/eclipse/internal/server/core/CloudFoundryClientTest.java
  28. +4 −2 ...e.server.tests/src/org/cloudfoundry/ide/eclipse/internal/server/core/CloudFoundryConsoleTest.java
  29. +1 −1 ...pse.server.tests/src/org/cloudfoundry/ide/eclipse/internal/server/core/CloudFoundryDebugTest.java
  30. +18 −20 ...pse.server.tests/src/org/cloudfoundry/ide/eclipse/internal/server/core/CloudFoundryProxyTest.java
  31. +33 −45 ....tests/src/org/cloudfoundry/ide/eclipse/internal/server/core/CloudFoundryServerBehaviourTest.java
  32. +9 −8 .../src/org/cloudfoundry/ide/eclipse/internal/server/core/CloudFoundryWebApplicationContentTest.java
  33. +3 −3 ....ide.eclipse.server.tests/src/org/cloudfoundry/ide/eclipse/server/tests/AllCloudFoundryTests.java
  34. +99 −45 ...ipse.server.tests/src/org/cloudfoundry/ide/eclipse/server/tests/util/CloudFoundryTestFixture.java
  35. +6 −4 ...dry.ide.eclipse.server.tests/src/org/cloudfoundry/ide/eclipse/server/tests/util/TestCallback.java
  36. +16 −9 ...server.ui/src/org/cloudfoundry/ide/eclipse/internal/server/ui/ApplicationDeploymentUIHandler.java
  37. +4 −4 ...clipse.server.ui/src/org/cloudfoundry/ide/eclipse/internal/server/ui/CloudApplicationUrlPart.java
  38. +5 −6 ...oundry.ide.eclipse.server.ui/src/org/cloudfoundry/ide/eclipse/internal/server/ui/CloudUiUtil.java
  39. +2 −2 ...se.server.ui/src/org/cloudfoundry/ide/eclipse/internal/server/ui/RepublishApplicationHandler.java
  40. +3 −3 ...rver.ui/src/org/cloudfoundry/ide/eclipse/internal/server/ui/actions/CloudFoundryEditorAction.java
  41. +2 −2 ....ui/src/org/cloudfoundry/ide/eclipse/internal/server/ui/actions/DebugApplicationEditorAction.java
  42. +3 −2 ...e.server.ui/src/org/cloudfoundry/ide/eclipse/internal/server/ui/actions/DeleteServicesAction.java
  43. +3 −3 ...c/org/cloudfoundry/ide/eclipse/internal/server/ui/actions/ModifyServicesForApplicationAction.java
  44. +2 −2 ....ui/src/org/cloudfoundry/ide/eclipse/internal/server/ui/actions/RefreshInstancesEditorAction.java
  45. +3 −2 ...er.ui/src/org/cloudfoundry/ide/eclipse/internal/server/ui/actions/StartStopApplicationAction.java
  46. +2 −2 ...ui/src/org/cloudfoundry/ide/eclipse/internal/server/ui/actions/UpdateApplicationMemoryAction.java
  47. +2 −2 ...ver.ui/src/org/cloudfoundry/ide/eclipse/internal/server/ui/actions/UpdateInstanceCountAction.java
  48. +2 −2 ...ui/src/org/cloudfoundry/ide/eclipse/internal/server/ui/editor/AddServiceStartCaldecottAction.java
  49. +82 −40 ....server.ui/src/org/cloudfoundry/ide/eclipse/internal/server/ui/editor/ApplicationDetailsPart.java
  50. +2 −2 ...e.server.ui/src/org/cloudfoundry/ide/eclipse/internal/server/ui/tunnel/DataToolsTunnelAction.java
  51. +2 −2 ...rver.ui/src/org/cloudfoundry/ide/eclipse/internal/server/ui/tunnel/LaunchTunnelCommandAction.java
  52. +2 −2 ...se.server.ui/src/org/cloudfoundry/ide/eclipse/internal/server/ui/tunnel/TunnelActionProvider.java
  53. +6 −6 ....server.ui/src/org/cloudfoundry/ide/eclipse/internal/server/ui/wizards/AbstractURLWizardPage.java
  54. +5 −5 ...e.server.ui/src/org/cloudfoundry/ide/eclipse/internal/server/ui/wizards/ApplicationURLWizard.java
  55. +4 −4 ...ui/src/org/cloudfoundry/ide/eclipse/internal/server/ui/wizards/CloudFoundryApplicationWizard.java
  56. +18 −5 ...src/org/cloudfoundry/ide/eclipse/internal/server/ui/wizards/CloudFoundryDeploymentWizardPage.java
  57. +4 −2 ....eclipse.server.ui/src/org/cloudfoundry/ide/eclipse/internal/server/ui/wizards/EnvVarsWizard.java
  58. +3 −3 ...src/org/cloudfoundry/ide/eclipse/internal/server/ui/wizards/JavaWebApplicationWizardDelegate.java
View
40 ...erver/core/CloudApplicationUrlLookup.java → ...ver/core/ApplicationUrlLookupService.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2013 Pivotal Software, Inc.
+ * Copyright (c) 2013, 2014 Pivotal Software, 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
@@ -17,6 +17,7 @@
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
+import org.eclipse.osgi.util.NLS;
/**
* Verifies if a given application URL is valid, and checks if the host and
@@ -24,7 +25,7 @@
* domain portion (the last segments of the URL: e.g, "cfapps.io" in
* "myapp.cfapps.io") actually exists in the server.
*/
-public class CloudApplicationUrlLookup {
+public class ApplicationUrlLookupService {
private final CloudFoundryServer cloudServer;
@@ -32,7 +33,7 @@
private ApplicationUrlValidator validator;
- public CloudApplicationUrlLookup(CloudFoundryServer cloudServer) {
+ public ApplicationUrlLookupService(CloudFoundryServer cloudServer) {
this.cloudServer = cloudServer;
validator = new ApplicationUrlValidator();
}
@@ -56,15 +57,18 @@ public void refreshDomains(IProgressMonitor monitor) throws CoreException {
* @param subDomain
* @return Valid, available Cloud Application URL.
*/
- public CloudApplicationURL getDefaultApplicationURL(String subDomain) {
+ public CloudApplicationURL getDefaultApplicationURL(String subDomain) throws CoreException {
List<CloudDomain> domains = getDomains();
if (domains == null || domains.isEmpty()) {
- return null;
+
+ throw CloudErrorUtil.toCoreException(NLS.bind(
+ "No application domains resolved for {0}. Unable to generate a default application URL for {1}",
+ cloudServer.getServerId(), subDomain));
}
CloudApplicationURL appURL = null;
-
+ CoreException lastError = null;
for (CloudDomain domain : domains) {
String suggestedURL = subDomain + "." + domain.getName();
try {
@@ -72,9 +76,17 @@ public CloudApplicationURL getDefaultApplicationURL(String subDomain) {
break;
}
catch (CoreException ce) {
- // Ignore. Move on to the next one
+ lastError = ce;
}
}
+ if (appURL == null) {
+ if (lastError == null) {
+ lastError = CloudErrorUtil.toCoreException(NLS.bind(
+ "Unable to generate a default application URL for {0} in server {1}", subDomain,
+ cloudServer.getServerId()));
+ }
+ throw lastError;
+ }
return appURL;
}
@@ -117,7 +129,7 @@ public CloudApplicationURL getCloudApplicationURL(String url) throws CoreExcepti
if (domainsPerActiveSpace == null || domainsPerActiveSpace.isEmpty()) {
throw new CoreException(
CloudFoundryPlugin
- .getErrorStatus("No domains found for the current active space. Unable to map the URL to the application."));
+ .getErrorStatus("No domains found for the current active space. Unable to generate a default application URL."));
}
// String url = domain.getName();
@@ -156,12 +168,14 @@ public CloudApplicationURL getCloudApplicationURL(String url) throws CoreExcepti
/**
*
* @param cloudServer
- * @return Non-null Cloud application URL lookup. Will attempt to fetch a
- * cached version in the server if available, or create a new one if not.
+ * @return Cloud Application URL look service. Is never null.
*/
- public static CloudApplicationUrlLookup getCurrentLookup(CloudFoundryServer cloudServer) {
- return cloudServer.getBehaviour().getApplicationUrlLookup() != null ? cloudServer.getBehaviour()
- .getApplicationUrlLookup() : new CloudApplicationUrlLookup(cloudServer);
+ public static ApplicationUrlLookupService getCurrentLookup(CloudFoundryServer cloudServer) {
+ ApplicationUrlLookupService service = cloudServer.getBehaviour().getApplicationUrlLookup();
+ if (service == null) {
+ service = new ApplicationUrlLookupService(cloudServer);
+ }
+ return service;
}
}
View
22 ...pse.server.core/src/org/cloudfoundry/ide/eclipse/internal/server/core/CloudErrorUtil.java
@@ -35,21 +35,13 @@ private CloudErrorUtil() {
// Util class
}
- public static String getValidationErrorMessage(CoreException e) {
- if (isForbiddenException(e)) {
- return "Validation failed: Wrong email or password";
- }
- else if (isUnknownHostException(e)) {
- return "Validation failed: Unable to establish connection";
- }
- else if (isRestClientException(e)) {
- return "Validation failed: Unknown URL";
- }
-
- return "Validation failed";
- }
-
- public static String getV2ValidationErrorMessage(CoreException e) {
+ /**
+ *
+ * @param e error to check if it is a connection error.
+ * @return User-friendly error message IFF the error is a validation error due to wrong
+ * credentials or connection error. Return null otherwise.
+ */
+ public static String getConnectionError(CoreException e) {
if (isUnauthorisedException(e)) {
return "Validation failed: Wrong email or password";
}
View
15 ...rver.core/src/org/cloudfoundry/ide/eclipse/internal/server/core/CloudFoundryCallback.java
@@ -19,6 +19,7 @@
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.wst.server.core.IModule;
/**
* Callback interface to support clients to hook into CloudFoundry Server
@@ -65,6 +66,20 @@ public abstract void stopApplicationConsole(CloudFoundryApplicationModule cloudM
public abstract void displayCaldecottTunnelConnections(CloudFoundryServer server,
List<CaldecottTunnelDescriptor> descriptors);
+ /**
+ * Prepares an application to either be deployed, started or restarted.
+ * The main purpose to ensure that the application's deployment
+ * information is complete. If incomplete, it will prompt the user for
+ * missing information.
+ * @param monitor
+ * @return Cloud Foundry application mapped to the deployed WST
+ * {@link IModule}. Must not be null. If null, it indicates error,
+ * therefore throw {@link CoreException} instead.
+ * @throws CoreException if failure while preparing the application for deployment
+ * @throws OperationCanceledException if the user cancelled deploying or
+ * starting the application. The application's deployment information
+ * should not be modified in this case.
+ */
public abstract void prepareForDeployment(CloudFoundryServer server, CloudFoundryApplicationModule module,
IProgressMonitor monitor) throws CoreException, OperationCanceledException;
View
9 ...rc/org/cloudfoundry/ide/eclipse/internal/server/core/application/ApplicationDelegate.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2013 Pivotal Software, Inc.
+ * Copyright (c) 2013, 2014 Pivotal Software, 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
@@ -25,6 +25,8 @@
import org.cloudfoundry.ide.eclipse.internal.server.core.client.ApplicationDeploymentInfo;
import org.cloudfoundry.ide.eclipse.internal.server.core.client.CloudFoundryApplicationModule;
import org.cloudfoundry.ide.eclipse.internal.server.core.client.LocalCloudService;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
@@ -37,10 +39,11 @@
* IApplicationDelegate
* #getDefaultApplicationDeploymentInfo(org.cloudfoundry.
* ide.eclipse.internal.server.core.client.CloudFoundryApplicationModule,
- * org.cloudfoundry.ide.eclipse.internal.server.core.CloudFoundryServer)
+ * org.cloudfoundry.ide.eclipse.internal.server.core.CloudFoundryServer,
+ * org.eclipse.core.runtime.IProgressMonitor)
*/
public ApplicationDeploymentInfo getDefaultApplicationDeploymentInfo(CloudFoundryApplicationModule appModule,
- CloudFoundryServer cloudServer) {
+ CloudFoundryServer cloudServer, IProgressMonitor monitor) throws CoreException {
// Set default values.
String appName = appModule.getDeployedApplicationName();
View
4 ...c/org/cloudfoundry/ide/eclipse/internal/server/core/application/IApplicationDelegate.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2013 Pivotal Software, Inc.
+ * Copyright (c) 2013, 2014 Pivotal Software, 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
@@ -139,6 +139,6 @@ public ApplicationDeploymentInfo resolveApplicationDeploymentInfo(CloudFoundryAp
* @return Non-null application deployment information with default values.
*/
public ApplicationDeploymentInfo getDefaultApplicationDeploymentInfo(CloudFoundryApplicationModule appModule,
- CloudFoundryServer cloudServer);
+ CloudFoundryServer cloudServer, IProgressMonitor monitor) throws CoreException;
}
View
29 ...cloudfoundry/ide/eclipse/internal/server/core/application/JavaWebApplicationDelegate.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2012, 2013 Pivotal Software, Inc.
+ * Copyright (c) 2012, 2014 Pivotal Software, 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
@@ -17,7 +17,7 @@
import org.cloudfoundry.client.lib.archive.ApplicationArchive;
import org.cloudfoundry.ide.eclipse.internal.server.core.CloudApplicationURL;
-import org.cloudfoundry.ide.eclipse.internal.server.core.CloudApplicationUrlLookup;
+import org.cloudfoundry.ide.eclipse.internal.server.core.ApplicationUrlLookupService;
import org.cloudfoundry.ide.eclipse.internal.server.core.CloudFoundryConstants;
import org.cloudfoundry.ide.eclipse.internal.server.core.CloudFoundryPlugin;
import org.cloudfoundry.ide.eclipse.internal.server.core.CloudFoundryProjectUtil;
@@ -199,25 +199,24 @@ public IStatus validateDeploymentInfo(ApplicationDeploymentInfo deploymentInfo)
* (non-Javadoc)
*
* @see org.cloudfoundry.ide.eclipse.internal.server.core.application.
- * IApplicationDelegate
- * #getDefaultApplicationDeploymentInfo(org.cloudfoundry.
- * ide.eclipse.internal.server.core.CloudFoundryServer,
- * org.cloudfoundry.ide.
- * eclipse.internal.server.core.client.CloudFoundryApplicationModule)
+ * ApplicationDelegate
+ * #getDefaultApplicationDeploymentInfo(org.cloudfoundry.ide
+ * .eclipse.internal.server.core.client.CloudFoundryApplicationModule,
+ * org.cloudfoundry.ide.eclipse.internal.server.core.CloudFoundryServer,
+ * org.eclipse.core.runtime.IProgressMonitor)
*/
@Override
public ApplicationDeploymentInfo getDefaultApplicationDeploymentInfo(CloudFoundryApplicationModule appModule,
- CloudFoundryServer cloudServer) {
- ApplicationDeploymentInfo info = super.getDefaultApplicationDeploymentInfo(appModule, cloudServer);
+ CloudFoundryServer cloudServer, IProgressMonitor monitor) throws CoreException {
+ ApplicationDeploymentInfo info = super.getDefaultApplicationDeploymentInfo(appModule, cloudServer, monitor);
// Set a default URL for the application.
if ((info.getUris() == null || info.getUris().isEmpty()) && info.getDeploymentName() != null) {
- CloudApplicationUrlLookup urlLookup = CloudApplicationUrlLookup.getCurrentLookup(cloudServer);
- if (urlLookup != null) {
- CloudApplicationURL url = urlLookup.getDefaultApplicationURL(info.getDeploymentName());
- if (url != null) {
- info.setUris(Arrays.asList(url.getUrl()));
- }
+ ApplicationUrlLookupService urlLookup = ApplicationUrlLookupService.getCurrentLookup(cloudServer);
+ urlLookup.refreshDomains(monitor);
+ CloudApplicationURL url = urlLookup.getDefaultApplicationURL(info.getDeploymentName());
+ if (url != null) {
+ info.setUris(Arrays.asList(url.getUrl()));
}
}
View
81 ...ore/src/org/cloudfoundry/ide/eclipse/internal/server/core/application/ManifestParser.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2013 Pivotal Software, Inc.
+ * Copyright (c) 2013, 2014 Pivotal Software, 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
@@ -27,8 +27,8 @@
import org.cloudfoundry.client.lib.domain.CloudService;
import org.cloudfoundry.client.lib.domain.Staging;
+import org.cloudfoundry.ide.eclipse.internal.server.core.ApplicationUrlLookupService;
import org.cloudfoundry.ide.eclipse.internal.server.core.CloudApplicationURL;
-import org.cloudfoundry.ide.eclipse.internal.server.core.CloudApplicationUrlLookup;
import org.cloudfoundry.ide.eclipse.internal.server.core.CloudErrorUtil;
import org.cloudfoundry.ide.eclipse.internal.server.core.CloudFoundryPlugin;
import org.cloudfoundry.ide.eclipse.internal.server.core.CloudFoundryProjectUtil;
@@ -42,6 +42,7 @@
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.SubMonitor;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.DumperOptions.FlowStyle;
import org.yaml.snakeyaml.Yaml;
@@ -301,42 +302,59 @@ protected Integer getIntegerValue(Map<?, ?> containingMap, String propertyName)
* @throws CoreException if error occurred while loading an existing
* manifest file.
*/
- public DeploymentInfoWorkingCopy load() throws CoreException {
+ public DeploymentInfoWorkingCopy load(IProgressMonitor monitor) throws CoreException {
+ SubMonitor subMonitor = SubMonitor.convert(monitor);
+ subMonitor.beginTask("Parsing and loading application manifest file", 5);
+ DeploymentInfoWorkingCopy workingCopy;
+ try {
+ workingCopy = appModule.getDeploymentInfoWorkingCopy(subMonitor);
- DeploymentInfoWorkingCopy workingCopy = appModule.getDeploymentInfoWorkingCopy();
+ Map<?, ?> application = getApplication(null);
- Map<?, ?> application = getApplication(null);
+ subMonitor.worked(1);
+ if (application == null) {
+ return null;
+ }
- if (application == null) {
- return null;
- }
+ // NOTE: When reading from manifest, the manifest may be INCOMPLETE,
+ // therefore do not automatically
+ // set all properties in the deployment info. Check if the value of
+ // the
+ // property is actually set before set value
+ // in the info
+ String appName = getStringValue(application, NAME_PROP);
+
+ subMonitor.worked(1);
+ if (appName != null) {
+ workingCopy.setDeploymentName(appName);
+ }
- // NOTE: When reading from manifest, the manifest may be INCOMPLETE,
- // therefore do not automatically
- // set all properties in the deployment info. Check if the value of the
- // property is actually set before set value
- // in the info
- String appName = getStringValue(application, NAME_PROP);
+ readMemory(application, workingCopy);
+ subMonitor.worked(1);
- if (appName != null) {
- workingCopy.setDeploymentName(appName);
- }
- readMemory(application, workingCopy);
+ readApplicationURL(application, workingCopy, appName);
+ subMonitor.worked(1);
- readApplicationURL(application, workingCopy, appName);
- String buildpackurl = getStringValue(application, BUILDPACK_PROP);
- if (buildpackurl != null) {
- Staging staging = new Staging(null, buildpackurl);
- workingCopy.setStaging(staging);
- }
+ String buildpackurl = getStringValue(application, BUILDPACK_PROP);
+ if (buildpackurl != null) {
+ Staging staging = new Staging(null, buildpackurl);
+ workingCopy.setStaging(staging);
+ }
- readServices(workingCopy, application);
+ readServices(workingCopy, application);
+ subMonitor.worked(1);
- String archiveURL = getStringValue(application, PATH_PROP);
- if (archiveURL != null) {
- workingCopy.setArchive(archiveURL);
+
+ String archiveURL = getStringValue(application, PATH_PROP);
+ if (archiveURL != null) {
+ workingCopy.setArchive(archiveURL);
+ }
+
+ }
+ finally {
+ subMonitor.done();
}
return workingCopy;
@@ -383,7 +401,8 @@ protected void readServices(DeploymentInfoWorkingCopy workingCopy, Map<?, ?> app
}
}
- protected void readApplicationURL(Map<?, ?> application, DeploymentInfoWorkingCopy workingCopy, String appName) {
+ protected void readApplicationURL(Map<?, ?> application, DeploymentInfoWorkingCopy workingCopy, String appName)
+ throws CoreException {
String subdomain = getStringValue(application, SUB_DOMAIN_PROP);
String domain = getStringValue(application, DOMAIN_PROP);
@@ -396,7 +415,7 @@ protected void readApplicationURL(Map<?, ?> application, DeploymentInfoWorkingCo
}
else {
// Get a default domain since no domain has been specified
- CloudApplicationUrlLookup lookup = CloudApplicationUrlLookup.getCurrentLookup(cloudServer);
+ ApplicationUrlLookupService lookup = ApplicationUrlLookupService.getCurrentLookup(cloudServer);
CloudApplicationURL cloudURL = lookup.getDefaultApplicationURL(subdomain);
if (cloudURL != null) {
url = cloudURL.getUrl();
@@ -652,7 +671,7 @@ else if (previousName != null && previousName.equals(name)) {
// Persist only the first URL
String url = urls.get(0);
- CloudApplicationUrlLookup lookup = CloudApplicationUrlLookup.getCurrentLookup(cloudServer);
+ ApplicationUrlLookupService lookup = ApplicationUrlLookupService.getCurrentLookup(cloudServer);
CloudApplicationURL cloudUrl = lookup.getCloudApplicationURL(url);
String subdomain = cloudUrl.getSubdomain();
String domain = cloudUrl.getDomain();
View
235 ...rver.core/src/org/cloudfoundry/ide/eclipse/internal/server/core/client/ClientRequest.java
@@ -0,0 +1,235 @@
+/*******************************************************************************
+ * Copyright (c) 2012, 2014 Pivotal Software, 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 Software, Inc. - initial API and implementation
+ *******************************************************************************/
+package org.cloudfoundry.ide.eclipse.internal.server.core.client;
+
+import org.cloudfoundry.client.lib.CloudFoundryException;
+import org.cloudfoundry.client.lib.CloudFoundryOperations;
+import org.cloudfoundry.ide.eclipse.internal.server.core.CloudErrorUtil;
+import org.cloudfoundry.ide.eclipse.internal.server.core.CloudFoundryLoginHandler;
+import org.cloudfoundry.ide.eclipse.internal.server.core.CloudFoundryPlugin;
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.SubMonitor;
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * A Request performs a CF request via the cloudfoundry-client-lib API. It
+ * performs various error handling and connection checks that are generally
+ * common to most client requests, and therefore any client request should be
+ * wrapped around a Request.
+ * <p/>
+ * By default, the set of client calls in the Request is made twice, the first
+ * time it is executed immediate. If it fails due to connection error error, it
+ * will attempt a second time.
+ * <p/>
+ * Subtypes can modify this behaviour and add conditions that will result in
+ * further retries aside from connection errors.
+ *
+ *
+ * @param <T>
+ *
+ */
+public abstract class ClientRequest<T> {
+
+ private static final String NO_CLIENT_ERROR = "No Cloud Foundry client available to process the following request: {0} ";
+
+ private static final String UNKNOWN_REQUEST_ERROR = "Unknown Cloud Foundry plugin error while trying to perform client call in {0}";
+
+ /**
+ *
+ */
+ private final String label;
+
+ public ClientRequest(String label) {
+ Assert.isNotNull(label);
+ this.label = label;
+ }
+
+ /**
+ *
+ * @return result of client operation
+ * @throws CoreException if failure occurred while attempting to execute the
+ * client operation.
+ */
+ public T run(IProgressMonitor monitor) throws CoreException {
+
+ SubMonitor subProgress = SubMonitor.convert(monitor, label, 100);
+
+ CloudFoundryOperations client = getClient(subProgress);
+ if (client == null) {
+ throw CloudErrorUtil.toCoreException(NLS.bind(NO_CLIENT_ERROR, label));
+ }
+ T result;
+ try {
+ result = runAsClientRequestCheckConnection(client, subProgress);
+ }
+ finally {
+ subProgress.done();
+ }
+
+ return result;
+ }
+
+ /**
+ * Attempts to execute the client request by first checking proxy settings,
+ * and if unauthorised/forbidden exceptions thrown the first time, will
+ * attempt to log in. If that succeeds, it will attempt one more time.
+ * Otherwise it will fail and not attempt the request any further.
+ * @param client
+ * @param cloudServer
+ * @param subProgress
+ * @return
+ * @throws CoreException if attempt to execute failed, even after a second
+ * attempt after a client login.
+ */
+ protected T runAsClientRequestCheckConnection(CloudFoundryOperations client, SubMonitor subProgress)
+ throws CoreException {
+ // Check that a user is logged in and proxy is updated
+ String cloudURL = getCloudServerUrl();
+ CloudFoundryLoginHandler handler = new CloudFoundryLoginHandler(client, cloudURL);
+
+ // Always check if proxy settings have changed.
+ handler.updateProxyInClient(client);
+
+ try {
+ return runAndWait(client, subProgress);
+ }
+ catch (CoreException ce) {
+ CloudFoundryException cfe = ce.getCause() instanceof CloudFoundryException ? (CloudFoundryException) ce
+ .getCause() : null;
+ if (cfe != null && handler.shouldAttemptClientLogin(cfe)) {
+ handler.login(subProgress, 3, CloudOperationsConstants.LOGIN_INTERVAL);
+ return runAndWait(client, subProgress);
+ }
+ else {
+ // Translate to a error message that the user can understand
+ String validationMessage = CloudErrorUtil.getConnectionError(ce);
+ if (validationMessage != null) {
+ ce = new CoreException(CloudFoundryPlugin.getErrorStatus(validationMessage));
+ }
+ throw ce;
+ }
+ }
+ }
+
+ protected T runAndWait(CloudFoundryOperations client, SubMonitor subProgress) throws CoreException {
+ Throwable error = null;
+
+ boolean reattempt = true;
+ long timeLeft = getTotalTimeWait();
+ while (reattempt) {
+
+ long interval = -1;
+
+ try {
+ return doRun(client, subProgress);
+ }
+ catch (Throwable e) {
+ error = e;
+ }
+
+ interval = getWaitInterval(error, subProgress);
+ timeLeft -= interval;
+
+ if (interval > 0 && timeLeft >= 0) {
+
+ try {
+ Thread.sleep(interval);
+ }
+ catch (InterruptedException e) {
+ // Ignore, continue with the next iteration
+ }
+
+ reattempt = true;
+ }
+ else {
+ break;
+ }
+ }
+
+ // If reached here, some error has occurred, although if for some
+ // reason no error is set, it still means that the operation
+ // failed somehow
+ if (error == null) {
+ error = new CoreException(CloudFoundryPlugin.getErrorStatus(NLS.bind(UNKNOWN_REQUEST_ERROR,
+ ClientRequest.class.getName())));
+ }
+
+ if (error instanceof CoreException) {
+ throw (CoreException) error;
+ }
+ else {
+ throw CloudErrorUtil.toCoreException(error);
+ }
+ }
+
+ /**
+ * Given an error, determine how long the operation should wait before
+ * trying again before timeout is reached. Return -1 if the operation should
+ * stop trying and handle the last error that was caught, or throw
+ * CoreException if further errors occurred while determining the wait
+ * interval.
+ *
+ * <p/>
+ *
+ * By default it returns -1, meaning that the request is attempted only
+ * once, and any exceptions thrown will not result in reattempts. Subclasses
+ * can override to determine different reattempt conditions.
+ * @param exception to determine how long to wait until another attempt is
+ * made to run the operation. Note that if timeout is sooner than the
+ * interval, no further attempts will be made.
+ * @param monitor
+ * @return interval to wait , or -1 if operation should terminate right away
+ * without attempting again.
+ * @throw CoreException if failed to determine interval. A CoreException
+ * will result in no further attempts.
+ */
+ protected long getWaitInterval(Throwable exception, SubMonitor monitor) throws CoreException {
+ return -1;
+ }
+
+ /**
+ * Perform the actual client operation. The client is guaranteed to be
+ * non-null at this stage.
+ * @param client non-null client
+ * @param progress
+ * @return result of operation.
+ * @throws CoreException
+ */
+ protected abstract T doRun(CloudFoundryOperations client, SubMonitor progress) throws CoreException;
+
+ /**
+ * This must never be null. This is the client used to perform operations.
+ * @return Non-null Java client.
+ * @throws CoreException if failed to obtain a client
+ */
+ protected abstract CloudFoundryOperations getClient(IProgressMonitor monitor) throws CoreException;
+
+ /**
+ *
+ * @return the Cloud Foundry server URL. If null, some request checks may
+ * not be available (e.g. proxy connections)
+ */
+ protected String getCloudServerUrl() {
+ return null;
+ }
+
+ /**
+ * Total amount of time to wait. If less than the wait interval length, only
+ * one attempt will be made {@link #getWaitInterval(Throwable, SubMonitor)}
+ * @return
+ */
+ protected long getTotalTimeWait() {
+ return CloudOperationsConstants.DEFAULT_CF_CLIENT_REQUEST_TIMEOUT;
+ }
+
+}
View
147 .../src/org/cloudfoundry/ide/eclipse/internal/server/core/client/ClientRequestOperation.java
@@ -1,147 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2013 Pivotal Software, 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 Software, Inc. - initial API and implementation
- *******************************************************************************/
-package org.cloudfoundry.ide.eclipse.internal.server.core.client;
-
-import org.cloudfoundry.client.lib.CloudFoundryOperations;
-import org.cloudfoundry.ide.eclipse.internal.server.core.CloudErrorUtil;
-import org.cloudfoundry.ide.eclipse.internal.server.core.CloudFoundryPlugin;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.SubMonitor;
-
-/**
- * Performs a CF client call, and times out if the call fails due to errors, as
- * well as proxy checks prior to sending the request. Also handles any errors
- * thrown when calling the client.
- */
-public abstract class ClientRequestOperation<T> {
-
- /*
- * Intervals are how long a thread should sleep before moving to the next
- * iteration, or how long a refresh operation should wait before refreshing
- * the deployed apps.
- */
- public static final long DEFAULT_INTERVAL = 60 * 1000;
-
- public static final long SHORT_INTERVAL = 5 * 1000;
-
- public static final long MEDIUM_INTERVAL = 10 * 1000;
-
- public static final long ONE_SECOND_INTERVAL = 1000;
-
- public static final long LOGIN_INTERVAL = 2000;
-
- public static final long DEPLOYMENT_TIMEOUT = 10 * 60 * 1000;
-
- public static final long UPLOAD_TIMEOUT = 60 * 1000;
-
- public static final long DEFAULT_CF_CLIENT_REQUEST_TIMEOUT = 15 * 1000;
-
- private final CloudFoundryOperations client;
-
- private long timeLeft;
-
- public ClientRequestOperation(CloudFoundryOperations client, long requestTimeOut) {
- this.timeLeft = requestTimeOut;
- this.client = client;
- }
-
- /**
- * Calling this constructor means a client operation will only be performed
- * once when the run command is invoked. No waiting and re-attempts will be
- * made in case of failure.
- * @param client
- */
- public ClientRequestOperation(CloudFoundryOperations client) {
- this.timeLeft = 0;
- this.client = client;
- }
-
- abstract protected T doRun(CloudFoundryOperations client, SubMonitor progress) throws CoreException;
-
- public T run(SubMonitor progress) throws CoreException {
-
- Throwable error = null;
-
- boolean reattempt = true;
- while (reattempt) {
-
- long interval = -1;
-
- try {
- return doRun(client, progress);
- }
- catch (Throwable e) {
- error = e;
- }
-
- interval = getWaitInterval(error, progress);
- timeLeft -= interval;
-
- if (interval > 0 && timeLeft >= 0) {
-
- try {
- Thread.sleep(interval);
- }
- catch (InterruptedException e) {
- // Ignore, continue with the next iteration
- }
-
- reattempt = true;
- }
- else {
- break;
- }
- }
-
- // If reached here, some error has occurred, although if for some
- // reason no error is set, it still means that the operation
- // failed somehow
- if (error == null) {
- error = new CoreException(
- CloudFoundryPlugin
- .getErrorStatus("Unknown Cloud Foundry plugin error while trying to perform client call in "
- + CloudFoundryServerBehaviour.Request.class.getName()));
- }
-
- if (error instanceof CoreException) {
- throw (CoreException) error;
- }
- else {
- throw CloudErrorUtil.toCoreException(error);
- }
- }
-
- /**
- * Given an error, determine how long the operation should wait before
- * trying again before timeout is reached. Return -1 if the operation should
- * stop trying and handle the last error that was caught, or throw
- * CoreException if further errors occurred while determining the wait
- * interval.
- *
- * <p/>
- *
- * By default it returns -1, meaning that the request is attempted only
- * once, and any exceptions thrown will not result in reattempts. Subclasses
- * can override to determine different reattempt conditions.
- * @param exception to determine how long to wait until another attempt is
- * made to run the operation. Note that if timeout is sooner than the
- * interval, no further attempts will be made.
- * @param monitor
- * @return interval to wait , or -1 if operation should terminate right away
- * without attempting again.
- * @throw CoreException if failed to determine interval. A CoreException
- * will result in no further attempts.
- */
- protected long getWaitInterval(Throwable exception, SubMonitor monitor) throws CoreException {
- return -1;
- }
-
-}
View
14 ...g/cloudfoundry/ide/eclipse/internal/server/core/client/CloudFoundryApplicationModule.java
@@ -24,6 +24,7 @@
import org.cloudfoundry.ide.eclipse.internal.server.core.application.IApplicationDelegate;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.wst.server.core.IModule;
import org.eclipse.wst.server.core.IServer;
@@ -258,13 +259,16 @@ public synchronized ApplicationDeploymentInfo getDeploymentInfo() {
* copy will be generated from the app's deployment default values. A new
* copy is always returned. No changes take effect in the app modules'
* deployment info unless the working copy is saved.
- *
+ * <p/>
* @return a new working copy with either existing deployment information,
* or default deployment information, if an deployment information does not
* exist.
*/
- public synchronized DeploymentInfoWorkingCopy getDeploymentInfoWorkingCopy() {
- return new ModuleDeploymentInfoWorkingCopy(this);
+ public synchronized DeploymentInfoWorkingCopy getDeploymentInfoWorkingCopy(IProgressMonitor monitor)
+ throws CoreException {
+ DeploymentInfoWorkingCopy wc = new ModuleDeploymentInfoWorkingCopy(this);
+ wc.fill(monitor);
+ return wc;
}
/**
@@ -481,13 +485,13 @@ protected void setDeployedApplicationName(String applicationName) {
* @return non-null default deployment info. This default information is
* also set in the module as the module's current deployment information.
*/
- protected ApplicationDeploymentInfo getDefaultDeploymentInfo() {
+ protected ApplicationDeploymentInfo getDefaultDeploymentInfo(IProgressMonitor monitor) throws CoreException {
IApplicationDelegate delegate = ApplicationRegistry.getApplicationDelegate(getLocalModule());
ApplicationDeploymentInfo defaultInfo = null;
if (delegate != null) {
- defaultInfo = delegate.getDefaultApplicationDeploymentInfo(this, getCloudFoundryServer());
+ defaultInfo = delegate.getDefaultApplicationDeploymentInfo(this, getCloudFoundryServer(), monitor);
}
if (defaultInfo == null) {
View
17 ...c/org/cloudfoundry/ide/eclipse/internal/server/core/client/CloudFoundryClientFactory.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2012, 2013 Pivotal Software, Inc.
+ * Copyright (c) 2012, 2014 Pivotal Software, 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
@@ -32,7 +32,7 @@
* operations prior to invoking client API, including automatic client login and
* proxy setting handling.
*
- * @see org.cloudfoundry.ide.eclipse.internal.server.core.client.CloudFoundryServerBehaviour.Request
+ * @see org.cloudfoundry.ide.eclipse.internal.server.core.client.ClientRequest
*
*
*/
@@ -73,6 +73,19 @@ public CloudFoundryOperations getCloudFoundryOperations(CloudCredentials credent
}
}
+ public CloudFoundryOperations getCloudFoundryOperations(CloudCredentials credentials, URL url, String orgName,
+ String spaceName) {
+
+ // Proxies are always updated on each client call by the
+ // CloudFoundryServerBehaviour Request as well as the client login
+ // handler
+ // therefore it is not critical to set the proxy in the client on
+ // client
+ // creation
+ HttpProxyConfiguration proxyConfiguration = getProxy(url);
+ return new CloudFoundryClient(credentials, url, orgName, spaceName, proxyConfiguration);
+ }
+
/**
* For testing purposes only.
* @param userName
View
569 ...org/cloudfoundry/ide/eclipse/internal/server/core/client/CloudFoundryServerBehaviour.java
@@ -27,6 +27,8 @@
import org.cloudfoundry.client.lib.CloudCredentials;
import org.cloudfoundry.client.lib.CloudFoundryException;
import org.cloudfoundry.client.lib.CloudFoundryOperations;
+import org.cloudfoundry.client.lib.NotFinishedStagingException;
+import org.cloudfoundry.client.lib.StagingErrorException;
import org.cloudfoundry.client.lib.StartingInfo;
import org.cloudfoundry.client.lib.UploadStatusCallback;
import org.cloudfoundry.client.lib.archive.ApplicationArchive;
@@ -36,11 +38,12 @@
import org.cloudfoundry.client.lib.domain.CloudDomain;
import org.cloudfoundry.client.lib.domain.CloudService;
import org.cloudfoundry.client.lib.domain.CloudServiceOffering;
+import org.cloudfoundry.client.lib.domain.CloudSpace;
import org.cloudfoundry.client.lib.domain.InstancesInfo;
import org.cloudfoundry.client.lib.domain.Staging;
import org.cloudfoundry.ide.eclipse.internal.server.core.ApplicationAction;
+import org.cloudfoundry.ide.eclipse.internal.server.core.ApplicationUrlLookupService;
import org.cloudfoundry.ide.eclipse.internal.server.core.CachingApplicationArchive;
-import org.cloudfoundry.ide.eclipse.internal.server.core.CloudApplicationUrlLookup;
import org.cloudfoundry.ide.eclipse.internal.server.core.CloudErrorUtil;
import org.cloudfoundry.ide.eclipse.internal.server.core.CloudFoundryLoginHandler;
import org.cloudfoundry.ide.eclipse.internal.server.core.CloudFoundryPlugin;
@@ -56,8 +59,7 @@
import org.cloudfoundry.ide.eclipse.internal.server.core.debug.DebugCommandBuilder;
import org.cloudfoundry.ide.eclipse.internal.server.core.debug.DebugModeType;
import org.cloudfoundry.ide.eclipse.internal.server.core.spaces.CloudFoundrySpace;
-import org.cloudfoundry.ide.eclipse.internal.server.core.spaces.CloudSpaceServerLookup;
-import org.eclipse.core.runtime.Assert;
+import org.cloudfoundry.ide.eclipse.internal.server.core.spaces.CloudOrgsAndSpaces;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
@@ -127,7 +129,7 @@
private BehaviourRefreshJob refreshJob;
- private CloudApplicationUrlLookup applicationUrlLookup;
+ private ApplicationUrlLookupService applicationUrlLookup;
private final boolean REFRESH_MODULES[] = { false };
@@ -141,8 +143,11 @@
public void serverChanged(ServerEvent event) {
if (event.getKind() == ServerEvent.SERVER_CHANGE) {
- // reset client to consume updated credentials
- resetClient();
+ // reset client to consume updated credentials at a later stage.
+ // Do not connect
+ // right away
+ //
+ internalResetClient();
}
}
};
@@ -165,7 +170,7 @@ public boolean canControlModule(IModule[] module) {
public void connect(IProgressMonitor monitor) throws CoreException {
final CloudFoundryServer cloudServer = getCloudFoundryServer();
- new Request<Void>(NLS.bind("Loggging in to {0}", cloudServer.getUrl())) {
+ new BehaviourRequest<Void>(NLS.bind("Loggging in to {0}", cloudServer.getUrl())) {
@Override
protected Void doRun(CloudFoundryOperations client, SubMonitor progress) throws CoreException {
client.login();
@@ -177,6 +182,8 @@ protected Void doRun(CloudFoundryOperations client, SubMonitor progress) throws
server.setServerState(IServer.STATE_STARTED);
server.setServerPublishState(IServer.PUBLISH_STATE_NONE);
+ getApplicationUrlLookup().refreshDomains(monitor);
+
internalRefreshAndFireEvent(monitor);
}
@@ -202,7 +209,7 @@ protected synchronized void requestAllowDebug(CloudFoundryOperations client) thr
*/
public void createService(final CloudService[] services, IProgressMonitor monitor) throws CoreException {
- new Request<Void>(services.length == 1 ? NLS.bind("Creating service {0}", services[0].getName())
+ new BehaviourRequest<Void>(services.length == 1 ? NLS.bind("Creating service {0}", services[0].getName())
: "Creating services") {
@Override
protected Void doRun(CloudFoundryOperations client, SubMonitor progress) throws CoreException {
@@ -218,7 +225,7 @@ protected Void doRun(CloudFoundryOperations client, SubMonitor progress) throws
}
public synchronized List<CloudDomain> getDomainsFromOrgs(IProgressMonitor monitor) throws CoreException {
- return new Request<List<CloudDomain>>("Getting domains for orgs") {
+ return new BehaviourRequest<List<CloudDomain>>("Getting domains for orgs") {
@Override
protected List<CloudDomain> doRun(CloudFoundryOperations client, SubMonitor progress) throws CoreException {
return client.getDomainsForOrg();
@@ -228,7 +235,8 @@ protected Void doRun(CloudFoundryOperations client, SubMonitor progress) throws
}
public synchronized List<CloudDomain> getDomainsForSpace(IProgressMonitor monitor) throws CoreException {
- return new Request<List<CloudDomain>>("Getting domains for current space") {
+
+ return new BehaviourRequest<List<CloudDomain>>("Getting domains for current space") {
@Override
protected List<CloudDomain> doRun(CloudFoundryOperations client, SubMonitor progress) throws CoreException {
return client.getDomains();
@@ -258,7 +266,7 @@ protected void internalDeleteModules(final IModule[] modules, final boolean dele
throws CoreException {
final CloudFoundryServer cloudServer = getCloudFoundryServer();
- new Request<Void>() {
+ new BehaviourRequest<Void>("Deleting applications") {
@Override
protected Void doRun(CloudFoundryOperations client, SubMonitor progress) throws CoreException {
for (IModule module : modules) {
@@ -328,7 +336,7 @@ public ICloudFoundryOperation getDeleteServicesOperation(final List<String> serv
@Override
protected void performOperation(IProgressMonitor monitor) throws CoreException {
- new Request<Void>("Deleting services") {
+ new BehaviourRequest<Void>("Deleting services") {
@Override
protected Void doRun(CloudFoundryOperations client, SubMonitor progress) throws CoreException {
TunnelBehaviour handler = new TunnelBehaviour(getCloudFoundryServer());
@@ -347,19 +355,25 @@ protected Void doRun(CloudFoundryOperations client, SubMonitor progress) throws
/**
* The Cloud application URL lookup is used to resolve a list of URL domains
- * that an application can user when specifying a URL. It also validates
- * suggested application URLs, to check that the host and domain portions of
- * the URL are correction.
+ * that an application can user when specifying a URL.
* <p/>
* Note that this only returns a cached lookup. The lookup may have to be
* refreshed separately to get the most recent list of domains.
* @return Lookup to retrieve list of application URL domains, as well as
* verify validity of an application URL. May be null as its a cached
* version.
- * @throws CoreException if server related errors, like failing to connect
- * or resolve server
*/
- public CloudApplicationUrlLookup getApplicationUrlLookup() {
+ public ApplicationUrlLookupService getApplicationUrlLookup() {
+ if (applicationUrlLookup == null) {
+ try {
+ applicationUrlLookup = new ApplicationUrlLookupService(getCloudFoundryServer());
+ }
+ catch (CoreException e) {
+ CloudFoundryPlugin.logError(
+ NLS.bind("Failed to create the Cloud Foundry Application URL lookup service due to {0}",
+ e.getMessage()), e);
+ }
+ }
return applicationUrlLookup;
}
@@ -439,7 +453,7 @@ public CloudFoundryServer getCloudFoundryServer() throws CoreException {
}
public CloudApplication getApplication(final String applicationId, IProgressMonitor monitor) throws CoreException {
- return new Request<CloudApplication>() {
+ return new BehaviourRequest<CloudApplication>(NLS.bind("Getting Application {0}", applicationId)) {
@Override
protected CloudApplication doRun(CloudFoundryOperations client, SubMonitor progress) throws CoreException {
return client.getApplication(applicationId);
@@ -448,7 +462,7 @@ protected CloudApplication doRun(CloudFoundryOperations client, SubMonitor progr
}
public List<CloudApplication> getApplications(IProgressMonitor monitor) throws CoreException {
- return new Request<List<CloudApplication>>("Getting applications") {
+ return new BehaviourRequest<List<CloudApplication>>("Getting applications") {
@Override
protected List<CloudApplication> doRun(CloudFoundryOperations client, SubMonitor progress)
throws CoreException {
@@ -498,7 +512,7 @@ protected String doRun(CloudFoundryOperations client, SubMonitor progress) throw
}
public int[] getApplicationMemoryChoices(IProgressMonitor monitor) throws CoreException {
- return new Request<int[]>("Getting memory choices") {
+ return new BehaviourRequest<int[]>("Getting memory choices") {
@Override
protected int[] doRun(CloudFoundryOperations client, SubMonitor progress) throws CoreException {
@@ -510,7 +524,7 @@ protected String doRun(CloudFoundryOperations client, SubMonitor progress) throw
}
public DeploymentConfiguration getDeploymentConfiguration(IProgressMonitor monitor) throws CoreException {
- return new Request<DeploymentConfiguration>("Getting available service options") {
+ return new BehaviourRequest<DeploymentConfiguration>("Getting available service options") {
@Override
protected DeploymentConfiguration doRun(CloudFoundryOperations client, SubMonitor progress)
throws CoreException {
@@ -525,7 +539,7 @@ protected DeploymentConfiguration doRun(CloudFoundryOperations client, SubMonito
}
public List<CloudServiceOffering> getServiceOfferings(IProgressMonitor monitor) throws CoreException {
- return new Request<List<CloudServiceOffering>>("Getting available service options") {
+ return new BehaviourRequest<List<CloudServiceOffering>>("Getting available service options") {
@Override
protected List<CloudServiceOffering> doRun(CloudFoundryOperations client, SubMonitor progress)
throws CoreException {
@@ -538,7 +552,7 @@ protected DeploymentConfiguration doRun(CloudFoundryOperations client, SubMonito
* For testing only.
*/
public void deleteAllApplications(IProgressMonitor monitor) throws CoreException {
- new Request<Object>("Deleting all applications") {
+ new BehaviourRequest<Object>("Deleting all applications") {
@Override
protected Object doRun(CloudFoundryOperations client, SubMonitor progress) throws CoreException {
client.deleteAllApplications();
@@ -548,7 +562,7 @@ protected Object doRun(CloudFoundryOperations client, SubMonitor progress) throw
}
public List<CloudService> getServices(IProgressMonitor monitor) throws CoreException {
- return new Request<List<CloudService>>("Getting available services") {
+ return new BehaviourRequest<List<CloudService>>("Getting available services") {
@Override
protected List<CloudService> doRun(CloudFoundryOperations client, SubMonitor progress) throws CoreException {
return client.getServices();
@@ -577,7 +591,36 @@ public void refreshModules(IProgressMonitor monitor) {
restartRefreshJob();
}
- public void resetClient() {
+ /**
+ * Resets the client. Note that any cached information used by the previous
+ * client will be cleared. Credentials used to reset the client will be
+ * retrieved from the the local server store.
+ * @param monitor
+ * @throws CoreException failure to reset client, disconnect using current
+ * client, or login/connect to the server using new client
+ */
+ public CloudFoundryOperations resetClient(IProgressMonitor monitor) throws CoreException {
+ return resetClient(null, monitor);
+ }
+
+ /**
+ * Public for testing only. Clients should not call outside of test
+ * framework.Use {@link #resetClient(IProgressMonitor)} for actual client
+ * reset, as credentials should not be normally be passed through this API.
+ * Credentials typically are stored and retrieved indirectly by the
+ * behaviour through the server instance.
+ *
+ * @param monitor
+ * @param credentials
+ * @throws CoreException
+ */
+ public CloudFoundryOperations resetClient(CloudCredentials credentials, IProgressMonitor monitor)
+ throws CoreException {
+ internalResetClient();
+ return getClient(credentials, monitor);
+ }
+
+ protected void internalResetClient() {
client = null;
applicationUrlLookup = null;
}
@@ -622,7 +665,7 @@ protected CloudFoundryApplicationModule prepareForDeployment(IProgressMonitor mo
CloudFoundryApplicationModule appModule = super.prepareForDeployment(monitor);
- DeploymentInfoWorkingCopy workingCopy = appModule.getDeploymentInfoWorkingCopy();
+ DeploymentInfoWorkingCopy workingCopy = appModule.getDeploymentInfoWorkingCopy(monitor);
workingCopy.setDeploymentMode(ApplicationAction.DEBUG);
workingCopy.save();
return appModule;
@@ -827,7 +870,7 @@ protected CloudFoundryApplicationModule prepareForDeployment(IProgressMonitor mo
CloudFoundryApplicationModule appModule = super.prepareForDeployment(monitor);
- DeploymentInfoWorkingCopy workingCopy = appModule.getDeploymentInfoWorkingCopy();
+ DeploymentInfoWorkingCopy workingCopy = appModule.getDeploymentInfoWorkingCopy(monitor);
workingCopy.setDeploymentMode(ApplicationAction.DEBUG);
workingCopy.save();
@@ -836,18 +879,6 @@ protected CloudFoundryApplicationModule prepareForDeployment(IProgressMonitor mo
}.run(monitor);
}
- public String getStagingLogs(final StartingInfo info, final int offset, IProgressMonitor monitor)
- throws CoreException {
- return new FileRequest<String>("Reading staging logs") {
-
- @Override
- protected String doRun(CloudFoundryOperations client, SubMonitor progress) throws CoreException {
- return client.getStagingLogs(info, offset);
- }
-
- }.run(monitor);
- }
-
/**
* Update restart republishes redeploys the application with changes. This
* is not the same as restarting an application which simply restarts the
@@ -890,7 +921,7 @@ public BehaviourOperation getRestartOperation(IModule[] modules) throws CoreExce
public void updateApplicationInstances(final CloudFoundryApplicationModule module, final int instanceCount,
IProgressMonitor monitor) throws CoreException {
final String appName = module.getApplication().getName();
- new AppInStoppedStateAwareRequest<Void>() {
+ new AppInStoppedStateAwareRequest<Void>("Updating application instances") {
@Override
protected Void doRun(CloudFoundryOperations client, SubMonitor progress) throws CoreException {
client.updateApplicationInstances(appName, instanceCount);
@@ -902,7 +933,7 @@ protected Void doRun(CloudFoundryOperations client, SubMonitor progress) throws
}
public void updatePassword(final String newPassword, IProgressMonitor monitor) throws CoreException {
- new Request<Void>() {
+ new BehaviourRequest<Void>("Updating password") {
@Override
protected Void doRun(CloudFoundryOperations client, SubMonitor progress) throws CoreException {
@@ -928,7 +959,8 @@ protected Void doRun(CloudFoundryOperations client, SubMonitor progress) throws
public void updateApplicationMemory(final CloudFoundryApplicationModule module, final int memory,
IProgressMonitor monitor) throws CoreException {
final String appName = module.getApplication().getName();
- new AppInStoppedStateAwareRequest<Void>() {
+ new AppInStoppedStateAwareRequest<Void>(NLS.bind("Updating application memory for {0}",
+ module.getDeployedApplicationName())) {
@Override
protected Void doRun(CloudFoundryOperations client, SubMonitor progress) throws CoreException {
client.updateApplicationMemory(appName, memory);
@@ -939,7 +971,7 @@ protected Void doRun(CloudFoundryOperations client, SubMonitor progress) throws
public void updateApplicationUrls(final String appName, final List<String> uris, IProgressMonitor monitor)
throws CoreException {
- new AppInStoppedStateAwareRequest<Void>() {
+ new AppInStoppedStateAwareRequest<Void>(NLS.bind("Updating application URLs for {0}", appName)) {
@Override
protected Void doRun(CloudFoundryOperations client, SubMonitor progress) throws CoreException {
client.updateApplicationUris(appName, uris);
@@ -983,7 +1015,7 @@ public void updateServices(String appName, List<String> services, IProgressMonit
public void refreshApplicationBoundServices(CloudFoundryApplicationModule appModule, IProgressMonitor monitor)
throws CoreException {
- DeploymentInfoWorkingCopy copy = appModule.getDeploymentInfoWorkingCopy();
+ DeploymentInfoWorkingCopy copy = appModule.getDeploymentInfoWorkingCopy(monitor);
List<CloudService> boundServices = copy.getServices();
if (boundServices != null && !boundServices.isEmpty()) {
@@ -1024,7 +1056,7 @@ public void updateServicesAndCloseCaldecottTunnels(String appName, List<String>
protected void updateServices(final String appName, final List<String> services,
final boolean closeRelatedCaldecottTunnels, IProgressMonitor monitor) throws CoreException {
- new StagingAwareRequest<Void>() {
+ new StagingAwareRequest<Void>("Update services") {
@Override
protected Void doRun(CloudFoundryOperations client, SubMonitor progress) throws CoreException {
// Prior to updating the services, obtain the current list of
@@ -1053,7 +1085,7 @@ protected Void doRun(CloudFoundryOperations client, SubMonitor progress) throws
}
public void register(final String email, final String password, IProgressMonitor monitor) throws CoreException {
- new Request<Void>() {
+ new BehaviourRequest<Void>("Registering account") {
@Override
protected Void doRun(CloudFoundryOperations client, SubMonitor progress) throws CoreException {
client.register(email, password);
@@ -1063,23 +1095,38 @@ protected Void doRun(CloudFoundryOperations client, SubMonitor progress) throws
}
/**
- * Public for testing only. Use alternate public getClient() API for actual
- * client operations. If credentials are not used, as in the case when only
- * a URL is present for a server, null must be passed for the credentials.
+ * Gets the active client used by the behaviour for server operations.
+ * However, clients are created lazily, and invoking it multipe times does
+ * not recreate the client, as only one client is created per lifecycle of
+ * the server behaviour (but not necessarily per connection session, as the
+ * server behaviour may be created and disposed multiple times by the WST
+ * framework). To use the server-stored credentials, pass null credentials.
+ * <p/>
+ * This API is not suitable to changing credentials. User appropriate API
+ * for the latter like {@link #updatePassword(String, IProgressMonitor)}
*/
- public synchronized CloudFoundryOperations getClient(CloudCredentials credentials, IProgressMonitor monitor)
+ protected synchronized CloudFoundryOperations getClient(CloudCredentials credentials, IProgressMonitor monitor)
throws CoreException {
if (client == null) {
- CloudFoundrySpace cloudSpace = new CloudSpaceServerLookup(getCloudFoundryServer(), credentials)
- .getCloudSpace(monitor);
+ CloudFoundryServer cloudServer = getCloudFoundryServer();
+
+ String url = cloudServer.getUrl();
+ if (!cloudServer.hasCloudSpace()) {
+ throw CloudErrorUtil
+ .toCoreException(NLS
+ .bind("Unable to resolve locally stored organisation and space for the server instance {0}. The server instance may have to be cloned or created again.",
+ cloudServer.getServerId()));
+ }
+
+ CloudFoundrySpace cloudFoundrySpace = cloudServer.getCloudFoundrySpace();
if (credentials != null) {
- client = createClient(getCloudFoundryServer().getUrl(), credentials, cloudSpace);
+ client = createClient(url, credentials, cloudFoundrySpace);
}
else {
String userName = getCloudFoundryServer().getUsername();
String password = getCloudFoundryServer().getPassword();
- client = createClient(getCloudFoundryServer().getUrl(), userName, password, cloudSpace);
+ client = createClient(url, userName, password, cloudFoundrySpace);
}
}
return client;
@@ -1092,7 +1139,7 @@ public synchronized CloudFoundryOperations getClient(CloudCredentials credential
* @return
* @throws CoreException
*/
- public synchronized CloudFoundryOperations getClient(IProgressMonitor monitor) throws CoreException {
+ protected synchronized CloudFoundryOperations getClient(IProgressMonitor monitor) throws CoreException {
return getClient((CloudCredentials) null, monitor);
}
@@ -1110,7 +1157,7 @@ public synchronized CloudFoundryOperations getClient(IProgressMonitor monitor) t
*/
public void updateEnvironmentVariables(final CloudFoundryApplicationModule appModule, IProgressMonitor monitor)
throws CoreException {
- new Request<Void>() {
+ new BehaviourRequest<Void>("Updating environment variables") {
@Override
protected Void doRun(CloudFoundryOperations client, SubMonitor progress) throws CoreException {
@@ -1166,7 +1213,7 @@ private void restartRefreshJob() {
if (refreshJob == null) {
refreshJob = new BehaviourRefreshJob();
}
- refreshJob.reschedule(ClientRequestOperation.DEFAULT_INTERVAL);
+ refreshJob.reschedule(CloudOperationsConstants.DEFAULT_INTERVAL);
}
/**
@@ -1193,35 +1240,35 @@ public void stopRefreshModules() {
private boolean waitForStart(CloudFoundryOperations client, String deploymentId, IProgressMonitor monitor)
throws InterruptedException {
- long initialInterval = ClientRequestOperation.SHORT_INTERVAL;
+ long initialInterval = CloudOperationsConstants.SHORT_INTERVAL;
Thread.sleep(initialInterval);
- long timeLeft = ClientRequestOperation.DEPLOYMENT_TIMEOUT - initialInterval;
+ long timeLeft = CloudOperationsConstants.DEPLOYMENT_TIMEOUT - initialInterval;
while (timeLeft > 0) {
CloudApplication deploymentDetails = client.getApplication(deploymentId);
if (isApplicationReady(deploymentDetails)) {
return true;
}
- Thread.sleep(ClientRequestOperation.ONE_SECOND_INTERVAL);
- timeLeft -= ClientRequestOperation.ONE_SECOND_INTERVAL;
+ Thread.sleep(CloudOperationsConstants.ONE_SECOND_INTERVAL);
+ timeLeft -= CloudOperationsConstants.ONE_SECOND_INTERVAL;
}
return false;
}
private CloudApplication getDeployedCloudApplication(CloudFoundryOperations client, String applicationId,
IProgressMonitor monitor) {
- long timeLeft = ClientRequestOperation.UPLOAD_TIMEOUT;
+ long timeLeft = CloudOperationsConstants.UPLOAD_TIMEOUT;
while (timeLeft > 0) {
CloudApplication application = client.getApplication(applicationId);
if (applicationId.equals(application.getName())) {
return application;
}
try {
- Thread.sleep(ClientRequestOperation.SHORT_INTERVAL);
+ Thread.sleep(CloudOperationsConstants.SHORT_INTERVAL);
}
catch (InterruptedException e) {
// Ignore. Try again until time runs out
}
- timeLeft -= ClientRequestOperation.SHORT_INTERVAL;
+ timeLeft -= CloudOperationsConstants.SHORT_INTERVAL;
}
return null;
}
@@ -1346,7 +1393,8 @@ protected void publishModule(int kind, int deltaKind, IModule[] module, IProgres
final CloudFoundryServer cloudServer = getCloudFoundryServer();
final CloudFoundryApplicationModule cloudModule = cloudServer.getCloudModule(module[0]);
if (cloudModule.getApplication() != null) {
- new Request<Void>() {
+ new BehaviourRequest<Void>(NLS.bind("Deleting application {0}",
+ cloudModule.getDeployedApplicationName())) {
@Override
protected Void doRun(CloudFoundryOperations client, SubMonitor progress) throws CoreException {
client.deleteApplication(cloudModule.getDeployedApplicationName());
@@ -1440,7 +1488,8 @@ public boolean isApplicationRunning(CloudFoundryApplicationModule appModule, IPr
// Refresh the stats FIRST before checking for the app state, as
// stat refresh will upate the cloud application mapping (and
// therefore also update the app state)
- return internalRefreshAppStats(appModule, monitor) && appModule.getState() == IServer.STATE_STARTED;
+ return internalRefreshAppStats(appModule, monitor) && appModule.getApplication() != null
+ && isApplicationReady(appModule.getApplication());
}
catch (CoreException e) {
CloudFoundryPlugin.logError(e);
@@ -1449,6 +1498,74 @@ public boolean isApplicationRunning(CloudFoundryApplicationModule appModule, IPr
}
/**
+ * Retrieves the orgs and spaces for the current server instance.
+ * @param monitor
+ * @return
+ * @throws CoreException if it failed to retrieve the orgs and spaces.
+ */
+ public CloudOrgsAndSpaces getCloudSpaces(IProgressMonitor monitor) throws CoreException {
+ return new BehaviourRequest<CloudOrgsAndSpaces>("Getting orgs and spaces") {
+
+ @Override
+ protected CloudOrgsAndSpaces doRun(CloudFoundryOperations client, SubMonitor progress) throws CoreException {
+ return internalGetCloudSpaces(client);
+ }
+
+ }.run(monitor);
+ }
+
+ /**
+ * Attempts to retrieve cloud spaces using the given set of credentials and
+ * server URL. This bypasses the session client in a Cloud Foundry server
+ * instance, if one exists for the given server URL, and therefore attempts
+ * to retrieve the cloud spaces with a disposable, temporary client that
+ * logs in with the given credentials.Therefore, if fetching orgs and spaces
+ * from an existing server instance, please use
+ * {@link CloudFoundryServerBehaviour#getCloudSpaces(IProgressMonitor)}.
+ * @param client
+ * @param monitor which performs client login checks, and basic error
+ * handling. False if spaces should be obtained directly from the client
+ * API.
+ * @return resolved orgs and spaces for the given credential and server URL.
+ */
+ public static CloudOrgsAndSpaces getCloudSpacesExternalClient(CloudCredentials credentials, String url,
+ IProgressMonitor monitor) throws CoreException {
+
+ final CloudFoundryOperations operations = CloudFoundryServerBehaviour.createClient(url, credentials.getEmail(),
+ credentials.getPassword());
+
+ return new ClientRequest<CloudOrgsAndSpaces>("Getting orgs and spaces") {
+ @Override
+ protected CloudOrgsAndSpaces doRun(CloudFoundryOperations client, SubMonitor progress) throws CoreException {
+ return internalGetCloudSpaces(client);
+ }
+
+ @Override
+ protected CloudFoundryOperations getClient(IProgressMonitor monitor) throws CoreException {
+ return operations;
+ }
+ }.run(monitor);
+
+ }
+
+ /**
+ * This should be called within a {@link ClientRequest}, as it makes a direct
+ * client call.
+ * @param client
+ * @return
+ */
+ private static CloudOrgsAndSpaces internalGetCloudSpaces(CloudFoundryOperations client) {
+ List<CloudSpace> foundSpaces = client.getSpaces();
+ if (foundSpaces != null && !foundSpaces.isEmpty()) {
+ List<CloudSpace> actualSpaces = new ArrayList<CloudSpace>(foundSpaces);
+ CloudOrgsAndSpaces orgsAndSpaces = new CloudOrgsAndSpaces(actualSpaces);
+ return orgsAndSpaces;
+ }
+
+ return null;
+ }
+
+ /**
* Updates the application instances stats for the given cloud application
* module. It does not update the Cloud app module -> cloud application
* mapping.
@@ -1557,49 +1674,78 @@ public static void register(String location, String userName, String password, I
/**
* Creates a standalone client with no association with a server behaviour.
* This is used only for connecting to a Cloud Foundry server for credential
- * verification verification. To create a client bound to a server
- * behaviour, it must be done through the server behaviour
+ * verification. The session client for the server behaviour is created when the
+ * latter is created
* @param location
* @param userName
* @param password
* @return
* @throws CoreException
*/
- public static CloudFoundryOperations createClient(String location, String userName, String password)
- throws CoreException {
+ static CloudFoundryOperations createClient(String location, String userName, String password) throws CoreException {
return createClient(location, userName, password, null);
}
- private static CloudFoundryOperations createClient(String location, String userName, String password,
+ /**
+ * Creates a new client to the given server URL using the specified
+ * credentials. This does NOT connect the client to the server, nor does it
+ * set the client as a session client for the server delegate.
+ *
+ * @param serverURL must not be null
+ * @param userName must not be null
+ * @param password must not be null
+ * @param cloudSpace optional, as a valid client can still be created
+ * without org/space (for example, a client can be used to do an org/space
+ * lookup.
+ * @return Non-null client.
+ * @throws CoreException if failed to create the client.
+ */
+ private static CloudFoundryOperations createClient(String serverURL, String userName, String password,
CloudFoundrySpace cloudSpace) throws CoreException {
if (password == null) {
// lost the password, start with an empty one to avoid assertion
// error
password = "";
}
- return createClient(location, new CloudCredentials(userName, password), cloudSpace);
+ return createClient(serverURL, new CloudCredentials(userName, password), cloudSpace);
}
- private static CloudFoundryOperations createClient(String location, CloudCredentials credentials,
+ /**
+ * Creates a new client to the specified server URL using the given
+ * credentials. This does NOT connect the client to the server, nor does it
+ * set the client as the session client for the server behaviour. The
+ * session client is set indirectly via {@link #connect(IProgressMonitor)}
+ * @param serverURL server to connect to. Must NOT be null.
+ * @param credentials must not be null.
+ * @param cloudSpace optional. Can be null, as a client can be created
+ * without specifying an org/space (e.g. a client can be created for the
+ * purpose of looking up all the orgs/spaces in a server)
+ * @return non-null client.
+ * @throws CoreException if failed to create client.
+ */
+ private static CloudFoundryOperations createClient(String serverURL, CloudCredentials credentials,
CloudFoundrySpace cloudSpace) throws CoreException {
URL url;
try {
- url = new URL(location);
+ url = new URL(serverURL);
int port = url.getPort();
if (port == -1) {
port = url.getDefaultPort();
}
- // At this stage, determine if it is a cloud server and account that
- // supports orgs and spaces
+ // If no cloud space is specified, use appropriate client factory
+ // API to create a non-space client
+ // NOTE that using a space API with null org and space will result
+ // in errors as that API will
+ // expect valid org and space values.
return cloudSpace != null ? CloudFoundryPlugin.getCloudFoundryClientFactory().getCloudFoundryOperations(
- credentials, url, cloudSpace.getSpace()) : CloudFoundryPlugin.getCloudFoundryClientFactory()
- .getCloudFoundryOperations(credentials, url);
+ credentials, url, cloudSpace.getOrgName(), cloudSpace.getSpaceName()) : CloudFoundryPlugin
+ .getCloudFoundryClientFactory().getCloudFoundryOperations(credentials, url);
}
catch (MalformedURLException e) {
throw new CoreException(new Status(IStatus.ERROR, CloudFoundryPlugin.PLUGIN_ID, NLS.bind(
- "The server url ''{0}'' is invalid: {1}", location, e.getMessage()), e));
+ "The server url ''{0}'' is invalid: {1}", serverURL, e.getMessage()), e));
}
}
@@ -1634,174 +1780,6 @@ private static CloudFoundryOperations createClient(String location, CloudCredent
// }
/**
- * A Request performs a CF request via the cloudfoundry-client-lib API. It
- * performs various error handling that are generally common to most client
- * requests, and therefore any client request should be wrapped around a
- * Request.
- * <p/>
- * By default, the set of client calls in the Request is made twice, the
- * first time it is executed immediate. If it fails due to
- * unauthorisation/forbidden error, it will attempt a second time. If it
- * still fails, it will no longer attempt and propagate a client error to
- * the caller in the form of a CoreException
- * <p/>
- * Subtypes can modify this behaviour and add conditions that will result in
- * further retries aside from unauthorised/forbidden errors given an
- * exception thrown while invoking a client API.
- * <p/>
- * In addition, all requests are performed in a sub monitor, therefore
- * submonitor operations like creating a new child to track progress worked
- * should be used.
- *
- * @param <T>
- *
- */
- abstract class Request<T> {
-
- private final String label;
-
- public Request() {
- this("");
- }
-
- public Request(String label) {
- Assert.isNotNull(label);
- this.label = label;
- }
-
- /**
- *
- * @param monitor
- * @return result of client operation
- * @throws CoreException if failure occurred while attempting to execute
- * the client operation.
- */
- public T run(IProgressMonitor monitor) throws CoreException {
- CloudFoundryServer cloudServer = getCloudFoundryServer();
-
- if (cloudServer.getUsername() == null || cloudServer.getUsername().length() == 0
- || cloudServer.getPassword() == null || cloudServer.getPassword().length() == 0) {
- CloudFoundryPlugin.getCallback().getCredentials(cloudServer);
- }
-
- Server server = (Server) getServer();
- if (server.getServerState() == IServer.STATE_STOPPED || server.getServerState() == IServer.STATE_STOPPING) {
- server.setServerState(IServer.STATE_STARTING);
- }
-
- SubMonitor subProgress = SubMonitor.convert(monitor, label, 100);
-
- T result;
- boolean succeeded = false;
- try {
-
- CloudFoundryOperations client = getClient(subProgress);
-
- // Execute the request through a client request handler that
- // handles errors as well as proxy checks, and reattempts the
- // request once
- // if unauthorised/forbidden exception is thrown, and client
- // login is
- // attempted again.
- result = runAsClientRequestCheckConnection(client, cloudServer, subProgress);
-
- succeeded = true;
-
- try {
- // At this stage, the client is connected, otherwise the
- // client request would have failed.
- // Now retrieve information that should be done once per
- // connection session,
- // including whether the server supports debug, list of
- // application plans, and domains for the org.
- // Since request succeeded, at this stage determine
- // if the server supports debugging.
-
- // FIXNS: Disabled for CF 1.5.0 until V2 MCF is released
- // that supports debug.
- // requestAllowDebug(client);
- if (applicationUrlLookup == null) {
- applicationUrlLookup = new CloudApplicationUrlLookup(getCloudFoundryServer());
- applicationUrlLookup.refreshDomains(subProgress);
- }
-
- }
- catch (RestClientException e) {
- throw CloudErrorUtil.toCoreException(e);
- }
-
- }
- finally {
- if (!succeeded) {
- if (server.getServerState() == IServer.STATE_STARTING) {
- server.setServerState(IServer.STATE_STOPPED);
- }
- }
- subProgress.done();
- }
-
- if (server.getServerState() != IServer.STATE_STARTED) {
- server.setServerState(IServer.STATE_STARTED);
- }
- // server.setServerPublishState(IServer.PUBLISH_STATE_NONE);
-
- return result;
- }
-
- /**
- * Attempts to execute the client request by first checking proxy
- * settings, and if unauthorised/forbidden exceptions thrown the first
- * time, will attempt to log in. If that succeeds, it will attempt one
- * more time. Otherwise it will fail and not attempt the request any
- * further.
- * @param client
- * @param cloudServer
- * @param subProgress
- * @return
- * @throws CoreException if attempt to execute failed, even after a
- * second attempt after a client login.
- */
- protected T runAsClientRequestCheckConnection(CloudFoundryOperations client, CloudFoundryServer cloudServer,
- SubMonitor subProgress) throws CoreException {
- // Check that a user is logged in and proxy is updated
- String cloudURL = cloudServer.getUrl();
- CloudFoundryLoginHandler handler = new CloudFoundryLoginHandler(client, cloudURL);
-
- // Always check if proxy settings have changed.
- handler.updateProxyInClient(client);
-
- try {
- return runAsClientRequest(client, subProgress);
- }
- catch (CoreException ce) {
- CloudFoundryException cfe = ce.getCause() instanceof CloudFoundryException ? (CloudFoundryException) ce
- .getCause() : null;
- if (cfe != null && handler.shouldAttemptClientLogin(cfe)) {
- handler.login(subProgress, 3, ClientRequestOperation.LOGIN_INTERVAL);
- return runAsClientRequest(client, subProgress);
- }
- else {
- throw ce;
- }
- }
- }
-
- protected T runAsClientRequest(CloudFoundryOperations client, SubMonitor subProgress) throws CoreException {
- return new ClientRequestOperation<T>(client) {
-
- @Override
- protected T doRun(CloudFoundryOperations client, SubMonitor progress) throws CoreException {
- return Request.this.doRun(client, progress);
- }
-
- }.run(subProgress);
- }
-
- protected abstract T doRun(CloudFoundryOperations client, SubMonitor progress) throws CoreException;
-
- }
-
- /**
*
* Request that is aware of potential staging related errors and may attempt
* the request again on certain types of staging errors like Staging Not
@@ -1823,33 +1801,26 @@ protected T doRun(CloudFoundryOperations client, SubMonitor progress) throws Cor
* (e.g. creating a service, getting list of all apps), should not use this
* request.
*/
- abstract class StagingAwareRequest<T> extends Request<T> {
-
- protected final long requestTimeOut;
-
- public StagingAwareRequest() {
- this("");
- }
+ abstract class StagingAwareRequest<T> extends BehaviourRequest<T> {
public StagingAwareRequest(String label) {
- this(label, ClientRequestOperation.DEFAULT_CF_CLIENT_REQUEST_TIMEOUT);
- }
-
- public StagingAwareRequest(String label, long requestTimeOut) {
super(label);
- this.requestTimeOut = requestTimeOut > 0 ? requestTimeOut
- : ClientRequestOperation.DEFAULT_CF_CLIENT_REQUEST_TIMEOUT;
}
- protected T runAsClientRequest(CloudFoundryOperations client, SubMonitor subProgress) throws CoreException {
- return new RetryNotFinishedStagingOperation<T>(client, requestTimeOut) {
+ protected long getWaitInterval(Throwable exception, SubMonitor monitor) throws CoreException {
- @Override
- protected T doRun(CloudFoundryOperations client, SubMonitor progress) throws CoreException {
- return StagingAwareRequest.this.doRun(client, progress);
- }
+ if (exception instanceof CoreException) {
+ exception = ((CoreException) exception).getCause();
+ }
- }.run(subProgress);
+ if (exception instanceof NotFinishedStagingException) {
+ return CloudOperationsConstants.ONE_SECOND_INTERVAL * 2;
+ }
+ else if (exception instanceof CloudFoundryException
+ && CloudErrorUtil.isAppStoppedStateError((CloudFoundryException) exception)) {
+ return CloudOperationsConstants.ONE_SECOND_INTERVAL;
+ }
+ return -1;
}
protected abstract T doRun(CloudFoundryOperations client, SubMonitor progress) throws CoreException;
@@ -1861,27 +1832,23 @@ protected T doRun(CloudFoundryOperations client, SubMonitor progress) throws Cor
* Reattempts the operation if a app in stopped state error is encountered.
*
*/
- abstract class AppInStoppedStateAwareRequest<T> extends Request<T> {
-
- protected final long requestTimeOut;
-
- public AppInStoppedStateAwareRequest() {
- this("");
- }
+ abstract class AppInStoppedStateAwareRequest<T> extends BehaviourRequest<T> {
public AppInStoppedStateAwareRequest(String label) {
- this.requestTimeOut = ClientRequestOperation.DEFAULT_CF_CLIENT_REQUEST_TIMEOUT;
+ super(label);
}
- protected T runAsClientRequest(CloudFoundryOperations client, SubMonitor subProgress) throws CoreException {
- return new RetryAppInStoppedStateOperation<T>(client, requestTimeOut) {
+ protected long getWaitInterval(Throwable exception, SubMonitor monitor) throws CoreException {
- @Override
- protected T doRun(CloudFoundryOperations client, SubMonitor progress) throws CoreException {
- return AppInStoppedStateAwareRequest.this.doRun(client, progress);
- }
+ if (exception instanceof CoreException) {
+ exception = ((CoreException) exception).getCause();
+ }
- }.run(subProgress);
+ if (exception instanceof CloudFoundryException
+ && CloudErrorUtil.isAppStoppedStateError((CloudFoundryException) exception)) {
+ return CloudOperationsConstants.ONE_SECOND_INTERVAL;
+ }
+ return -1;
}
protected abstract T doRun(CloudFoundryOperations client, SubMonitor progress) throws CoreException;
@@ -2113,7 +2080,6 @@ public boolean onProgress(String status) {
return false;
}
});
- printlnToConsole(appModule, "\nFINSHED Processing payload...", false, false, monitor);
}
}
@@ -2200,7 +2166,7 @@ protected CloudFoundryApplicationModule prepareForDeployment(IProgressMonitor mo
CloudFoundryApplicationModule appModule = super.prepareForDeployment(monitor);
- DeploymentInfoWorkingCopy workingCopy = appModule.getDeploymentInfoWorkingCopy();
+ DeploymentInfoWorkingCopy workingCopy = appModule.getDeploymentInfoWorkingCopy(monitor);
workingCopy.setIncrementalPublish(incrementalPublish);
workingCopy.save();
return appModule;
@@ -2274,7 +2240,7 @@ protected void performDeployment(CloudFoundryApplicationModule appModule, IProgr
printlnToConsole(appModule, APP_PUSH_MESSAGE, false, true, monitor);
- new Request<Void>("Pushing the application: " + deploymentName) {
+ new BehaviourRequest<Void>(NLS.bind("Pushing the application {0} ", deploymentName)) {
@Override
protected Void doRun(final CloudFoundryOperations client, SubMonitor progress)
throws CoreException {
@@ -2499,7 +2465,7 @@ protected void performDeployment(CloudFoundryApplicationModule appModule, IProgr
printlnToConsole(cloudModule, PRE_STAGING_MESSAGE, false, true, monitor);
- new Request<Void>("Starting application " + deploymentName) {
+ new BehaviourRequest<Void>(NLS.bind("Starting application {0}", deploymentName)) {
@Override
protected Void doRun(final CloudFoundryOperations client, SubMonitor progress)
throws CoreException {
@@ -2533,8 +2499,7 @@ protected Void doRun(final CloudFoundryOperations client, SubMonitor progress)
// This should be staging aware, in order to reattempt on
// staging related issues when checking if an app has
// started or not
- new StagingAwareRequest<Void>("Waiting for application to start: " + deploymentName,
- ClientRequestOperation.DEPLOYMENT_TIMEOUT) {
+ new StagingAwareRequest<Void>(NLS.bind("Waiting for application to start: {0}", deploymentName)) {
@Override
protected Void doRun(final CloudFoundryOperations client, SubMonitor progress)
throws CoreException {
@@ -2590,11 +2555,6 @@ protected String getOperationName() {
FileRequest() {
super("Retrieving file");
}
-
- FileRequest(String label) {
- super(label, ClientRequestOperation.ONE_SECOND_INTERVAL * 2);
- }
-
}
/**
@@ -2702,7 +2662,8 @@ protected void performDeployment(CloudFoundryApplicationModule appModule, IProgr
// CloudFoundryPlugin.getCallback().applicationStopping(getCloudFoundryServer(),
// cloudModule);
- new Request<Void>() {
+ new BehaviourRequest<Void>(NLS.bind("Stopping application {0}",
+ cloudModule.getDeployedApplicationName())) {
@Override
protected Void doRun(CloudFoundryOperations client, SubMonitor progress) throws CoreException {
client.stopApplication(cloudModule.getDeployedApplicationName());
@@ -2737,4 +2698,22 @@ protected String getOperationName() {
}
}
+ abstract class BehaviourRequest<T> extends LocalServerRequest<T> {
+
+ public BehaviourRequest(String label) {
+ super(label);
+ }
+
+ @Override
+ protected CloudFoundryOperations getClient(IProgressMonitor monitor) throws CoreException {
+ return CloudFoundryServerBehaviour.this.getClient(monitor);
+ }
+
+ @Override
+ protected CloudFoundryServer getCloudServer() throws CoreException {
+ return CloudFoundryServerBehaviour.this.getCloudFoundryServer();
+ }
+
+ }
+
}
View
35 ...rc/org/cloudfoundry/ide/eclipse/internal/server/core/client/CloudOperationsConstants.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright (c) 2014 Pivotal Software, 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 Software, Inc. - initial API and implementation
+ *******************************************************************************/
+package org.cloudfoundry.ide.eclipse.internal.server.core.client;
+
+public class CloudOperationsConstants {
+
+ /*
+ * Intervals are how long a thread should sleep before moving to the next
+ * iteration, or how long a refresh operation should wait before refreshing
+ * the deployed apps.
+ */
+ public static final long DEFAULT_INTERVAL = 60 * 1000;
+
+ public static final long SHORT_INTERVAL = 5 * 1000;
+
+ public static final long MEDIUM_INTERVAL = 10 * 1000;