Download
Getting Started
Members
Projects
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
More
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
Toggle navigation
Bugzilla – Attachment 259551 Details for
Bug 486957
Application deployment wizard hangs on publish due to blocking host taken detection routes check
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
Log In
[x]
|
Terms of Use
|
Copyright Agent
[patch]
Patch to server.core and server.ui to fix host take detection hang
eclipse-cft-486957.patch (text/plain), 29.36 KB, created by
Jonathan West
on 2016-02-03 15:35:35 EST
(
hide
)
Description:
Patch to server.core and server.ui to fix host take detection hang
Filename:
MIME Type:
Creator:
Jonathan West
Created:
2016-02-03 15:35:35 EST
Size:
29.36 KB
patch
obsolete
>### Eclipse Workspace Patch 1.0 >#P org.eclipse.cft.server.core >diff --git src/org/eclipse/cft/server/core/internal/client/ClientRequestFactory.java src/org/eclipse/cft/server/core/internal/client/ClientRequestFactory.java >index 6f22766..f3b1a09 100644 >--- src/org/eclipse/cft/server/core/internal/client/ClientRequestFactory.java >+++ src/org/eclipse/cft/server/core/internal/client/ClientRequestFactory.java >@@ -1,7 +1,7 @@ > /******************************************************************************* > * Copied from Spring Tool Suite. Original license: > * >- * Copyright (c) 2015, 2016 Pivotal Software Inc and IBM Corporation. >+ * Copyright (c) 2015, 2016 Pivotal Software Inc. and IBM Corporation > * 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 >@@ -20,6 +20,7 @@ > import java.util.List; > import java.util.Map; > >+import org.cloudfoundry.client.lib.CloudFoundryException; > import org.cloudfoundry.client.lib.CloudFoundryOperations; > import org.cloudfoundry.client.lib.domain.ApplicationLog; > import org.cloudfoundry.client.lib.domain.ApplicationStats; >@@ -513,10 +514,8 @@ > } > > /** >- * Check if the 'host' in the 'domainName' is already taken. Optionally delete the route after the check or keep it to >- * reserve it. Clients are expected to call {@link #deleteRoute(String, String)} after to remove any unused routes. >- * >- * Throws a CoreException if the host is taken. >+ * Check if the 'host' in the 'domainName' is reserved (route owned by us or someone else), and if not reserve it. >+ * Clients are expected to call {@link #deleteRoute(String, String)} after to remove any unused routes. > * > * @see deleteRoute(String, String) > * @param host - the Subdomain of the deployed URL >@@ -524,47 +523,27 @@ > * @param deleteRoute - true to delete the route (if it was created in this method), false to reserve it and leave deletion to the calling method if necessary > * @return true if the route was created, false otherwise > */ >- public BaseClientRequest<Boolean> checkHostTaken(final String host, final String domainName, final boolean deleteRoute) { >+ public BaseClientRequest<Boolean> reserveRouteIfAvailable(final String host, final String domainName) { > return new BehaviourRequest<Boolean>(Messages.bind(Messages.CloudFoundryServerBehaviour_CHECKING_HOSTNAME_AVAILABLE, host), behaviour) { > @Override >- protected Boolean doRun(CloudFoundryOperations client, SubMonitor progress) throws CoreException { >+ protected Boolean doRun(CloudFoundryOperations client, SubMonitor progress) { > >- // First, check the existing list of routes, before attempting an add below >- List<CloudRoute> cloudRoutes = client.getRoutes(domainName); >- >- if(cloudRoutes != null) { >- for(CloudRoute cr : cloudRoutes) { >- // If we own the route... >- if(cr.getHost().equalsIgnoreCase(host)) { >- if(cr.inUse()) { >- // ... but it is in use, then throw an exception to indicate this. >- throw new CoreException(new Status(Status.ERROR, CloudFoundryPlugin.PLUGIN_ID, "Client error - The host is taken: "+host)); >- >- } else { >- // ... but route is not in use, then we may deploy with it. >- return false; >- } >- } >- } >+ // Check if the route can be added. If successful, then it is not taken. >+ try { >+ client.addRoute(host, domainName); >+ } catch(CloudFoundryException t) { >+ // addRoute will throw a CloudFoundryException indicating the route is taken; but we should also return false for any other >+ // exceptions that might be thrown here. >+ return false; > } >- >- // check if the route can be added. If successful, then it is not taken. >- client.addRoute(host, domainName); >- >- // if addRoute is successful (no CoreException), then delete it so it is available again >- // Specify deleteRoute = false to 'reserve' the hostname >- if (deleteRoute) { >- client.deleteRoute(host, domainName); >- } >- >- // The URL is considered created if we didn't delete it above. >- return !deleteRoute; >+ >+ return true; > } > }; > } > > /** >- * Delete the route. Use also with {@link #checkHostTaken(String, String, boolean) >+ * Delete the route. > * > * @see checkHostTaken(String, String, boolean) { > * @param host - the Subdomain of the deployed URL >diff --git src/org/eclipse/cft/server/core/internal/client/CloudFoundryServerBehaviour.java src/org/eclipse/cft/server/core/internal/client/CloudFoundryServerBehaviour.java >index e162d40..d22bf9c 100644 >--- src/org/eclipse/cft/server/core/internal/client/CloudFoundryServerBehaviour.java >+++ src/org/eclipse/cft/server/core/internal/client/CloudFoundryServerBehaviour.java >@@ -1,5 +1,5 @@ > /******************************************************************************* >- * Copyright (c) 2012, 2016 Pivotal Software, Inc. >+ * Copyright (c) 2012, 2016 Pivotal Software, Inc. and IBM Corporation > * > * All rights reserved. This program and the accompanying materials > * are made available under the terms of the Eclipse Public License v1.0 >@@ -74,6 +74,7 @@ > import org.eclipse.core.runtime.IStatus; > import org.eclipse.core.runtime.MultiStatus; > import org.eclipse.core.runtime.NullProgressMonitor; >+import org.eclipse.core.runtime.OperationCanceledException; > import org.eclipse.core.runtime.Status; > import org.eclipse.core.runtime.SubMonitor; > import org.eclipse.core.runtime.jobs.IJobChangeEvent; >@@ -1267,8 +1268,15 @@ > }.run(monitor); > } > >+ /** Retrieves the routes for the given domain name; will return early if cancelled, with >+ * an OperationCanceledException. */ > public List<CloudRoute> getRoutes(final String domainName, IProgressMonitor monitor) throws CoreException { >- return getRequestFactory().getRoutes(domainName).run(monitor); >+ >+ BaseClientRequest<List<CloudRoute>> request = getRequestFactory().getRoutes(domainName); >+ >+ CancellableRequestThread<List<CloudRoute>> t = new CancellableRequestThread<List<CloudRoute>>(request, monitor); >+ return t.runAndWaitForCompleteOrCancelled(); >+ > } > > public void deleteRoute(final List<CloudRoute> routes, IProgressMonitor monitor) throws CoreException { >@@ -1288,20 +1296,21 @@ > } > > /** >- * Determine if a given host is taken; if it is, an exception is thrown. >- * Otherwise a boolean will be returned which indicates whether or not the >- * host route was created: a route will not be created if it already exists, >- * or if deleteRoute is true. >+ * Attempt to reserve a route; returns true if the route could be reserved, or false otherwise. >+ * Note: This will return false if user already owns the route, or if the route is owned by another user. >+ * Will return early if cancelled, with an OperationCanceledException. > */ >- public boolean checkHostTaken(final String host, final String domainName, final boolean deleteRoute, >- IProgressMonitor monitor) throws CoreException { >+ public boolean reserveRouteIfAvailable(final String host, final String domainName, IProgressMonitor monitor) throws CoreException { > >- BaseClientRequest<Boolean> request = getRequestFactory().checkHostTaken(host, domainName, deleteRoute); >- if (request != null) { >- boolean result = request.run(monitor); >+ BaseClientRequest<Boolean> request = getRequestFactory().reserveRouteIfAvailable(host, domainName); >+ >+ CancellableRequestThread<Boolean> t = new CancellableRequestThread<Boolean>(request, monitor); >+ Boolean result = t.runAndWaitForCompleteOrCancelled(); >+ >+ if(result != null) { > return result; > } >- >+ > return false; > } > >@@ -1763,3 +1772,124 @@ > return new ApplicationInstanceRunningTracker(appModule, getCloudFoundryServer()); > } > } >+ >+ >+/** Requests may be wrapped using this class, such that if the user cancels the monitor, the thread will automatically return. >+ * >+ * Note: Since the BaseClientRequest itself does not check the monitor, the BaseClientRequest may still be running even though >+ * the calling thread has return. Care should be taken to consider this logic. */ >+class CancellableRequestThread<T> { >+ >+ private T result = null; >+ private Throwable exceptionThrown = null; >+ >+ private boolean threadComplete = false; >+ >+ private final Object lock = new Object(); >+ >+ private final IProgressMonitor monitor; >+ private final BaseClientRequest<T> request; >+ >+ public CancellableRequestThread(BaseClientRequest<T> request, IProgressMonitor monitor) { >+ this.request = request; >+ this.monitor = monitor; >+ } >+ >+ /** This is called by ThreadWrapper.run(...) */ >+ private void runInThread() { >+ >+ try { >+ result = request.run(monitor); >+ } catch (Exception e) { >+ exceptionThrown = e; >+ } finally { >+ synchronized(lock) { >+ threadComplete = true; >+ lock.notify(); >+ } >+ } >+ >+ } >+ >+ /** Starts the thread to invoke the request, and begins waiting for the thread to complete or be cancelled. */ >+ public T runAndWaitForCompleteOrCancelled() { >+ try { >+ >+ // Start the thread that runs the requst >+ ThreadWrapper tw = new ThreadWrapper(); >+ tw.start(); >+ >+ >+ while(!monitor.isCanceled()) { >+ >+ synchronized(lock) { >+ // Check for cancelled every 0.25 seconds. >+ lock.wait(250); >+ >+ if(threadComplete) { >+ break; >+ } >+ } >+ } >+ >+ >+ Throwable thr = getExceptionThrown(); >+ // Throw any caught exceptions >+ if(thr != null ) { >+ if(thr instanceof RuntimeException) { >+ // Throw unchecked exception >+ throw (RuntimeException)thr; >+ >+ } else { >+ // Convert checked to unchecked exception >+ throw new RuntimeException(thr); >+ } >+ >+ } >+ >+ // Check for cancelled >+ if(!isThreadComplete() && getResult() == null) { >+ throw new OperationCanceledException(); >+ } >+ >+ T result = getResult(); >+ >+ return result; >+ >+ } catch (InterruptedException e) { >+ throw new OperationCanceledException(); >+ } >+ } >+ >+ public Throwable getExceptionThrown() { >+ synchronized(lock) { >+ return exceptionThrown; >+ } >+ } >+ >+ public boolean isThreadComplete() { >+ synchronized(lock) { >+ return threadComplete; >+ } >+ } >+ >+ public T getResult() { >+ synchronized(lock) { >+ return result; >+ } >+ } >+ >+ /** Simple thread that calls runInThread(...), to ensure that the BaseClientRequest may only be started by calling the runAndWaitForCompleteOrCancelled(...) method. */ >+ private class ThreadWrapper extends Thread { >+ >+ private ThreadWrapper() { >+ setDaemon(true); >+ setName(CancellableRequestThread.class.getName()); >+ } >+ >+ @Override >+ public void run() { >+ runInThread(); >+ } >+ } >+} >#P org.eclipse.cft.server.ui >diff --git src/org/eclipse/cft/server/ui/internal/CloudUiUtil.java src/org/eclipse/cft/server/ui/internal/CloudUiUtil.java >index e35be6f..7ba90ac 100644 >--- src/org/eclipse/cft/server/ui/internal/CloudUiUtil.java >+++ src/org/eclipse/cft/server/ui/internal/CloudUiUtil.java >@@ -33,6 +33,7 @@ > import java.util.regex.Pattern; > > import org.cloudfoundry.client.lib.CloudCredentials; >+import org.cloudfoundry.client.lib.domain.CloudRoute; > import org.eclipse.cft.server.core.AbstractCloudFoundryUrl; > import org.eclipse.cft.server.core.internal.ApplicationUrlLookupService; > import org.eclipse.cft.server.core.internal.CloudApplicationURL; >@@ -540,7 +541,7 @@ > } > > >- public static UniqueSubdomain getUniqueSubdomain(String url, CloudFoundryServer server) { >+ public static UniqueSubdomain getUniqueSubdomain(String url, CloudFoundryServer server, IProgressMonitor monitor) throws CoreException { > if (url == null) return null; // Incorrect usage. Provide a non-null string > > ApplicationUrlLookupService lookup = ApplicationUrlLookupService.getCurrentLookup(server); >@@ -550,27 +551,71 @@ > > UniqueSubdomain result = null; > >+ if(monitor == null) { >+ // Monitor is optional, so use a NullProgressMonitor. >+ monitor = new NullProgressMonitor(); >+ } >+ >+ List<CloudRoute> routes = null; >+ > do { >+ > try { >- // It does NOT check if the URL is taken already, even if valid. >+ // It does NOT check if the URL is taken already, even if valid. > cloudUrl = lookup.getCloudApplicationURL(url); >- } catch (CoreException e) { >+ } catch(CoreException e) { > // if error occurred, eg. url is null, then don't check for host taken and simply return > break; > } > >- try { >- // CheckHostTaken - reserve the route when we get a unused name >+ if(cloudUrl == null) { >+ // if error occurred, eg. url is null, then don't check for host taken and simply return >+ break; >+ } >+ >+ if(routes == null) { >+ routes = server.getBehaviour().getRoutes(cloudUrl.getDomain(), monitor); >+ } >+ >+ boolean isFound = false; // is in route list? >+ boolean isRouteReservedAndUnused = false; // is route reserve and unused? >+ boolean isRouteCreated = false; // did we create the route in reserveRoute? >+ >+ // First check the existing cloud routes >+ for(CloudRoute cr : routes) { >+ // If we own the route... >+ if(cr.getHost().equalsIgnoreCase(cloudUrl.getSubdomain())) { >+ isFound = true; >+ isRouteCreated = false; >+ >+ if(!cr.inUse()) { >+ isRouteReservedAndUnused = true; >+ } else { >+ isRouteReservedAndUnused = false; >+ } >+ >+ break; >+ } >+ } >+ >+ if(!isFound) { >+ // If the route was not found in the getRoutes(...) list, then attempt to reserve it > >- boolean isRouteCreated = server.getBehaviour().checkHostTaken(cloudUrl.getSubdomain(), cloudUrl.getDomain(), false, new NullProgressMonitor()); >- >+ isRouteReservedAndUnused = server.getBehaviour().reserveRouteIfAvailable(cloudUrl.getSubdomain(), cloudUrl.getDomain(), monitor); >+ isRouteCreated = isRouteReservedAndUnused; >+ } >+ >+ if(isRouteReservedAndUnused) { > result = new UniqueSubdomain(); > result.setRouteCreated(isRouteCreated); > result.setCloudUrl(cloudUrl); > > // break or just set boolean to true > isUniqueURL = true; >- } catch (CoreException ce) { >+ >+ } else { >+ // The route is taken (as determined either by checking the route list, or by attempting to reserve) >+ > isUniqueURL = false; > StringBuilder sb = new StringBuilder(url); > String subdomain = cloudUrl.getSubdomain(); >@@ -590,9 +635,10 @@ > } else { // Otherwise, simply append 1 to the end of the subdomain > // Example: subdomain = MyApp --> MyApp1 > url = sb.insert(sb.indexOf(subdomain) + subdomain.length(), "1").toString(); >- } >+ } > } >- } while (!isUniqueURL && intSuffix < Integer.MAX_VALUE - 1); // Support suffix up to the number 2^31 - 1 >+ >+ } while (!isUniqueURL && intSuffix < Integer.MAX_VALUE - 1 && !monitor.isCanceled()); // Support suffix up to the number 2^31 - 1 > > return result; > } >diff --git src/org/eclipse/cft/server/ui/internal/HostnameValidator.java src/org/eclipse/cft/server/ui/internal/HostnameValidator.java >index a9547b3..5b1f1cc 100644 >--- src/org/eclipse/cft/server/ui/internal/HostnameValidator.java >+++ src/org/eclipse/cft/server/ui/internal/HostnameValidator.java >@@ -21,7 +21,9 @@ > package org.eclipse.cft.server.ui.internal; > > import java.lang.reflect.InvocationTargetException; >+import java.util.List; > >+import org.cloudfoundry.client.lib.domain.CloudRoute; > import org.eclipse.cft.server.core.internal.CloudApplicationURL; > import org.eclipse.cft.server.core.internal.CloudFoundryPlugin; > import org.eclipse.cft.server.core.internal.CloudFoundryServer; >@@ -37,12 +39,15 @@ > */ > public class HostnameValidator implements IRunnableWithProgress { > >- private CloudApplicationURL appUrl; >+ private final CloudApplicationURL appUrl; >+ private final CloudFoundryServer server; >+ > private IStatus status; >- private CloudFoundryServer server; >+ > // Allow override of the default message for the host name taken problem (for initialization of the wizard) > private String message = null; > >+ /** True if a route was created during validation; a route will not be created if it already exists. */ > private boolean routeCreated = false; > > public HostnameValidator(CloudApplicationURL appUrl, CloudFoundryServer server) { >@@ -62,26 +67,59 @@ > > public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { > monitor.beginTask(Messages.CloudApplicationUrlPart_HOST_CHECK_JOB_DISPLAY_INFO, IProgressMonitor.UNKNOWN); >+ >+ boolean isRouteOurs = false; // Whether we (space/org) own the route (true if either in use or not in use) >+ boolean isInUse = false; // In use by another application or user >+ > try { >- routeCreated = server.getBehaviour().checkHostTaken(appUrl.getSubdomain(), appUrl.getDomain(), false, monitor); >- } catch (CoreException ce) { >- status = ce.getStatus(); >- String errorMessage = ce.getMessage(); >- // host name taken is potentially one cause of the CoreException >- // Look for it specifically, and change the error message so it's more user-friendly. >- // Message from java client is: "Client error - The host is taken". >- // Replace it with ours that is more meaningful. >- if (errorMessage != null && errorMessage.contains("Client error - The host is taken")) { // $NON-NLS-N$ >- status = new Status(IStatus.ERROR, status.getPlugin(), message != null ? message : Messages.bind( >- Messages.CloudApplicationUrlPart_ERROR_HOSTNAME_TAKEN, appUrl.getUrl())); >- } else { >- // For other errors (like connection time out), give a more user-friendly message than the one provided >- status = new Status(IStatus.ERROR, status.getPlugin(), Messages.CloudApplicationUrlPart_ERROR_UNABLE_TO_CHECK_HOSTNAME); >- // Log the error at least. >- CloudFoundryPlugin.logError(Messages.CloudApplicationUrlPart_ERROR_UNABLE_TO_CHECK_HOSTNAME, ce); >+ >+ List<CloudRoute> routes = server.getBehaviour().getRoutes(appUrl.getDomain(), monitor); >+ >+ for(CloudRoute cr : routes) { >+ // If we own the route... >+ if(cr.getHost().equalsIgnoreCase(appUrl.getSubdomain())) { >+ isRouteOurs = true; >+ isInUse = cr.inUse(); >+ >+ if(!isInUse) { >+ // We own it, but it's not in use by us, so we are ok. >+ status = Status.OK_STATUS; >+ this.routeCreated = false; >+ return; >+ } >+ >+ >+ break; >+ } > } >- } >- finally { >+ >+ if(!isRouteOurs) { >+ // If we couldn't find the route in the route list, so attempt to reserve it >+ boolean routeReserved = server.getBehaviour().reserveRouteIfAvailable(appUrl.getSubdomain(), appUrl.getDomain(), monitor); >+ >+ if(routeReserved) { >+ // We successfully reserved a route that we did not previously own >+ this.routeCreated = true; >+ isInUse = false; >+ } else { >+ // We could not reserve the route as some other user owns it >+ isInUse = true; >+ this.routeCreated = false; >+ } >+ } >+ >+ if(isInUse) { >+ // We found it in the route list (and it was in use), or we couldn't reserve it, so it is taken. >+ status = new Status(IStatus.ERROR, status.getPlugin(), message != null ? message : Messages.bind( >+ Messages.CloudApplicationUrlPart_ERROR_HOSTNAME_TAKEN, appUrl.getUrl())); >+ } >+ >+ } catch (CoreException ce) { >+ // For other errors (like connection time out), give a more user-friendly message than the one provided >+ status = new Status(IStatus.ERROR, status.getPlugin(), Messages.CloudApplicationUrlPart_ERROR_UNABLE_TO_CHECK_HOSTNAME); >+ // Log the error at least. >+ CloudFoundryPlugin.logError(Messages.CloudApplicationUrlPart_ERROR_UNABLE_TO_CHECK_HOSTNAME, ce); >+ } finally { > monitor.done(); > } > } >diff --git src/org/eclipse/cft/server/ui/internal/wizards/CloudFoundryApplicationServicesWizardPage.java src/org/eclipse/cft/server/ui/internal/wizards/CloudFoundryApplicationServicesWizardPage.java >index 4b53abc..c6f37b3 100644 >--- src/org/eclipse/cft/server/ui/internal/wizards/CloudFoundryApplicationServicesWizardPage.java >+++ src/org/eclipse/cft/server/ui/internal/wizards/CloudFoundryApplicationServicesWizardPage.java >@@ -308,7 +308,7 @@ > } > } > }; >- runAsynchWithWizardProgress(runnable, Messages.CloudFoundryApplicationServicesWizardPage_TEXT_VERIFY_SERVICE_PROGRESS); >+ runAsync(runnable, Messages.CloudFoundryApplicationServicesWizardPage_TEXT_VERIFY_SERVICE_PROGRESS); > > } > >diff --git src/org/eclipse/cft/server/ui/internal/wizards/CloudFoundryApplicationWizardPage.java src/org/eclipse/cft/server/ui/internal/wizards/CloudFoundryApplicationWizardPage.java >index 78d517d..84653f5 100644 >--- src/org/eclipse/cft/server/ui/internal/wizards/CloudFoundryApplicationWizardPage.java >+++ src/org/eclipse/cft/server/ui/internal/wizards/CloudFoundryApplicationWizardPage.java >@@ -40,10 +40,13 @@ > import org.eclipse.cft.server.ui.internal.CloudFoundryImages; > import org.eclipse.cft.server.ui.internal.CloudUiUtil; > import org.eclipse.cft.server.ui.internal.CloudUiUtil.UniqueSubdomain; >+import org.eclipse.cft.server.ui.internal.ICoreRunnable; > import org.eclipse.cft.server.ui.internal.Messages; > import org.eclipse.cft.server.ui.internal.PartChangeEvent; > import org.eclipse.cft.server.ui.internal.UIPart; > import org.eclipse.cft.server.ui.internal.WizardPartChangeEvent; >+import org.eclipse.core.runtime.CoreException; >+import org.eclipse.core.runtime.IProgressMonitor; > import org.eclipse.core.runtime.IStatus; > import org.eclipse.core.runtime.Status; > import org.eclipse.jface.resource.ImageDescriptor; >@@ -57,6 +60,7 @@ > import org.eclipse.swt.widgets.Button; > import org.eclipse.swt.widgets.Composite; > import org.eclipse.swt.widgets.Control; >+import org.eclipse.swt.widgets.Display; > import org.eclipse.swt.widgets.Label; > import org.eclipse.swt.widgets.Text; > >@@ -76,6 +80,8 @@ > > private String buildpack; > >+ private AppNamePart appNamePart; >+ > private Text buildpackText; > > private String serverTypeId; >@@ -88,6 +94,38 @@ > > protected final ApplicationWizardDescriptor descriptor; > >+ /** The current state of the page, as determined by setVisible(...) */ >+ private boolean isPageVisible = false; >+ >+ /** Whether or not we have started the wizard progress thread to validate the application name */ >+ private boolean isAppnameValidated = false; >+ >+ @Override >+ public void setVisible(boolean newVisibleState) { >+ >+ super.setVisible(newVisibleState); >+ >+ // If we are on this page, and the name has not been previously checked if it is valid, then check it >+ if(!this.isPageVisible && newVisibleState && !this.isAppnameValidated) { >+ >+ this.isAppnameValidated = true; >+ this.isPageVisible = newVisibleState; >+ >+ runAsynchWithWizardProgress(new ICoreRunnable() { >+ >+ @Override >+ public void run(IProgressMonitor monitor) throws CoreException { >+ IStatus hostnameStatus = validateHostname(monitor); >+ if (hostnameStatus != null && !hostnameStatus.isOK()) { >+ setErrorMessage(hostnameStatus.getMessage()); >+ handleChange(new PartChangeEvent(appName, hostnameStatus, CloudUIEvent.VALIDATE_HOST_TAKEN_EVENT)); >+ } >+ >+ }} , null); >+ } >+ >+ } >+ > // Preserving the old constructor to avoid API breakage > public CloudFoundryApplicationWizardPage(CloudFoundryServer server, CloudFoundryDeploymentWizardPage deploymentPage, > CloudFoundryApplicationModule module, ApplicationWizardDescriptor descriptor) { >@@ -147,18 +185,17 @@ > // This must be called first as the values are then populate into the UI > // widgets > init(); >- IStatus hostnameStatus = validateHostname(); > > Composite composite = new Composite(parent, SWT.NONE); > composite.setLayout(new GridLayout(2, false)); > composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); > >- final UIPart appPart = new AppNamePart(); >+ appNamePart = new AppNamePart(); > // Add the listener first so that it can be notified of changes during > // the part creation. >- appPart.addPartChangeListener(this); >+ appNamePart.addPartChangeListener(this); > >- appPart.createPart(composite); >+ appNamePart.createPart(composite); > > Label nameLabel = new Label(composite, SWT.NONE); > nameLabel.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false)); >@@ -180,12 +217,6 @@ > validateBuildPack(); > } > }); >- >- // Show hostname taken error message first over buildpack URL errors >- if (hostnameStatus != null && !hostnameStatus.isOK()) { >- setErrorMessage(hostnameStatus.getMessage()); >- handleChange(new PartChangeEvent(appName, hostnameStatus, CloudUIEvent.VALIDATE_HOST_TAKEN_EVENT)); >- } > > return composite; > } >@@ -321,9 +352,13 @@ > > return parent; > } >+ >+ protected Text getNameText() { >+ return nameText; >+ } > } > >- private IStatus validateHostname() { >+ private IStatus validateHostname(IProgressMonitor monitor) { > ApplicationDeploymentInfo workingCopy = descriptor.getDeploymentInfo(); > IStatus status = Status.OK_STATUS; > >@@ -360,29 +395,47 @@ > // } > // } > } else { >- // IFF there is no manifest, then we will do the hostname validation AND suggest a new unique name >+ // IFF there is no manifest, then we will do the hostname >+ // validation AND suggest a new unique name > List<String> urls = workingCopy.getUris(); > String url = urls != null && !urls.isEmpty() ? urls.get(0) : null; >- >+ > if (url != null) { >- UniqueSubdomain uniqueSubdomain = CloudUiUtil.getUniqueSubdomain(url, server); >- >+ UniqueSubdomain uniqueSubdomain; >+ try { >+ uniqueSubdomain = CloudUiUtil.getUniqueSubdomain(url, server, monitor); >+ } catch (CoreException e) { >+ // Return the exception to calling class >+ return e.getStatus(); >+ } >+ > if (uniqueSubdomain != null && uniqueSubdomain.getCloudUrl() != null) { > cloudUrl = uniqueSubdomain.getCloudUrl(); >- // Set the new deployment name and update the URIs only if it needs to be changed >+ // Set the new deployment name and update the URIs only >+ // if it needs to be changed > if (!cloudUrl.getSubdomain().equals(workingCopy.getDeploymentName())) { >- workingCopy.setDeploymentName(cloudUrl.getSubdomain()); >- appName = cloudUrl.getSubdomain(); >- List<String>newList = new ArrayList<String>(); >- newList.add(cloudUrl.getUrl()); >- workingCopy.setUris(newList); >+ workingCopy.setDeploymentName(cloudUrl.getSubdomain()); >+ appName = cloudUrl.getSubdomain(); >+ >+ // Update the app name Text widget w/ the new name. >+ Display.getDefault().syncExec(new Runnable() { >+ >+ @Override >+ public void run() { >+ appNamePart.getNameText().setText(appName); >+ } >+ }); >+ >+ List<String> newList = new ArrayList<String>(); >+ newList.add(cloudUrl.getUrl()); >+ workingCopy.setUris(newList); > } >- >+ > getApplicationWizard().addToReserved(cloudUrl, uniqueSubdomain.isRouteCreated()); > } >- >+ > } >- >+ > } > } > return status; >diff --git src/org/eclipse/cft/server/ui/internal/wizards/PartsWizardPage.java src/org/eclipse/cft/server/ui/internal/wizards/PartsWizardPage.java >index b083fb7..eba1fb2 100644 >--- src/org/eclipse/cft/server/ui/internal/wizards/PartsWizardPage.java >+++ src/org/eclipse/cft/server/ui/internal/wizards/PartsWizardPage.java >@@ -1,5 +1,5 @@ > /******************************************************************************* >- * Copyright (c) 2013, 2014 Pivotal Software, Inc. >+ * Copyright (c) 2013, 2016 Pivotal Software Inc. and IBM Corporation > * > * All rights reserved. This program and the accompanying materials > * are made available under the terms of the Eclipse Public License v1.0 >@@ -17,6 +17,7 @@ > * > * Contributors: > * Pivotal Software, Inc. - initial API and implementation >+ * IBM Corporation - Add additional async invocation method > ********************************************************************************/ > package org.eclipse.cft.server.ui.internal.wizards; > >@@ -37,6 +38,7 @@ > import org.eclipse.core.runtime.IStatus; > import org.eclipse.core.runtime.OperationCanceledException; > import org.eclipse.core.runtime.Status; >+import org.eclipse.core.runtime.jobs.Job; > import org.eclipse.jface.dialogs.DialogPage; > import org.eclipse.jface.resource.ImageDescriptor; > import org.eclipse.jface.wizard.WizardPage; >@@ -179,6 +181,48 @@ > // Do nothing by default; > } > >+ /** Runs the specific runnable without using the wizard container progress context */ >+ protected void runAsync(final ICoreRunnable runnable, String operationLabel) { >+ if (runnable == null) { >+ return; >+ } >+ >+ if (operationLabel == null) { >+ operationLabel = ""; //$NON-NLS-1$ >+ } >+ >+ Job job = new Job(operationLabel) { >+ >+ @Override >+ protected IStatus run(IProgressMonitor monitor) { >+ CoreException cex = null; >+ try { >+ >+ runnable.run(monitor); >+ } >+ catch (OperationCanceledException e) { >+ // Not an error. User can still enter manual values >+ } >+ catch (CoreException ce) { >+ cex = ce; >+ } >+ // Do not update the wizard with an error, as users can still >+ // complete the wizard with manual values. >+ if (cex != null) { >+ CloudFoundryPlugin.logError(cex); >+ } >+ >+ return Status.OK_STATUS; >+ >+ } >+ >+ }; >+ >+ job.setSystem(false); >+ job.schedule(); >+ >+ } >+ > /** > * Runs the specified runnable asynchronously in a worker thread. Caller is > * responsible for ensuring that any UI behaviour in the runnable is
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 486957
: 259551