//
// This file is part of the Prose Development Tools for Eclipse package.
//
// The contents of this file are subject to the Mozilla Public License
// Version 1.1 (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.mozilla.org/MPL/
//
// Software distributed under the License is distributed on an "AS IS" basis,
// WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
// for the specific language governing rights and limitations under the
// License.
//
// The Original Code is Prose Development Tools for Eclipse.
//
// The Initial Developer of the Original Code is Angela Nicoara. Portions
// created by Angela Nicoara are Copyright (C) 2006 Angela Nicoara.
// All Rights Reserved.
//
// Contributor(s):
// $Id: ProseMainTab.java,v 1.1 2008/11/18 12:18:41 anicoara Exp $
// ==============================================================================
//
package ch.ethz.prose.eclipse.internal.launcher;
import java.lang.reflect.InvocationTargetException;
import java.text.MessageFormat;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.jdt.core.IClassFile;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaModel;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IMember;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.search.IJavaSearchScope;
import org.eclipse.jdt.core.search.SearchEngine;
import org.eclipse.jdt.internal.debug.ui.launcher.SharedJavaMainTab;
import org.eclipse.jdt.internal.ui.util.MainMethodSearchEngine;
import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants;
import org.eclipse.jdt.ui.IJavaElementSearchConstants;
import org.eclipse.jdt.ui.JavaElementLabelProvider;
import org.eclipse.jdt.ui.JavaUI;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.dialogs.ElementListSelectionDialog;
import org.eclipse.ui.dialogs.SelectionDialog;
import ch.ethz.prose.eclipse.internal.core.ProsePlugin;
/**
* Launch configuration tab for Prose applications.
*
* @author Angela Nicoara
* @author Johann Gyger
* @version $Id: ProseMainTab.java,v 1.1 2008/11/18 12:18:41 anicoara Exp $
*/
public class ProseMainTab extends SharedJavaMainTab {
// Project widgets
protected Text fProjText;
protected Button fProjButton;
// Main class widgets
protected Text fMainText;
protected Button fSearchButton;
// Server widgets
protected Button fLaunchServerButton;
protected static final String EMPTY_STRING = ""; //$NON-NLS-1$
/* (non-Javadoc)
* @see org.eclipse.debug.ui.ILaunchConfigurationTab#createControl(org.eclipse.swt.widgets.Composite)
*/
public void createControl(Composite parent) {
Font font = parent.getFont();
Composite comp = new Composite(parent, SWT.NONE);
setControl(comp);
GridLayout topLayout = new GridLayout();
topLayout.verticalSpacing = 0;
topLayout.numColumns = 3;
comp.setLayout(topLayout);
comp.setFont(font);
createVerticalSpacer(comp, 3);
createProjectWidgets(comp);
createVerticalSpacer(comp, 3);
createMainClassWidgets(comp);
createVerticalSpacer(comp, 3);
createServerWidgets(comp);
Dialog.applyDialogFont(comp);
}
protected void createProjectWidgets(Composite comp) {
Label projLabel = new Label(comp, SWT.NONE);
projLabel.setText("Project:");
GridData gd = new GridData();
projLabel.setLayoutData(gd);
fProjText = new Text(comp, SWT.SINGLE | SWT.BORDER);
gd = new GridData(GridData.FILL_HORIZONTAL);
fProjText.setLayoutData(gd);
fProjText.addModifyListener(new ModifyListener() {
public void modifyText(ModifyEvent e) {
updateLaunchConfigurationDialog();
}
});
fProjButton = createPushButton(comp, "Browse...", null);
fProjButton.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent evt) {
handleProjectButtonSelected();
}
});
}
/**
* Show a dialog that lets the user select a project. This in turn provides
* context for the main type, allowing the user to key a main type name, or
* constraining the search for main types to the specified project.
*/
protected void handleProjectButtonSelected() {
IJavaProject project = chooseJavaProject();
if (project == null) { return; }
String projectName = project.getElementName();
fProjText.setText(projectName);
}
/**
* Realize a Java project selection dialog.
*
* @return First selected project, or <code>null</code> if ther was none
*/
protected IJavaProject chooseJavaProject() {
IJavaProject[] projects;
try {
projects = JavaCore.create(getWorkspaceRoot()).getJavaProjects();
} catch (JavaModelException e) {
ProsePlugin.log(e.getStatus());
projects = new IJavaProject[0];
}
ILabelProvider labelProvider = new JavaElementLabelProvider(JavaElementLabelProvider.SHOW_DEFAULT);
ElementListSelectionDialog dialog = new ElementListSelectionDialog(getShell(), labelProvider);
dialog.setTitle("Project Selection");
dialog.setMessage("Choose a project to constrain the search for main types:");
dialog.setElements(projects);
IJavaProject javaProject = getJavaProject();
if (javaProject != null) {
dialog.setInitialSelections(new Object[] { javaProject});
}
if (dialog.open() == ElementListSelectionDialog.OK) { return (IJavaProject) dialog.getFirstResult(); }
return null;
}
/**
* @return Java project corresponding to the project name in the project
* name text field, or <code>null</code> if the text does not match a project name.
*/
protected IJavaProject getJavaProject() {
String projectName = fProjText.getText().trim();
if (projectName.length() < 1) { return null; }
return getJavaModel().getJavaProject(projectName);
}
protected void createMainClassWidgets(Composite comp) {
Label mainLabel = new Label(comp, SWT.NONE);
mainLabel.setText("Main class:");
GridData gd = new GridData();
mainLabel.setLayoutData(gd);
fMainText = new Text(comp, SWT.SINGLE | SWT.BORDER);
gd = new GridData(GridData.FILL_HORIZONTAL);
fMainText.setLayoutData(gd);
fMainText.addModifyListener(new ModifyListener() {
public void modifyText(ModifyEvent e) {
updateLaunchConfigurationDialog();
}
});
fSearchButton = createPushButton(comp, "Search...", null);
fSearchButton.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent evt) {
handleSearchButtonSelected();
}
});
}
/**
* Show a dialog that lists all main types.
*/
protected void handleSearchButtonSelected() {
IJavaProject javaProject = getJavaProject();
IJavaSearchScope searchScope = null;
if ((javaProject == null) || !javaProject.exists()) {
searchScope = SearchEngine.createWorkspaceScope();
} else {
searchScope = SearchEngine.createJavaSearchScope(new IJavaElement[] { javaProject}, false);
}
int constraints = IJavaElementSearchConstants.CONSIDER_BINARIES;
MainMethodSearchEngine engine = new MainMethodSearchEngine();
IType[] types = null;
try {
types = engine.searchMainMethods(getLaunchConfigurationDialog(), searchScope, constraints);
} catch (InvocationTargetException e) {
setErrorMessage(e.getMessage());
return;
} catch (InterruptedException e) {
setErrorMessage(e.getMessage());
return;
}
SelectionDialog dialog;
try {
dialog = JavaUI.createTypeDialog(
getShell(),
getLaunchConfigurationDialog(),
SearchEngine.createJavaSearchScope(types),
IJavaElementSearchConstants.CONSIDER_CLASSES,
false,
"**");
} catch (JavaModelException e) {
setErrorMessage(e.getMessage());
return;
}
dialog.setTitle("Choose Main Type");
dialog.setMessage("Choose Main Type");
if (dialog.open() == Window.CANCEL) { return; }
Object[] results = dialog.getResult();
if ((results == null) || (results.length < 1)) { return; }
IType type = (IType) results[0];
if (type != null) {
fMainText.setText(type.getFullyQualifiedName());
javaProject = type.getJavaProject();
fProjText.setText(javaProject.getElementName());
}
}
protected void createServerWidgets(Composite comp) {
fLaunchServerButton = new Button(comp, SWT.CHECK);
fLaunchServerButton.addSelectionListener(new SelectionListener() {
public void widgetSelected(SelectionEvent e) {
updateLaunchConfigurationDialog();
}
public void widgetDefaultSelected(SelectionEvent e) {
}
});
fLaunchServerButton.setText("Launch server component");
GridData gd = new GridData();
gd.horizontalAlignment = GridData.FILL;
gd.horizontalSpan = 3;
fLaunchServerButton.setLayoutData(gd);
}
/* (non-Javadoc)
* @see org.eclipse.debug.ui.ILaunchConfigurationTab#setDefaults(org.eclipse.debug.core.ILaunchConfigurationWorkingCopy)
*/
public void setDefaults(ILaunchConfigurationWorkingCopy config) {
IJavaElement javaElement = getContext();
if (javaElement != null) {
initializeJavaProject(javaElement, config);
} else {
// We set empty attributes for project & main type so that when one config is
// compared to another, the existence of empty attributes doesn't cause an
// incorrect result (the performApply() method can result in empty values
// for these attributes being set on a config if there is nothing in the
// corresponding text boxes)
config.setAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, ""); //$NON-NLS-1$
}
initializeMainTypeAndName(javaElement, config);
}
/**
* Set the main type & name attributes on the working copy based on the IJavaElement.
*
* @param javaElement Java element
* @param config Launch configuration
*/
protected void initializeMainTypeAndName(IJavaElement javaElement, ILaunchConfigurationWorkingCopy config) {
String name = null;
if (javaElement instanceof IMember) {
IMember member = (IMember) javaElement;
if (member.isBinary()) {
javaElement = member.getClassFile();
} else {
javaElement = member.getCompilationUnit();
}
}
if (javaElement instanceof ICompilationUnit || javaElement instanceof IClassFile) {
try {
IJavaSearchScope scope = SearchEngine.createJavaSearchScope(new IJavaElement[] { javaElement}, false);
MainMethodSearchEngine engine = new MainMethodSearchEngine();
IType[] types = engine.searchMainMethods(getLaunchConfigurationDialog(), scope,
IJavaElementSearchConstants.CONSIDER_BINARIES | IJavaElementSearchConstants.CONSIDER_EXTERNAL_JARS);
if (types != null && (types.length > 0)) {
// Simply grab the first main type found in the searched
// element
name = types[0].getFullyQualifiedName();
}
} catch (InterruptedException ie) {
} catch (InvocationTargetException ite) {
}
}
if (name == null) {
name = ""; //$NON-NLS-1$
}
config.setAttribute(IJavaLaunchConfigurationConstants.ATTR_MAIN_TYPE_NAME, name);
if (name.length() > 0) {
int index = name.lastIndexOf('.');
if (index > 0) {
name = name.substring(index + 1);
}
name = getLaunchConfigurationDialog().generateName(name);
config.rename(name);
}
}
/* (non-Javadoc)
* @see org.eclipse.debug.ui.ILaunchConfigurationTab#initializeFrom(org.eclipse.debug.core.ILaunchConfiguration)
*/
public void initializeFrom(ILaunchConfiguration config) {
updateProjectFromConfig(config);
updateMainTypeFromConfig(config);
updateServerFromConfig(config);
}
protected void updateProjectFromConfig(ILaunchConfiguration config) {
String projectName = EMPTY_STRING;
try {
projectName = config.getAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, EMPTY_STRING);
} catch (CoreException ce) {
ProsePlugin.log(ce);
}
fProjText.setText(projectName);
}
protected void updateMainTypeFromConfig(ILaunchConfiguration config) {
String mainTypeName = EMPTY_STRING;
try {
mainTypeName = config.getAttribute(IJavaLaunchConfigurationConstants.ATTR_MAIN_TYPE_NAME, EMPTY_STRING);
} catch (CoreException ce) {
ProsePlugin.log(ce);
}
fMainText.setText(mainTypeName);
}
protected void updateServerFromConfig(ILaunchConfiguration config) {
boolean launchServer = true;
try {
launchServer = config.getAttribute(ProseLaunchConfiguration.ATTR_LAUNCH_PROSE_SERVER, true);
} catch (CoreException ce) {
ProsePlugin.log(ce);
}
fLaunchServerButton.setSelection(launchServer);
}
/* (non-Javadoc)
* @see org.eclipse.debug.ui.ILaunchConfigurationTab#performApply(org.eclipse.debug.core.ILaunchConfigurationWorkingCopy)
*/
public void performApply(ILaunchConfigurationWorkingCopy config) {
config.setAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, fProjText.getText());
config.setAttribute(IJavaLaunchConfigurationConstants.ATTR_MAIN_TYPE_NAME, fMainText.getText());
config.setAttribute(ProseLaunchConfiguration.ATTR_LAUNCH_PROSE_SERVER, fLaunchServerButton.getSelection());
}
/* (non-Javadoc)
* @see org.eclipse.debug.ui.ILaunchConfigurationTab#getName()
*/
public String getName() {
return "Prose";
}
/* (non-Javadoc)
* @see org.eclipse.debug.ui.ILaunchConfigurationTab#isValid(org.eclipse.debug.core.ILaunchConfiguration)
*/
public boolean isValid(ILaunchConfiguration config) {
setErrorMessage(null);
setMessage(null);
String name = fProjText.getText().trim();
if (name.length() > 0) {
IWorkspace workspace = ResourcesPlugin.getWorkspace();
IStatus status = workspace.validateName(name, IResource.PROJECT);
if (status.isOK()) {
IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(name);
if (!project.exists()) {
setErrorMessage(MessageFormat.format("Project {0} does not exist", new String[] { name}));
return false;
}
if (!project.isOpen()) {
setErrorMessage(MessageFormat.format("Project {0} is closed", new String[] { name}));
return false;
}
} else {
setErrorMessage(MessageFormat.format("Illegal project name: {0}", new String[] { status.getMessage()}));
return false;
}
}
name = fMainText.getText().trim();
if (name.length() == 0) {
setErrorMessage("Main type not specified"); //$NON-NLS-1$
return false;
}
return true;
}
/**
* Convenience method to get access to the Java model.
*
* @return Java model
*/
private IJavaModel getJavaModel() {
return JavaCore.create(getWorkspaceRoot());
}
}