Java tutorial
/******************************************************************************* * Copyright (c) 2000, 2012 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 * Sebastian Davids <sdavids@gmx.de> - bug 74959 * Maik Schreiber - bug 102461 * William Mitsuda (wmitsuda@gmail.com) - Bug 153879 [Wizards] configurable size of cvs commit comment history *******************************************************************************/ package org.eclipse.team.internal.ccvs.ui.repo; import java.io.*; import java.lang.reflect.InvocationTargetException; import java.util.*; import javax.xml.parsers.*; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.*; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.jface.window.Window; import org.eclipse.osgi.util.NLS; import org.eclipse.swt.widgets.Shell; import org.eclipse.team.core.TeamException; import org.eclipse.team.internal.ccvs.core.*; import org.eclipse.team.internal.ccvs.core.connection.CVSRepositoryLocation; 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.IWorkingSet; import org.xml.sax.InputSource; import org.xml.sax.SAXException; /** * This class is repsible for maintaining the UI's list of known repositories, * and a list of known tags within each of those repositories. * * It also provides a number of useful methods for assisting in repository operations. */ public class RepositoryManager { // old state file private static final String STATE_FILE = ".repositoryManagerState"; //$NON-NLS-1$ private static final int STATE_FILE_VERSION_1 = -1; // new state file private static final String REPOSITORIES_VIEW_FILE = "repositoriesView.xml"; //$NON-NLS-1$ private static final String COMMENT_HIST_FILE = "commitCommentHistory.xml"; //$NON-NLS-1$ private static final String COMMENT_TEMPLATES_FILE = "commentTemplates.xml"; //$NON-NLS-1$ static final String ELEMENT_COMMIT_COMMENT = "CommitComment"; //$NON-NLS-1$ static final String ELEMENT_COMMIT_HISTORY = "CommitComments"; //$NON-NLS-1$ static final String ELEMENT_COMMENT_TEMPLATES = "CommitCommentTemplates"; //$NON-NLS-1$ private Map repositoryRoots = new HashMap(); List listeners = new ArrayList(); // The previously remembered comment static String[] previousComments = new String[0]; static String[] commentTemplates = new String[0]; public static boolean notifyRepoView = true; // Cache of changed repository roots private int notificationLevel = 0; private Map changedRepositories = new HashMap(); public static final int DEFAULT_MAX_COMMENTS = 10; private int maxComments = DEFAULT_MAX_COMMENTS; public void setMaxComments(int maxComments) { if (maxComments > 0) { this.maxComments = maxComments; if (maxComments < previousComments.length) { String[] newComments = new String[maxComments]; System.arraycopy(previousComments, 0, newComments, 0, maxComments); previousComments = newComments; } } } /** * Answer an array of all known remote roots. */ public ICVSRepositoryLocation[] getKnownRepositoryLocations() { return KnownRepositories.getInstance().getRepositories(); } /** * Method getRepositoryRoots. * @param iCVSRepositoryLocations * @return RepositoryRoot[] */ private RepositoryRoot[] getRepositoryRoots(ICVSRepositoryLocation[] locations) { List roots = new ArrayList(); for (int i = 0; i < locations.length; i++) { ICVSRepositoryLocation location = locations[i]; RepositoryRoot root = getRepositoryRootFor(location); if (root != null) roots.add(root); } return (RepositoryRoot[]) roots.toArray(new RepositoryRoot[roots.size()]); } public RepositoryRoot[] getKnownRepositoryRoots() { return getRepositoryRoots(getKnownRepositoryLocations()); } /** * Get the list of known branch tags for a given remote root. */ public CVSTag[] getKnownTags(ICVSFolder project, int tagType) { try { CVSTag[] tags = getKnownTags(project); Set result = new HashSet(); for (int i = 0; i < tags.length; i++) { CVSTag tag = tags[i]; if (tag.getType() == tagType) result.add(tag); } return (CVSTag[]) result.toArray(new CVSTag[result.size()]); } catch (CVSException e) { CVSUIPlugin.log(e); return new CVSTag[0]; } } /** * Get the list of known version tags for a given project. */ public CVSTag[] getKnownTags(ICVSRepositoryLocation location, int tagType) { Set result = new HashSet(); RepositoryRoot root = (RepositoryRoot) repositoryRoots.get(location.getLocation(false)); if (root != null) { CVSTag[] tags = root.getAllKnownTags(); for (int i = 0; i < tags.length; i++) { CVSTag tag = tags[i]; if (tag.getType() == tagType) result.add(tag); } } return (CVSTag[]) result.toArray(new CVSTag[0]); } /** * Method getKnownTags. * @param repository * @param set * @param i * @param monitor * @return CVSTag[] */ public CVSTag[] getKnownTags(ICVSRepositoryLocation repository, IWorkingSet set, int tagType, IProgressMonitor monitor) throws CVSException { if (set == null) { return getKnownTags(repository, tagType); } ICVSRemoteResource[] folders = getFoldersForTag(repository, CVSTag.DEFAULT, monitor); folders = filterResources(set, folders); Set tags = new HashSet(); for (int i = 0; i < folders.length; i++) { ICVSRemoteFolder folder = (ICVSRemoteFolder) folders[i]; tags.addAll(Arrays.asList(getKnownTags(folder, tagType))); } return (CVSTag[]) tags.toArray(new CVSTag[tags.size()]); } public CVSTag[] getKnownTags(ICVSFolder project) throws CVSException { RepositoryRoot root = getRepositoryRootFor(project); String remotePath = RepositoryRoot.getRemotePathFor(project); return root.getAllKnownTags(remotePath); } /* * XXX I hope this methos is not needed in this form */ public Map getKnownProjectsAndVersions(ICVSRepositoryLocation location) { Map knownTags = new HashMap(); RepositoryRoot root = getRepositoryRootFor(location); String[] paths = root.getKnownRemotePaths(); for (int i = 0; i < paths.length; i++) { String path = paths[i]; Set result = new HashSet(); result.addAll(Arrays.asList(root.getAllKnownTags(path))); knownTags.put(path, result); } return knownTags; } public ICVSRemoteResource[] getFoldersForTag(ICVSRepositoryLocation location, CVSTag tag, IProgressMonitor monitor) throws CVSException { monitor = Policy.monitorFor(monitor); try { monitor.beginTask( NLS.bind(CVSUIMessages.RepositoryManager_fetchingRemoteFolders, new String[] { tag.getName() }), 100); if (tag.getType() == CVSTag.HEAD) { ICVSRemoteResource[] resources = location.members(tag, false, Policy.subMonitorFor(monitor, 60)); RepositoryRoot root = getRepositoryRootFor(location); ICVSRemoteResource[] modules = root.getDefinedModules(tag, Policy.subMonitorFor(monitor, 40)); ICVSRemoteResource[] result = new ICVSRemoteResource[resources.length + modules.length]; System.arraycopy(resources, 0, result, 0, resources.length); System.arraycopy(modules, 0, result, resources.length, modules.length); return result; } if (tag.getType() == CVSTag.DATE) { ICVSRemoteResource[] resources = location.members(tag, false, Policy.subMonitorFor(monitor, 60)); RepositoryRoot root = getRepositoryRootFor(location); ICVSRemoteResource[] modules = root.getDefinedModules(tag, Policy.subMonitorFor(monitor, 40)); ICVSRemoteResource[] result = new ICVSRemoteResource[resources.length + modules.length]; System.arraycopy(resources, 0, result, 0, resources.length); System.arraycopy(modules, 0, result, resources.length, modules.length); return result; } Set result = new HashSet(); // Get the tags for the location RepositoryRoot root = getRepositoryRootFor(location); String[] paths = root.getRemoteChildrenForTag(null, tag); for (int i = 0; i < paths.length; i++) { String path = paths[i]; ICVSRemoteFolder remote = root.getRemoteFolder(path, tag, Policy.subMonitorFor(monitor, 100)); result.add(remote); } return (ICVSRemoteResource[]) result.toArray(new ICVSRemoteResource[result.size()]); } finally { monitor.done(); } } /** * Returns a list of child resources for given folder that are known to * contain given tag. If the return list is empty than given tag exists * directly in given folder and its children should be retrieved directly * from the repository. * * NOTE: Resources are cached only for tags of type CVSTag.Branch and * CVSTag.Version. Other types of tags will always return empty list. * * @param location * CVS repository location * @param parentFolder * folder to check tags for * @param tag * @param monitor * @return a list of remote resources that are known to contain given tag or * empty list if resources should be retrieved from the repository * @throws CVSException */ public ICVSRemoteResource[] getCachedChildrenForTag(ICVSRepositoryLocation location, ICVSRemoteFolder parentFolder, CVSTag tag, IProgressMonitor monitor) throws CVSException { if (tag == null || tag.getType() == CVSTag.HEAD || tag.getType() == CVSTag.DATE) { // folders are kept in cache only for tags and versions return new ICVSRemoteResource[0]; } monitor = Policy.monitorFor(monitor); Set result = new HashSet(); RepositoryRoot root = getRepositoryRootFor(location); // if remote folder is null return the subfolders of repository root String[] paths = root.getRemoteChildrenForTag( parentFolder == null ? null : RepositoryRoot.getRemotePathFor(parentFolder), tag); monitor.beginTask(NLS.bind(CVSUIMessages.RemoteFolderElement_fetchingRemoteChildren, new String[] { NLS.bind(CVSUIMessages.RemoteFolderElement_nameAndTag, new String[] { parentFolder.getName(), tag.getName() }) }), 10 * paths.length); try { for (int i = 0; i < paths.length; i++) { String path = paths[i]; ICVSRemoteFolder remote = root.getRemoteFolder(path, tag, Policy.subMonitorFor(monitor, 10)); result.add(remote); } return (ICVSRemoteResource[]) result.toArray(new ICVSRemoteResource[result.size()]); } finally { monitor.done(); } } /* * Fetches tags from auto-refresh files if they exist. Then fetches tags from the user defined auto-refresh file * list. The fetched tags are cached in the CVS ui plugin's tag cache. */ public CVSTag[] refreshDefinedTags(ICVSFolder folder, boolean recurse, boolean notify, IProgressMonitor monitor) throws TeamException { RepositoryRoot root = getRepositoryRootFor(folder); CVSTag[] tags = root.refreshDefinedTags(folder, recurse, monitor); if (tags.length > 0 && notify) broadcastRepositoryChange(root); return tags; } /** * A repository root has been added. Notify any listeners. */ public void rootAdded(ICVSRepositoryLocation root) { Iterator it = listeners.iterator(); while (it.hasNext()) { IRepositoryListener listener = (IRepositoryListener) it.next(); listener.repositoryAdded(root); } } /** * A repository root has been removed. * Remove the tags defined for this root and notify any listeners */ public void rootRemoved(ICVSRepositoryLocation root) { RepositoryRoot repoRoot = (RepositoryRoot) repositoryRoots.remove(root.getLocation(false)); if (repoRoot != null) broadcastRepositoryChange(repoRoot); } /** * Accept tags for any CVS resource. However, for the time being, * the given version tags are added to the list of known tags for the * remote ancestor of the resource that is a direct child of the remote root */ public void addTags(ICVSResource resource, CVSTag[] tags) throws CVSException { RepositoryRoot root = getRepositoryRootFor(resource); // XXX could be a file or folder String remotePath = RepositoryRoot.getRemotePathFor(resource); root.addTags(remotePath, tags); broadcastRepositoryChange(root); } public void addDateTag(ICVSRepositoryLocation location, CVSTag tag) { if (tag == null) return; RepositoryRoot root = getRepositoryRootFor(location); root.addDateTag(tag); broadcastRepositoryChange(root); } public CVSTag[] getDateTags(ICVSRepositoryLocation location) { RepositoryRoot root = getRepositoryRootFor(location); return root.getDateTags(); } public void removeDateTag(ICVSRepositoryLocation location, CVSTag tag) { RepositoryRoot root = getRepositoryRootFor(location); root.removeDateTag(tag); broadcastRepositoryChange(root); } public void setAutoRefreshFiles(ICVSFolder project, String[] filePaths) throws CVSException { RepositoryRoot root = getRepositoryRootFor(project); String remotePath = RepositoryRoot.getRemotePathFor(project); root.setAutoRefreshFiles(remotePath, filePaths); } public String[] getAutoRefreshFiles(ICVSFolder project) throws CVSException { RepositoryRoot root = getRepositoryRootFor(project); String remotePath = RepositoryRoot.getRemotePathFor(project); return root.getAutoRefreshFiles(remotePath); } /** * Remove the given tags from the list of known tags for the * given remote root. */ public void removeTags(ICVSFolder project, CVSTag[] tags) throws CVSException { RepositoryRoot root = getRepositoryRootFor(project); String remotePath = RepositoryRoot.getRemotePathFor(project); root.removeTags(remotePath, tags); broadcastRepositoryChange(root); } public void startup() { loadState(); loadCommentHistory(); loadCommentTemplates(); CVSProviderPlugin.getPlugin().addRepositoryListener(new ICVSListener() { public void repositoryAdded(ICVSRepositoryLocation root) { rootAdded(root); } public void repositoryRemoved(ICVSRepositoryLocation root) { rootRemoved(root); } }); IPreferenceStore store = CVSUIPlugin.getPlugin().getPreferenceStore(); store.addPropertyChangeListener(new IPropertyChangeListener() { public void propertyChange(PropertyChangeEvent event) { if (event.getProperty().equals(ICVSUIConstants.PREF_COMMIT_COMMENTS_MAX_HISTORY)) { Object newValue = event.getNewValue(); if (newValue instanceof String) { try { setMaxComments(Integer.parseInt((String) newValue)); } catch (NumberFormatException e) { // fail silently } } } } }); setMaxComments(store.getInt(ICVSUIConstants.PREF_COMMIT_COMMENTS_MAX_HISTORY)); } public void shutdown() throws TeamException { saveState(); saveCommentHistory(); saveCommentTemplates(); } private void loadState() { IPath pluginStateLocation = CVSUIPlugin.getPlugin().getStateLocation().append(REPOSITORIES_VIEW_FILE); File file = pluginStateLocation.toFile(); if (file.exists()) { try { BufferedInputStream is = new BufferedInputStream(new FileInputStream(file)); try { readState(is); } finally { is.close(); } } catch (IOException e) { CVSUIPlugin.log(IStatus.ERROR, CVSUIMessages.RepositoryManager_ioException, e); } catch (TeamException e) { CVSUIPlugin.log(e); } } else { IPath oldPluginStateLocation = CVSUIPlugin.getPlugin().getStateLocation().append(STATE_FILE); file = oldPluginStateLocation.toFile(); if (file.exists()) { try { DataInputStream dis = new DataInputStream(new FileInputStream(file)); try { readOldState(dis); } finally { dis.close(); } saveState(); file.delete(); } catch (IOException e) { CVSUIPlugin.log(IStatus.ERROR, CVSUIMessages.RepositoryManager_ioException, e); } catch (TeamException e) { CVSUIPlugin.log(e); } } } } private void loadCommentHistory() { IPath pluginStateLocation = CVSUIPlugin.getPlugin().getStateLocation().append(COMMENT_HIST_FILE); File file = pluginStateLocation.toFile(); if (!file.exists()) return; try { BufferedInputStream is = new BufferedInputStream(new FileInputStream(file)); try { readCommentHistory(is); } finally { is.close(); } } catch (IOException e) { CVSUIPlugin.log(IStatus.ERROR, CVSUIMessages.RepositoryManager_ioException, e); } catch (TeamException e) { CVSUIPlugin.log(e); } } private void loadCommentTemplates() { IPath pluginStateLocation = CVSUIPlugin.getPlugin().getStateLocation().append(COMMENT_TEMPLATES_FILE); File file = pluginStateLocation.toFile(); if (!file.exists()) return; try { BufferedInputStream is = new BufferedInputStream(new FileInputStream(file)); try { readCommentTemplates(is); } finally { is.close(); } } catch (IOException e) { CVSUIPlugin.log(IStatus.ERROR, CVSUIMessages.RepositoryManager_ioException, e); } catch (TeamException e) { CVSUIPlugin.log(e); } } protected void saveState() throws TeamException { IPath pluginStateLocation = CVSUIPlugin.getPlugin().getStateLocation(); File tempFile = pluginStateLocation.append(REPOSITORIES_VIEW_FILE + ".tmp").toFile(); //$NON-NLS-1$ File stateFile = pluginStateLocation.append(REPOSITORIES_VIEW_FILE).toFile(); try { XMLWriter writer = new XMLWriter(new BufferedOutputStream(new FileOutputStream(tempFile))); try { writeState(writer); } finally { writer.close(); } if (stateFile.exists()) { stateFile.delete(); } boolean renamed = tempFile.renameTo(stateFile); if (!renamed) { throw new TeamException(new Status(IStatus.ERROR, CVSUIPlugin.ID, TeamException.UNABLE, NLS .bind(CVSUIMessages.RepositoryManager_rename, new String[] { tempFile.getAbsolutePath() }), null)); } } catch (IOException e) { throw new TeamException(new Status(IStatus.ERROR, CVSUIPlugin.ID, TeamException.UNABLE, NLS.bind(CVSUIMessages.RepositoryManager_save, new String[] { stateFile.getAbsolutePath() }), e)); } } private void writeState(XMLWriter writer) { writer.startTag(RepositoriesViewContentHandler.REPOSITORIES_VIEW_TAG, null, true); // Write the repositories Collection repos = Arrays.asList(getKnownRepositoryLocations()); Iterator it = repos.iterator(); while (it.hasNext()) { CVSRepositoryLocation location = (CVSRepositoryLocation) it.next(); RepositoryRoot root = getRepositoryRootFor(location); root.writeState(writer); } writer.endTag(RepositoriesViewContentHandler.REPOSITORIES_VIEW_TAG); } private void readState(InputStream stream) throws IOException, TeamException { try { SAXParserFactory factory = SAXParserFactory.newInstance(); SAXParser parser = factory.newSAXParser(); parser.parse(new InputSource(stream), new RepositoriesViewContentHandler(this)); } catch (SAXException ex) { IStatus status = new CVSStatus(IStatus.ERROR, CVSStatus.ERROR, NLS.bind( CVSUIMessages.RepositoryManager_parsingProblem, new String[] { REPOSITORIES_VIEW_FILE }), ex); throw new CVSException(status); } catch (ParserConfigurationException ex) { IStatus status = new CVSStatus(IStatus.ERROR, CVSStatus.ERROR, NLS.bind( CVSUIMessages.RepositoryManager_parsingProblem, new String[] { REPOSITORIES_VIEW_FILE }), ex); throw new CVSException(status); } } private void readCommentHistory(InputStream stream) throws IOException, TeamException { try { SAXParserFactory factory = SAXParserFactory.newInstance(); SAXParser parser = factory.newSAXParser(); parser.parse(new InputSource(stream), new CommentHistoryContentHandler()); } catch (SAXException ex) { IStatus status = new CVSStatus(IStatus.ERROR, CVSStatus.ERROR, NLS.bind(CVSUIMessages.RepositoryManager_parsingProblem, new String[] { COMMENT_HIST_FILE }), ex); throw new CVSException(status); } catch (ParserConfigurationException ex) { IStatus status = new CVSStatus(IStatus.ERROR, CVSStatus.ERROR, NLS.bind(CVSUIMessages.RepositoryManager_parsingProblem, new String[] { COMMENT_HIST_FILE }), ex); throw new CVSException(status); } } private void readOldState(DataInputStream dis) throws IOException, TeamException { int repoSize = dis.readInt(); boolean version1 = false; if (repoSize == STATE_FILE_VERSION_1) { version1 = true; repoSize = dis.readInt(); } for (int i = 0; i < repoSize; i++) { ICVSRepositoryLocation root = KnownRepositories.getInstance().getRepository(dis.readUTF()); RepositoryRoot repoRoot = getRepositoryRootFor(root); // read branch tags associated with this root int tagsSize = dis.readInt(); CVSTag[] branchTags = new CVSTag[tagsSize]; for (int j = 0; j < tagsSize; j++) { String tagName = dis.readUTF(); int tagType = dis.readInt(); branchTags[j] = new CVSTag(tagName, tagType); } // Ignore the branch tags since they are handled differently now // addBranchTags(root, branchTags); // read the number of projects for this root that have version tags int projSize = dis.readInt(); if (projSize > 0) { for (int j = 0; j < projSize; j++) { String name = dis.readUTF(); Set tagSet = new HashSet(); int numTags = dis.readInt(); for (int k = 0; k < numTags; k++) { tagSet.add(new CVSTag(dis.readUTF(), CVSTag.VERSION)); } CVSTag[] tags = (CVSTag[]) tagSet.toArray(new CVSTag[tagSet.size()]); repoRoot.addTags(name, tags); } } // read the auto refresh filenames for this project if (version1) { try { projSize = dis.readInt(); if (projSize > 0) { for (int j = 0; j < projSize; j++) { String name = dis.readUTF(); Set filenames = new HashSet(); int numFilenames = dis.readInt(); for (int k = 0; k < numFilenames; k++) { filenames.add(name + "/" + dis.readUTF()); //$NON-NLS-1$ } repoRoot.setAutoRefreshFiles(name, (String[]) filenames.toArray(new String[filenames.size()])); } } } catch (EOFException e) { // auto refresh files are not persisted, continue and save them next time. } } broadcastRepositoryChange(repoRoot); } } protected void saveCommentHistory() throws TeamException { IPath pluginStateLocation = CVSUIPlugin.getPlugin().getStateLocation(); File tempFile = pluginStateLocation.append(COMMENT_HIST_FILE + ".tmp").toFile(); //$NON-NLS-1$ File histFile = pluginStateLocation.append(COMMENT_HIST_FILE).toFile(); try { XMLWriter writer = new XMLWriter(new BufferedOutputStream(new FileOutputStream(tempFile))); try { writeCommentHistory(writer); } finally { writer.close(); } if (histFile.exists()) { histFile.delete(); } boolean renamed = tempFile.renameTo(histFile); if (!renamed) { throw new TeamException(new Status(IStatus.ERROR, CVSUIPlugin.ID, TeamException.UNABLE, NLS .bind(CVSUIMessages.RepositoryManager_rename, new String[] { tempFile.getAbsolutePath() }), null)); } } catch (IOException e) { throw new TeamException(new Status(IStatus.ERROR, CVSUIPlugin.ID, TeamException.UNABLE, NLS.bind(CVSUIMessages.RepositoryManager_save, new String[] { histFile.getAbsolutePath() }), e)); } } private void writeCommentHistory(XMLWriter writer) { writer.startTag(ELEMENT_COMMIT_HISTORY, null, false); for (int i = 0; i < previousComments.length && i < maxComments; i++) writer.printSimpleTag(ELEMENT_COMMIT_COMMENT, previousComments[i]); writer.endTag(ELEMENT_COMMIT_HISTORY); } public void addRepositoryListener(IRepositoryListener listener) { listeners.add(listener); } public void removeRepositoryListener(IRepositoryListener listener) { listeners.remove(listener); } /** * Return the entered comment or null if canceled. * @param proposedComment */ public String promptForComment(final Shell shell, IResource[] resourcesToCommit, String proposedComment) { final int[] result = new int[1]; final ReleaseCommentDialog dialog = new ReleaseCommentDialog(shell, resourcesToCommit, proposedComment, IResource.DEPTH_INFINITE); shell.getDisplay().syncExec(new Runnable() { public void run() { result[0] = dialog.open(); if (result[0] != Window.OK) return; } }); if (result[0] != Window.OK) return null; return dialog.getComment(); } /** * Prompt to add all or some of the provided resources to version control. * The value null is returned if the dialog is cancelled. * * @param shell * @param unadded * @return IResource[] */ public IResource[] promptForResourcesToBeAdded(Shell shell, IResource[] unadded) { if (unadded == null) return new IResource[0]; if (unadded.length == 0) return unadded; final IResource[][] result = new IResource[1][0]; result[0] = null; final AddToVersionControlDialog dialog = new AddToVersionControlDialog(shell, unadded); shell.getDisplay().syncExec(new Runnable() { public void run() { int code = dialog.open(); if (code == IDialogConstants.YES_ID) { result[0] = dialog.getResourcesToAdd(); } else if (code == IDialogConstants.NO_ID) { // allow the commit to continue. result[0] = new IResource[0]; } } }); return result[0]; } public ICVSRepositoryLocation getRepositoryLocationFor(ICVSResource resource) { try { return internalGetRepositoryLocationFor(resource); } catch (CVSException e) { CVSUIPlugin.log(e); return null; } } private ICVSRepositoryLocation internalGetRepositoryLocationFor(ICVSResource resource) throws CVSException { ICVSFolder folder; if (resource.isFolder()) { folder = (ICVSFolder) resource; } else { folder = resource.getParent(); } if (folder.isCVSFolder()) { ICVSRepositoryLocation location = KnownRepositories.getInstance() .getRepository(folder.getFolderSyncInfo().getRoot()); return location; } // XXX This is asking for trouble return null; } private RepositoryRoot getRepositoryRootFor(ICVSResource resource) throws CVSException { ICVSRepositoryLocation location = internalGetRepositoryLocationFor(resource); if (location == null) return null; return getRepositoryRootFor(location); } public RepositoryRoot getRepositoryRootFor(ICVSRepositoryLocation location) { RepositoryRoot root = (RepositoryRoot) repositoryRoots.get(location.getLocation(false)); if (root == null) { root = new RepositoryRoot(location); add(root); } return root; } /** * Add the given repository root to the receiver. The provided instance of RepositoryRoot * is used to provide extra information about the repository location * * @param currentRepositoryRoot */ public void add(RepositoryRoot root) { repositoryRoots.put(root.getRoot().getLocation(false), root); broadcastRepositoryChange(root); } private void broadcastRepositoryChange(RepositoryRoot root) { if (notificationLevel == 0) { broadcastRepositoriesChanged(new ICVSRepositoryLocation[] { root.getRoot() }); } else { changedRepositories.put(root.getRoot().getLocation(false), root.getRoot()); } } private void broadcastRepositoriesChanged(ICVSRepositoryLocation[] roots) { if (roots.length == 0) return; Iterator it = listeners.iterator(); while (it.hasNext()) { IRepositoryListener listener = (IRepositoryListener) it.next(); listener.repositoriesChanged(roots); } } /** * Run the given runnable, waiting until the end to perform a refresh * * @param runnable * @param monitor */ public void run(IRunnableWithProgress runnable, IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { try { notificationLevel++; runnable.run(monitor); } finally { notificationLevel = Math.max(0, notificationLevel - 1); if (notificationLevel == 0) { try { Collection roots = changedRepositories.values(); broadcastRepositoriesChanged( (ICVSRepositoryLocation[]) roots.toArray(new ICVSRepositoryLocation[roots.size()])); } finally { changedRepositories.clear(); } } } } /** * Method isDisplayingProjectVersions. * @param repository * @return boolean */ public boolean isDisplayingProjectVersions(ICVSRepositoryLocation repository) { return true; } /** * Method filterResources filters the given resources using the given * working set. * * @param current * @param resources * @return ICVSRemoteResource[] */ public ICVSRemoteResource[] filterResources(IWorkingSet workingSet, ICVSRemoteResource[] resources) { if (workingSet == null) return resources; // get the projects associated with the working set IAdaptable[] adaptables = workingSet.getElements(); Set projects = new HashSet(); for (int i = 0; i < adaptables.length; i++) { IAdaptable adaptable = adaptables[i]; Object adapted = adaptable.getAdapter(IResource.class); if (adapted != null) { // Can this code be generalized? IProject project = ((IResource) adapted).getProject(); projects.add(project); } } List result = new ArrayList(); for (int i = 0; i < resources.length; i++) { ICVSRemoteResource resource = resources[i]; for (Iterator iter = projects.iterator(); iter.hasNext();) { IProject project = (IProject) iter.next(); if (project.getName().equals(resource.getName())) { result.add(resource); break; } } } return (ICVSRemoteResource[]) result.toArray(new ICVSRemoteResource[result.size()]); } /** * Method setLabel. * @param location * @param label */ public void setLabel(CVSRepositoryLocation location, String label) { RepositoryRoot root = getRepositoryRootFor(location); String oldLabel = root.getName(); if (oldLabel == null) { if (label == null) return; root.setName(label); } else if (label == null) { root.setName(label); } else if (label.equals(oldLabel)) { return; } else { root.setName(label); } broadcastRepositoryChange(root); } /** * Replace the old repository location with the new one assuming that they * are the same location with different authentication informations * @param location * @param newLocation */ public void replaceRepositoryLocation(final ICVSRepositoryLocation oldLocation, final CVSRepositoryLocation newLocation) { try { run(new IRunnableWithProgress() { public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { RepositoryRoot root = getRepositoryRootFor(oldLocation); // Disposing of the old location will result in the deletion of the // cached root through a listener callback KnownRepositories.getInstance().disposeRepository(oldLocation); // Get the new location from the CVS plugin to ensure we use the // instance that will be returned by future calls to getRepository() boolean isNew = !KnownRepositories.getInstance().isKnownRepository(newLocation.getLocation()); root.setRepositoryLocation( KnownRepositories.getInstance().addRepository(newLocation, isNew /* broadcast */)); add(root); } }, Policy.monitorFor(null)); } catch (InvocationTargetException e) { CVSException.wrapException(e); } catch (InterruptedException e) { } } /** * Purge any cahced information. */ public void purgeCache() { for (Iterator iter = repositoryRoots.values().iterator(); iter.hasNext();) { RepositoryRoot root = (RepositoryRoot) iter.next(); root.clearCache(); } } /** * Answer the list of comments that were previously used when committing. * @return String[] */ public String[] getPreviousComments() { return previousComments; } /** * Method addComment. * @param string */ public void addComment(String comment) { // Make comment first element if it's already there int index = getCommentIndex(comment); if (index != -1) { makeFirstElement(index); return; } if (containsCommentTemplate(comment)) return; // Insert the comment as the first element String[] newComments = new String[Math.min(previousComments.length + 1, maxComments)]; newComments[0] = comment; for (int i = 1; i < newComments.length; i++) { newComments[i] = previousComments[i - 1]; } previousComments = newComments; } private int getCommentIndex(String comment) { for (int i = 0; i < previousComments.length; i++) { if (previousComments[i].equals(comment)) { return i; } } return -1; } private void makeFirstElement(int index) { String[] newComments = new String[previousComments.length]; newComments[0] = previousComments[index]; System.arraycopy(previousComments, 0, newComments, 1, index); int maxIndex = previousComments.length - 1; if (index != maxIndex) { int nextIndex = (index + 1); System.arraycopy(previousComments, nextIndex, newComments, nextIndex, (maxIndex - index)); } previousComments = newComments; } private void readCommentTemplates(InputStream stream) throws IOException, TeamException { try { SAXParserFactory factory = SAXParserFactory.newInstance(); SAXParser parser = factory.newSAXParser(); parser.parse(new InputSource(stream), new CommentTemplatesContentHandler()); } catch (SAXException ex) { IStatus status = new CVSStatus(IStatus.ERROR, CVSStatus.ERROR, NLS.bind( CVSUIMessages.RepositoryManager_parsingProblem, new String[] { COMMENT_TEMPLATES_FILE }), ex); throw new CVSException(status); } catch (ParserConfigurationException ex) { IStatus status = new CVSStatus(IStatus.ERROR, CVSStatus.ERROR, NLS.bind( CVSUIMessages.RepositoryManager_parsingProblem, new String[] { COMMENT_TEMPLATES_FILE }), ex); throw new CVSException(status); } } protected void saveCommentTemplates() throws TeamException { IPath pluginStateLocation = CVSUIPlugin.getPlugin().getStateLocation(); File tempFile = pluginStateLocation.append(COMMENT_TEMPLATES_FILE + ".tmp").toFile(); //$NON-NLS-1$ File histFile = pluginStateLocation.append(COMMENT_TEMPLATES_FILE).toFile(); try { XMLWriter writer = new XMLWriter(new BufferedOutputStream(new FileOutputStream(tempFile))); try { writeCommentTemplates(writer); } finally { writer.close(); } if (histFile.exists()) { histFile.delete(); } boolean renamed = tempFile.renameTo(histFile); if (!renamed) { throw new TeamException(new Status(IStatus.ERROR, CVSUIPlugin.ID, TeamException.UNABLE, NLS .bind(CVSUIMessages.RepositoryManager_rename, new String[] { tempFile.getAbsolutePath() }), null)); } } catch (IOException e) { throw new TeamException(new Status(IStatus.ERROR, CVSUIPlugin.ID, TeamException.UNABLE, NLS.bind(CVSUIMessages.RepositoryManager_save, new String[] { histFile.getAbsolutePath() }), e)); } } private void writeCommentTemplates(XMLWriter writer) { writer.startTag(ELEMENT_COMMENT_TEMPLATES, null, false); for (int i = 0; i < commentTemplates.length; i++) writer.printSimpleTag(ELEMENT_COMMIT_COMMENT, commentTemplates[i]); writer.endTag(ELEMENT_COMMENT_TEMPLATES); } private boolean containsCommentTemplate(String comment) { for (int i = 0; i < commentTemplates.length; i++) { if (commentTemplates[i].equals(comment)) { return true; } } return false; } /** * Get list of comment templates. */ public String[] getCommentTemplates() { return commentTemplates; } public void replaceAndSaveCommentTemplates(String[] templates) throws TeamException { commentTemplates = templates; saveCommentTemplates(); } }