blob: 815e52e6854c833853e0168633f2f67b3a1c312c [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2006 IBM Corporation and others.
* 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
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jdt.internal.ui.wizards.buildpaths.newsourcepage;
import java.util.List;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IResource;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.window.Window;
import org.eclipse.ui.dialogs.NewFolderDialog;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.internal.corext.util.Messages;
import org.eclipse.jdt.ui.PreferenceConstants;
import org.eclipse.jdt.ui.wizards.BuildPathDialogAccess;
import org.eclipse.jdt.internal.ui.JavaPlugin;
import org.eclipse.jdt.internal.ui.wizards.NewWizardMessages;
import org.eclipse.jdt.internal.ui.wizards.buildpaths.CPListElement;
import org.eclipse.jdt.internal.ui.wizards.buildpaths.ExclusionInclusionDialog;
import org.eclipse.jdt.internal.ui.wizards.buildpaths.OutputLocationDialog;
/**
* Helper class for queries used by the <code>ClasspathModifier</code>.
* Clients can either decide to implement their own queries or just taking
* the predefined queries.
*/
public class ClasspathModifierQueries {
/**
* A validator for the output location that can be
* used to find out whether the entred location can be
* used for an output folder or not.
*/
public static abstract class OutputFolderValidator {
protected IClasspathEntry[] fEntries;
protected List fElements;
/**
* Create a output folder validator.
*
* @param newElements a list of elements that will be added
* to the buildpath. The list's items can be of type:
* <li><code>IJavaProject</code></li>
* <li><code>IPackageFragment</code></li>
* <li><code>IFolder</code></li>
* @param project the Java project
* @throws JavaModelException
*/
public OutputFolderValidator(List newElements, IJavaProject project) throws JavaModelException {
fEntries= project.getRawClasspath();
fElements= newElements;
}
/**
* The path of the output location to be validated. The path
* should contain the full path within the project, for example:
* /ProjectXY/folderA/outputLocation.
*
* @param outputLocation the output location for the project
* @return <code>true</code> if the output location is valid,
* <code>false</code> otherwise.
*/
public abstract boolean validate(IPath outputLocation);
}
/**
* Query that processes the request of
* creating a link to an existing source
* folder.
*/
public static interface ILinkToQuery {
/**
* Query that processes the request of
* creating a link to an existing source
* folder.
*
* @return <code>true</code> if the query was
* executed successfully (that is the result of
* this query can be used), <code>false</code>
* otherwise
*/
public boolean doQuery();
/**
* Get the newly created folder.
* This method is only valid after having
* called <code>doQuery</code>.
*
* @return the created folder of type
* <code>IFolder</code>
*/
public IFolder getCreatedFolder();
/**
* Getter for an output folder query.
*
* @return an output folder query which will be needed
* when adding the folder to the build path
*
* @see OutputFolderQuery
*/
public OutputFolderQuery getOutputFolderQuery();
}
/**
* Query to get information about whether the project should be removed as
* source folder and update build folder to <code>outputLocation</code>
*/
public static abstract class OutputFolderQuery {
protected IPath fDesiredOutputLocation;
/**
* Constructor gets the desired output location
* of the project
*
* @param outputLocation desired output location for the
* project. It is possible that the desired output location
* equals the current project's output location (for example if
* it is not intended to change the output location at this time).
*/
public OutputFolderQuery(IPath outputLocation) {
if (outputLocation != null)
fDesiredOutputLocation= outputLocation.makeAbsolute();
}
/**
* Getter for the desired output location.
*
* @return the project's desired output location
*/
public IPath getDesiredOutputLocation() {
return fDesiredOutputLocation;
}
/**
* Get the output location that was determined by the
* query for the project. Note that this output location
* does not have to be the same as the desired output location
* that is passed to the constructor.
*
* This method is only intended to be called if <code>doQuery</code>
* has been executed successfully and had return <code>true</code> to
* indicate that changes were accepted.
*
*@return the effective output location
*/
public abstract IPath getOutputLocation();
/**
* Find out wheter the project should be removed from the classpath
* or not.
*
* This method is only intended to be called if <code>doQuery</code>
* has been executed successfully and had return <code>true</code> to
* indicate that changes were accepted.
*
* @return <code>true</code> if the project should be removed from
* the classpath, <code>false</code> otherwise.
*/
public abstract boolean removeProjectFromClasspath();
/**
* Query to get information about whether the project should be removed as
* source folder and update build folder to <code>outputLocation</code>.
*
* There are several situations for setting up a project where it is not possible
* to have the project folder itself as output folder. Therefore, the query asks in the
* first place for changing the output folder. Additionally, it also can be usefull to
* remove the project from the classpath. This information can be retrieved by calling
* <code>removeProjectFromClasspath()</code>.
*
* Note: if <code>doQuery</code> returns false, the started computation will stop immediately.
* There is no additional dialog that informs the user about this abort. Therefore it is important
* that the query informs the users about the consequences of not allowing to change the output
* folder.
*
* @param editingOutputFolder <code>true</code> if currently an output folder is changed,
* <code>false</code> otherwise. This information can be usefull to generate an appropriate
* message to ask the user for an action.
* @param validator a validator to find out whether the chosen output location is valid or not
* @param project the Java project
* @return <code>true</code> if the execution was successfull (e.g. not aborted) and
* the caller should execute additional steps as setting the output location for the project or (optionally)
* removing the project from the classpath, <code>false</code> otherwise.
* @throws JavaModelException if the output location of the project could not be retrieved
*/
public abstract boolean doQuery(final boolean editingOutputFolder, final OutputFolderValidator validator, final IJavaProject project) throws JavaModelException;
}
/**
* Query to get information about the inclusion and exclusion filters of
* an element.
*/
public static interface IInclusionExclusionQuery {
/**
* Query to get information about the
* inclusion and exclusion filters of
* an element.
*
* While executing <code>doQuery</code>,
* these filter might change.
*
* On calling <code>getInclusionPattern()</code>
* or <code>getExclusionPattern()</code> it
* is expected to get the new and updated
* filters back.
*
* @param element the element to get the
* information from
* @param focusOnExcluded
* @return <code>true</code> if changes
* have been accepted and <code>getInclusionPatter</code>
* or <code>getExclusionPattern</code> can
* be called.
*/
public boolean doQuery(CPListElement element, boolean focusOnExcluded);
/**
* Can only be called after <code>
* doQuery</code> has been executed and
* has returned <code>true</code>
*
* @return the new inclusion filters
*/
public IPath[] getInclusionPattern();
/**
* Can only be called after <code>
* doQuery</code> has been executed and
* has returned <code>true</code>
*
* @return the new exclusion filters
*/
public IPath[] getExclusionPattern();
}
/**
* Query to get information about the output location that should be used for a
* given element.
*/
public static interface IOutputLocationQuery {
/**
* Query to get information about the output
* location that should be used for a
* given element.
*
* @param element the element to get
* an output location for
* @return <code>true</code> if the output
* location has changed, <code>false</code>
* otherwise.
*/
public boolean doQuery(CPListElement element);
/**
* Gets the new output location.
*
* May only be called after having
* executed <code>doQuery</code> which
* must have returned <code>true</code>
*
* @return the new output location, can be <code>null</code>
*/
public IPath getOutputLocation();
/**
* Get a query for information about whether the project should be removed as
* source folder and update build folder
*
* @param outputLocation desired output location for the
* project
* @return query giving information about output and source folders
* @throws JavaModelException
*
* @see OutputFolderQuery
*/
public OutputFolderQuery getOutputFolderQuery(IPath outputLocation) throws JavaModelException;
}
/**
* Query to determine whether a linked folder should be removed.
*/
public static interface IRemoveLinkedFolderQuery {
/** Remove status indicating that the removal should be cancelled */
public static final int REMOVE_CANCEL= 0;
/** Remove status indicating that the folder should be removed from the build path only */
public static final int REMOVE_BUILD_PATH= 1;
/** Remove status indicating that the folder should be removed from the build path and deleted */
public static final int REMOVE_BUILD_PATH_AND_FOLDER= 2;
/**
* Query to determined whether the linked folder should be removed as well.
*
* @param folder the linked folder to remove
* @return a status code corresponding to one of the IRemoveLinkedFolderQuery#REMOVE_XXX constants
*/
public int doQuery(IFolder folder);
}
/**
* Query to create a folder.
*/
public static interface ICreateFolderQuery {
/**
* Query to create a folder.
*
* @return <code>true</code> if the operation
* was successful (e.g. no cancelled), <code>
* false</code> otherwise
*/
public boolean doQuery();
/**
* Find out whether a source folder is about
* to be created or a normal folder which
* is not on the classpath (and therefore
* might have to be excluded).
*
* Should only be called after having executed
* <code>doQuery</code>, because otherwise
* it might not be sure if a result exists or
* not.
*
* @return <code>true</code> if a source
* folder should be created, <code>false
* </code> otherwise
*/
public boolean isSourceFolder();
/**
* Get the newly created folder.
* This method is only valid after having
* called <code>doQuery</code>.
*
* @return the created folder of type
* <code>IFolder</code>
*/
public IFolder getCreatedFolder();
}
/**
* Query to add archives (.jar or .zip files) to the buildpath.
*/
public static interface IAddArchivesQuery {
/**
* Get the paths to the new archive entries that should be added to the buildpath.
*
* @return Returns the new classpath container entry paths or an empty array if the query has
* been cancelled by the user.
*/
public IPath[] doQuery();
}
/**
* Query to add libraries to the buildpath.
*/
public static interface IAddLibrariesQuery {
/**
* Get the new classpath entries for libraries to be added to the buildpath.
*
* @param project the Java project
* @param entries an array of classpath entries for the project
* @return Returns the selected classpath container entries or an empty if the query has
* been cancelled by the user.
*/
public IClasspathEntry[] doQuery(final IJavaProject project, final IClasspathEntry[] entries);
}
/**
* The query is used to get information about whether the project should be removed as
* source folder and update build folder to <code>outputLocation</code>
*
* @param shell shell if there is any or <code>null</code>
* @param outputLocation the desired project's output location
* @return an <code>IOutputFolderQuery</code> that can be executed
*
* @see OutputFolderQuery
* @see org.eclipse.jdt.internal.corext.buildpath.AddSelectedSourceFolderOperation
*/
public static OutputFolderQuery getDefaultFolderQuery(final Shell shell, IPath outputLocation) {
return new OutputFolderQuery(outputLocation) {
protected IPath fOutputLocation;
protected boolean fRemoveProject;
public boolean doQuery(final boolean editingOutputFolder, final OutputFolderValidator validator, final IJavaProject project) throws JavaModelException {
final boolean[] result= { false };
fRemoveProject= false;
fOutputLocation= project.getOutputLocation();
Display.getDefault().syncExec(new Runnable() {
public void run() {
Shell sh= shell != null ? shell : JavaPlugin.getActiveWorkbenchShell();
String title= NewWizardMessages.ClasspathModifier_ChangeOutputLocationDialog_title;
if (fDesiredOutputLocation.segmentCount() == 1) {
String outputFolderName= PreferenceConstants.getPreferenceStore().getString(PreferenceConstants.SRCBIN_BINNAME);
IPath newOutputFolder= fDesiredOutputLocation.append(outputFolderName);
newOutputFolder= getValidPath(newOutputFolder, validator);
String message= Messages.format(NewWizardMessages.ClasspathModifier_ChangeOutputLocationDialog_project_outputLocation, newOutputFolder);
fRemoveProject= true;
if (MessageDialog.openConfirm(sh, title, message)) {
fOutputLocation= newOutputFolder;
result[0]= true;
}
} else {
IPath newOutputFolder= fDesiredOutputLocation;
newOutputFolder= getValidPath(newOutputFolder, validator);
if (editingOutputFolder) {
fOutputLocation= newOutputFolder;
result[0]= true;
return; // show no dialog
}
String message= NewWizardMessages.ClasspathModifier_ChangeOutputLocationDialog_project_message;
fRemoveProject= true;
if (MessageDialog.openQuestion(sh, title, message)) {
fOutputLocation= newOutputFolder;
result[0]= true;
}
}
}
});
return result[0];
}
public IPath getOutputLocation() {
return fOutputLocation;
}
public boolean removeProjectFromClasspath() {
return fRemoveProject;
}
private IPath getValidPath(IPath newOutputFolder, OutputFolderValidator validator) {
int i= 1;
IPath path= newOutputFolder;
while (!validator.validate(path)) {
path= new Path(newOutputFolder.toString() + i);
i++;
}
return path;
}
};
}
/**
* A default query for inclusion and exclusion filters.
* The query is used to get information about the
* inclusion and exclusion filters of an element.
*
* @param shell shell if there is any or <code>null</code>
* @return an <code>IInclusionExclusionQuery</code> that can be executed
*
* @see ClasspathModifierQueries.IInclusionExclusionQuery
* @see org.eclipse.jdt.internal.corext.buildpath.EditFiltersOperation
*/
public static IInclusionExclusionQuery getDefaultInclusionExclusionQuery(final Shell shell) {
return new IInclusionExclusionQuery() {
protected IPath[] fInclusionPattern;
protected IPath[] fExclusionPattern;
public boolean doQuery(final CPListElement element, final boolean focusOnExcluded) {
final boolean[] result= { false };
Display.getDefault().syncExec(new Runnable() {
public void run() {
Shell sh= shell != null ? shell : JavaPlugin.getActiveWorkbenchShell();
ExclusionInclusionDialog dialog= new ExclusionInclusionDialog(sh, element, focusOnExcluded);
result[0]= dialog.open() == Window.OK;
fInclusionPattern= dialog.getInclusionPattern();
fExclusionPattern= dialog.getExclusionPattern();
}
});
return result[0];
}
public IPath[] getInclusionPattern() {
return fInclusionPattern;
}
public IPath[] getExclusionPattern() {
return fExclusionPattern;
}
};
}
/**
* A default query for the output location.
* The query is used to get information about the output location
* that should be used for a given element.
*
* @param shell shell if there is any or <code>null</code>
* @param projectOutputLocation the projects desired output location
* @param classpathList a list of <code>CPListElement</code>s which represents the
* current list of source folders
* @return an <code>IOutputLocationQuery</code> that can be executed
*
* @see ClasspathModifierQueries.IOutputLocationQuery
* @see org.eclipse.jdt.internal.corext.buildpath.CreateOutputFolderOperation
* @see org.eclipse.jdt.internal.corext.buildpath.EditFiltersOperation
*/
public static IOutputLocationQuery getDefaultOutputLocationQuery(final Shell shell, final IPath projectOutputLocation, final List classpathList) {
return new IOutputLocationQuery() {
protected IPath fOutputLocation;
public boolean doQuery(final CPListElement element) {
final boolean[] result= new boolean[1];
Display.getDefault().syncExec(new Runnable() {
public void run() {
Shell sh= shell != null ? shell : JavaPlugin.getActiveWorkbenchShell();
OutputLocationDialog dialog= new OutputLocationDialog(sh, element, classpathList);
result[0]= dialog.open() == Window.OK;
fOutputLocation= dialog.getOutputLocation();
}
});
return result[0];
}
public IPath getOutputLocation() {
return fOutputLocation;
}
public ClasspathModifierQueries.OutputFolderQuery getOutputFolderQuery(IPath p) {
return getDefaultFolderQuery(shell, projectOutputLocation);
}
};
}
/**
* Query to create a linked source folder.
*
* The default query shows a dialog which allows
* the user to specify the new folder that should
* be created.
*
* @param shell shell if there is any or <code>null</code>
* @param project the Java project to create the linked source folder for
* @return an <code>ILinkToQuery</code> showing a dialog
* to create a linked source folder.
*
* @see ClasspathModifierQueries.ICreateFolderQuery
* @see LinkFolderDialog
*/
public static ILinkToQuery getDefaultLinkQuery(final Shell shell, final IJavaProject project, final IPath desiredOutputLocation) {
return new ILinkToQuery() {
protected IFolder fFolder;
public boolean doQuery() {
final boolean[] isOK= {false};
Display.getDefault().syncExec(new Runnable() {
public void run() {
Shell sh= shell != null ? shell : JavaPlugin.getActiveWorkbenchShell();
LinkFolderDialog dialog= new LinkFolderDialog(sh, project.getProject());
isOK[0]= dialog.open() == Window.OK;
if (isOK[0])
fFolder= dialog.getCreatedFolder();
}
});
return isOK[0];
}
public IFolder getCreatedFolder() {
return fFolder;
}
public OutputFolderQuery getOutputFolderQuery() {
return getDefaultFolderQuery(shell, desiredOutputLocation);
}
};
}
/**
* Shows the UI to select new external JAR or ZIP archive entries. If the query
* was aborted, the result is an empty array.
*
* @param shell The parent shell for the dialog, can be <code>null</code>
* @return an <code>IAddArchivesQuery</code> showing a dialog to selected archive files
* to be added to the buildpath
*
* @see IAddArchivesQuery
*/
public static IAddArchivesQuery getDefaultArchivesQuery(final Shell shell) {
return new IAddArchivesQuery() {
public IPath[] doQuery() {
final IPath[][] selected= {null};
Display.getDefault().syncExec(new Runnable() {
public void run() {
Shell sh= shell != null ? shell : JavaPlugin.getActiveWorkbenchShell();
selected[0]= BuildPathDialogAccess.chooseExternalJAREntries(sh);
}
});
if(selected[0] == null)
return new IPath[0];
return selected[0];
}
};
}
/**
* Shows the UI to prompt whether a linked folder which has been removed from the build path should be deleted as well.
*
* @param shell The parent shell for the dialog, can be <code>null</code>
* @return an <code>IRemoveLinkedFolderQuery</code> showing a dialog to prompt whether the linked folder should be deleted as well
*
* @see IRemoveLinkedFolderQuery
*/
public static IRemoveLinkedFolderQuery getDefaultRemoveLinkedFolderQuery(final Shell shell) {
return new IRemoveLinkedFolderQuery() {
public final int doQuery(final IFolder folder) {
final int[] result= { IRemoveLinkedFolderQuery.REMOVE_BUILD_PATH};
Display.getDefault().syncExec(new Runnable() {
public final void run() {
final RemoveLinkedFolderDialog dialog= new RemoveLinkedFolderDialog((shell != null ? shell : JavaPlugin.getActiveWorkbenchShell()), folder);
final int status= dialog.open();
if (status == 0)
result[0]= dialog.getRemoveStatus();
else
result[0]= IRemoveLinkedFolderQuery.REMOVE_CANCEL;
}
});
return result[0];
}
};
}
/**
* Shows the UI to choose new classpath container classpath entries. See {@link IClasspathEntry#CPE_CONTAINER} for
* details about container classpath entries.
* The query returns the selected classpath entries or an empty array if the query has
* been cancelled.
*
* @param shell The parent shell for the dialog, can be <code>null</code>
* @return Returns the selected classpath container entries or an empty array if the query has
* been cancelled by the user.
*/
public static IAddLibrariesQuery getDefaultLibrariesQuery(final Shell shell) {
return new IAddLibrariesQuery() {
public IClasspathEntry[] doQuery(final IJavaProject project, final IClasspathEntry[] entries) {
final IClasspathEntry[][] selected= {null};
Display.getDefault().syncExec(new Runnable() {
public void run() {
Shell sh= shell != null ? shell : JavaPlugin.getActiveWorkbenchShell();
selected[0]= BuildPathDialogAccess.chooseContainerEntries(sh, project, entries);
}
});
if(selected[0] == null)
return new IClasspathEntry[0];
return selected[0];
}
};
}
/**
* Shows the UI to create a new source folder.
*
* @param shell The parent shell for the dialog, can be <code>null</code>
* @param project the Java project to create the source folder for
* @return returns the query
*/
public static ICreateFolderQuery getDefaultCreateFolderQuery(final Shell shell, final IJavaProject project) {
return new ICreateFolderQuery() {
private IFolder fNewFolder;
public boolean doQuery() {
final boolean[] isOK= {false};
Display.getDefault().syncExec(new Runnable() {
public void run() {
Shell sh= shell != null ? shell : JavaPlugin.getActiveWorkbenchShell();
NewFolderDialog dialog= new NewFolderDialog(sh, project.getProject());
isOK[0]= dialog.open() == Window.OK;
if (isOK[0]) {
IResource sourceContainer= (IResource) dialog.getResult()[0];
if (sourceContainer instanceof IFolder) {
fNewFolder= (IFolder)sourceContainer;
} else {
fNewFolder= null;
}
}
}
});
return isOK[0];
}
public boolean isSourceFolder() {
return true;
}
public IFolder getCreatedFolder() {
return fNewFolder;
}
};
}
}