Java tutorial
/* * Copyright 2000-2010 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.community.intellij.plugins.communitycase; import com.intellij.execution.ui.ConsoleViewContentType; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.diff.impl.patch.formove.FilePathComparator; import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.options.Configurable; import com.intellij.openapi.progress.BackgroundTaskQueue; import com.intellij.openapi.progress.Task; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.vcs.*; import com.intellij.openapi.vcs.changes.CommitExecutor; import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager; import com.intellij.openapi.vcs.history.VcsFileRevision; import com.intellij.openapi.vcs.history.VcsHistoryProvider; import com.intellij.openapi.vcs.history.VcsRevisionNumber; import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList; import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.EventDispatcher; import com.intellij.util.containers.ComparatorDelegate; import com.intellij.util.containers.Convertor; import com.intellij.util.ui.UIUtil; import org.community.intellij.plugins.communitycase.annotate.IntellijAnnotationProvider; import org.community.intellij.plugins.communitycase.changes.ChangeUtils; import org.community.intellij.plugins.communitycase.changes.CommittedChangeListProvider; import org.community.intellij.plugins.communitycase.changes.OutgoingChangesProvider; import org.community.intellij.plugins.communitycase.checkin.CheckinEnvironment; import org.community.intellij.plugins.communitycase.checkin.CommitAndPushExecutor; import org.community.intellij.plugins.communitycase.checkout.branches.BranchConfigurations; import org.community.intellij.plugins.communitycase.commands.Command; import org.community.intellij.plugins.communitycase.commands.SimpleHandler; import org.community.intellij.plugins.communitycase.config.*; import org.community.intellij.plugins.communitycase.diff.TreeDiffProvider; import org.community.intellij.plugins.communitycase.history.HistoryProvider; import org.community.intellij.plugins.communitycase.history.NewUsersComponent; import org.community.intellij.plugins.communitycase.history.browser.ProjectLogManager; import org.community.intellij.plugins.communitycase.i18n.Bundle; import org.community.intellij.plugins.communitycase.merge.MergeProvider; import org.community.intellij.plugins.communitycase.update.UpdateEnvironment; import org.community.intellij.plugins.communitycase.vfs.*; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.File; import java.text.SimpleDateFormat; import java.util.Collections; import java.util.Date; import java.util.List; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; /** * VCS implementation */ public class Vcs extends AbstractVcs<CommittedChangeList> { public static final String NOTIFICATION_GROUP_ID = "ClearCase"; public static final String NAME = "ClearCase"; // Vcs name //private static final Logger log = Logger.getInstance("#"+Vcs.class.getName()); private static final VcsKey ourKey = createKey(NAME); private final com.intellij.openapi.vcs.changes.ChangeProvider myChangeProvider; private final CheckinEnvironment myCheckinEnvironment; private final com.intellij.openapi.vcs.rollback.RollbackEnvironment myRollbackEnvironment; private final UpdateEnvironment myUpdateEnvironment; private final IntellijAnnotationProvider myAnnotationProvider; private final com.intellij.openapi.vcs.diff.DiffProvider myDiffProvider; private final VcsHistoryProvider myHistoryProvider; private final com.intellij.openapi.vcs.EditFileProvider myEditFileProvider; private final ProjectLevelVcsManager myVcsManager; private final VcsSettings mySettings; private final Configurable myConfigurable; private final com.intellij.openapi.vcs.diff.RevisionSelector myRevSelector; private final MergeProvider myMergeProvider; private final MergeProvider myReverseMergeProvider; private final CommittedChangeListProvider myCommittedChangeListProvider; private VfsListener myVfsListener; // a VFS listener that tracks file addition, deletion, and renaming. @SuppressWarnings({ "FieldAccessedSynchronizedAndUnsynchronized" }) private Version myVersion; // The currently detected version or null. private final Object myCheckingVersion = new Object(); // Checking the version lock (used to prevent infinite recursion) private String myVersionCheckExcecutable = ""; // The path to executable at the time of version check private RootTracker myRootTracker; // The tracker that checks validity of roots private final EventDispatcher<RootsListener> myRootListeners = EventDispatcher.create(RootsListener.class); private final EventDispatcher<ConfigListener> myConfigListeners = EventDispatcher.create(ConfigListener.class); private final EventDispatcher<ReferenceListener> myReferenceListeners = EventDispatcher .create(ReferenceListener.class); private IgnoreTracker myIgnoreTracker; private ConfigTracker myConfigTracker; private final BackgroundTaskQueue myTaskQueue; // The queue that is used to schedule background task from actions private final ReadWriteLock myCommandLock = new ReentrantReadWriteLock(true); // The command read/write lock private final TreeDiffProvider myTreeDiffProvider; private final CommitAndPushExecutor myCommitAndPushExecutor; private ReferenceTracker myReferenceTracker; private boolean isActivated; // If true, the vcs was activated private ExecutableValidator myExecutableValidator; public static Vcs getInstance(@NotNull Project project) { return (Vcs) ProjectLevelVcsManager.getInstance(project).findVcsByName(NAME); } public Vcs(@NotNull Project project, @NotNull final org.community.intellij.plugins.communitycase.changes.ChangeProvider changeProvider, @NotNull final CheckinEnvironment checkinEnvironment, @NotNull final ProjectLevelVcsManager vcsManager, @NotNull final IntellijAnnotationProvider annotationProvider, @NotNull final org.community.intellij.plugins.communitycase.diff.DiffProvider diffProvider, @NotNull final HistoryProvider historyProvider, @NotNull final org.community.intellij.plugins.communitycase.rollback.RollbackEnvironment rollbackEnvironment, @NotNull final org.community.intellij.plugins.communitycase.edit.EditFileProvider editFileProvider, @NotNull final VcsSettings settings) { super(project, NAME); myVcsManager = vcsManager; mySettings = settings; myChangeProvider = changeProvider; myCheckinEnvironment = checkinEnvironment; myAnnotationProvider = annotationProvider; myDiffProvider = diffProvider; myHistoryProvider = historyProvider; myRollbackEnvironment = rollbackEnvironment; myEditFileProvider = editFileProvider; myRevSelector = new RevisionSelector(); myConfigurable = new VcsConfigurable(settings, myProject); myUpdateEnvironment = new org.community.intellij.plugins.communitycase.update.UpdateEnvironment(myProject, this, settings); myMergeProvider = new org.community.intellij.plugins.communitycase.merge.MergeProvider(myProject); myReverseMergeProvider = new org.community.intellij.plugins.communitycase.merge.MergeProvider(myProject, true); myCommittedChangeListProvider = new CommittedChangeListProvider(myProject); myOutgoingChangesProvider = new OutgoingChangesProvider(myProject); myTreeDiffProvider = new TreeDiffProvider(myProject); myCommitAndPushExecutor = new CommitAndPushExecutor(checkinEnvironment); myReferenceTracker = new ReferenceTracker(myProject, this, myReferenceListeners.getMulticaster()); myTaskQueue = new BackgroundTaskQueue(myProject, Bundle.getString("task.queue.title")); } /** * @return the vfs listener instance */ public VfsListener getVfsListener() { return myVfsListener; } /** * @return the command lock */ public ReadWriteLock getCommandLock() { return myCommandLock; } /** * Run task in background using the common queue (per project) * * @param task the task to run */ public void runInBackground(Task.Backgroundable task) { myTaskQueue.run(task); } /** * Add listener for roots * * @param listener the listener to add */ public void addConfigListener(ConfigListener listener) { myConfigListeners.addListener(listener); } /** * Remove listener for roots * * @param listener the listener to remove */ public void removeConfigListener(ConfigListener listener) { myConfigListeners.removeListener(listener); } /** * Add listener for roots * * @param listener the listener to add */ public void addReferenceListener(ReferenceListener listener) { myReferenceListeners.addListener(listener); } /** * Remove listener for roots * * @param listener the listener to remove */ public void removeReferenceListener(ReferenceListener listener) { myReferenceListeners.removeListener(listener); } /** * Add listener for roots * * @param listener the listener to add */ public void addRootsListener(RootsListener listener) { myRootListeners.addListener(listener); } /** * Remove listener for roots * * @param listener the listener to remove */ public void removeRootsListener(RootsListener listener) { myRootListeners.removeListener(listener); } /** * @return a reverse merge provider for (with reversed meaning of "theirs" and "yours", needed for the rebase and unstash) */ @NotNull public com.intellij.openapi.vcs.merge.MergeProvider getReverseMergeProvider() { return myReverseMergeProvider; } /** * {@inheritDoc} */ @Override public CommittedChangesProvider getCommittedChangesProvider() { return myCommittedChangeListProvider; } /** * {@inheritDoc} */ @Override public String getRevisionPattern() { // return the full commit hash pattern, possibly other revision formats should be supported as well return "[0-9a-fA-F]{40}"; } /** * {@inheritDoc} */ @Override @NotNull public CheckinEnvironment getCheckinEnvironment() { return myCheckinEnvironment; } /** * {@inheritDoc} */ @NotNull @Override public com.intellij.openapi.vcs.merge.MergeProvider getMergeProvider() { return myMergeProvider; } /** * {@inheritDoc} */ @Override @NotNull public com.intellij.openapi.vcs.rollback.RollbackEnvironment getRollbackEnvironment() { return myRollbackEnvironment; } /** * {@inheritDoc} */ @Override @NotNull public VcsHistoryProvider getVcsHistoryProvider() { return myHistoryProvider; } @Override public VcsHistoryProvider getVcsBlockHistoryProvider() { return myHistoryProvider; } /** * {@inheritDoc} */ @Override @NotNull public String getDisplayName() { return NAME; } /** * {@inheritDoc} */ @Override @Nullable public com.intellij.openapi.vcs.update.UpdateEnvironment getUpdateEnvironment() { return myUpdateEnvironment; } /** * {@inheritDoc} */ @Override @NotNull public IntellijAnnotationProvider getAnnotationProvider() { return myAnnotationProvider; } /** * {@inheritDoc} */ @Override @NotNull public com.intellij.openapi.vcs.diff.DiffProvider getDiffProvider() { return myDiffProvider; } /** * {@inheritDoc} */ @Override @Nullable public com.intellij.openapi.vcs.diff.RevisionSelector getRevisionSelector() { return myRevSelector; } /** * {@inheritDoc} */ @SuppressWarnings({ "deprecation" }) @Override @Nullable public VcsRevisionNumber parseRevisionNumber(String revision, FilePath path) { return parseRevisionNumber(revision); } /** * {@inheritDoc} */ @SuppressWarnings({ "deprecation" }) @Override @Nullable public VcsRevisionNumber parseRevisionNumber(String revision) { return parseRevisionNumber(revision, null); } /** * {@inheritDoc} */ @Override public boolean isVersionedDirectory(VirtualFile dir) { return dir.isDirectory() && Util.rootOrNull(dir) != null; } /** * {@inheritDoc} */ @Override protected void start() throws VcsException { } /** * {@inheritDoc} */ @Override protected void shutdown() throws VcsException { } /** * {@inheritDoc} */ @Override protected void activate() { isActivated = true; myExecutableValidator = new ExecutableValidator(myProject); myExecutableValidator.checkExecutableAndNotifyIfNeeded(); if (!myProject.isDefault() && myRootTracker == null) { myRootTracker = new RootTracker(this, myProject, myRootListeners.getMulticaster()); } if (myVfsListener == null) { myVfsListener = new VfsListener(myProject, this); } if (myConfigTracker == null) { myConfigTracker = new ConfigTracker(myProject, this, myConfigListeners.getMulticaster()); } if (myIgnoreTracker == null) { myIgnoreTracker = new IgnoreTracker(myProject, this); } myReferenceTracker.activate(); NewUsersComponent.getInstance(myProject).activate(); ProjectLogManager.getInstance(myProject).activate(); //BranchConfigurations.getInstance(myProject).activate(); //TODO wc do we need this? } /** * {@inheritDoc} */ @Override protected void deactivate() { isActivated = false; BranchConfigurations.getInstance(myProject).deactivate(); if (myRootTracker != null) { myRootTracker.dispose(); myRootTracker = null; } if (myVfsListener != null) { Disposer.dispose(myVfsListener); myVfsListener = null; } if (myIgnoreTracker != null) { myIgnoreTracker.dispose(); myIgnoreTracker = null; } if (myConfigTracker != null) { myConfigTracker.dispose(); myConfigTracker = null; } myReferenceTracker.deactivate(); NewUsersComponent.getInstance(myProject).deactivate(); ProjectLogManager.getInstance(myProject).deactivate(); } /** * {@inheritDoc} */ @NotNull @Override public synchronized Configurable getConfigurable() { return myConfigurable; } /** * {@inheritDoc} */ @Nullable public com.intellij.openapi.vcs.changes.ChangeProvider getChangeProvider() { return myChangeProvider; } /** * Show errors as popup and as messages in vcs view. * * @param list a list of errors * @param action an action */ public void showErrors(@NotNull List<VcsException> list, @NotNull String action) { if (list.size() > 0) { StringBuffer buffer = new StringBuffer(); buffer.append("\n"); buffer.append(Bundle.message("error.list.title", action)); for (final VcsException exception : list) { buffer.append("\n"); buffer.append(exception.getMessage()); } final String msg = buffer.toString(); UIUtil.invokeLaterIfNeeded(new Runnable() { @Override public void run() { Messages.showErrorDialog(myProject, msg, Bundle.getString("error.dialog.title")); } }); } } /** * Show a plain message in vcs view * * @param message a message to show */ public void showMessages(@NotNull String message) { if (message.length() == 0) return; showMessage(message, ConsoleViewContentType.NORMAL_OUTPUT.getAttributes()); } /** * @return vcs settings for the current project */ @NotNull public VcsSettings getSettings() { return mySettings; } /** * Show message in the VCS view * * @param message a message to show * @param style a style to use */ private void showMessage(@NotNull String message, final TextAttributes style) { myVcsManager.addMessageToConsoleWindow(message, style); } /** * Check version and report problem */ public void checkVersion() { final String executable = mySettings.getPathToExecutable(); synchronized (myCheckingVersion) { if (myVersion != null && myVersionCheckExcecutable.equals(executable)) { return; } myVersionCheckExcecutable = executable; // this assignment is done to prevent recursive version check myVersion = Version.INVALID; final String version; try { version = version(myProject).trim(); } catch (VcsException e) { String reason = (e.getCause() != null ? e.getCause() : e).getMessage(); if (!myProject.isDefault()) { showMessage(Bundle.message("vcs.unable.to.run", executable, reason), ConsoleViewContentType.SYSTEM_OUTPUT.getAttributes()); } return; } myVersion = Version.parse(version); if (!Version.parse(version).isSupported() && !myProject.isDefault()) { showMessage(Bundle.message("vcs.unsupported.version", version, Version.MIN), ConsoleViewContentType.SYSTEM_OUTPUT.getAttributes()); } } } /** * @return the configured version of */ public Version version() { checkVersion(); return myVersion; } /** * Get the version of configured * * @param project the project * @return a version of configured * @throws com.intellij.openapi.vcs.VcsException an error if there is a problem with running */ public static String version(Project project) throws VcsException { final String s; SimpleHandler h = new SimpleHandler(project, new File("."), Command.VERSION); h.setRemote(true); h.setSilent(true); s = h.run(); return s; } /** * Show command line * * @param cmdLine a command line text */ public void showCommandLine(final String cmdLine) { SimpleDateFormat f = new SimpleDateFormat("HH:mm:ss.SSS"); showMessage(f.format(new Date()) + ": " + cmdLine, ConsoleViewContentType.SYSTEM_OUTPUT.getAttributes()); } /** * The error line * * @param line a line to show */ public void showErrorMessages(final String line) { showMessage(line, ConsoleViewContentType.ERROR_OUTPUT.getAttributes()); } /** * {@inheritDoc} */ @Override public boolean allowsNestedRoots() { return true; } /** * {@inheritDoc} */ @Override public <S> List<S> filterUniqueRoots(final List<S> in, final Convertor<S, VirtualFile> convertor) { Collections.sort(in, new ComparatorDelegate<S, VirtualFile>(convertor, FilePathComparator.getInstance())); for (int i = 1; i < in.size(); i++) { final S sChild = in.get(i); final VirtualFile child = convertor.convert(sChild); final VirtualFile childRoot = Util.rootOrNull(child); if (childRoot == null) { // non- file actually, skip it continue; } for (int j = i - 1; j >= 0; --j) { final S sParent = in.get(j); final VirtualFile parent = convertor.convert(sParent); // the method check both that parent is an ancestor of the child and that they share common root if (VfsUtil.isAncestor(parent, child, false) && VfsUtil.isAncestor(childRoot, parent, false)) { in.remove(i); //noinspection AssignmentToForLoopParameter --i; break; } } } return in; } /** * {@inheritDoc} */ @Override public RootsConvertor getCustomConvertor() { return RootConverter.INSTANCE; } public static VcsKey getKey() { return ourKey; } @Override public VcsType getType() { return VcsType.centralized; } private final VcsOutgoingChangesProvider<CommittedChangeList> myOutgoingChangesProvider; @Override protected VcsOutgoingChangesProvider<CommittedChangeList> getOutgoingProviderImpl() { return myOutgoingChangesProvider; } @Override public RemoteDifferenceStrategy getRemoteDifferenceStrategy() { return RemoteDifferenceStrategy.ASK_TREE_PROVIDER; } @Override protected TreeDiffProvider getTreeDiffProviderImpl() { return myTreeDiffProvider; } @Override public List<CommitExecutor> getCommitExecutors() { return Collections.<CommitExecutor>singletonList(myCommitAndPushExecutor); } /** * @return true if vcs was activated */ public boolean isActivated() { return isActivated; } public ExecutableValidator getExecutableValidator() { return myExecutableValidator; } /** {@inheritDoc} */ @Override public com.intellij.openapi.vcs.EditFileProvider getEditFileProvider() { return myEditFileProvider; } public void refreshAllRoots() { VcsDirtyScopeManager.getInstance(myProject).markEverythingDirty(); //for(VirtualFile vf:ProjectLevelVcsManager.getInstance(myProject).getRootsUnderVcs(this)) } }