package com.aptana.radrails.cloud.deploy;
import java.text.MessageFormat;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.swt.widgets.Display;
import org.radrails.rails.internal.core.RailsPlugin;
import org.radrails.rails.internal.ui.console.RailsShellFactory;
import com.aptana.ide.core.model.user.AptanaUser;
import com.aptana.ide.core.model.user.User;
import com.aptana.ide.server.cloud.services.model.Event;
import com.aptana.ide.server.cloud.services.model.Site;
import com.aptana.ide.server.cloud.services.model.studio.StudioSite;
import com.aptana.ide.server.cloud.syncing.ICloudDeployer;
import com.aptana.radrails.cloud.Activator;
import com.aptana.radrails.cloud.internal.CloudUtil;
import com.aptana.radrails.cloud.internal.EndpointDialog;
import com.aptana.radrails.cloud.shell.AptanaCloudCommandProvider;
public class RailsCloudDeployer implements ICloudDeployer
{
private static final String CAPFILE = CloudUtil.CAPFILE;
public boolean supports(StudioSite site)
{
return site != null && site.isRails();
}
/**
* @param monitor
* the progress monitor to use for reporting progress to the user. It is the caller's responsibility to
* call done() on the given monitor. Accepts <code>null</code>, indicating that no progress should be
* reported and that the operation cannot be cancelled.
* @return IStatus indicating if the deployment was successful.
*/
public IStatus deploy(final StudioSite site, Endpoint target, IProgressMonitor monitor)
{
monitor.beginTask(Messages.RailsCloudDeployer_LBL_Deploying_job_title, 100);
IProject project = site.getProject().getLocalProject();
// Prompt user to make sure they want to deploy and to choose endpoint.
final Endpoint defaultChoice = target;
final int[] dialogExit = new int[1];
final Endpoint[] endpointChoice = new Endpoint[1];
final String[] comment = new String[1];
Display.getDefault().syncExec(new Runnable()
{
public void run()
{
EndpointDialog dialog = new EndpointDialog(Display.getDefault().getActiveShell(), defaultChoice);
dialogExit[0] = dialog.open();
endpointChoice[0] = dialog.getEndpoint();
comment[0] = dialog.getComment();
}
});
if (dialogExit[0] != IDialogConstants.OK_ID)
return Status.CANCEL_STATUS;
target = endpointChoice[0];
monitor.worked(2);
// Now actually start the deploy process...
IProgressMonitor sub = new SubProgressMonitor(monitor, 28);
IStatus status = CloudUtil.installCloudGemIfNecessary(sub);
sub.done();
if (!status.isOK())
return status;
if (monitor.isCanceled())
return Status.CANCEL_STATUS;
// Force open Rails Shell
new RailsShellFactory().openConsole();
monitor.worked(1);
sub = new SubProgressMonitor(monitor, 19);
status = checkProjectHasBeenApCloudified(site, project, sub);
sub.done();
if (!status.isOK())
return status;
if (monitor.isCanceled())
return Status.CANCEL_STATUS;
String targetName = AptanaCloudCommandProvider.PUBLIC;
if (target == Endpoint.STAGING)
targetName = AptanaCloudCommandProvider.STAGING;
try
{
ILaunch launch = CloudUtil.run(AptanaCloudCommandProvider.APCLOUD, targetName
+ " " + AptanaCloudCommandProvider.APTANA_DEPLOY, //$NON-NLS-1$
project, CloudUtil.getEnvMap(site), false);
while (!launch.isTerminated())
{
if (monitor.isCanceled())
{
launch.terminate();
return Status.CANCEL_STATUS;
}
Thread.yield();
}
monitor.worked(45);
// Check exit status
if (launch.getProcesses() != null && launch.getProcesses()[0] != null
&& launch.getProcesses()[0].getExitValue() != 0)
return new Status(IStatus.ERROR, Activator.PLUGIN_ID, -1, "Deployment failed", null);
}
catch (CoreException e)
{
return e.getStatus();
}
createEvent(site, endpointChoice[0], comment[0]);
monitor.done();
return Status.OK_STATUS;
}
private IStatus checkProjectHasBeenApCloudified(StudioSite site, IProject project, IProgressMonitor monitor)
{
IPath railsRoot = RailsPlugin.findRailsRoot(project);
IFile file = project.getFile(railsRoot.append(CAPFILE));
if (file.exists())
return Status.OK_STATUS;
if (monitor.isCanceled())
return Status.CANCEL_STATUS;
try
{
ILaunch launch = CloudUtil.run(AptanaCloudCommandProvider.APCLOUDIFY,
".", project, CloudUtil.getEnvMap(site), true); //$NON-NLS-1$
// We need to wait until this process/launch finishes!
while (!launch.isTerminated())
{
if (monitor.isCanceled())
{
launch.terminate();
return Status.CANCEL_STATUS;
}
// TODO Should we ever time out? It does interactively ask for input...
Thread.yield();
}
// Check exit status
if (launch.getProcesses() != null && launch.getProcesses()[0] != null
&& launch.getProcesses()[0].getExitValue() != 0)
return new Status(IStatus.ERROR, Activator.PLUGIN_ID, -1, "Running apcloudify on project failed", null);
}
catch (CoreException e)
{
return e.getStatus();
}
return Status.OK_STATUS;
}
/**
* Creates an event and sends it to cloud to let cloud know we've done the equivalent of a sync for the site.
*
* @param site
* @param comment
*/
private void createEvent(StudioSite site, Endpoint target, String comment)
{
User user = AptanaUser.getSignedInUser();
String domainName = site.getPrimaryDomainName();
if (target == Endpoint.STAGING)
domainName = site.getStagingDomainName();
String subject = MessageFormat.format(Messages.RailsCloudDeployer_TTL_Deploy_event_subject, user.getUsername(),
domainName);
StringBuilder buffer = new StringBuilder(subject);
if (comment != null && comment.length() > 0)
{
buffer.append("\n"); //$NON-NLS-1$
buffer.append(Messages.RailsCloudDeployer_MSG_Deploy_event_comment_header);
buffer.append("\n"); //$NON-NLS-1$
buffer.append(comment);
buffer.append("\n\n"); //$NON-NLS-1$
}
Event event = new Event(subject, buffer.toString());
event.setId(Integer.toString(Site.SITE_SYNCED));
event.setLocation(site.getEvents().getLocation());
event.setRequestBuilder(site.getRequestBuilder());
event.setServiceProvider(site.getServiceProvider());
event.setLogger(site.getLogger());
event.commit();
site.updateLastSync();
site.getEvents().updateMaxSizeWithSeverities();
}
}