Java tutorial
/******************************************************************************* * Copyright (c) 2000, 2010 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.team.internal.ccvs.ui.wizards; import java.io.BufferedInputStream; import java.io.InputStream; import java.lang.reflect.InvocationTargetException; import java.util.*; import org.eclipse.compare.*; import org.eclipse.core.resources.*; import org.eclipse.core.runtime.*; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.viewers.*; import org.eclipse.osgi.util.NLS; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Widget; import org.eclipse.team.core.TeamException; import org.eclipse.team.core.variants.IResourceVariant; import org.eclipse.team.internal.ccvs.core.*; import org.eclipse.team.internal.ccvs.core.resources.CVSWorkspaceRoot; import org.eclipse.team.internal.ccvs.core.syncinfo.FolderSyncInfo; import org.eclipse.team.internal.ccvs.core.util.KnownRepositories; import org.eclipse.team.internal.ccvs.ui.*; import org.eclipse.team.internal.ccvs.ui.Policy; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.model.WorkbenchLabelProvider; import org.eclipse.ui.views.navigator.ResourceComparator; /** * Select the files to restore */ public class RestoreFromRepositoryFileSelectionPage extends CVSWizardPage { private TreeViewer fileTree; private CompareViewerPane fileSelectionPane; private CompareViewerPane revisionSelectionPane; private CheckboxTableViewer revisionsTable; private CompareViewerSwitchingPane fileContentPane; private HistoryTableProvider historyTableProvider; private AdaptableHierarchicalResourceList treeInput = new AdaptableHierarchicalResourceList( ResourcesPlugin.getWorkspace().getRoot(), new IResource[0]); private IContainer folder; private IFile selectedFile; private ILogEntry selectedRevision; private Map entriesCache = new HashMap(); private Map filesToRestore = new HashMap(); private static final int WIZARD_WIDTH = 550; class HistoryInput implements ITypedElement, IEncodedStreamContentAccessor, IModificationDate { IFile file; ILogEntry logEntry; HistoryInput(IFile file, ILogEntry logEntry) { this.file = file; this.logEntry = logEntry; } public InputStream getContents() throws CoreException { IStorage s = getStorageFromLogEntry(logEntry); if (s == null) return null; return new BufferedInputStream(s.getContents()); } public String getName() { return file.getName(); } public String getType() { return file.getFileExtension(); } public Image getImage() { return CompareUI.getImage(file); } public long getModificationDate() { return logEntry.getDate().getTime(); } public String getCharset() throws CoreException { IStorage s = getStorageFromLogEntry(logEntry); if (s instanceof IEncodedStorage) { return ((IEncodedStorage) s).getCharset(); } return null; } } /** * Constructor for RestoreFromRepositoryFileSelectionPage. * @param pageName * @param title * @param titleImage * @param description */ public RestoreFromRepositoryFileSelectionPage(String pageName, String title, ImageDescriptor titleImage, String description) { super(pageName, title, titleImage, description); } /** * @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite) */ public void createControl(Composite parent) { Composite composite = createComposite(parent, 1, false); setControl(composite); PlatformUI.getWorkbench().getHelpSystem().setHelp(composite, IHelpContextIds.RESTORE_FROM_REPOSITORY_FILE_SELECTION_PAGE); // Top and bottom panes: top is the two selection panes, bottom is the file content viewer Splitter vsplitter = new Splitter(composite, SWT.VERTICAL); GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL | GridData.VERTICAL_ALIGN_FILL | GridData.GRAB_VERTICAL); // Set the width to be extra wide to accomodate the two selection lists data.widthHint = WIZARD_WIDTH; vsplitter.setLayoutData(data); // Top left and top right panes: the left for the files, the right for the log entries Splitter hsplitter = new Splitter(vsplitter, SWT.HORIZONTAL); // Top left: file selection pane fileSelectionPane = new CompareViewerPane(hsplitter, SWT.BORDER | SWT.FLAT); data = new GridData(GridData.FILL_HORIZONTAL | GridData.FILL_VERTICAL); fileSelectionPane.setLayoutData(data); fileTree = createFileSelectionTree(fileSelectionPane); // Top right: Revision selection pane revisionSelectionPane = new CompareViewerPane(hsplitter, SWT.BORDER | SWT.FLAT); data = new GridData(GridData.FILL_HORIZONTAL | GridData.FILL_VERTICAL); revisionSelectionPane.setLayoutData(data); historyTableProvider = new HistoryTableProvider(); revisionsTable = createRevisionSelectionTable(revisionSelectionPane, historyTableProvider); revisionSelectionPane.setText(CVSUIMessages.RestoreFromRepositoryFileSelectionPage_emptyRevisionPane); // Bottom: File content viewer fileContentPane = new CompareViewerSwitchingPane(vsplitter, SWT.BORDER | SWT.FLAT) { protected Viewer getViewer(Viewer oldViewer, Object input) { return CompareUI.findContentViewer(oldViewer, input, this, null); } }; hsplitter.setWeights(new int[] { 40, 60 }); initializeValues(); updateWidgetEnablements(); Dialog.applyDialogFont(parent); } protected CheckboxTableViewer createRevisionSelectionTable(CompareViewerPane composite, HistoryTableProvider tableProvider) { CheckboxTableViewer table = tableProvider.createCheckBoxTable(composite); table.setContentProvider(new IStructuredContentProvider() { public Object[] getElements(Object inputElement) { ILogEntry[] entries = getSelectedEntries(); if (entries != null) return entries; return new Object[0]; } public void dispose() { } public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { } }); table.setInput(this); table.getTable().addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { // Handle check selection in the check state listener if (e.detail == SWT.CHECK) return; handleRevisionSelection(e.item); } }); table.addCheckStateListener(new ICheckStateListener() { public void checkStateChanged(CheckStateChangedEvent event) { handleRevisionChecked(event); } }); composite.setContent(table.getControl()); return table; } protected TreeViewer createFileSelectionTree(CompareViewerPane composite) { TreeViewer tree = new TreeViewer(composite, SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER); tree.setUseHashlookup(true); tree.setContentProvider(treeInput.getTreeContentProvider()); tree.setLabelProvider(new DecoratingLabelProvider(new WorkbenchLabelProvider() { protected String decorateText(String input, Object element) { String text; if (element instanceof IFolder && element.equals(folder)) { text = super.decorateText(folder.getProjectRelativePath().toString(), element); } else { ILogEntry entry = (ILogEntry) filesToRestore.get(element); text = super.decorateText(input, element); if (entry != null) { text = NLS.bind(CVSUIMessages.RestoreFromRepositoryFileSelectionPage_fileToRestore, new String[] { text, entry.getRevision() }); } } return text; } }, CVSUIPlugin.getPlugin().getWorkbench().getDecoratorManager().getLabelDecorator())); tree.setComparator(new ResourceComparator(ResourceComparator.NAME)); tree.setInput(treeInput); GridData data = new GridData(GridData.FILL_BOTH | GridData.GRAB_VERTICAL); tree.getTree().setLayoutData(data); tree.addPostSelectionChangedListener(new ISelectionChangedListener() { public void selectionChanged(SelectionChangedEvent event) { handleFileSelection(event); } }); composite.setContent(tree.getControl()); return tree; } /** * Method updateWidgetEnablements. */ private void updateWidgetEnablements() { if (filesToRestore.isEmpty()) { setPageComplete(false); setErrorMessage(null); return; } for (Iterator iter = filesToRestore.keySet().iterator(); iter.hasNext();) { IFile file = (IFile) iter.next(); if (file.exists()) { setPageComplete(false); setErrorMessage(NLS.bind(CVSUIMessages.RestoreFromRepositoryFileSelectionPage_fileExists, new String[] { file.getName() })); return; } ILogEntry entry = (ILogEntry) filesToRestore.get(file); if (entry.isDeletion()) { setPageComplete(false); setErrorMessage(NLS.bind(CVSUIMessages.RestoreFromRepositoryFileSelectionPage_revisionIsDeletion, new String[] { entry.getRevision(), file.getName() })); return; } } setPageComplete(true); setErrorMessage(null); } /** * Method initializeValues. */ private void initializeValues() { refresh(); } /** * Sets the folder. * @param folder The folder to set */ public void setInput(IContainer folder, ICVSFile[] files) { if (folder.equals(this.folder)) return; this.folder = folder; setTreeInput(folder, files); initializeValues(); updateWidgetEnablements(); } /* * Set the resource tree input to the files that were deleted */ private void setTreeInput(IContainer folder, ICVSFile[] cvsFiles) { reset(); IResource[] files = new IResource[cvsFiles.length]; for (int i = 0; i < cvsFiles.length; i++) { files[i] = cvsFiles[i].getIResource(); } treeInput.setResources(files); // kludge to avoid auto-selection of first element // set the root to the folder's parent so the folder appears in the tree treeInput.setRoot(folder.getParent()); refresh(); } private void reset() { this.selectedFile = null; this.selectedRevision = null; treeInput.setResources(null); filesToRestore = new HashMap(); if (fileContentPane != null && !fileContentPane.isDisposed()) { fileContentPane.setInput(null); } updateWidgetEnablements(); } /** * Method refresh. */ private void refresh() { if (folder == null) return; if (fileSelectionPane != null && !fileSelectionPane.isDisposed()) { fileSelectionPane .setText(NLS.bind(CVSUIMessages.RestoreFromRepositoryFileSelectionPage_fileSelectionPaneTitle, new String[] { folder.getProject().getName() })); fileSelectionPane.setImage(CompareUI.getImage(folder.getProject())); } if (revisionSelectionPane != null && !revisionSelectionPane.isDisposed()) { if (selectedFile == null) { revisionSelectionPane .setText(CVSUIMessages.RestoreFromRepositoryFileSelectionPage_emptyRevisionPane); revisionSelectionPane.setImage(null); } } // Empty the file content viewer if (fileContentPane != null && !fileContentPane.isDisposed()) { fileContentPane.setInput(null); } // refresh the tree if (fileTree != null) { // If the parent folder is in the tree, make sure it is expanded fileTree.setExpandedState(folder, true); fileTree.refresh(); } if (revisionsTable != null) revisionsTable.refresh(); } /* * Set the log entry table input to the fetched entries in response to a file selection */ private void setLogEntryTableInput(ILogEntry[] entries) { this.selectedRevision = null; // Refresh the table so it picks up the selected entries through its content provider revisionsTable.refresh(); // Check the previously checked entry if one exists ILogEntry selectedEntry = (ILogEntry) filesToRestore.get(selectedFile); if (selectedEntry != null) { revisionsTable.setChecked(selectedEntry, true); } // Disable entries that represent deletions since they can't be loaded for (int i = 0; i < entries.length; i++) { ILogEntry entry = entries[i]; if (entry.isDeletion()) { revisionsTable.setGrayed(entry, true); } } // Set the titlebar text for the revisions table revisionSelectionPane .setText(NLS.bind(CVSUIMessages.RestoreFromRepositoryFileSelectionPage_revisionSelectionPaneTitle, new String[] { selectedFile.getName() })); revisionSelectionPane.setImage(CompareUI.getImage(selectedFile)); // Clear the file content pane fileContentPane.setInput(null); } private void handleFileSelection(SelectionChangedEvent event) { ISelection selection = event.getSelection(); if (selection == null || selection.isEmpty()) { clearSelection(); } else { if (selection instanceof IStructuredSelection) { IStructuredSelection structuredSelection = (IStructuredSelection) selection; IResource resource = (IResource) structuredSelection.getFirstElement(); if (resource instanceof IFile) { handleFileSelection((IFile) resource); } else { clearSelection(); } } } } /** * Method handleFileSelection. * @param file */ private void handleFileSelection(IFile file) { if (this.selectedFile == file) return; this.selectedFile = file; if (entriesCache.get(file) == null) { try { // First, we need to create a remote file handle so we can get the log entries ICVSFolder parent = CVSWorkspaceRoot.getCVSFolderFor(file.getParent()); FolderSyncInfo info = parent.getFolderSyncInfo(); ICVSRepositoryLocation location = KnownRepositories.getInstance().getRepository(info.getRoot()); final ICVSRemoteFile remoteFile = location.getRemoteFile( new Path(null, info.getRepository()).append(file.getName()).toString(), CVSTag.DEFAULT); // Then we need to fetch the log entries getContainer().run(true, true, new IRunnableWithProgress() { public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { try { // fetch the entries ILogEntry[] entries = remoteFile.getLogEntries(monitor); // cache the entries with the selected file entriesCache.put(selectedFile, entries); } catch (TeamException e) { throw new InvocationTargetException(e); } } }); } catch (CVSException e) { setErrorMessage(CVSUIPlugin.openError(getShell(), null, null, e, CVSUIPlugin.PERFORM_SYNC_EXEC) .getMessage()); return; } catch (InvocationTargetException e) { setErrorMessage(CVSUIPlugin.openError(getShell(), null, null, e, CVSUIPlugin.PERFORM_SYNC_EXEC) .getMessage()); return; } catch (InterruptedException e) { return; } } // Set the log table to display the entries for the selected file setLogEntryTableInput(getSelectedEntries()); } private ILogEntry[] getSelectedEntries() { return (ILogEntry[]) entriesCache.get(selectedFile); } private IStorage getStorageFromLogEntry(final ILogEntry logEntry) { final IStorage[] s = new IStorage[] { null }; try { getContainer().run(true, true, new IRunnableWithProgress() { public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { try { ICVSRemoteFile remoteFile = logEntry.getRemoteFile(); s[0] = ((IResourceVariant) remoteFile).getStorage(monitor); } catch (TeamException e) { throw new InvocationTargetException(e); } } }); } catch (InvocationTargetException e) { setErrorMessage( CVSUIPlugin.openError(getShell(), null, null, e, CVSUIPlugin.PERFORM_SYNC_EXEC).getMessage()); return null; } catch (InterruptedException e) { return null; } return s[0]; } private void handleRevisionChecked(CheckStateChangedEvent event) { if (event.getChecked()) { revisionsTable.setCheckedElements(new Object[] { event.getElement() }); filesToRestore.put(selectedFile, event.getElement()); } if (revisionsTable.getCheckedElements().length == 0) { filesToRestore.remove(selectedFile); } fileTree.refresh(); updateWidgetEnablements(); } /* * A revision in the revision table has been selected. * Populate the file contents pane with the selected log entry. */ private void handleRevisionSelection(Widget w) { if (fileContentPane != null && !fileContentPane.isDisposed()) { Object o = w.getData(); if (o instanceof ILogEntry) { ILogEntry selected = (ILogEntry) o; if (this.selectedRevision == selected) return; this.selectedRevision = selected; if (selected.isDeletion()) { fileContentPane.setInput(null); } else { fileContentPane.setInput(new HistoryInput(selectedFile, selected)); fileContentPane.setText(getEditionLabel(selectedFile, selected)); fileContentPane.setImage(CompareUI.getImage(selectedFile)); } } else { fileContentPane.setInput(null); } } } /** * Method getEditionLabel. * @param selectedFile * @param selected * @return String */ private String getEditionLabel(IFile selectedFile, ILogEntry selected) { return NLS.bind(CVSUIMessages.RestoreFromRepositoryFileSelectionPage_fileContentPaneTitle, (new Object[] { selectedFile.getName(), selected.getRevision(), selectedFile.getFullPath().makeRelative().removeLastSegments(1).toString() })); } public boolean restoreSelectedFiles() { try { getContainer().run(true, true, new IRunnableWithProgress() { public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { try { monitor.beginTask(null, 100 * filesToRestore.size()); for (Iterator iter = filesToRestore.keySet().iterator(); iter.hasNext();) { IFile file = (IFile) iter.next(); ILogEntry entry = (ILogEntry) filesToRestore.get(file); ensureParentExists(file); file.create(entry.getRemoteFile().getContents(Policy.subMonitorFor(monitor, 50)), false, Policy.subMonitorFor(monitor, 50)); } } catch (TeamException e) { throw new InvocationTargetException(e); } catch (CoreException e) { throw new InvocationTargetException(e); } finally { monitor.done(); } } }); } catch (InvocationTargetException e) { setErrorMessage( CVSUIPlugin.openError(getShell(), null, null, e, CVSUIPlugin.PERFORM_SYNC_EXEC).getMessage()); return false; } catch (InterruptedException e) { return false; } return true; } /** * Method ensureParentExists. * @param file */ private void ensureParentExists(IResource resource) throws CoreException { IContainer parent = resource.getParent(); if (!parent.exists() && parent.getType() == IResource.FOLDER) { ensureParentExists(parent); ((IFolder) parent).create(false, true, null); } } private void clearSelection() { this.selectedFile = null; this.selectedRevision = null; refresh(); } }