/* Copyright (C) 2009 Mobile Sorcery AB This program is free software; you can redistribute it and/or modify it under the terms of the Eclipse Public License v1.0. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Eclipse Public License v1.0 for more details. You should have received a copy of the Eclipse Public License v1.0 along with this program. It is also available at http://www.eclipse.org/legal/epl-v10.html */ package com.mobilesorcery.sdk.ui.targetphone.internal; import java.io.File; import java.text.MessageFormat; import java.util.List; import java.util.Map; import org.eclipse.core.resources.IResourceChangeEvent; 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.NullProgressMonitor; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.SubProgressMonitor; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.debug.internal.ui.DebugUIPlugin; import org.eclipse.debug.ui.IDebugUIConstants; import org.eclipse.jface.action.IAction; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.dialogs.MessageDialogWithToggle; import org.eclipse.jface.viewers.ISelection; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.IWorkbenchWindowActionDelegate; import org.eclipse.ui.PlatformUI; import com.mobilesorcery.sdk.core.IBuildResult; import com.mobilesorcery.sdk.core.IBuildSession; import com.mobilesorcery.sdk.core.IBuildVariant; import com.mobilesorcery.sdk.core.MoSyncBuilder; import com.mobilesorcery.sdk.core.MoSyncProject; import com.mobilesorcery.sdk.core.MoSyncTool; import com.mobilesorcery.sdk.profiles.IProfile; import com.mobilesorcery.sdk.ui.MosyncUIPlugin; import com.mobilesorcery.sdk.ui.targetphone.ITargetPhone; import com.mobilesorcery.sdk.ui.targetphone.ITargetPhoneTransport; import com.mobilesorcery.sdk.ui.targetphone.TargetPhonePlugin; import com.mobilesorcery.sdk.ui.targetphone.TargetPhoneTransportEvent; import com.mobilesorcery.sdk.ui.targetphone.internal.bt.BTTargetPhone; public class SendToTargetPhoneAction implements IWorkbenchWindowActionDelegate { class SendToTargetJob extends Job { private final ITargetPhone phone; private final MoSyncProject project; public SendToTargetJob(MoSyncProject project, ITargetPhone phone) { super(""); this.project = project; this.phone = phone; setRule(project.getWrappedProject()); setName(createProgressMessage(project, phone)); } private String createProgressMessage(MoSyncProject project, ITargetPhone phone) { if (project == null || phone == null) { return "Send to target"; } else { return MessageFormat.format("Send {0} to target {1} for profile {2}", project == null ? "?" : project.getName(), phone == null ? "?" : phone.getName(), MoSyncTool.toString(getProfile(project, phone))); } } private IProfile getProfile(MoSyncProject project, ITargetPhone phone) { IProfile targetProfile = phone == null ? null : phone.getPreferredProfile(project.getProfileManagerType()); return targetProfile; } @Override protected IStatus run(IProgressMonitor monitor) { ITargetPhone phone = this.phone; int workUnits = phone == null ? 4 : 3; monitor.beginTask(createProgressMessage(project, phone), workUnits); try { assertNotNull(project, "No project selected"); // No API for this. String savePref = DebugUIPlugin.getDefault().getPreferenceStore().getString(IDebugUIConstants.PLUGIN_ID + ".save_dirty_editors_before_launch"); if (!MessageDialogWithToggle.NEVER.equals(savePref)) { boolean confirm = MessageDialogWithToggle.PROMPT.equals(savePref); if (!MoSyncBuilder.saveAllEditors(project.getWrappedProject(), true, confirm)) { return Status.CANCEL_STATUS; } } int profileManagerType = project.getProfileManagerType(); if (phone == null || phone.getPreferredProfile(profileManagerType) == null) { SubProgressMonitor subMonitor = new SubProgressMonitor( monitor, 1); phone = SelectTargetPhoneAction.selectPhone(phone, profileManagerType, window, subMonitor); } if (phone != null) { IProfile targetProfile = getProfile(project, phone); assertNotNull(targetProfile, "No target profile selected"); IBuildVariant variant = MoSyncBuilder.createVariant(project, targetProfile); ITargetPhoneTransport transport = phone.getTransport(); TargetPhonePlugin.getDefault().notifyListeners(new TargetPhoneTransportEvent(TargetPhoneTransportEvent.PRE_SEND, phone, project, variant)); File packageToSend = buildBeforeSend(variant, monitor); if (monitor.isCanceled()) { return Status.CANCEL_STATUS; } transport.send(window, project, variant, phone, packageToSend, new SubProgressMonitor(monitor, 4)); } } catch (CoreException e) { return e.getStatus(); } return Status.OK_STATUS; } private void assertNotNull(Object o, String msgIfNull) throws CoreException { if (o == null) { throw new CoreException(new Status(IStatus.ERROR, TargetPhonePlugin.PLUGIN_ID, msgIfNull)); } } private File buildBeforeSend(IBuildVariant variant, IProgressMonitor monitor) throws CoreException { IBuildResult buildResult = null; IBuildSession session = MoSyncBuilder.createDefaultBuildSession(variant); buildResult = new MoSyncBuilder().build(project .getWrappedProject(), session, variant, null, new SubProgressMonitor(monitor, 1)); monitor.worked(1); Map<String, List<File>> buildArtifacts = buildResult.getBuildResult(); List<File> fileToSend = buildArtifacts == null ? null : buildResult.getBuildResult().get(IBuildResult.MAIN); if (fileToSend != null && !fileToSend.isEmpty()) { return fileToSend.get(0); } if (!monitor.isCanceled()) { throw new CoreException(new Status(IStatus.ERROR, TargetPhonePlugin.PLUGIN_ID, "Could not build for device: no executable app was built")); } return null; } } private static MoSyncProject lastSelected; private IAction action; private ISelection selection; IWorkbenchWindow window; @Override public void dispose() { } @Override public void init(IWorkbenchWindow window) { this.window = window; } @Override public void run(IAction action) { ITargetPhone phone = TargetPhonePlugin.getDefault() .getCurrentlySelectedPhone(); MoSyncProject project = MosyncUIPlugin.getDefault() .getCurrentlySelectedProject( PlatformUI.getWorkbench().getActiveWorkbenchWindow()); SendToTargetJob job = new SendToTargetJob(project, phone); job.setUser(true); job.schedule(); } /** * Sends the build result to the target phone CURRENTLY NOT USED */ public void sendTo(final BTTargetPhone phone) { if (phone != null) { Job job = new Job("Send to target") { @Override public IStatus run(IProgressMonitor monitor) { IPath mobex = MoSyncTool.getDefault().getBinary("mobex"); MoSyncProject project = MosyncUIPlugin.getDefault() .getCurrentlySelectedProject(window); // project.get IProfile currentProfile = project.getTargetProfile(); int result = 0; if (project != null) { String[] commandLine = getCommandLine(mobex, "", phone); try { Process process = Runtime.getRuntime().exec( commandLine); result = process.waitFor(); } catch (Exception e) { result = -1; } } return result == 0 ? Status.OK_STATUS : new Status( Status.ERROR, TargetPhonePlugin.PLUGIN_ID, "Could not send to phone"); } }; } } private String[] getCommandLine(IPath mobex, String fileToSend, BTTargetPhone phone) { return new String[] { mobex.toFile().getAbsolutePath(), fileToSend, phone.getAddress(), Integer.toString(phone.getPort()) }; } @Override public void selectionChanged(IAction action, ISelection selection) { this.action = action; this.selection = selection; } }