/*
* Copyright (c) 2012, the Dart project authors.
*
* Licensed under the Eclipse Public License v1.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.eclipse.org/legal/epl-v10.html
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.dart.tools.debug.ui.internal.util;
import com.google.dart.tools.core.DartCore;
import com.google.dart.tools.core.analysis.model.LightweightModel;
import com.google.dart.tools.debug.core.DartLaunchConfigWrapper;
import com.google.dart.tools.debug.ui.internal.DartUtil;
import org.apache.commons.lang3.ObjectUtils;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationType;
import org.eclipse.debug.ui.DebugUITools;
import org.eclipse.debug.ui.IDebugModelPresentation;
import org.eclipse.debug.ui.ILaunchShortcut2;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.window.Window;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.ElementListSelectionDialog;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* An abstract parent of Dart launch shortcuts.
*/
public abstract class AbstractLaunchShortcut implements ILaunchShortcut2 {
private String launchTypeLabel;
/**
* Create a new AbstractLaunchShortcut.
*
* @param launchTypeLabel
*/
public AbstractLaunchShortcut(String launchTypeLabel) {
this.launchTypeLabel = launchTypeLabel;
}
public ILaunchConfiguration[] getAssociatedLaunchConfigurations(IResource resource) {
List<ILaunchConfiguration> results = new ArrayList<ILaunchConfiguration>();
try {
ILaunchConfiguration[] configs = DebugPlugin.getDefault().getLaunchManager().getLaunchConfigurations(
getConfigurationType());
if (resource != null) {
for (int i = 0; i < configs.length; i++) {
ILaunchConfiguration config = configs[i];
if (testSimilar(resource, config)) {
results.add(config);
}
}
}
} catch (CoreException e) {
DartUtil.logError(e);
}
return results.toArray(new ILaunchConfiguration[results.size()]);
}
@Override
public final IResource getLaunchableResource(IEditorPart editor) {
IResource resource = (IResource) editor.getEditorInput().getAdapter(IResource.class);
if (resource != null) {
return getLaunchableResource(resource);
}
return null;
}
@Override
public final IResource getLaunchableResource(ISelection selection) {
if (!(selection instanceof IStructuredSelection)) {
return null;
}
Object obj = ((IStructuredSelection) selection).getFirstElement();
IResource resource;
if (obj instanceof IResource) {
resource = (IResource) obj;
} else if (obj instanceof IAdaptable) {
resource = (IResource) ((IAdaptable) obj).getAdapter(IResource.class);
} else {
resource = null;
}
return getLaunchableResource(resource);
}
@Override
public final ILaunchConfiguration[] getLaunchConfigurations(IEditorPart editorpart) {
// let the framework resolve configurations based on resource mapping
return null;
}
@Override
public final ILaunchConfiguration[] getLaunchConfigurations(ISelection selection) {
// let the framework resolve configurations based on resource mapping
return null;
}
@Override
public final void launch(IEditorPart editor, String mode) {
IResource resource = (IResource) editor.getEditorInput().getAdapter(IResource.class);
if (resource != null) {
resource = getLaunchableResource(resource);
if (resource != null) {
launch(resource, mode);
return;
}
}
MessageDialog.openWarning(
null,
"Error Launching " + launchTypeLabel,
"Unable to locate launchable resource.");
}
@Override
public final void launch(ISelection selection, String mode) {
IResource resource = getLaunchableResource(selection);
if (resource != null) {
launch(resource, mode);
return;
}
MessageDialog.openWarning(
null,
"Error Launching " + launchTypeLabel,
"Unable to locate associated html file");
}
@Override
public String toString() {
return getClass().getSimpleName();
}
/**
* Returns a configuration from the given collection of configurations that should be launched, or
* <code>null</code> to cancel. Default implementation opens a selection dialog that allows the
* user to choose one of the specified launch configurations. Returns the chosen configuration, or
* <code>null</code> if the user cancels.
*
* @param configList list of configurations to choose from
* @return configuration to launch or <code>null</code> to cancel
*/
protected ILaunchConfiguration chooseConfiguration(List<ILaunchConfiguration> configList) {
IDebugModelPresentation labelProvider = DebugUITools.newDebugModelPresentation();
ElementListSelectionDialog dialog = new ElementListSelectionDialog(
PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(),
labelProvider);
dialog.setElements(configList.toArray());
dialog.setTitle("Select Dart Application");
dialog.setMessage("&Select existing configuration:");
dialog.setMultipleSelection(false);
int result = dialog.open();
labelProvider.dispose();
if (result == Window.OK) {
return (ILaunchConfiguration) dialog.getFirstResult();
}
return null;
}
/**
* Find the launch configuration associated with the specified resource
*
* @param resource the resource
* @return the launch configuration or <code>null</code> if none
*/
protected final ILaunchConfiguration findConfig(IResource resource)
throws OperationCanceledException {
List<ILaunchConfiguration> candidateConfigs = Arrays.asList(getAssociatedLaunchConfigurations(resource));
int candidateCount = candidateConfigs.size();
if (candidateCount == 1) {
return candidateConfigs.get(0);
} else if (candidateCount > 1) {
ILaunchConfiguration result = chooseConfiguration(candidateConfigs);
if (result != null) {
return result;
} else {
throw new OperationCanceledException();
}
}
return null;
}
/**
* @return the launch configuration type for this launch shortcut
*/
protected abstract ILaunchConfigurationType getConfigurationType();
/**
* Answer the resource associated with the Dart application to be launched relative to the
* specified resource.
*
* @param originalResource the original resource or <code>null</code>
* @return the Dart resource to be launched or <code>null</code>
*/
protected IResource getLaunchableResource(Object originalResource) {
if (originalResource == null) {
return null;
}
if (originalResource instanceof IResource) {
IResource resource = (IResource) originalResource;
if (!resource.isAccessible()) {
return null;
}
return getPrimaryLaunchTarget(resource);
}
return null;
}
/**
* Checks if given resource is part of/is library that can be run on browser
*/
protected boolean isBrowserApplication(IResource resource) {
if (getPrimaryLaunchTarget(resource) != null) {
return true;
}
return false;
}
/**
* Find or create and launch the given resource.
*
* @param resource
* @param mode
*/
protected abstract void launch(IResource resource, String mode);
/**
* Return whether the launch configuration is used to launch the given resource.
*
* @param resource
* @param config
* @return whether the launch configuration is used to launch the given resource
*/
@SuppressWarnings("deprecation")
protected boolean testSimilar(IResource resource, ILaunchConfiguration config) {
DartLaunchConfigWrapper launchWrapper = new DartLaunchConfigWrapper(config);
IResource appResource = launchWrapper.getApplicationResource();
if (ObjectUtils.equals(appResource, resource)) {
return true;
}
return false;
}
private IResource getPrimaryLaunchTarget(IResource resource) {
// Html files are always launchable.
if (DartCore.isHtmlLikeFileName(resource.getName())) {
return resource;
}
LightweightModel model = LightweightModel.getModel();
if (resource instanceof IContainer) {
List<IFile> targets = model.getHtmlLaunchTargets((IContainer) resource);
if (targets.size() > 0) {
return targets.get(0);
}
} else {
IFile file = (IFile) resource;
if (model.isClientLibrary(file)) {
return model.getHtmlFileForLibrary(file);
} else {
IFile containingLib = model.getContainingLibrary(file);
if (containingLib != null && model.isClientLibrary(containingLib)) {
return model.getHtmlFileForLibrary(containingLib);
}
}
}
return null;
}
}