Java tutorial
/******************************************************************************* * Copyright (c) 2000, 2011 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 com.redhat.ceylon.eclipse.code.preferences; import static com.redhat.ceylon.eclipse.code.wizard.NewProjectWizard.DEFAULT_RESOURCE_FOLDER; import static com.redhat.ceylon.eclipse.code.wizard.NewProjectWizard.DEFAULT_SOURCE_FOLDER; import static com.redhat.ceylon.eclipse.core.builder.CeylonBuilder.getCeylonModulesOutputFolder; import java.io.File; import java.io.IOException; import java.net.URI; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeSet; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IProjectDescription; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceVisitor; import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.resources.ResourcesPlugin; 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.OperationCanceledException; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.SubProgressMonitor; import org.eclipse.jdt.core.IClasspathEntry; import org.eclipse.jdt.core.IJavaModelStatus; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.JavaConventions; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.internal.corext.util.JavaModelUtil; import org.eclipse.jdt.internal.corext.util.Messages; import org.eclipse.jdt.internal.ui.JavaPlugin; import org.eclipse.jdt.internal.ui.JavaPluginImages; import org.eclipse.jdt.internal.ui.dialogs.StatusInfo; import org.eclipse.jdt.internal.ui.dialogs.StatusUtil; import org.eclipse.jdt.internal.ui.util.CoreUtility; import org.eclipse.jdt.internal.ui.viewsupport.BasicElementLabels; import org.eclipse.jdt.internal.ui.viewsupport.ImageDisposer; import org.eclipse.jdt.internal.ui.wizards.IStatusChangeListener; import org.eclipse.jdt.internal.ui.wizards.NewWizardMessages; import org.eclipse.jdt.internal.ui.wizards.TypedElementSelectionValidator; import org.eclipse.jdt.internal.ui.wizards.TypedViewerFilter; import org.eclipse.jdt.internal.ui.wizards.buildpaths.BuildPathBasePage; import org.eclipse.jdt.internal.ui.wizards.buildpaths.BuildPathSupport; import org.eclipse.jdt.internal.ui.wizards.buildpaths.CPListElement; import org.eclipse.jdt.internal.ui.wizards.buildpaths.CPListLabelProvider; //import org.eclipse.jdt.internal.ui.wizards.buildpaths.ClasspathOrderingWorkbookPage; import org.eclipse.jdt.internal.ui.wizards.buildpaths.FolderSelectionDialog; //import org.eclipse.jdt.internal.ui.wizards.buildpaths.LibrariesWorkbookPage; import org.eclipse.jdt.internal.ui.wizards.buildpaths.ProjectsWorkbookPage; import org.eclipse.jdt.internal.ui.wizards.dialogfields.CheckedListDialogField; import org.eclipse.jdt.internal.ui.wizards.dialogfields.DialogField; import org.eclipse.jdt.internal.ui.wizards.dialogfields.IDialogFieldListener; import org.eclipse.jdt.internal.ui.wizards.dialogfields.IListAdapter; import org.eclipse.jdt.internal.ui.wizards.dialogfields.IStringButtonAdapter; import org.eclipse.jdt.internal.ui.wizards.dialogfields.ListDialogField; import org.eclipse.jdt.internal.ui.wizards.dialogfields.StringButtonDialogField; import org.eclipse.jdt.launching.JavaRuntime; import org.eclipse.jdt.ui.PreferenceConstants; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.viewers.ILabelProvider; import org.eclipse.jface.viewers.ITreeContentProvider; import org.eclipse.jface.viewers.ViewerFilter; import org.eclipse.jface.window.Window; import org.eclipse.swt.SWT; import org.eclipse.swt.events.FocusEvent; import org.eclipse.swt.events.FocusListener; import org.eclipse.swt.events.MenuEvent; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.MenuAdapter; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Link; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.MenuItem; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.TabFolder; import org.eclipse.swt.widgets.TabItem; import org.eclipse.swt.widgets.Tree; import org.eclipse.swt.widgets.TreeItem; import org.eclipse.swt.widgets.Widget; import org.eclipse.ui.IWorkbench; import org.eclipse.ui.PartInitException; import org.eclipse.ui.dialogs.ISelectionStatusValidator; import org.eclipse.ui.ide.IDE; import org.eclipse.ui.model.WorkbenchContentProvider; import org.eclipse.ui.model.WorkbenchLabelProvider; import org.eclipse.ui.preferences.IWorkbenchPreferenceContainer; import org.eclipse.ui.views.navigator.ResourceComparator; import com.redhat.ceylon.common.Constants; import com.redhat.ceylon.common.config.CeylonConfig; import com.redhat.ceylon.common.config.CeylonConfigFinder; import com.redhat.ceylon.eclipse.code.editor.Navigation; import com.redhat.ceylon.eclipse.code.outline.CeylonLabelProvider; import com.redhat.ceylon.eclipse.core.builder.CeylonProjectConfig; public class CeylonBuildPathsBlock { private final class CeylonConfigNotInSyncListener extends SelectionAdapter { @Override public void widgetSelected(SelectionEvent e) { if (".ceylon/config".equals(e.text)) { IFile configFile = fCurrJProject.getProject().getFile(".ceylon/config"); if (configFile.exists()) { if (!configFile.isSynchronized(IResource.DEPTH_ZERO)) { try { configFile.refreshLocal(IResource.DEPTH_ZERO, null); } catch (CoreException e1) { } } try { Navigation.openInEditor(configFile); } catch (PartInitException e1) { } } else { MessageDialog.openInformation(getShell(), "Ceylon Configuration File", "No configuration file exist\n" + "Default vaues apply :\n" + " 'source' for source files\n" + " 'resource' for resource files"); } } else if ("use".equals(e.text)) { refreshSourcePathsFromConfigFile(); if (fSourceContainerPage != null) { fSourceContainerPage.init(fCurrJProject); } updateUI(); } else if ("resolve".equals(e.text)) { final Set<String> sourceFoldersFromCeylonConfig = new TreeSet<String>(); final Set<String> sourceFoldersFromEclipseProject = new TreeSet<String>(); final Set<String> resourceFoldersFromCeylonConfig = new TreeSet<String>(); final Set<String> resourceFoldersFromEclipseProject = new TreeSet<String>(); fillBuildPathsSetsForComparison(fCurrJProject.getProject(), sourceFoldersFromCeylonConfig, sourceFoldersFromEclipseProject, resourceFoldersFromCeylonConfig, resourceFoldersFromEclipseProject); class BuildPathsComparisonDialog extends Dialog { Set<String> resultSourcesSet = new TreeSet<>(); Set<String> resultResourcesSet = new TreeSet<>(); Tree resultPathsTree; TreeItem resultSources; TreeItem resultResources; final String CONFLICTING = "conflicting"; final String RESULT_FOLDER_SET = "resultFolderSet"; protected BuildPathsComparisonDialog() { super(fSWTWidget.getShell()); } @Override protected void configureShell(Shell newShell) { super.configureShell(newShell); newShell.setText("Ceylon Build Paths Conflict Resolution"); newShell.setMinimumSize(700, 700); } @Override protected Control createDialogArea(Composite parent) { Color red = Display.getCurrent().getSystemColor(SWT.COLOR_RED); Composite composite = (Composite) super.createDialogArea(parent); GridLayout layout = (GridLayout) composite.getLayout(); layout.numColumns = 1; Group comparisonArea = new Group(composite, SWT.NONE); comparisonArea.setText("Conflicting build paths"); comparisonArea.setLayoutData(new GridData(GridData.FILL_BOTH)); GridLayout comparisonLayout = new GridLayout(); comparisonLayout.numColumns = 2; comparisonLayout.makeColumnsEqualWidth = true; comparisonLayout.verticalSpacing = 5; comparisonArea.setLayout(comparisonLayout); Label explanationLabel = new Label(comparisonArea, SWT.NONE); explanationLabel.setText("The red entries show conflicts.\n" + "You can decide what to do with them through the context menu."); explanationLabel .setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_INFO_BACKGROUND)); GridData explanationGridData = new GridData(GridData.FILL_HORIZONTAL); explanationGridData.horizontalSpan = 2; explanationLabel.setLayoutData(explanationGridData); Group resultArea = new Group(composite, SWT.NONE); resultArea.setText("Merged build paths"); resultArea.setLayoutData(new GridData(GridData.FILL_BOTH)); GridLayout resultLayout = new GridLayout(); resultLayout.numColumns = 1; resultArea.setLayout(resultLayout); resultPathsTree = new Tree(resultArea, SWT.NONE); resultPathsTree.setLayoutData(new GridData(GridData.FILL_BOTH)); Label label = new Label(comparisonArea, SWT.NONE); label.setText("Eclipse project"); label = new Label(comparisonArea, SWT.NONE); label.setText("Ceylon configuration file"); final Tree projectBasedPathsTree = new Tree(comparisonArea, SWT.NONE); projectBasedPathsTree.setLayoutData(new GridData(GridData.FILL_BOTH)); projectBasedPathsTree.addFocusListener(new FocusListener() { @Override public void focusLost(FocusEvent e) { projectBasedPathsTree.setSelection(new TreeItem[0]); } @Override public void focusGained(FocusEvent e) { } }); final Tree configBasedPathsTree = new Tree(comparisonArea, SWT.NONE); configBasedPathsTree.setLayoutData(new GridData(GridData.FILL_BOTH)); configBasedPathsTree.addFocusListener(new FocusListener() { @Override public void focusLost(FocusEvent e) { configBasedPathsTree.setSelection(new TreeItem[0]); } @Override public void focusGained(FocusEvent e) { } }); final TreeItem projectBasedSources = new TreeItem(projectBasedPathsTree, SWT.NONE); projectBasedSources.setText("Sources"); final TreeItem projectBasedResources = new TreeItem(projectBasedPathsTree, SWT.NONE); projectBasedResources.setText("Resources"); final TreeItem configBasedSources = new TreeItem(configBasedPathsTree, SWT.NONE); configBasedSources.setText("Sources"); final TreeItem configBasedResources = new TreeItem(configBasedPathsTree, SWT.NONE); configBasedResources.setText("Resources"); resultSources = new TreeItem(resultPathsTree, SWT.NONE); resultSources.setText("Sources"); resultResources = new TreeItem(resultPathsTree, SWT.NONE); resultResources.setText("Resources"); TreeItem pathItem = null; for (String folder : sourceFoldersFromEclipseProject) { pathItem = new TreeItem(projectBasedSources, SWT.NONE); pathItem.setText(folder); if (!sourceFoldersFromCeylonConfig.contains(folder)) { pathItem.setForeground(red); pathItem.setData(CONFLICTING, true); } else { resultSourcesSet.add(folder); pathItem.setData(CONFLICTING, false); } pathItem.setData(RESULT_FOLDER_SET, resultSourcesSet); } for (String folder : resourceFoldersFromEclipseProject) { pathItem = new TreeItem(projectBasedResources, SWT.NONE); pathItem.setText(folder); if (!resourceFoldersFromCeylonConfig.contains(folder)) { pathItem.setForeground(red); pathItem.setData(CONFLICTING, true); } else { resultResourcesSet.add(folder); pathItem.setData(CONFLICTING, false); } pathItem.setData(RESULT_FOLDER_SET, resultResourcesSet); } for (String folder : sourceFoldersFromCeylonConfig) { pathItem = new TreeItem(configBasedSources, SWT.NONE); pathItem.setText(folder); if (!sourceFoldersFromEclipseProject.contains(folder)) { pathItem.setForeground(red); pathItem.setData(CONFLICTING, true); } else { resultSourcesSet.add(folder); pathItem.setData(CONFLICTING, false); } pathItem.setData(RESULT_FOLDER_SET, resultSourcesSet); } for (String folder : resourceFoldersFromCeylonConfig) { pathItem = new TreeItem(configBasedResources, SWT.NONE); pathItem.setText(folder); if (!resourceFoldersFromEclipseProject.contains(folder)) { pathItem.setForeground(red); pathItem.setData(CONFLICTING, true); } else { resultResourcesSet.add(folder); pathItem.setData(CONFLICTING, false); } pathItem.setData(RESULT_FOLDER_SET, resultResourcesSet); } updateResultTree(); projectBasedSources.setExpanded(true); projectBasedResources.setExpanded(true); configBasedSources.setExpanded(true); configBasedResources.setExpanded(true); setupMenu(projectBasedPathsTree); setupMenu(configBasedPathsTree); return composite; } private void setupMenu(final Tree projectBasedPathsTree) { final Menu projectBasedMenu = new Menu(projectBasedPathsTree); projectBasedPathsTree.setMenu(projectBasedMenu); projectBasedMenu.addMenuListener(new MenuAdapter() { public void menuShown(MenuEvent e) { MenuItem[] items = projectBasedMenu.getItems(); for (int i = 0; i < items.length; i++) { items[i].dispose(); } TreeItem[] selection = projectBasedPathsTree.getSelection(); if (selection.length > 0) { final TreeItem selectedItem = selection[0]; if ((Boolean) selectedItem.getData(CONFLICTING)) { MenuItem newItem = new MenuItem(projectBasedMenu, SWT.NONE); @SuppressWarnings("unchecked") final Set<String> resultFolderSet = (Set<String>) selectedItem .getData(RESULT_FOLDER_SET); final boolean alreadyInResult = resultFolderSet .contains(selectedItem.getText()); newItem.setText((alreadyInResult ? "Remove from" : "Add to") + " merged build paths"); newItem.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { if (alreadyInResult) { resultFolderSet.remove(selectedItem.getText()); } else { resultFolderSet.add(selectedItem.getText()); } updateResultTree(); } }); } } } }); } private void updateResultTree() { TreeItem pathItem; resultSources.removeAll(); for (String folder : resultSourcesSet) { pathItem = new TreeItem(resultSources, SWT.NONE); pathItem.setText(folder); } resultResources.removeAll(); for (String folder : resultResourcesSet) { pathItem = new TreeItem(resultResources, SWT.NONE); pathItem.setText(folder); } resultSources.setExpanded(true); resultResources.setExpanded(true); } } BuildPathsComparisonDialog dialog = new BuildPathsComparisonDialog(); if (dialog.open() == Dialog.OK && !(dialog.resultSourcesSet.equals(sourceFoldersFromEclipseProject) && dialog.resultResourcesSet.equals(resourceFoldersFromEclipseProject))) { updateClassPathsFromConfigFile(Arrays.asList(dialog.resultSourcesSet.toArray(new String[0])), new HashSet<String>()); if (fSourceContainerPage != null) { fSourceContainerPage.init(fCurrJProject); } updateUI(); } } } } public static interface IRemoveOldBinariesQuery { /** * Do the callback. Returns <code>true</code> if .class files should be removed from the * old output location. * @param removeLocation true if the folder at oldOutputLocation should be removed, false if only its content * @param oldOutputLocation The old output location * @return Returns true if .class files should be removed. * @throws OperationCanceledException if the operation was canceled */ boolean doQuery(boolean removeLocation, IPath oldOutputLocation) throws OperationCanceledException; } private IWorkspaceRoot fWorkspaceRoot; private CheckedListDialogField<CPListElement> fClassPathList; private CheckedListDialogField<CPListElement> fResourcePathList; private StringButtonDialogField fJavaBuildPathDialogField; private Link fNotInSyncText; private boolean wasInSyncWhenOpening; private boolean someFoldersNeedToBeCreated; private StatusInfo fClassPathStatus; private StatusInfo fOutputFolderStatus; private StatusInfo fBuildPathStatus; private IJavaProject fCurrJProject; private IPath fJavaOutputLocationPath; private IStatusChangeListener fContext; private Control fSWTWidget; private TabFolder fTabFolder; private int fPageIndex; private SourceContainerWorkbookPage fSourceContainerPage; private ResourceContainerWorkbookPage fResourceContainerPage; private ProjectsWorkbookPage fProjectsPage; // private LibrariesWorkbookPage fLibrariesPage; private BuildPathBasePage fCurrPage; private String fUserSettingsTimeStamp; private long fFileTimeStamp; //private IRunnableContext fRunnableContext; //private boolean fUseNewPage; private final IWorkbenchPreferenceContainer fPageContainer; // null when invoked from a non-property page context private final static int IDX_UP = 0; private final static int IDX_DOWN = 1; private final static int IDX_TOP = 3; private final static int IDX_BOTTOM = 4; private final static int IDX_SELECT_ALL = 6; private final static int IDX_UNSELECT_ALL = 7; public CeylonBuildPathsBlock(/*IRunnableContext runnableContext,*/ IStatusChangeListener context, int pageToShow, /*boolean useNewPage,*/ IWorkbenchPreferenceContainer pageContainer) { fPageContainer = pageContainer; fWorkspaceRoot = JavaPlugin.getWorkspace().getRoot(); fContext = context; //fUseNewPage= useNewPage; fPageIndex = pageToShow; fSourceContainerPage = null; fNotInSyncText = null; fResourceContainerPage = null; // fLibrariesPage= null; fProjectsPage = null; fCurrPage = null; //fRunnableContext= runnableContext; JavaBuildPathAdapter jadapter = new JavaBuildPathAdapter(); String[] buttonLabels = new String[] { /* IDX_UP */ NewWizardMessages.BuildPathsBlock_classpath_up_button, /* IDX_DOWN */ NewWizardMessages.BuildPathsBlock_classpath_down_button, /* 2 */ null, /* IDX_TOP */ NewWizardMessages.BuildPathsBlock_classpath_top_button, /* IDX_BOTTOM */ NewWizardMessages.BuildPathsBlock_classpath_bottom_button, /* 5 */ null, /* IDX_SELECT_ALL */ NewWizardMessages.BuildPathsBlock_classpath_checkall_button, /* IDX_UNSELECT_ALL */ NewWizardMessages.BuildPathsBlock_classpath_uncheckall_button }; fClassPathList = new CheckedListDialogField<CPListElement>(jadapter, buttonLabels, new CPListLabelProvider()); fClassPathList.setDialogFieldListener(jadapter); fClassPathList.setLabelText(NewWizardMessages.BuildPathsBlock_classpath_label); fClassPathList.setUpButtonIndex(IDX_UP); fClassPathList.setDownButtonIndex(IDX_DOWN); fClassPathList.setCheckAllButtonIndex(IDX_SELECT_ALL); fClassPathList.setUncheckAllButtonIndex(IDX_UNSELECT_ALL); fClassPathList.setDialogFieldListener(new IDialogFieldListener() { @Override public void dialogFieldChanged(DialogField field) { System.out.print(""); } }); fResourcePathList = new CheckedListDialogField<CPListElement>(jadapter, buttonLabels, new ResourceListLabelProvider()); fResourcePathList.setDialogFieldListener(jadapter); fResourcePathList.setLabelText("Build &resource path order"); fResourcePathList.setUpButtonIndex(IDX_UP); fResourcePathList.setDownButtonIndex(IDX_DOWN); fResourcePathList.setCheckAllButtonIndex(IDX_SELECT_ALL); fResourcePathList.setUncheckAllButtonIndex(IDX_UNSELECT_ALL); fJavaBuildPathDialogField = new StringButtonDialogField(jadapter); fJavaBuildPathDialogField.setButtonLabel(NewWizardMessages.BuildPathsBlock_buildpath_button); fJavaBuildPathDialogField.setDialogFieldListener(jadapter); //fJavaPathDialogField.setLabelText(NewWizardMessages.BuildPathsBlock_buildpath_label); fJavaBuildPathDialogField.setLabelText("Default Java binary class output folder:"); fBuildPathStatus = new StatusInfo(); fClassPathStatus = new StatusInfo(); fOutputFolderStatus = new StatusInfo(); fCurrJProject = null; } public boolean wasInSyncWithCeylonConfigWhenOpening() { return wasInSyncWhenOpening; } public boolean isInSyncWithCeylonConfig() { if (fCurrJProject == null) { return true; } IProject project = fCurrJProject.getProject(); Set<String> sourceFoldersFromCeylonConfig = new TreeSet<String>(); Set<String> sourceFoldersFromEclipseProject = new TreeSet<String>(); Set<String> resourceFoldersFromCeylonConfig = new TreeSet<String>(); Set<String> resourceFoldersFromEclipseProject = new TreeSet<String>(); fillBuildPathsSetsForComparison(project, sourceFoldersFromCeylonConfig, sourceFoldersFromEclipseProject, resourceFoldersFromCeylonConfig, resourceFoldersFromEclipseProject); return sourceFoldersFromCeylonConfig.equals(sourceFoldersFromEclipseProject) && resourceFoldersFromCeylonConfig.equals(resourceFoldersFromEclipseProject); } private void fillBuildPathsSetsForComparison(IProject project, Set<String> sourceFoldersFromCeylonConfig, Set<String> sourceFoldersFromEclipseProject, Set<String> resourceFoldersFromCeylonConfig, Set<String> resourceFoldersFromEclipseProject) { CeylonProjectConfig ceylonConfig = CeylonProjectConfig.get(project); for (String path : ceylonConfig.getProjectSourceDirectories()) { sourceFoldersFromCeylonConfig.add(Path.fromOSString(path).toString()); } for (String path : ceylonConfig.getProjectResourceDirectories()) { resourceFoldersFromCeylonConfig.add(Path.fromOSString(path).toString()); } for (CPListElement elem : fClassPathList.getElements()) { if (elem.getClasspathEntry().getEntryKind() == IClasspathEntry.CPE_SOURCE) { IPath path = null; if (elem.getLinkTarget() == null) { path = elem.getPath().makeRelativeTo(project.getFullPath()); } else { path = elem.getLinkTarget(); } sourceFoldersFromEclipseProject.add(path.toString()); } } for (CPListElement elem : fResourcePathList.getElements()) { if (elem.getClasspathEntry().getEntryKind() == IClasspathEntry.CPE_SOURCE) { IPath path = null; if (elem.getLinkTarget() == null) { path = elem.getPath().makeRelativeTo(project.getFullPath()); } else { path = elem.getLinkTarget(); } resourceFoldersFromEclipseProject.add(path.toString()); } } if (sourceFoldersFromEclipseProject.isEmpty()) { sourceFoldersFromEclipseProject.add(Constants.DEFAULT_SOURCE_DIR); } if (resourceFoldersFromEclipseProject.isEmpty()) { resourceFoldersFromEclipseProject.add(Constants.DEFAULT_RESOURCE_DIR); } } // -------- UI creation --------- public Control createControl(Composite parent) { fSWTWidget = parent; Composite composite = new Composite(parent, SWT.NONE); composite.setFont(parent.getFont()); GridLayout layout = new GridLayout(); layout.marginWidth = 0; layout.marginHeight = 0; layout.numColumns = 1; composite.setLayout(layout); fNotInSyncText = new Link(composite, SWT.NONE); wasInSyncWhenOpening = isInSyncWithCeylonConfig(); fNotInSyncText.setVisible(!wasInSyncWhenOpening); GridData notInSyncLayoutData = new GridData(GridData.FILL_HORIZONTAL); notInSyncLayoutData.exclude = wasInSyncWhenOpening; fNotInSyncText.setLayoutData(notInSyncLayoutData); fNotInSyncText .setText("The Ceylon configuration file (<a>.ceylon/config</a>) is not in sync with the current\n" + "Ceylon Build Paths. You can :\n" + " - simply overwrite the Ceylon configuration with OK\n" + " - <a>use</a> the original configuration file settings\n" + " - <a>resolve</a> the conflicts yourself."); fNotInSyncText.setForeground(Display.getCurrent().getSystemColor(SWT.COLOR_DARK_RED)); fNotInSyncText.addSelectionListener(new CeylonConfigNotInSyncListener()); TabFolder folder = new TabFolder(composite, SWT.NONE); folder.setLayoutData(new GridData(GridData.FILL_BOTH)); folder.setFont(composite.getFont()); TabItem item; item = new TabItem(folder, SWT.NONE); item.setText(NewWizardMessages.BuildPathsBlock_tab_source); item.setImage(JavaPluginImages.get(JavaPluginImages.IMG_OBJS_PACKFRAG_ROOT)); /*if (fUseNewPage) { fSourceContainerPage= new NewSourceContainerWorkbookPage(fClassPathList, fBuildPathDialogField, fRunnableContext, this); } else {*/ fSourceContainerPage = new SourceContainerWorkbookPage(fClassPathList, fJavaBuildPathDialogField); //} item.setData(fSourceContainerPage); item.setControl(fSourceContainerPage.getControl(folder)); item = new TabItem(folder, SWT.NONE); item.setText("Resources"); item.setImage(CeylonLabelProvider.FOLDER); fResourceContainerPage = new ResourceContainerWorkbookPage(fResourcePathList, fJavaBuildPathDialogField); item.setData(fResourceContainerPage); item.setControl(fResourceContainerPage.getControl(folder)); IWorkbench workbench = JavaPlugin.getDefault().getWorkbench(); Image projectImage = workbench.getSharedImages().getImage(IDE.SharedImages.IMG_OBJ_PROJECT); fProjectsPage = new ProjectsWorkbookPage(fClassPathList, fPageContainer); item = new TabItem(folder, SWT.NONE); item.setText(NewWizardMessages.BuildPathsBlock_tab_projects); item.setImage(projectImage); item.setData(fProjectsPage); item.setControl(fProjectsPage.getControl(folder)); // fLibrariesPage= new LibrariesWorkbookPage(fClassPathList, fPageContainer); // item= new TabItem(folder, SWT.NONE); // item.setText(NewWizardMessages.BuildPathsBlock_tab_libraries); // item.setImage(JavaPluginImages.get(JavaPluginImages.IMG_OBJS_LIBRARY)); // item.setData(fLibrariesPage); // item.setControl(fLibrariesPage.getControl(folder)); // a non shared image Image cpoImage = JavaPluginImages.DESC_TOOL_CLASSPATH_ORDER.createImage(); composite.addDisposeListener(new ImageDisposer(cpoImage)); // ClasspathOrderingWorkbookPage ordpage= new ClasspathOrderingWorkbookPage(fClassPathList); // item= new TabItem(folder, SWT.NONE); // item.setText(NewWizardMessages.BuildPathsBlock_tab_order); // item.setImage(cpoImage); // item.setData(ordpage); // item.setControl(ordpage.getControl(folder)); if (fCurrJProject != null) { fSourceContainerPage.init(fCurrJProject); fResourceContainerPage.init(fCurrJProject); // fLibrariesPage.init(fCurrJProject); fProjectsPage.init(fCurrJProject); } folder.setSelection(fPageIndex); fCurrPage = (BuildPathBasePage) folder.getItem(fPageIndex).getData(); folder.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { tabChanged(e.item); } }); fTabFolder = folder; Dialog.applyDialogFont(composite); return composite; } private Shell getShell() { if (fSWTWidget != null) { return fSWTWidget.getShell(); } return JavaPlugin.getActiveWorkbenchShell(); } /** * Initializes the classpath for the given project. Multiple calls to init are allowed, * but all existing settings will be cleared and replace by the given or default paths. * @param jproject The java project to configure. Does not have to exist. * @param javaOutputLocation The output location to be set in the page. If <code>null</code> * is passed, jdt default settings are used, or - if the project is an existing Java project- the * output location of the existing project * @param classpathEntries The classpath entries to be set in the page. If <code>null</code> * is passed, jdt default settings are used, or - if the project is an existing Java project - the * classpath entries of the existing project */ public void init(IJavaProject jproject, IPath javaOutputLocation, IClasspathEntry[] classpathEntries, boolean javaCompilationEnabled) { fCurrJProject = jproject; boolean projectExists = false; someFoldersNeedToBeCreated = false; final List<CPListElement> newClassPath; IProject project = fCurrJProject.getProject(); projectExists = (project.exists() && project.getFile(".classpath").exists()); //$NON-NLS-1$ List<String> configSourceDirectories; List<String> configResourceDirectories; if (projectExists) { CeylonProjectConfig config = CeylonProjectConfig.get(project); configSourceDirectories = config.getProjectSourceDirectories(); configResourceDirectories = config.getProjectResourceDirectories(); } else { File configFile = jproject.getProject().getFile(".ceylon/config").getLocation().toFile(); CeylonConfig ceylonConfig; try { ceylonConfig = CeylonConfigFinder.DEFAULT.loadConfigFromFile(configFile); configSourceDirectories = CeylonProjectConfig.getConfigSourceDirectories(ceylonConfig); configResourceDirectories = CeylonProjectConfig.getConfigResourceDirectories(ceylonConfig); } catch (IOException e) { configSourceDirectories = Collections.emptyList(); configResourceDirectories = Collections.emptyList(); } } IClasspathEntry[] existingEntries = null; if (projectExists) { if (javaOutputLocation == null) { javaOutputLocation = fCurrJProject.readOutputLocation(); } existingEntries = fCurrJProject.readRawClasspath(); if (classpathEntries == null) { classpathEntries = existingEntries; //TODO: read existing ceylon output location from classpathEntries } } if (javaOutputLocation == null) { javaOutputLocation = getDefaultJavaOutputLocation(jproject); } if (classpathEntries != null) { newClassPath = getCPListElements(classpathEntries, existingEntries); } else { newClassPath = getDefaultClassPath(jproject); } Set<String> newFolderNames = new HashSet<>(); final List<CPListElement> newResourcePath = new ArrayList<CPListElement>(); if (!configResourceDirectories.isEmpty()) { someFoldersNeedToBeCreated = resourcePathsFromStrings(fCurrJProject, configResourceDirectories, newFolderNames, newResourcePath); } else { IFolder defaultResourceFolder = fCurrJProject.getProject().getFolder(DEFAULT_RESOURCE_FOLDER); newResourcePath.add(new CPListElement(fCurrJProject, IClasspathEntry.CPE_SOURCE, defaultResourceFolder.getFullPath(), defaultResourceFolder)); } List<CPListElement> exportedEntries = new ArrayList<CPListElement>(); for (int i = 0; i < newClassPath.size(); i++) { CPListElement curr = newClassPath.get(i); if (curr.isExported() || curr.getEntryKind() == IClasspathEntry.CPE_SOURCE) { exportedEntries.add(curr); } } fJavaOutputLocationPath = javaOutputLocation.makeRelative(); // inits the dialog field fJavaBuildPathDialogField.setText(fJavaOutputLocationPath.toString()); fJavaBuildPathDialogField.enableButton(project.exists()); fClassPathList.setElements(newClassPath); fClassPathList.setCheckedElements(exportedEntries); if (!projectExists) { IPreferenceStore store = PreferenceConstants.getPreferenceStore(); if (!configSourceDirectories.isEmpty() && store.getBoolean(PreferenceConstants.SRCBIN_FOLDERS_IN_NEWPROJ)) { updateClassPathsFromConfigFile(configSourceDirectories, newFolderNames); } } fClassPathList.selectFirstElement(); fResourcePathList.setElements(newResourcePath); // fResourcePathList.setCheckedElements(exportedEntries); fResourcePathList.selectFirstElement(); if (fSourceContainerPage != null) { fSourceContainerPage.init(fCurrJProject); fResourceContainerPage.init(fCurrJProject); fProjectsPage.init(fCurrJProject); // fLibrariesPage.init(fCurrJProject); } initializeTimeStamps(); updateUI(); } public static boolean resourcePathsFromStrings(final IJavaProject javaProject, List<String> configResourceDirectories, Set<String> newFolderNames, final List<CPListElement> newResourcePath) { boolean someFoldersNeedToBeCreated = false; IProject project = javaProject.getProject(); for (final String path : configResourceDirectories) { final IPath iPath = Path.fromOSString(path); if (!iPath.isAbsolute()) { IFolder folder = project.getFolder(iPath); newResourcePath.add( new CPListElement(javaProject, IClasspathEntry.CPE_SOURCE, folder.getFullPath(), folder)); if (!folder.exists()) { someFoldersNeedToBeCreated = true; } } else { try { class CPListElementHolder { public CPListElement value = null; } final CPListElementHolder cpListElement = new CPListElementHolder(); project.accept(new IResourceVisitor() { @Override public boolean visit(IResource resource) throws CoreException { if (resource instanceof IFolder && resource.isLinked() && resource.getLocation() != null && resource.getLocation().equals(iPath)) { cpListElement.value = new CPListElement(null, javaProject, IClasspathEntry.CPE_SOURCE, resource.getFullPath(), resource, resource.getLocation()); return false; } return resource instanceof IFolder || resource instanceof IProject; } }); if (cpListElement.value == null) { String newFolderName = iPath.lastSegment(); IFolder newFolder = project.getFolder(newFolderName); int counter = 1; while (newFolderNames.contains(newFolderName) || newFolder.exists()) { newFolderName = iPath.lastSegment() + "_" + counter++; newFolder = project.getFolder(newFolderName); } newFolderNames.add(newFolderName); cpListElement.value = new CPListElement(null, javaProject, IClasspathEntry.CPE_SOURCE, newFolder.getFullPath(), newFolder, iPath); someFoldersNeedToBeCreated = true; } newResourcePath.add(cpListElement.value); } catch (CoreException e) { e.printStackTrace(); } } } return someFoldersNeedToBeCreated; } protected void updateUI() { if (fSWTWidget == null || fSWTWidget.isDisposed()) { return; } if (Display.getCurrent() != null) { doUpdateUI(); } else { Display.getDefault().asyncExec(new Runnable() { public void run() { if (fSWTWidget == null || fSWTWidget.isDisposed()) { return; } doUpdateUI(); } }); } } protected void doUpdateUI() { boolean isInSync = isInSyncWithCeylonConfig(); boolean notInSyncWasVisible = fNotInSyncText.isVisible(); fNotInSyncText.setVisible(!isInSync); GridData notInSyncLayoutData = (GridData) fNotInSyncText.getLayoutData(); notInSyncLayoutData.exclude = isInSync; fJavaBuildPathDialogField.refresh(); fClassPathList.refresh(); fResourcePathList.refresh(); doStatusLineUpdate(); if (notInSyncWasVisible && isInSync) { fNotInSyncText.getParent().layout(true); } } private String getEncodedSettings() { StringBuffer buf = new StringBuffer(); CPListElement.appendEncodePath(fJavaOutputLocationPath, buf).append(';'); int nElements = fClassPathList.getSize(); buf.append('[').append(nElements).append(']'); for (int i = 0; i < nElements; i++) { CPListElement elem = fClassPathList.getElement(i); elem.appendEncodedSettings(buf); } nElements = fResourcePathList.getSize(); buf.append('[').append(nElements).append(']'); for (int i = 0; i < nElements; i++) { CPListElement elem = fResourcePathList.getElement(i); elem.appendEncodedSettings(buf); } return buf.toString(); } public boolean hasChangesInDialog() { String currSettings = getEncodedSettings(); return !currSettings.equals(fUserSettingsTimeStamp) || someFoldersNeedToBeCreated; } public boolean hasChangesInClasspathFile() { IFile file = fCurrJProject.getProject().getFile(".classpath"); //$NON-NLS-1$ return fFileTimeStamp != file.getModificationStamp(); } public boolean isClassfileMissing() { return !fCurrJProject.getProject().getFile(".classpath").exists(); //$NON-NLS-1$ } public void initializeTimeStamps() { IFile file = fCurrJProject.getProject().getFile(".classpath"); //$NON-NLS-1$ fFileTimeStamp = file.getModificationStamp(); fUserSettingsTimeStamp = getEncodedSettings(); } private ArrayList<CPListElement> getCPListElements(IClasspathEntry[] classpathEntries, IClasspathEntry[] existingEntries) { List<IClasspathEntry> existing = existingEntries == null ? Collections.<IClasspathEntry>emptyList() : Arrays.asList(existingEntries); ArrayList<CPListElement> newClassPath = new ArrayList<CPListElement>(); for (int i = 0; i < classpathEntries.length; i++) { IClasspathEntry curr = classpathEntries[i]; newClassPath.add(CPListElement.create(curr, !existing.contains(curr), fCurrJProject)); } return newClassPath; } // -------- public api -------- /** * @return Returns the Java project. Can return <code>null<code> if the page has not * been initialized. */ public IJavaProject getJavaProject() { return fCurrJProject; } /** * @return Returns the current output location. Note that the path returned must not be valid. */ public IPath getJavaOutputLocation() { String text = fJavaBuildPathDialogField.getText(); if (text.isEmpty()) { return null; } else { return new Path(text).makeAbsolute(); } } /** * @return Returns the current class path (raw). Note that the entries returned must not be valid. */ public IClasspathEntry[] getRawClassPath() { List<CPListElement> elements = fClassPathList.getElements(); int nElements = elements.size(); IClasspathEntry[] entries = new IClasspathEntry[elements.size()]; for (int i = 0; i < nElements; i++) { CPListElement currElement = elements.get(i); entries[i] = currElement.getClasspathEntry(); } return entries; } public int getPageIndex() { return fPageIndex; } // -------- evaluate default settings -------- private List<CPListElement> getDefaultClassPath(IJavaProject jproj) { List<CPListElement> list = new ArrayList<CPListElement>(); IResource srcFolder; IPreferenceStore store = PreferenceConstants.getPreferenceStore(); String sourceFolderName = DEFAULT_SOURCE_FOLDER;//store.getString(PreferenceConstants.SRCBIN_SRCNAME); if (store.getBoolean(PreferenceConstants.SRCBIN_FOLDERS_IN_NEWPROJ) && sourceFolderName.length() > 0) { srcFolder = jproj.getProject().getFolder(sourceFolderName); } else { srcFolder = jproj.getProject(); } list.add(new CPListElement(jproj, IClasspathEntry.CPE_SOURCE, srcFolder.getFullPath(), srcFolder)); IClasspathEntry[] jreEntries = PreferenceConstants.getDefaultJRELibrary(); list.addAll(getCPListElements(jreEntries, null)); return list; } public static IPath getDefaultJavaOutputLocation(IJavaProject jproj) { return jproj.getProject().getFullPath().append("classes"); } private class JavaBuildPathAdapter implements IStringButtonAdapter, IDialogFieldListener, IListAdapter<CPListElement> { // -------- IStringButtonAdapter -------- public void changeControlPressed(DialogField field) { buildPathChangeControlPressed(field); } // ---------- IDialogFieldListener -------- public void dialogFieldChanged(DialogField field) { buildPathDialogFieldChanged(field); } // ---------- IListAdapter -------- public void customButtonPressed(ListDialogField<CPListElement> field, int index) { buildPathCustomButtonPressed(field, index); } public void doubleClicked(ListDialogField<CPListElement> field) { } public void selectionChanged(ListDialogField<CPListElement> field) { updateTopButtonEnablement(); } } private void buildPathChangeControlPressed(DialogField field) { if (field == fJavaBuildPathDialogField) { IContainer container = chooseContainer(fJavaOutputLocationPath); if (container != null) { fJavaBuildPathDialogField.setText(container.getFullPath().makeRelative().toString()); } } } public void updateTopButtonEnablement() { fClassPathList.enableButton(IDX_BOTTOM, fClassPathList.canMoveDown()); fClassPathList.enableButton(IDX_TOP, fClassPathList.canMoveUp()); } public void buildPathCustomButtonPressed(ListDialogField<CPListElement> field, int index) { List<CPListElement> elems = field.getSelectedElements(); field.removeElements(elems); if (index == IDX_BOTTOM) { field.addElements(elems); } else if (index == IDX_TOP) { field.addElements(elems, 0); } } private void buildPathDialogFieldChanged(DialogField field) { if (field == fClassPathList) { updateClassPathStatus(); updateTopButtonEnablement(); } else if (field == fJavaBuildPathDialogField) { updateJavaOutputLocationStatus(); } doStatusLineUpdate(); } // -------- verification ------------------------------- private void doStatusLineUpdate() { if (Display.getCurrent() != null) { IStatus res = findMostSevereStatus(); fContext.statusChanged(res); } } private IStatus findMostSevereStatus() { return StatusUtil.getMostSevere(new IStatus[] { fClassPathStatus, fOutputFolderStatus, fBuildPathStatus }); } /** * Validates the build path. */ public void updateClassPathStatus() { fClassPathStatus.setOK(); List<CPListElement> elements = fClassPathList.getElements(); CPListElement entryMissing = null; CPListElement entryDeprecated = null; int nEntriesMissing = 0; IClasspathEntry[] entries = new IClasspathEntry[elements.size()]; for (int i = elements.size() - 1; i >= 0; i--) { CPListElement currElement = elements.get(i); boolean isChecked = fClassPathList.isChecked(currElement); if (currElement.getEntryKind() == IClasspathEntry.CPE_SOURCE) { if (!isChecked) { fClassPathList.setCheckedWithoutUpdate(currElement, true); } if (!fClassPathList.isGrayed(currElement)) { fClassPathList.setGrayedWithoutUpdate(currElement, true); } } else { currElement.setExported(isChecked); } entries[i] = currElement.getClasspathEntry(); if (currElement.isMissing()) { nEntriesMissing++; if (entryMissing == null) { entryMissing = currElement; } } if (entryDeprecated == null & currElement.isDeprecated()) { entryDeprecated = currElement; } } if (nEntriesMissing > 0) { if (nEntriesMissing == 1) { fClassPathStatus.setWarning(Messages.format(NewWizardMessages.BuildPathsBlock_warning_EntryMissing, BasicElementLabels.getPathLabel(entryMissing.getPath(), false))); } else { fClassPathStatus.setWarning(Messages.format( NewWizardMessages.BuildPathsBlock_warning_EntriesMissing, String.valueOf(nEntriesMissing))); } } else if (entryDeprecated != null) { fClassPathStatus.setInfo(entryDeprecated.getDeprecationMessage()); } /* if (fCurrJProject.hasClasspathCycle(entries)) { fClassPathStatus.setWarning(NewWizardMessages.getString("BuildPathsBlock.warning.CycleInClassPath")); //$NON-NLS-1$ } */ updateBuildPathStatus(); } /** * Validates output location & build path. */ private void updateJavaOutputLocationStatus() { fJavaOutputLocationPath = null; String text = fJavaBuildPathDialogField.getText(); if ("".equals(text)) { //$NON-NLS-1$ fOutputFolderStatus.setError(NewWizardMessages.BuildPathsBlock_error_EnterBuildPath); return; } IPath path = getJavaOutputLocation(); fJavaOutputLocationPath = path; IResource res = fWorkspaceRoot.findMember(path); if (res != null) { // if exists, must be a folder or project if (res.getType() == IResource.FILE) { fOutputFolderStatus.setError(NewWizardMessages.BuildPathsBlock_error_InvalidBuildPath); return; } } fOutputFolderStatus.setOK(); String pathStr = fJavaBuildPathDialogField.getText(); Path outputPath = (new Path(pathStr)); pathStr = outputPath.lastSegment(); if (pathStr.equals(".settings") && outputPath.segmentCount() == 2) { //$NON-NLS-1$ fOutputFolderStatus.setWarning(NewWizardMessages.OutputLocation_SettingsAsLocation); } if (pathStr.charAt(0) == '.' && pathStr.length() > 1) { fOutputFolderStatus.setWarning(Messages.format(NewWizardMessages.OutputLocation_DotAsLocation, BasicElementLabels.getResourceName(pathStr))); } updateBuildPathStatus(); } private void updateBuildPathStatus() { List<CPListElement> elements = fClassPathList.getElements(); IClasspathEntry[] entries = new IClasspathEntry[elements.size()]; for (int i = elements.size() - 1; i >= 0; i--) { CPListElement currElement = elements.get(i); entries[i] = currElement.getClasspathEntry(); } IJavaModelStatus status = JavaConventions.validateClasspath(fCurrJProject, entries, fJavaOutputLocationPath); if (!status.isOK()) { fBuildPathStatus.setError(status.getMessage()); return; } fBuildPathStatus.setOK(); } // -------- creation ------------------------------- public static void createProject(IProject project, URI locationURI, IProgressMonitor monitor) throws CoreException { if (monitor == null) { monitor = new NullProgressMonitor(); } monitor.beginTask(NewWizardMessages.BuildPathsBlock_operationdesc_project, 10); // create the project try { if (!project.exists()) { IProjectDescription desc = project.getWorkspace().newProjectDescription(project.getName()); if (locationURI != null && ResourcesPlugin.getWorkspace().getRoot().getLocationURI().equals(locationURI)) { locationURI = null; } desc.setLocationURI(locationURI); project.create(desc, monitor); monitor = null; } if (!project.isOpen()) { project.open(monitor); monitor = null; } } finally { if (monitor != null) { monitor.done(); } } } public static void addJavaNature(IProject project, IProgressMonitor monitor) throws CoreException { if (monitor != null && monitor.isCanceled()) { throw new OperationCanceledException(); } if (!project.hasNature(JavaCore.NATURE_ID)) { IProjectDescription description = project.getDescription(); String[] prevNatures = description.getNatureIds(); String[] newNatures = new String[prevNatures.length + 1]; System.arraycopy(prevNatures, 0, newNatures, 0, prevNatures.length); newNatures[prevNatures.length] = JavaCore.NATURE_ID; description.setNatureIds(newNatures); project.setDescription(description, monitor); } else { if (monitor != null) { monitor.worked(1); } } } public void configureJavaProject(IProgressMonitor monitor) throws CoreException, OperationCanceledException { configureJavaProject(null, monitor); } public void configureJavaProject(String newProjectCompliance, IProgressMonitor monitor) throws CoreException, OperationCanceledException { flush(fClassPathList.getElements(), fResourcePathList.getElements(), getJavaOutputLocation(), getJavaProject(), newProjectCompliance, monitor); initializeTimeStamps(); updateUI(); } /** * Sets the configured build path and output location to the given Java project. * If the project already exists, only build paths are updated. * <p> * If the classpath contains an Execution Environment entry, the EE's compiler compliance options * are used as project-specific options (unless the classpath already contained the same Execution Environment) * * @param classPathEntries the new classpath entries (list of {@link CPListElement}) * @param javaOutputLocation the output location * @param javaProject the Java project * @param newProjectCompliance compliance to set for a new project, can be <code>null</code> * @param monitor a progress monitor, or <code>null</code> * @throws CoreException if flushing failed * @throws OperationCanceledException if flushing has been cancelled */ public static void flush(List<CPListElement> classPathEntries, List<CPListElement> resourcePathEntries, IPath javaOutputLocation, IJavaProject javaProject, String newProjectCompliance, IProgressMonitor monitor) throws CoreException, OperationCanceledException { if (monitor == null) { monitor = new NullProgressMonitor(); } monitor.setTaskName(NewWizardMessages.BuildPathsBlock_operationdesc_java); monitor.beginTask("", classPathEntries.size() * 4 + 4); //$NON-NLS-1$ try { IProject project = javaProject.getProject(); IPath projPath = project.getFullPath(); IPath oldOutputLocation; try { oldOutputLocation = javaProject.getOutputLocation(); } catch (CoreException e) { oldOutputLocation = projPath.append( PreferenceConstants.getPreferenceStore().getString(PreferenceConstants.SRCBIN_BINNAME)); } if (oldOutputLocation.equals(projPath) && !javaOutputLocation.equals(projPath)) { if (CeylonBuildPathsBlock.hasClassfiles(project)) { if (CeylonBuildPathsBlock.getRemoveOldBinariesQuery(JavaPlugin.getActiveWorkbenchShell()) .doQuery(false, projPath)) { CeylonBuildPathsBlock.removeOldClassfiles(project); } } } else if (!javaOutputLocation.equals(oldOutputLocation)) { IFolder folder = ResourcesPlugin.getWorkspace().getRoot().getFolder(oldOutputLocation); if (folder.exists()) { if (folder.members().length == 0) { CeylonBuildPathsBlock.removeOldClassfiles(folder); } else { if (CeylonBuildPathsBlock.getRemoveOldBinariesQuery(JavaPlugin.getActiveWorkbenchShell()) .doQuery(folder.isDerived(), oldOutputLocation)) { CeylonBuildPathsBlock.removeOldClassfiles(folder); } } } } getCeylonModulesOutputFolder(project).delete(true, monitor); monitor.worked(1); IWorkspaceRoot fWorkspaceRoot = JavaPlugin.getWorkspace().getRoot(); //create and set the output path first if (!fWorkspaceRoot.exists(javaOutputLocation)) { CoreUtility.createDerivedFolder(fWorkspaceRoot.getFolder(javaOutputLocation), true, true, new SubProgressMonitor(monitor, 1)); } else { monitor.worked(1); } if (monitor.isCanceled()) { throw new OperationCanceledException(); } for (Iterator<CPListElement> iter = resourcePathEntries.iterator(); iter.hasNext();) { CPListElement entry = iter.next(); IResource res = entry.getResource(); //1 tick if (res instanceof IFolder && entry.getLinkTarget() == null && !res.exists()) { CoreUtility.createFolder((IFolder) res, true, true, new SubProgressMonitor(monitor, 1)); } else { monitor.worked(1); } //3 ticks if (entry.getEntryKind() == IClasspathEntry.CPE_SOURCE) { IPath folderOutput = (IPath) entry.getAttribute(CPListElement.OUTPUT); if (folderOutput != null && folderOutput.segmentCount() > 1) { IFolder folder = fWorkspaceRoot.getFolder(folderOutput); CoreUtility.createDerivedFolder(folder, true, true, new SubProgressMonitor(monitor, 1)); } else { monitor.worked(1); } IPath path = entry.getPath(); if (projPath.equals(path)) { monitor.worked(2); continue; } if (projPath.isPrefixOf(path)) { path = path.removeFirstSegments(projPath.segmentCount()); } IFolder folder = project.getFolder(path); IPath orginalPath = entry.getOrginalPath(); if (orginalPath == null) { if (!folder.exists()) { //New source folder needs to be created if (entry.getLinkTarget() == null) { CoreUtility.createFolder(folder, true, true, new SubProgressMonitor(monitor, 2)); } else { folder.createLink(entry.getLinkTarget(), IResource.ALLOW_MISSING_LOCAL, new SubProgressMonitor(monitor, 2)); } } } else { if (projPath.isPrefixOf(orginalPath)) { orginalPath = orginalPath.removeFirstSegments(projPath.segmentCount()); } IFolder orginalFolder = project.getFolder(orginalPath); if (entry.getLinkTarget() == null) { if (!folder.exists()) { //Source folder was edited, move to new location IPath parentPath = entry.getPath().removeLastSegments(1); if (projPath.isPrefixOf(parentPath)) { parentPath = parentPath.removeFirstSegments(projPath.segmentCount()); } if (parentPath.segmentCount() > 0) { IFolder parentFolder = project.getFolder(parentPath); if (!parentFolder.exists()) { CoreUtility.createFolder(parentFolder, true, true, new SubProgressMonitor(monitor, 1)); } else { monitor.worked(1); } } else { monitor.worked(1); } orginalFolder.move(entry.getPath(), true, true, new SubProgressMonitor(monitor, 1)); } } else { if (!folder.exists() || !entry.getLinkTarget().equals(entry.getOrginalLinkTarget())) { orginalFolder.delete(true, new SubProgressMonitor(monitor, 1)); folder.createLink(entry.getLinkTarget(), IResource.ALLOW_MISSING_LOCAL, new SubProgressMonitor(monitor, 1)); } } } } if (monitor.isCanceled()) { throw new OperationCanceledException(); } } int nEntries = classPathEntries.size(); IClasspathEntry[] classpath = new IClasspathEntry[nEntries]; int i = 0; for (Iterator<CPListElement> iter = classPathEntries.iterator(); iter.hasNext();) { CPListElement entry = iter.next(); classpath[i] = entry.getClasspathEntry(); i++; IResource res = entry.getResource(); //1 tick if (res instanceof IFolder && entry.getLinkTarget() == null && !res.exists()) { CoreUtility.createFolder((IFolder) res, true, true, new SubProgressMonitor(monitor, 1)); } else { monitor.worked(1); } //3 ticks if (entry.getEntryKind() == IClasspathEntry.CPE_SOURCE) { IPath folderOutput = (IPath) entry.getAttribute(CPListElement.OUTPUT); if (folderOutput != null && folderOutput.segmentCount() > 1) { IFolder folder = fWorkspaceRoot.getFolder(folderOutput); CoreUtility.createDerivedFolder(folder, true, true, new SubProgressMonitor(monitor, 1)); } else { monitor.worked(1); } IPath path = entry.getPath(); if (projPath.equals(path)) { monitor.worked(2); continue; } if (projPath.isPrefixOf(path)) { path = path.removeFirstSegments(projPath.segmentCount()); } IFolder folder = project.getFolder(path); IPath orginalPath = entry.getOrginalPath(); if (orginalPath == null) { if (!folder.exists()) { //New source folder needs to be created if (entry.getLinkTarget() == null) { CoreUtility.createFolder(folder, true, true, new SubProgressMonitor(monitor, 2)); } else { folder.createLink(entry.getLinkTarget(), IResource.ALLOW_MISSING_LOCAL, new SubProgressMonitor(monitor, 2)); } } } else { if (projPath.isPrefixOf(orginalPath)) { orginalPath = orginalPath.removeFirstSegments(projPath.segmentCount()); } IFolder orginalFolder = project.getFolder(orginalPath); if (entry.getLinkTarget() == null) { if (!folder.exists()) { //Source folder was edited, move to new location IPath parentPath = entry.getPath().removeLastSegments(1); if (projPath.isPrefixOf(parentPath)) { parentPath = parentPath.removeFirstSegments(projPath.segmentCount()); } if (parentPath.segmentCount() > 0) { IFolder parentFolder = project.getFolder(parentPath); if (!parentFolder.exists()) { CoreUtility.createFolder(parentFolder, true, true, new SubProgressMonitor(monitor, 1)); } else { monitor.worked(1); } } else { monitor.worked(1); } orginalFolder.move(entry.getPath(), true, true, new SubProgressMonitor(monitor, 1)); } } else { if (!folder.exists() || !entry.getLinkTarget().equals(entry.getOrginalLinkTarget())) { orginalFolder.delete(true, new SubProgressMonitor(monitor, 1)); folder.createLink(entry.getLinkTarget(), IResource.ALLOW_MISSING_LOCAL, new SubProgressMonitor(monitor, 1)); } } } } else { if (entry.getEntryKind() == IClasspathEntry.CPE_CONTAINER) { IPath path = entry.getPath(); if (!path.equals(entry.getOrginalPath())) { String eeID = JavaRuntime.getExecutionEnvironmentId(path); if (eeID != null) { BuildPathSupport.setEEComplianceOptions(javaProject, eeID, newProjectCompliance); newProjectCompliance = null; // don't set it again below } } if (newProjectCompliance != null) { setOptionsFromJavaProject(javaProject, newProjectCompliance); } } monitor.worked(3); } if (monitor.isCanceled()) { throw new OperationCanceledException(); } } javaProject.setRawClasspath(classpath, javaOutputLocation, new SubProgressMonitor(monitor, 2)); CeylonProjectConfig config = CeylonProjectConfig.get(project); List<String> srcDirs = new ArrayList<String>(); for (CPListElement cpe : classPathEntries) { if (cpe.getEntryKind() == IClasspathEntry.CPE_SOURCE) { srcDirs.add(configFilePath(project, cpe)); } } config.setProjectSourceDirectories(srcDirs); List<String> rsrcDirs = new ArrayList<String>(); for (CPListElement cpe : resourcePathEntries) { rsrcDirs.add(configFilePath(project, cpe)); } config.setProjectResourceDirectories(rsrcDirs); config.save(); } finally { monitor.done(); } } private static String configFilePath(IProject project, CPListElement cpe) { IPath linkTarget = cpe.getLinkTarget(); if (linkTarget == null) { // It's a relative path return cpe.getPath().makeRelativeTo(project.getFullPath()).toString(); } else { return cpe.getLinkTarget().toOSString(); } } private static void setOptionsFromJavaProject(IJavaProject javaProject, String newProjectCompliance) { @SuppressWarnings("unchecked") Map<String, String> options = javaProject.getOptions(false); JavaModelUtil.setComplianceOptions(options, newProjectCompliance); JavaModelUtil.setDefaultClassfileOptions(options, newProjectCompliance); // complete compliance options javaProject.setOptions(options); } public static boolean hasClassfiles(IResource resource) throws CoreException { if (resource.isDerived()) { return true; } if (resource instanceof IContainer) { IResource[] members = ((IContainer) resource).members(); for (int i = 0; i < members.length; i++) { if (hasClassfiles(members[i])) { return true; } } } return false; } public static void removeOldClassfiles(IResource resource) throws CoreException { if (resource.isDerived()) { resource.delete(false, null); } else if (resource instanceof IContainer) { IResource[] members = ((IContainer) resource).members(); for (int i = 0; i < members.length; i++) { removeOldClassfiles(members[i]); } } } public static IRemoveOldBinariesQuery getRemoveOldBinariesQuery(final Shell shell) { return new IRemoveOldBinariesQuery() { public boolean doQuery(final boolean removeFolder, final IPath oldOutputLocation) throws OperationCanceledException { final int[] res = new int[] { 1 }; Display.getDefault().syncExec(new Runnable() { public void run() { Shell sh = shell != null ? shell : JavaPlugin.getActiveWorkbenchShell(); String title = NewWizardMessages.BuildPathsBlock_RemoveBinariesDialog_title; String message; String pathLabel = BasicElementLabels.getPathLabel(oldOutputLocation, false); if (removeFolder) { message = Messages.format( NewWizardMessages.BuildPathsBlock_RemoveOldOutputFolder_description, pathLabel); } else { message = Messages.format( NewWizardMessages.BuildPathsBlock_RemoveBinariesDialog_description, pathLabel); } MessageDialog dialog = new MessageDialog(sh, title, null, message, MessageDialog.QUESTION, new String[] { IDialogConstants.YES_LABEL, IDialogConstants.NO_LABEL, IDialogConstants.CANCEL_LABEL }, 0); res[0] = dialog.open(); } }); if (res[0] == 0) { return true; } else if (res[0] == 1) { return false; } throw new OperationCanceledException(); } }; } // ---------- util method ------------ private IContainer chooseContainer(IPath outputPath) { Class<?>[] acceptedClasses = new Class[] { IProject.class, IFolder.class }; ISelectionStatusValidator validator = new TypedElementSelectionValidator(acceptedClasses, false); IProject[] allProjects = fWorkspaceRoot.getProjects(); ArrayList<IProject> rejectedElements = new ArrayList<IProject>(allProjects.length); IProject currProject = fCurrJProject.getProject(); for (int i = 0; i < allProjects.length; i++) { if (!allProjects[i].equals(currProject)) { rejectedElements.add(allProjects[i]); } } ViewerFilter filter = new TypedViewerFilter(acceptedClasses, rejectedElements.toArray()); ILabelProvider lp = new WorkbenchLabelProvider(); ITreeContentProvider cp = new WorkbenchContentProvider(); IResource initSelection = null; if (outputPath != null) { initSelection = fWorkspaceRoot.findMember(outputPath); } FolderSelectionDialog dialog = new FolderSelectionDialog(getShell(), lp, cp); dialog.setTitle(NewWizardMessages.BuildPathsBlock_ChooseOutputFolderDialog_title); dialog.setValidator(validator); dialog.setMessage(NewWizardMessages.BuildPathsBlock_ChooseOutputFolderDialog_description); dialog.addFilter(filter); dialog.setInput(fWorkspaceRoot); dialog.setInitialSelection(initSelection); dialog.setComparator(new ResourceComparator(ResourceComparator.NAME)); if (dialog.open() == Window.OK) { return (IContainer) dialog.getFirstResult(); } return null; } // -------- tab switching ---------- private void tabChanged(Widget widget) { if (widget instanceof TabItem) { TabItem tabItem = (TabItem) widget; BuildPathBasePage newPage = (BuildPathBasePage) tabItem.getData(); if (fCurrPage != null) { List<?> selection = fCurrPage.getSelection(); if (!selection.isEmpty()) { newPage.setSelection(selection, false); } } fCurrPage = newPage; fPageIndex = tabItem.getParent().getSelectionIndex(); } } private int getPageIndex(int entryKind) { switch (entryKind) { case IClasspathEntry.CPE_CONTAINER: case IClasspathEntry.CPE_LIBRARY: case IClasspathEntry.CPE_VARIABLE: return 2; case IClasspathEntry.CPE_PROJECT: return 1; case IClasspathEntry.CPE_SOURCE: return 0; } return 0; } private CPListElement findElement(IClasspathEntry entry) { CPListElement prefixMatch = null; int entryKind = entry.getEntryKind(); for (int i = 0, len = fClassPathList.getSize(); i < len; i++) { CPListElement curr = fClassPathList.getElement(i); if (curr.getEntryKind() == entryKind) { IPath entryPath = entry.getPath(); IPath currPath = curr.getPath(); if (currPath.equals(entryPath)) { return curr; } // in case there's no full match, look for a similar container (same ID segment): if (prefixMatch == null && entryKind == IClasspathEntry.CPE_CONTAINER) { int n = entryPath.segmentCount(); if (n > 0) { IPath genericContainerPath = n == 1 ? entryPath : entryPath.removeLastSegments(n - 1); if (n > 1 && genericContainerPath.isPrefixOf(currPath)) { prefixMatch = curr; } } } } } return prefixMatch; } public void setElementToReveal(IClasspathEntry entry, String attributeKey) { int pageIndex = getPageIndex(entry.getEntryKind()); if (fTabFolder == null) { fPageIndex = pageIndex; } else { fTabFolder.setSelection(pageIndex); CPListElement element = findElement(entry); if (element != null) { Object elementToSelect = element; if (attributeKey != null) { Object attrib = element.findAttributeElement(attributeKey); if (attrib != null) { elementToSelect = attrib; } } BuildPathBasePage page = (BuildPathBasePage) fTabFolder.getItem(pageIndex).getData(); List<Object> selection = new ArrayList<Object>(1); selection.add(elementToSelect); page.setSelection(selection, true); } } } public void addElement(IClasspathEntry entry) { int pageIndex = getPageIndex(entry.getEntryKind()); if (fTabFolder == null) { fPageIndex = pageIndex; } else { fTabFolder.setSelection(pageIndex); // Object page= fTabFolder.getItem(pageIndex).getData(); // if (page instanceof LibrariesWorkbookPage) { // CPListElement element= CPListElement.create(entry, true, fCurrJProject); // ((LibrariesWorkbookPage) page).addElement(element); // } } } public boolean isOKStatus() { return findMostSevereStatus().isOK(); } public void setFocus() { fSourceContainerPage.setFocus(); } private void refreshSourcePathsFromConfigFile() { final IProject project = fCurrJProject.getProject(); CeylonProjectConfig config = CeylonProjectConfig.get(project); List<String> sourceDirectories = config.getProjectSourceDirectories(); updateClassPathsFromConfigFile(sourceDirectories, new HashSet<String>()); } private void updateClassPathsFromConfigFile(List<String> sourceDirectories, final Set<String> newFolderNames) { final IProject project = fCurrJProject.getProject(); final List<CPListElement> newSourcePath = new ArrayList<CPListElement>(); for (final String path : sourceDirectories) { final IPath iPath = Path.fromOSString(path); if (!iPath.isAbsolute()) { IFolder folder = project.getFolder(iPath); newSourcePath.add( new CPListElement(fCurrJProject, IClasspathEntry.CPE_SOURCE, folder.getFullPath(), folder)); if (!folder.exists()) { someFoldersNeedToBeCreated = true; } } else { try { class CPListElementHolder { public CPListElement value = null; } final CPListElementHolder cpListElement = new CPListElementHolder(); project.accept(new IResourceVisitor() { @Override public boolean visit(IResource resource) throws CoreException { if (resource instanceof IFolder && resource.isLinked() && resource.getLocation() != null && resource.getLocation().equals(iPath)) { cpListElement.value = new CPListElement(null, fCurrJProject, IClasspathEntry.CPE_SOURCE, resource.getFullPath(), resource, resource.getLocation()); return false; } return resource instanceof IFolder || resource instanceof IProject; } }); if (cpListElement.value == null) { String newFolderName = iPath.lastSegment(); IFolder newFolder = project.getFolder(newFolderName); int counter = 1; while (newFolderNames.contains(newFolderName) || newFolder.exists()) { newFolderName = iPath.lastSegment() + "_" + counter++; newFolder = project.getFolder(newFolderName); } newFolderNames.add(newFolderName); cpListElement.value = new CPListElement(null, fCurrJProject, IClasspathEntry.CPE_SOURCE, newFolder.getFullPath(), newFolder, iPath); someFoldersNeedToBeCreated = true; } newSourcePath.add(cpListElement.value); } catch (CoreException ex) { ex.printStackTrace(); } } } ArrayList<CPListElement> exportedEntries = new ArrayList<>(); ArrayList<CPListElement> newClassPath = new ArrayList<>(); // Don't change all the non-source classpath entries for (CPListElement elem : fClassPathList.getElements()) { if (elem.getClasspathEntry().getEntryKind() != IClasspathEntry.CPE_SOURCE) { newClassPath.add(elem); } } for (CPListElement elem : fClassPathList.getCheckedElements()) { if (elem.getClasspathEntry().getEntryKind() != IClasspathEntry.CPE_SOURCE) { exportedEntries.add(elem); } } // Now all the new source entries newClassPath.addAll(newSourcePath); for (CPListElement elem : fClassPathList.getCheckedElements()) { if (newSourcePath.contains(elem)) { exportedEntries.add(elem); } } fClassPathList.setElements(newClassPath); fClassPathList.setCheckedElements(exportedEntries); fClassPathList.selectFirstElement(); } }