diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java
index 98a8e90fcc45..485e3b5b6aac 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java
@@ -634,7 +634,7 @@ public class GenericsHighlightUtil {
type instanceof PsiWildcardType && ((PsiWildcardType)type).getBound() instanceof PsiPrimitiveType) {
final PsiElement element = new PsiMatcherImpl(typeElement)
.parent(PsiMatchers.hasClass(PsiReferenceParameterList.class))
- .parent(PsiMatchers.hasClass(PsiJavaCodeReferenceElement.class))
+ .parent(PsiMatchers.hasClass(PsiJavaCodeReferenceElement.class, PsiNewExpression.class))
.getElement();
if (element == null) return null;
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightClassUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightClassUtil.java
index 47b45ae324ce..4f6dd56b696d 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightClassUtil.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightClassUtil.java
@@ -836,11 +836,15 @@ public class HighlightClassUtil {
PsiClass targetClass = aClass.getSuperClass();
if (targetClass == null) return null;
PsiExpression qualifier = superCall.getMethodExpression().getQualifierExpression();
- if (qualifier != null && PsiUtil.isInnerClass(targetClass)) {
- PsiClass outerClass = targetClass.getContainingClass();
- if (outerClass != null) {
- PsiClassType outerType = JavaPsiFacade.getInstance(project).getElementFactory().createType(outerClass);
- return HighlightUtil.checkAssignability(outerType, null, qualifier, qualifier);
+ if (qualifier != null) {
+ if (PsiUtil.isInnerClass(targetClass)) {
+ PsiClass outerClass = targetClass.getContainingClass();
+ if (outerClass != null) {
+ PsiClassType outerType = JavaPsiFacade.getInstance(project).getElementFactory().createType(outerClass);
+ return HighlightUtil.checkAssignability(outerType, null, qualifier, qualifier);
+ }
+ } else {
+ return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, qualifier, "'" + HighlightUtil.formatClass(targetClass) + "' is not an inner class");
}
}
return null;
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java
index d1a44922714a..9e2e28ba6007 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java
@@ -1236,6 +1236,12 @@ public class HighlightMethodUtil {
}
if (classReference != null && aClass.hasModifierProperty(PsiModifier.PROTECTED) && callingProtectedConstructorFromDerivedClass(constructorCall, aClass)) {
holder.add(buildAccessProblem(classReference, typeResolveResult, aClass));
+ } else if (aClass.isInterface() && constructorCall instanceof PsiNewExpression) {
+ final PsiReferenceParameterList typeArgumentList = ((PsiNewExpression)constructorCall).getTypeArgumentList();
+ if (typeArgumentList.getTypeArguments().length > 0) {
+ holder.add(HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, typeArgumentList,
+ "Anonymous class implements interface; cannot have type arguments"));
+ }
}
}
else {
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/ExplicitConstructorInvocation.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/ExplicitConstructorInvocation.java
new file mode 100644
index 000000000000..0bb53bfec1a3
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/ExplicitConstructorInvocation.java
@@ -0,0 +1,42 @@
+class A {
+ class S {
+ }
+
+ class C extends S {
+ C(A c) {
+ c.super();
+ }
+ C(B b) {
+ b.super();
+ }
+ }
+}
+class B extends A {}
+
+class A1 {
+ static class S {
+ }
+
+ class C extends S {
+ C(A1 c) {
+ c.super();
+ }
+ }
+}
+
+class C2 {
+ C2(String c){
+ c.super();
+ }
+}
+
+class A3 {
+ class S {
+ }
+
+ class C extends S {
+ C(String c) {
+ c.super();
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/annotations/wrongPlace.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/annotations/wrongPlace.java
index 89c407950bfc..8f050d14d909 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/annotations/wrongPlace.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/annotations/wrongPlace.java
@@ -11,4 +11,6 @@ abstract class C {
@Anno(nested = {@Anno, @Anno})
void notWrong() { }
-}
\ No newline at end of file
+}
+
+class B extends @Deprecated Object{}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA57275.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA57275.java
new file mode 100644
index 000000000000..7111b8d872b6
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA57275.java
@@ -0,0 +1,13 @@
+abstract class A {
+ abstract > void foo();
+
+ {
+ foo();
+ }
+}
+
+class X{
+ > void foo(){
+ foo();
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA57378.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA57378.java
new file mode 100644
index 000000000000..541079ed4a7c
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA57378.java
@@ -0,0 +1,9 @@
+interface IA {
+ void foo(T x);
+ void foo(T x);
+}
+
+abstract class A {
+ abstract & Iterable> void foo(T x, A> y);
+ abstract > void foo(T x, A extends Throwable> y);
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA57533.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA57533.java
new file mode 100644
index 000000000000..5bf8674b63d8
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA57533.java
@@ -0,0 +1,6 @@
+class C>>{
+ void foo(C> x){
+ bar(x);
+ }
+ > void bar(C x){}
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA57557.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA57557.java
new file mode 100644
index 000000000000..56efec17184c
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA57557.java
@@ -0,0 +1,7 @@
+abstract class A {
+ abstract void foo(Enum> x);
+}
+
+class B extends A {
+ void foo(Enum extends Enum>> x) { }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA57563.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA57563.java
new file mode 100644
index 000000000000..a8cb239a3cd6
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA57563.java
@@ -0,0 +1,7 @@
+class C {
+ void foo(){}
+}
+
+class D extends C{
+ static void foo(){}
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA57650.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA57650.java
new file mode 100644
index 000000000000..8f5bb73e6785
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA57650.java
@@ -0,0 +1,7 @@
+abstract class A {
+ abstract T foo();
+
+ {
+ int x = foo();
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA57667.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA57667.java
new file mode 100644
index 000000000000..9f27fa0f14d4
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA57667.java
@@ -0,0 +1,7 @@
+class A {
+ A(T x) {}
+
+ {
+ new <String>A(1);
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA57668.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA57668.java
new file mode 100644
index 000000000000..cc49162b0b8d
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA57668.java
@@ -0,0 +1,17 @@
+class A {
+ A() {}
+
+ {
+ new <int>A();
+ }
+}
+
+class B {
+ {
+ new B<int>();
+ B.<int>m();
+ }
+
+ void m(){}
+
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA67599.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA67599.java
new file mode 100644
index 000000000000..fd6c6b4e8aff
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA67599.java
@@ -0,0 +1,8 @@
+abstract class A
+{
+ abstract S bar();
+ void foo(A a)
+ {
+ int x = a.bar().length;
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/TypeArgumentsGivenOnAnonymousClassCreation.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/TypeArgumentsGivenOnAnonymousClassCreation.java
new file mode 100644
index 000000000000..33214e28fe0e
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/TypeArgumentsGivenOnAnonymousClassCreation.java
@@ -0,0 +1,12 @@
+class C
+{
+ Object x = new D() { };
+ Object x1 = new P() { };
+ Object x2 = new U() { };
+ Object x3 = new I() { };
+ interface D{}
+ abstract class P {}
+}
+
+interface I {}
+class U {}
\ No newline at end of file
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java
index 29ac394b4c04..c0532abbcfcc 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java
@@ -150,11 +150,21 @@ public class GenericsHighlightingTest extends LightDaemonAnalyzerTestCase {
public void testIDEA89771() throws Exception { doTest(false); }
public void testIDEA89801() throws Exception { doTest(false); }
public void testIDEA67681() throws Exception { doTest(false); }
+ public void testIDEA67599() throws Exception { doTest(false); }
+ public void testIDEA57668() throws Exception { doTest(false); }
+ public void testIDEA57667() throws Exception { doTest(false); }
+ public void testIDEA57650() throws Exception { doTest(false); }
+ public void testIDEA57378() throws Exception { doTest(false); }
+ public void testIDEA57557() throws Exception { doTest(false); }
+ public void testIDEA57563() throws Exception { doTest(false); }
+ public void testIDEA57275() throws Exception { doTest(false); }
+ public void testIDEA57533() throws Exception { doTest(false); }
public void testInconvertibleTypes() throws Exception { doTest(false); }
public void testIncompatibleReturnType() throws Exception { doTest(false); }
public void testContinueInferenceAfterFirstRawResult() throws Exception { doTest(false); }
public void testStaticOverride() throws Exception { doTest(false); }
public void testTypeArgumentsGivenOnRawType() throws Exception { doTest(false); }
+ public void testTypeArgumentsGivenOnAnonymousClassCreation() throws Exception { doTest(false); }
public void testJavaUtilCollections_NoVerify() throws Exception {
PsiClass collectionsClass = getJavaFacade().findClass("java.util.Collections", GlobalSearchScope.moduleWithLibrariesScope(getModule()));
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingTest.java
index 9d3b286eb4cc..646805fc7031 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingTest.java
@@ -358,4 +358,5 @@ public class LightAdvHighlightingTest extends LightDaemonAnalyzerTestCase {
public void testRegexp() throws Exception { doTest(false, false); }
public void testUnsupportedFeatures() throws Exception { doTest(false, false); }
public void testThisBeforeSuper() throws Exception { doTest(false, false); }
+ public void testExplicitConstructorInvocation() throws Exception { doTest(false, false); }
}
diff --git a/java/openapi/src/com/intellij/psi/util/PsiMatchers.java b/java/openapi/src/com/intellij/psi/util/PsiMatchers.java
index 32be1cdb136e..72f93672e072 100644
--- a/java/openapi/src/com/intellij/psi/util/PsiMatchers.java
+++ b/java/openapi/src/com/intellij/psi/util/PsiMatchers.java
@@ -71,7 +71,7 @@ public class PsiMatchers {
};
}
- public static PsiMatcherExpression hasClass(final Class[] classes) {
+ public static PsiMatcherExpression hasClass(final Class... classes) {
return new PsiMatcherExpression() {
@Override
public Boolean match(PsiElement element) {
diff --git a/platform/indexing-api/src/com/intellij/psi/search/SearchRequestCollector.java b/platform/indexing-api/src/com/intellij/psi/search/SearchRequestCollector.java
index ea7f247546a2..22fbfa1b4947 100644
--- a/platform/indexing-api/src/com/intellij/psi/search/SearchRequestCollector.java
+++ b/platform/indexing-api/src/com/intellij/psi/search/SearchRequestCollector.java
@@ -15,6 +15,7 @@
*/
package com.intellij.psi.search;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFileSystemItem;
import com.intellij.psi.PsiReference;
@@ -57,6 +58,9 @@ public class SearchRequestCollector {
if (searchScope instanceof LocalSearchScope && ((LocalSearchScope)searchScope).getScope().length == 0) {
return;
}
+ if (StringUtil.isEmpty(word)) {
+ return;
+ }
synchronized (lock) {
myWordRequests.add(new PsiSearchRequest(searchScope, word, searchContext, caseSensitive, processor));
diff --git a/platform/platform-api/src/com/intellij/ui/MouseDragHelper.java b/platform/platform-api/src/com/intellij/ui/MouseDragHelper.java
index 52f0d57f5d4c..3aab2f8df622 100644
--- a/platform/platform-api/src/com/intellij/ui/MouseDragHelper.java
+++ b/platform/platform-api/src/com/intellij/ui/MouseDragHelper.java
@@ -186,15 +186,10 @@ public abstract class MouseDragHelper implements MouseListener, MouseMotionListe
}
}
- boolean needConsume = true;
if (myDetachingMode) {
processDragOut(e, draggedTo, (Point)myPressPointScreen.clone(), dragOutStarted);
} else {
- needConsume = processDrag(e, draggedTo, (Point)myPressPointScreen.clone());
- }
-
- if (needConsume) {
- e.consume();
+ processDrag(e, draggedTo, (Point)myPressPointScreen.clone());
}
}
}
@@ -232,14 +227,14 @@ public abstract class MouseDragHelper implements MouseListener, MouseMotionListe
return myDragJustStarted;
}
- protected abstract boolean processDrag(MouseEvent event, Point dragToScreenPoint, Point startScreenPoint);
+ protected abstract void processDrag(MouseEvent event, Point dragToScreenPoint, Point startScreenPoint);
protected boolean isDragOut(MouseEvent event, Point dragToScreenPoint, Point startScreenPoint) {
return false;
}
protected void processDragOut(MouseEvent event, Point dragToScreenPoint, Point startScreenPoint, boolean justStarted) {
-
+ event.consume();
}
private boolean isWithinDeadZone(final MouseEvent e) {
diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/DragHelper.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/DragHelper.java
index d052c9f999e0..bd8364813049 100644
--- a/platform/platform-api/src/com/intellij/ui/tabs/impl/DragHelper.java
+++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/DragHelper.java
@@ -71,6 +71,7 @@ class DragHelper extends MouseDragHelper {
} else {
delegate.processDragOut(event, myDragOutSource);
}
+ event.consume();
}
@Override
@@ -92,13 +93,13 @@ class DragHelper extends MouseDragHelper {
myPressedTabLabel = findLabel(new RelativePoint(event).getPoint(myTabs));
}
- protected boolean processDrag(MouseEvent event, Point targetScreenPoint, Point startPointScreen) {
- if (!myTabs.isTabDraggingEnabled() || !isDragSource(event)) return false;
+ protected void processDrag(MouseEvent event, Point targetScreenPoint, Point startPointScreen) {
+ if (!myTabs.isTabDraggingEnabled() || !isDragSource(event)) return;
SwingUtilities.convertPointFromScreen(startPointScreen, myTabs);
if (isDragJustStarted()) {
- if (myPressedTabLabel == null) return false;
+ if (myPressedTabLabel == null) return;
final Rectangle labelBounds = myPressedTabLabel.getBounds();
@@ -111,7 +112,7 @@ class DragHelper extends MouseDragHelper {
myDragOriginalRec.y -= myHoldDelta.height;
}
else {
- if (myDragRec == null) return false;
+ if (myDragRec == null) return;
final Point toPoint = SwingUtilities.convertPoint(event.getComponent(), event.getPoint(), myTabs);
@@ -163,7 +164,7 @@ class DragHelper extends MouseDragHelper {
headerRec.height += border * 2;
myTabs.repaint(headerRec);
}
- return true;
+ event.consume();
}
private boolean isDragSource(MouseEvent event) {
diff --git a/platform/platform-api/src/com/intellij/util/ui/OptionsDialog.java b/platform/platform-api/src/com/intellij/util/ui/OptionsDialog.java
index 856ee05b2227..f54e827e4cf8 100644
--- a/platform/platform-api/src/com/intellij/util/ui/OptionsDialog.java
+++ b/platform/platform-api/src/com/intellij/util/ui/OptionsDialog.java
@@ -15,7 +15,6 @@
*/
package com.intellij.util.ui;
-import com.intellij.CommonBundle;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import org.jetbrains.annotations.Nullable;
@@ -47,7 +46,7 @@ public abstract class OptionsDialog extends DialogWrapper {
}
public String getDoNotShowMessage() {
- return CommonBundle.message("dialog.options.do.not.show");
+ return OptionsDialog.this.getDoNotShowMessage();
}
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/ex/util/EditorUtil.java b/platform/platform-impl/src/com/intellij/openapi/editor/ex/util/EditorUtil.java
index d498e9614e7d..e334aa93b527 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/ex/util/EditorUtil.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/ex/util/EditorUtil.java
@@ -228,7 +228,7 @@ public class EditorUtil {
SoftWrapModel softWrapModel = editor.getSoftWrapModel();
List extends SoftWrap> softWraps = softWrapModel.getSoftWrapsForRange(start, maxScanIndex);
int startToUse = start;
- int x = editor.getPrefixTextWidthInPixels();
+ int x = editor.getDocument().getLineNumber(start) == 0 ? editor.getPrefixTextWidthInPixels() : 0;
int[] currentColumn = {0};
for (SoftWrap softWrap : softWraps) {
// There is a possible case that target column points inside soft wrap-introduced virtual space.
diff --git a/platform/platform-impl/src/com/intellij/ui/EditorTextField.java b/platform/platform-impl/src/com/intellij/ui/EditorTextField.java
index 6bf4fb24d57e..a7b479fd371b 100644
--- a/platform/platform-impl/src/com/intellij/ui/EditorTextField.java
+++ b/platform/platform-impl/src/com/intellij/ui/EditorTextField.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * Copyright 2000-2012 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.
@@ -246,7 +246,7 @@ public class EditorTextField extends NonOpaquePanel implements DocumentListener,
}
}
- public void setText(@NotNull final String text) {
+ public void setText(@Nullable final String text) {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
diff --git a/platform/platform-impl/src/com/intellij/ui/Win7TaskBar.java b/platform/platform-impl/src/com/intellij/ui/Win7TaskBar.java
index 81387f2556c7..69db0602be92 100644
--- a/platform/platform-impl/src/com/intellij/ui/Win7TaskBar.java
+++ b/platform/platform-impl/src/com/intellij/ui/Win7TaskBar.java
@@ -81,8 +81,15 @@ class Win7TaskBar {
}
}
+ private static boolean ourInitialized = true;
static {
- initialize();
+ try {
+ initialize();
+ }
+ catch (Throwable e) {
+ LOG.error(e);
+ ourInitialized = false;
+ }
}
private static void initialize() {
@@ -109,7 +116,7 @@ class Win7TaskBar {
}
static void setProgress(IdeFrame frame, double value, boolean isOk) {
- if (ApplicationManager.getApplication().isUnitTestMode()) {
+ if (!isEnabled()) {
return;
}
@@ -118,8 +125,12 @@ class Win7TaskBar {
mySetProgressValue.invokeInt(new Object[]{myInterfacePointer, handle, new WinDef.ULONGLONG((long)(value * 100)), TOTAL_PROGRESS});
}
+ private static boolean isEnabled() {
+ return !ApplicationManager.getApplication().isUnitTestMode() && ourInitialized;
+ }
+
static void hideProgress(IdeFrame frame) {
- if (ApplicationManager.getApplication().isUnitTestMode()) {
+ if (!isEnabled()) {
return;
}
@@ -127,7 +138,7 @@ class Win7TaskBar {
}
static void setOverlayIcon(IdeFrame frame, Object icon, boolean dispose) {
- if (ApplicationManager.getApplication().isUnitTestMode()) {
+ if (!isEnabled()) {
return;
}
@@ -141,7 +152,7 @@ class Win7TaskBar {
}
static Object createIcon(byte[] ico) {
- if (ApplicationManager.getApplication().isUnitTestMode()) {
+ if (!isEnabled()) {
return new Object();
}
@@ -163,7 +174,7 @@ class Win7TaskBar {
}
static void attention(IdeFrame frame, boolean critical) {
- if (ApplicationManager.getApplication().isUnitTestMode()) {
+ if (!isEnabled()) {
return;
}
diff --git a/platform/vcs-api/src/com/intellij/vcsUtil/LearningProxy.java b/platform/vcs-api/src/com/intellij/vcsUtil/LearningProxy.java
index 6795aa114156..381c43e52b0e 100644
--- a/platform/vcs-api/src/com/intellij/vcsUtil/LearningProxy.java
+++ b/platform/vcs-api/src/com/intellij/vcsUtil/LearningProxy.java
@@ -28,7 +28,7 @@ import java.util.*;
* Date: 10/19/12
* Time: 12:42 PM
*/
-public abstract class LearningProxy implements InvocationHandler {
+public abstract class LearningProxy {
private final static Map ourDefaultValues = new HashMap();
static {
ourDefaultValues.put("byte", new Byte((byte) 0));
@@ -42,13 +42,25 @@ public abstract class LearningProxy implements InvocationHandler {
ourDefaultValues.put("void", null);
}
private final Set myTrackedMethods;
+ private final InvocationHandler myLearn;
public LearningProxy() {
myTrackedMethods = new HashSet();
+ myLearn = new InvocationHandler() {
+ @Override
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ myTrackedMethods.add(new MethodDescriptor(method));
+ final Class> returnType = method.getReturnType();
+ if (returnType.isPrimitive()) {
+ return ourDefaultValues.get(returnType.getName());
+ }
+ return null;
+ }
+ };
}
- protected abstract void onBefore();
- protected abstract void onAfter();
+ protected abstract void onBefore() throws E;
+ protected abstract void onAfter() throws E;
public T create(Class clazz, final T t) {
return (T) Proxy.newProxyInstance(clazz.getClassLoader(), new Class[]{clazz}, new InvocationHandler() {
@@ -58,6 +70,7 @@ public abstract class LearningProxy implements InvocationHandler {
if (myTrackedMethods.contains(current)) {
try {
onBefore();
+ method.setAccessible(true);
return method.invoke(t, args);
} finally {
onAfter();
@@ -69,17 +82,7 @@ public abstract class LearningProxy implements InvocationHandler {
}
public T learn(Class clazz) {
- return (T) Proxy.newProxyInstance(clazz.getClassLoader(), new Class[]{clazz}, this);
- }
-
- @Override
- public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
- myTrackedMethods.add(new MethodDescriptor(method));
- final Class> returnType = method.getReturnType();
- if (returnType.isPrimitive()) {
- return ourDefaultValues.get(returnType.getName());
- }
- return null;
+ return (T) Proxy.newProxyInstance(clazz.getClassLoader(), new Class[]{clazz}, myLearn);
}
private static class MethodDescriptor {
diff --git a/platform/vcs-api/src/com/intellij/vcsUtil/PseudoImplementProxy.java b/platform/vcs-api/src/com/intellij/vcsUtil/PseudoImplementProxy.java
new file mode 100644
index 000000000000..4d9872589264
--- /dev/null
+++ b/platform/vcs-api/src/com/intellij/vcsUtil/PseudoImplementProxy.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2000-2012 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 com.intellij.vcsUtil;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: Irina.Chernushina
+ * Date: 10/22/12
+ * Time: 10:58 AM
+ */
+public class PseudoImplementProxy {
+ public static T create(final Class theInterface, final Impl implementation) {
+ checkMethodsExist(theInterface, implementation);
+ final Class> implementationClass = implementation.getClass();
+ return (T) Proxy.newProxyInstance(theInterface.getClassLoader(), new Class[]{theInterface},
+ new InvocationHandler() {
+ @Override
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ final Method implementationClassMethod =
+ implementationClass.getMethod(method.getName(), method.getParameterTypes());
+ implementationClassMethod.setAccessible(true);
+ return implementationClassMethod.invoke(implementation, args);
+ }
+ });
+ }
+
+ private static void checkMethodsExist(Class theInterface, Impl implementation) {
+ final Class> implementationClass = implementation.getClass();
+ final Method[] methods = theInterface.getDeclaredMethods();
+ for (Method method : methods) {
+ try {
+ implementationClass.getMethod(method.getName(), method.getParameterTypes());
+ }
+ catch (NoSuchMethodException e) {
+ throw new UnsupportedOperationException(e);
+ }
+ }
+ }
+}
diff --git a/plugins/svn4idea/lib/sqljetsrc.zip b/plugins/svn4idea/lib/sqljetsrc.zip
new file mode 100644
index 000000000000..3d7a71ef7078
Binary files /dev/null and b/plugins/svn4idea/lib/sqljetsrc.zip differ
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/RootsToWorkingCopies.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/RootsToWorkingCopies.java
index 9eaf64b48e2b..1717ea261c9c 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/RootsToWorkingCopies.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/RootsToWorkingCopies.java
@@ -90,7 +90,7 @@ public class RootsToWorkingCopies implements VcsListener {
@Nullable
@CalledInBackground
public WorkingCopy getMatchingCopy(final SVNURL url) {
- assert ! ApplicationManager.getApplication().isDispatchThread();
+ assert (! ApplicationManager.getApplication().isDispatchThread()) || ApplicationManager.getApplication().isUnitTestMode();
if (url == null) return null;
final VirtualFile[] roots = ProjectLevelVcsManager.getInstance(myProject).getRootsUnderVcs(SvnVcs.getInstance(myProject));
@@ -111,7 +111,7 @@ public class RootsToWorkingCopies implements VcsListener {
@CalledInBackground
@Nullable
public WorkingCopy getWcRoot(final VirtualFile root) {
- assert ! ApplicationManager.getApplication().isDispatchThread();
+ assert (! ApplicationManager.getApplication().isDispatchThread()) || ApplicationManager.getApplication().isUnitTestMode();
synchronized (myLock) {
if (myUnversioned.contains(root)) return null;
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAbstractWriteOperationLocks.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAbstractWriteOperationLocks.java
new file mode 100644
index 000000000000..fea3d259982c
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAbstractWriteOperationLocks.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright 2000-2012 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.jetbrains.idea.svn;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.vcs.changes.FilePathsHelper;
+import org.jetbrains.annotations.Nullable;
+import org.tmatesoft.sqljet.core.SqlJetException;
+import org.tmatesoft.sqljet.core.table.ISqlJetBusyHandler;
+import org.tmatesoft.sqljet.core.table.ISqlJetTransaction;
+import org.tmatesoft.sqljet.core.table.SqlJetDb;
+import org.tmatesoft.svn.core.SVNException;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: Irina.Chernushina
+ * Date: 10/19/12
+ * Time: 12:09 PM
+ */
+public abstract class SvnAbstractWriteOperationLocks {
+ private final long myTimeout;
+ private final static Map myLockMap = new HashMap();
+ private final static Object myLock = new Object();
+ private static final Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.SvnAbstractWriteOperationLocks");
+ private ISqlJetBusyHandler ourBusyHandler;
+
+ protected SvnAbstractWriteOperationLocks(long timeout) {
+ myTimeout = timeout;
+ ourBusyHandler = new ISqlJetBusyHandler() {
+ @Override
+ public boolean call(int i) {
+ try {
+ Thread.sleep(myTimeout);
+ }
+ catch (InterruptedException e) {
+ //
+ }
+ return true;
+ }
+ };
+ }
+
+ // null if not 1.7+ copy
+ @Nullable
+ private Lock getLockObject(File file) throws SVNException {
+ final boolean directory = file.isDirectory();
+ final WorkingCopy wcRoot = getCopy(file, directory);
+ if (! wcRoot.is17Copy()) return null;
+ Lock lock;
+ final String path = FilePathsHelper.convertPath(wcRoot.getFile().getPath());
+ synchronized (myLock) {
+ lock = myLockMap.get(path);
+ if (lock == null) {
+ lock = new ReentrantLock();
+ myLockMap.put(path, lock);
+ }
+ }
+ return lock;
+ }
+
+ protected abstract WorkingCopy getCopy(File file, boolean directory) throws SVNException;
+
+ public void lockWrite(final File file) throws SVNException {
+ final Lock lock = getLockObject(file);
+ if (lock != null) {
+ lock.lock();
+ }
+ }
+
+ public void unlockWrite(final File file) throws SVNException {
+ final Lock lock = getLockObject(file);
+ if (lock != null) {
+ lock.unlock();
+ }
+ }
+
+ // would wait until read is available
+ public void wrapRead(final File file, final Runnable runnable) throws SVNException {
+ final WorkingCopy copy = getCopy(file, file.isDirectory());
+ if (! copy.is17Copy()) {
+ runnable.run();
+ return;
+ }
+
+ final File root = copy.getFile();
+ SqlJetDb open = null;
+ final boolean run[] = new boolean[1];
+ run[0] = false;
+ try {
+ open = SqlJetDb.open(SvnUtil.getWcDb(root), false);
+ open.setBusyHandler(ourBusyHandler);
+ try {
+ final SqlJetDb finalOpen = open;
+ open.runReadTransaction(new ISqlJetTransaction() {
+ @Override
+ public Object run(SqlJetDb db) throws SqlJetException {
+ run[0] = true;
+ runnable.run();
+ return null;
+ }
+ });
+ } finally {
+ open.rollback();
+ }
+ }
+ catch (SqlJetException e) {
+ LOG.info(e);
+ if (! run[0]) {
+ runnable.run();
+ }
+ }
+ finally {
+ if (open != null) {
+ try {
+ open.close();
+ }
+ catch (SqlJetException e) {
+ LOG.info(e);
+ }
+ }
+ }
+ }
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnProxies.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnProxies.java
new file mode 100644
index 000000000000..97b87efaa7f9
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnProxies.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2000-2012 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.jetbrains.idea.svn;
+
+import com.intellij.vcsUtil.LearningProxy;
+import org.jetbrains.idea.svn.portable.SVNChangelistClientI;
+import org.jetbrains.idea.svn.portable.SvnUpdateClientI;
+import org.tmatesoft.svn.core.SVNException;
+
+import java.io.File;
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: Irina.Chernushina
+ * Date: 10/19/12
+ * Time: 4:22 PM
+ */
+public class SvnProxies {
+ private final SvnAbstractWriteOperationLocks myLocks;
+ private final AtomicReference> myChangelist;
+ private final AtomicReference> myUpdate;
+
+ public SvnProxies(SvnAbstractWriteOperationLocks locks) {
+ myLocks = locks;
+ myChangelist = new AtomicReference>();
+ myUpdate = new AtomicReference>();
+ }
+
+ public LearningProxy getChangelistsProfessor(final File file) {
+ if (myChangelist.get() == null) {
+ final MyLearningProxy proxy = new MyLearningProxy(myLocks, file);
+ final SVNChangelistClientI learn = proxy.learn(SVNChangelistClientI.class);
+ try {
+ learn.addToChangelist(null, null, null, null);
+ learn.doAddToChangelist(null, null, null, null);
+ learn.doRemoveFromChangelist(null, null, null);
+ learn.removeFromChangelist(null, null, null);
+ } catch (SVNException e) {
+ //can not occur since methods are not really called
+ throw new RuntimeException(e);
+ }
+
+ myChangelist.set(proxy);
+ }
+ return myChangelist.get();
+ }
+
+ public LearningProxy getUpdateProfessor(final File file) {
+ if (myUpdate.get() == null) {
+ final MyLearningProxy proxy = new MyLearningProxy(myLocks, file);
+ final SvnUpdateClientI learn = proxy.learn(SvnUpdateClientI.class);
+ try {
+ learn.doUpdate(null, null, false);
+ learn.doUpdate(null, null, false, false);
+ learn.doUpdate((File[]) null, null, null, false, false);
+ learn.doUpdate((File[]) null, null, null, false, false, false);
+ learn.doUpdate((File) null, null, null, false, false);
+
+ learn.doSwitch(null, null, null, false);
+ learn.doSwitch(null, null, null, null, false);
+ learn.doSwitch(null, null, null, null, false, false);
+ learn.doSwitch(null, null, null, null, null, false, false);
+ learn.doSwitch(null, null, null, null, null, false, false, false);
+
+ learn.doCheckout(null, null, null, null, false);
+ // todo continue
+ //learn.doCheckout();
+ //learn.doCheckout();
+ }
+ catch (SVNException e) {
+ //can not occur since methods are not really called
+ throw new RuntimeException(e);
+ }
+ myUpdate.set(proxy);
+ }
+ return myUpdate.get();
+ }
+
+ private static class MyLearningProxy extends LearningProxy {
+ private final SvnAbstractWriteOperationLocks myLocks;
+ private final File myFile;
+
+ private MyLearningProxy(SvnAbstractWriteOperationLocks locks, final File file) {
+ myLocks = locks;
+ myFile = file;
+ }
+
+ @Override
+ protected void onBefore() throws SVNException {
+ myLocks.lockWrite(myFile);
+ }
+
+ @Override
+ protected void onAfter() throws SVNException {
+ myLocks.unlockWrite(myFile);
+ }
+ }
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnTestWriteOperationLocks.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnTestWriteOperationLocks.java
new file mode 100644
index 000000000000..853e995ca219
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnTestWriteOperationLocks.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2000-2012 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.jetbrains.idea.svn;
+
+import org.tmatesoft.svn.core.SVNException;
+
+import java.io.File;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: Irina.Chernushina
+ * Date: 10/23/12
+ * Time: 2:31 PM
+ */
+public class SvnTestWriteOperationLocks extends SvnAbstractWriteOperationLocks {
+ private final WorkingCopy myWorkingCopy;
+
+ public SvnTestWriteOperationLocks(WorkingCopy copy) {
+ super(10);
+ myWorkingCopy = copy;
+ }
+
+ @Override
+ protected WorkingCopy getCopy(File file, boolean directory) throws SVNException {
+ return myWorkingCopy;
+ }
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java
index 840f34ae23aa..cae785cbf77a 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java
@@ -583,6 +583,10 @@ public class SvnUtil {
}
}
+ public static File getWcDb(final File file) {
+ return new File(file, ".svn/wc.db");
+ }
+
@Nullable
public static File getWcCopyRootIf17(final File file, @Nullable final File upperBound) {
File current = file;
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnWriteOperationLocks.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnWriteOperationLocks.java
index 01f784cd4875..36e0b08c5a86 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnWriteOperationLocks.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnWriteOperationLocks.java
@@ -15,80 +15,36 @@
*/
package org.jetbrains.idea.svn;
-import com.intellij.openapi.project.Project;
import com.intellij.openapi.vcs.FilePathImpl;
-import com.intellij.openapi.vcs.ProjectLevelVcsManager;
-import com.intellij.openapi.vcs.changes.FilePathsHelper;
+import com.intellij.openapi.vcs.changes.ChangesUtil;
import com.intellij.openapi.vfs.VirtualFile;
import org.tmatesoft.svn.core.SVNErrorCode;
import org.tmatesoft.svn.core.SVNErrorMessage;
import org.tmatesoft.svn.core.SVNException;
import java.io.File;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReentrantLock;
/**
* Created with IntelliJ IDEA.
* User: Irina.Chernushina
- * Date: 10/19/12
- * Time: 12:09 PM
+ * Date: 10/23/12
+ * Time: 2:29 PM
*/
-public class SvnWriteOperationLocks {
- private final ProjectLevelVcsManager myVcsManager;
- private final Map myLockMap;
- private final Object myLock;
+public class SvnWriteOperationLocks extends SvnAbstractWriteOperationLocks {
+ private final RootsToWorkingCopies myRootsToWorkingCopies;
- public SvnWriteOperationLocks(final Project project) {
- myVcsManager = ProjectLevelVcsManager.getInstance(project);
- myLockMap = new HashMap();
- myLock = new Object();
+ public SvnWriteOperationLocks(RootsToWorkingCopies rootsToWorkingCopies) {
+ super(1000);
+ myRootsToWorkingCopies = rootsToWorkingCopies;
}
- public void lock(final File file) throws SVNException {
- final Lock lock = getLockObject(file);
- lock.lock();
- }
-
- private Lock getLockObject(File file) throws SVNException {
- return getLockObject(new FilePathImpl(file, file.isDirectory()), FilePathsHelper.convertPath(file.getPath()));
- }
-
- private Lock getLockObject(VirtualFile file) throws SVNException {
- return getLockObject(new FilePathImpl(file), FilePathsHelper.convertPath(file.getPath()));
- }
-
- private Lock getLockObject(FilePathImpl file, final String path) throws SVNException {
- final boolean directory = file.isDirectory();
- final VirtualFile root = myVcsManager.getVcsRootFor(file);
- if (root == null) {
+ protected WorkingCopy getCopy(File file, boolean directory) throws SVNException {
+ final VirtualFile parentOrSelf = ChangesUtil.findValidParentAccurately(new FilePathImpl(file, directory));
+ final WorkingCopy wcRoot = myRootsToWorkingCopies.getWcRoot(parentOrSelf);
+ if (wcRoot == null) {
throw new SVNException(SVNErrorMessage.create(directory ? SVNErrorCode.WC_NOT_WORKING_COPY : SVNErrorCode.WC_NOT_FILE));
}
- Lock lock;
- synchronized (myLock) {
- lock = myLockMap.get(path);
- if (lock == null) {
- lock = new ReentrantLock();
- myLockMap.put(path, lock);
- }
- }
- return lock;
- }
-
- public void unlock(final File file) throws SVNException {
- final Lock lock = getLockObject(file);
- lock.unlock();
- }
-
- public void lock(final VirtualFile vf) throws SVNException {
- final Lock lock = getLockObject(vf);
- lock.lock();
- }
-
- public void unlock(final VirtualFile vf) throws SVNException {
- final Lock lock = getLockObject(vf);
- lock.unlock();
+ // todo check about externals!
+ return wcRoot;
}
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnEditCommitMessageAction.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnEditCommitMessageAction.java
new file mode 100644
index 000000000000..ae04a1aa292e
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnEditCommitMessageAction.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2000-2012 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.jetbrains.idea.svn.history;
+
+import com.intellij.openapi.actionSystem.AnAction;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: Irina.Chernushina
+ * Date: 10/23/12
+ * Time: 7:23 PM
+ */
+public class SvnEditCommitMessageAction extends AnAction {
+
+ // todo we need:
+ // todo repo url
+ // todo revision number, and current text
+
+ @Override
+ public void actionPerformed(AnActionEvent e) {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRevisionComment.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRevisionComment.java
new file mode 100644
index 000000000000..a2f48aafc478
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRevisionComment.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2000-2012 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.jetbrains.idea.svn.history;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: Irina.Chernushina
+ * Date: 10/23/12
+ * Time: 7:24 PM
+ */
+public class SvnRevisionComment {
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SVNChangelistClientI.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SVNChangelistClientI.java
new file mode 100644
index 000000000000..58ee56902b79
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SVNChangelistClientI.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2000-2012 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.jetbrains.idea.svn.portable;
+
+import org.tmatesoft.svn.core.SVNDepth;
+import org.tmatesoft.svn.core.SVNException;
+import org.tmatesoft.svn.core.wc.ISVNChangelistHandler;
+
+import java.io.File;
+import java.util.Collection;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: Irina.Chernushina
+ * Date: 10/19/12
+ * Time: 3:50 PM
+ */
+public interface SVNChangelistClientI extends SvnMarkerInterface {
+ void getChangeLists(File path, Collection changeLists, SVNDepth depth, ISVNChangelistHandler handler) throws SVNException;
+
+ void getChangeListPaths(Collection changeLists, Collection targets, SVNDepth depth, ISVNChangelistHandler handler) throws SVNException;
+
+ void addToChangelist(File[] paths, SVNDepth depth, String changelist, String[] changelists) throws SVNException;
+
+ void removeFromChangelist(File[] paths, SVNDepth depth, String[] changelists) throws SVNException;
+
+ void doAddToChangelist(File[] paths, SVNDepth depth, String changelist, String[] changelists) throws SVNException;
+
+ void doRemoveFromChangelist(File[] paths, SVNDepth depth, String[] changelists) throws SVNException;
+
+ void doGetChangeListPaths(Collection changeLists, Collection targets, SVNDepth depth, ISVNChangelistHandler handler) throws SVNException;
+
+ void doGetChangeLists(File path, Collection changeLists, SVNDepth depth, ISVNChangelistHandler handler) throws SVNException;
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnMarkerInterface.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnMarkerInterface.java
new file mode 100644
index 000000000000..c043188a990f
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnMarkerInterface.java
@@ -0,0 +1,10 @@
+package org.jetbrains.idea.svn.portable;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: Irina.Chernushina
+ * Date: 10/19/12
+ * Time: 3:48 PM
+ */
+public interface SvnMarkerInterface {
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnStatusClientI.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnStatusClientI.java
index 978e44c9272b..3b5828239abd 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnStatusClientI.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnStatusClientI.java
@@ -30,7 +30,7 @@ import java.util.Collection;
* Date: 1/24/12
* Time: 9:46 AM
*/
-public interface SvnStatusClientI {
+public interface SvnStatusClientI extends SvnMarkerInterface {
long doStatus(File path, boolean recursive, boolean remote, boolean reportAll,
boolean includeIgnored, ISVNStatusHandler handler) throws SVNException;
long doStatus(File path, boolean recursive, boolean remote, boolean reportAll, boolean includeIgnored, boolean collectParentExternals, ISVNStatusHandler handler) throws SVNException;
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnSvnkitChangelistClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnSvnkitChangelistClient.java
new file mode 100644
index 000000000000..b57f73139667
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnSvnkitChangelistClient.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2000-2012 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.jetbrains.idea.svn.portable;
+
+import org.tmatesoft.svn.core.SVNDepth;
+import org.tmatesoft.svn.core.SVNException;
+import org.tmatesoft.svn.core.wc.ISVNChangelistHandler;
+import org.tmatesoft.svn.core.wc.SVNChangelistClient;
+
+import java.io.File;
+import java.util.Collection;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: Irina.Chernushina
+ * Date: 10/19/12
+ * Time: 3:51 PM
+ */
+public class SvnSvnkitChangelistClient implements SVNChangelistClientI {
+ private final SVNChangelistClient myClient;
+
+ public SvnSvnkitChangelistClient(SVNChangelistClient client) {
+ myClient = client;
+ }
+
+ @Override
+ public void getChangeLists(File path, Collection changeLists, SVNDepth depth, ISVNChangelistHandler handler) throws SVNException {
+ myClient.getChangeLists(path, changeLists, depth, handler);
+ }
+
+ @Override
+ public void getChangeListPaths(Collection changeLists,
+ Collection targets,
+ SVNDepth depth,
+ ISVNChangelistHandler handler) throws SVNException {
+ myClient.getChangeListPaths(changeLists, targets, depth, handler);
+ }
+
+ @Override
+ public void addToChangelist(File[] paths, SVNDepth depth, String changelist, String[] changelists) throws SVNException {
+ myClient.addToChangelist(paths, depth, changelist, changelists);
+ }
+
+ @Override
+ public void removeFromChangelist(File[] paths, SVNDepth depth, String[] changelists) throws SVNException {
+ myClient.removeFromChangelist(paths, depth, changelists);
+ }
+
+ @Override
+ public void doAddToChangelist(File[] paths, SVNDepth depth, String changelist, String[] changelists) throws SVNException {
+ myClient.doAddToChangelist(paths, depth, changelist, changelists);
+ }
+
+ @Override
+ public void doRemoveFromChangelist(File[] paths, SVNDepth depth, String[] changelists) throws SVNException {
+ myClient.doRemoveFromChangelist(paths, depth, changelists);
+ }
+
+ @Override
+ public void doGetChangeListPaths(Collection changeLists,
+ Collection targets,
+ SVNDepth depth,
+ ISVNChangelistHandler handler) throws SVNException {
+ myClient.doGetChangeListPaths(changeLists, targets, depth, handler);
+ }
+
+ @Override
+ public void doGetChangeLists(File path, Collection changeLists, SVNDepth depth, ISVNChangelistHandler handler)
+ throws SVNException {
+ myClient.doGetChangeLists(path, changeLists, depth, handler);
+ }
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnUpdateClientI.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnUpdateClientI.java
index f587581f2c31..8eaafa4c8034 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnUpdateClientI.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnUpdateClientI.java
@@ -29,7 +29,7 @@ import java.io.File;
* Date: 2/1/12
* Time: 11:59 AM
*/
-public interface SvnUpdateClientI {
+public interface SvnUpdateClientI extends SvnMarkerInterface {
long doUpdate(File file, SVNRevision revision, boolean recursive) throws SVNException;
long doUpdate(File file, SVNRevision revision, boolean recursive, boolean force) throws SVNException;
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnWcClientI.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnWcClientI.java
index 5aeb4374e145..973058fe3f1b 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnWcClientI.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnWcClientI.java
@@ -28,7 +28,7 @@ import java.util.Collection;
* Date: 1/20/12
* Time: 6:54 PM
*/
-public interface SvnWcClientI {
+public interface SvnWcClientI extends SvnMarkerInterface {
void setAddParameters(ISVNAddParameters addParameters);
ISVNCommitHandler getCommitHandler();
void setCommitHandler(ISVNCommitHandler handler);
diff --git a/plugins/svn4idea/svn4idea-tests.iml b/plugins/svn4idea/svn4idea-tests.iml
index 39e6c6bb024d..e95ff454160d 100644
--- a/plugins/svn4idea/svn4idea-tests.iml
+++ b/plugins/svn4idea/svn4idea-tests.iml
@@ -27,6 +27,15 @@
+
+
+
+
+
+
+
+
+
diff --git a/plugins/svn4idea/svn4idea.iml b/plugins/svn4idea/svn4idea.iml
index 58d83821070b..bd4e9cc30efc 100644
--- a/plugins/svn4idea/svn4idea.iml
+++ b/plugins/svn4idea/svn4idea.iml
@@ -51,7 +51,13 @@
-
+
+
+
+
+
+
+
diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnBusyOnAddTest.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnBusyOnAddTest.java
index 1ad195c1ac24..a93251736d57 100644
--- a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnBusyOnAddTest.java
+++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnBusyOnAddTest.java
@@ -108,8 +108,8 @@ public class SvnBusyOnAddTest extends TestCase {
final File ioFile = new File(myWorkingCopyRoot, filename);
ioFile.getParentFile().mkdirs();
- SVNWCClient client11 = new SVNWCClient((ISVNRepositoryPool)null, new DefaultSVNOptions());
- client11.doAdd(ioFile.getParentFile(), true, false, true, true);
+ /*SVNWCClient client11 = new SVNWCClient((ISVNRepositoryPool)null, new DefaultSVNOptions());
+ client11.doAdd(ioFile.getParentFile(), true, false, true, true);*/
ioFile.createNewFile();
try {
@@ -153,7 +153,7 @@ public class SvnBusyOnAddTest extends TestCase {
//
}
SVNWCClient client = new SVNWCClient((ISVNRepositoryPool)null, new DefaultSVNOptions());
- client.doAdd(ioFile, true, false, true, true);
+ client.doAdd(ioFile.getParentFile(), true, false, true, true);
semaphore.up();
semaphoreWokeUp.waitFor();
diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnLockingTest.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnLockingTest.java
new file mode 100644
index 000000000000..b4949543b66b
--- /dev/null
+++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnLockingTest.java
@@ -0,0 +1,412 @@
+/*
+ * Copyright 2000-2012 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.jetbrains.idea.svn;
+
+import com.intellij.idea.Bombed;
+import com.intellij.openapi.application.PathManager;
+import com.intellij.openapi.application.PluginPathManager;
+import com.intellij.util.concurrency.Semaphore;
+import junit.framework.Assert;
+import junit.framework.TestCase;
+import org.junit.Before;
+import org.tmatesoft.sqljet.core.SqlJetException;
+import org.tmatesoft.sqljet.core.table.ISqlJetBusyHandler;
+import org.tmatesoft.sqljet.core.table.ISqlJetTransaction;
+import org.tmatesoft.sqljet.core.table.SqlJetDb;
+import org.tmatesoft.svn.core.SVNException;
+import org.tmatesoft.svn.core.SVNURL;
+import org.tmatesoft.svn.core.internal.wc.DefaultSVNOptions;
+import org.tmatesoft.svn.core.wc.ISVNRepositoryPool;
+import org.tmatesoft.svn.core.wc.SVNRevision;
+import org.tmatesoft.svn.core.wc.SVNWCClient;
+
+import java.io.File;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: Irina.Chernushina
+ * Date: 10/23/12
+ * Time: 2:27 PM
+ */
+public class SvnLockingTest extends TestCase {
+ private File myWorkingCopyRoot;
+ private SvnTestWriteOperationLocks myLocks;
+
+ @Before
+ public void setUp() throws Exception {
+ //PlatformTestCase.initPlatformLangPrefix();
+ File pluginRoot = new File(PluginPathManager.getPluginHomePath("svn4idea"));
+ if (!pluginRoot.isDirectory()) {
+ // try standalone mode
+ Class aClass = Svn17TestCase.class;
+ String rootPath = PathManager.getResourceRoot(aClass, "/" + aClass.getName().replace('.', '/') + ".class");
+ pluginRoot = new File(rootPath).getParentFile().getParentFile().getParentFile();
+ }
+ myWorkingCopyRoot = new File(pluginRoot, "testData/move2unv");
+ myLocks = new SvnTestWriteOperationLocks(new WorkingCopy(myWorkingCopyRoot, SVNURL.parseURIEncoded("http://a.b.c"), true));
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ }
+
+ public void testPrepare() throws Exception {
+ final HangInWrite operation1 = new HangInWrite("one", false);
+ operation1.hang();
+ operation1.go();
+ }
+
+ public void testPrepareRead() throws Exception {
+ final HangInRead read = new HangInRead("READ", false);
+ read.run();
+ read.go();
+ }
+
+ public void testWritesSequential() throws Exception {
+ final HangInWrite operation1 = new HangInWrite("one_");
+ final HangInWrite operation2 = new HangInWrite("two_");
+
+ final Thread thread1 = new Thread(operation1);
+ final Thread thread2 = new Thread(operation2);
+ try {
+ thread1.start();
+ waitForRunning(operation1);
+ Assert.assertTrue(operation1.isRunning());
+
+ thread2.start();
+ waitForRunning(operation2);
+ Assert.assertFalse(operation2.isRunning());
+
+ operation1.go();
+ waitForRunning(operation2);
+ Assert.assertTrue(operation2.isRunning());
+ operation2.go();
+ Thread.sleep(10);
+ } finally {
+ operation1.stop();
+ operation2.stop();
+
+ thread1.interrupt();
+ thread2.interrupt();
+ }
+ }
+
+ @Bombed(year=2020, month = 1,day = 1,description = "waiting for http://issues.tmatesoft.com/issue/SVNKIT-317")
+ public void testOnlyWrites() throws Exception {
+ final OnlyWrite operation1 = new OnlyWrite("one");
+ final OnlyWrite operation2 = new OnlyWrite("two");
+
+ final Thread thread1 = new Thread(operation1);
+ final Thread thread2 = new Thread(operation2);
+
+ try {
+ thread1.start();
+ try {
+ Thread.sleep(500);
+ } catch (InterruptedException e) {
+ //
+ }
+ Assert.assertTrue(operation1.isInsideWrite());
+ thread2.start();
+ try {
+ Thread.sleep(500);
+ } catch (InterruptedException e) {
+ //
+ }
+ Assert.assertFalse(operation2.isInsideWrite());
+ operation1.go();
+ try {
+ Thread.sleep(500);
+ } catch (InterruptedException e) {
+ //
+ }
+ Assert.assertTrue(operation2.isInsideWrite());
+ operation2.go();
+ try {
+ Thread.sleep(500);
+ } catch (InterruptedException e) {
+ //
+ }
+ } finally {
+ operation1.stop();
+ operation2.stop();
+
+ thread1.interrupt();
+ thread2.interrupt();
+ }
+ }
+
+ @Bombed(year=2020, month = 1,day = 1,description = "waiting for http://issues.tmatesoft.com/issue/SVNKIT-317")
+ public void testReadInBetweenWrites() throws Exception {
+ final HangInWrite operation1 = new HangInWrite("one1");
+ final HangInWrite operation2 = new HangInWrite("two1");
+ final HangInRead read = new HangInRead("READ");
+
+ final Thread thread1 = new Thread(operation1);
+ final Thread threadRead = new Thread(read);
+ final Thread thread2 = new Thread(operation2);
+
+ try {
+ thread1.start();
+ waitForRunning(operation1);
+ Assert.assertTrue(operation1.isRunning());
+
+ threadRead.start();
+ waitForRunning(read);
+ Assert.assertFalse(read.isRunning()); // not clear why read is allowed to run when write is active, but I've not thought it over so much
+
+ operation1.go();
+ waitForRunning(read);
+ Assert.assertTrue(read.isRunning());
+
+ thread2.start();
+ waitForRunning(operation2);
+ Assert.assertFalse(operation2.isRunning()); // again, not clear why write is allowed to run when read is active, but I've not thought it over so much
+
+ read.go();
+ waitForRunning(operation2);
+ Assert.assertTrue(operation2.isRunning());
+ } finally {
+ operation1.stop();
+ operation2.stop();
+
+ thread1.interrupt();
+ thread2.interrupt();
+ threadRead.interrupt();
+ }
+ }
+
+ private void waitForRunning(HangRun operation1) {
+ int cnt = 10;
+ while (cnt > 0) {
+ try {
+ Thread.sleep(10);
+ } catch (InterruptedException e) {
+ //
+ }
+ if (operation1.isRunning()) break;
+ -- cnt;
+ }
+ }
+
+ public interface HangRun {
+ void go();
+ boolean isRunning();
+ void stop();
+ }
+
+ private class HangInRead implements Runnable, HangRun {
+ private final AtomicBoolean myIsRunning;
+ private final String myName;
+ private final boolean myWaitFor;
+ private final Semaphore mySemaphore;
+
+ private HangInRead(String name) {
+ this(name, true);
+ }
+
+ private HangInRead(String name, final boolean waitFor) {
+ myName = name;
+ myWaitFor = waitFor;
+ myIsRunning = new AtomicBoolean(false);
+ mySemaphore = new Semaphore();
+ }
+
+ @Override
+ public void run() {
+ mySemaphore.down();
+ try {
+ System.out.println("starting read " + myName);
+ myLocks.wrapRead(myWorkingCopyRoot, new Runnable() {
+ @Override
+ public void run() {
+ myIsRunning.set(true);
+ System.out.println("inside read " + myName);
+ final SVNWCClient client = new SVNWCClient((ISVNRepositoryPool)null, new DefaultSVNOptions());
+ try {
+ client.doInfo(myWorkingCopyRoot, SVNRevision.BASE);
+ }
+ catch (SVNException e) {
+ e.printStackTrace();
+ throw new RuntimeException(e);
+ }
+ System.out.println("got status " + myName);
+ if (myWaitFor) {
+ mySemaphore.waitFor();
+ }
+ System.out.println("have read " + myName);
+ }
+ });
+ }
+ catch (SVNException e) {
+ e.printStackTrace();
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public void go() {
+ System.out.println("read going " + myName);
+ mySemaphore.up();
+ }
+
+ @Override
+ public boolean isRunning() {
+ System.out.println("read running " + myName + " " + myIsRunning.get());
+ return myIsRunning.get();
+ }
+
+ @Override
+ public void stop() {
+ }
+ }
+
+ private class OnlyWrite extends HangInWrite {
+ private OnlyWrite(String name) {
+ super(name);
+ }
+
+ @Override
+ public void run() {
+ mySemaphore.down();
+ operation();
+ }
+ }
+
+ private class HangInWrite implements Runnable, HangRun {
+ protected final Semaphore mySemaphore;
+ private final AtomicBoolean myIsRunning;
+ private final AtomicBoolean myInsideWrite;
+ private final String myName;
+ private boolean shouldWait;
+ private volatile boolean myStopped;
+
+ private HangInWrite(final String name) {
+ this(name, true);
+ }
+
+ private HangInWrite(final String name, final boolean shouldWait) {
+ myName = name;
+ mySemaphore = new Semaphore();
+ this.shouldWait = shouldWait;
+ myIsRunning = new AtomicBoolean(false);
+ myInsideWrite = new AtomicBoolean(false);
+ }
+
+ @Override
+ public void run() {
+ try {
+ hang();
+ }
+ catch (SVNException e) {
+ e.printStackTrace();
+ throw new RuntimeException(e);
+ }
+ }
+
+ protected void operation() {
+ System.out.println("TRY OPEN FOR WRITE===");
+ SqlJetDb open = null;
+ try {
+ open = SqlJetDb.open(SvnUtil.getWcDb(myWorkingCopyRoot), true);
+ open.setBusyHandler(new ISqlJetBusyHandler() {
+ @Override
+ public boolean call(int i) {
+ if (myStopped) return false;
+ System.out.println("busy " + myName);
+ try {
+ Thread.sleep(10);
+ }
+ catch (InterruptedException e) {
+ //
+ }
+ return true;
+ }
+ });
+ try {
+ System.out.println("TRY OPEN FOR WRITE " + myName);
+ open.runWriteTransaction(new ISqlJetTransaction() {
+ @Override
+ public Object run(SqlJetDb db) throws SqlJetException {
+ System.out.println("OPENed FOR WRITE " + myName);
+ myInsideWrite.set(true);
+ if (shouldWait) {
+ mySemaphore.waitFor();
+ }
+ return null;
+ }
+ });
+ } finally {
+ myInsideWrite.set(false);
+ open.rollback();
+ }
+ }
+ catch (SqlJetException e) {
+ e.printStackTrace();
+ throw new RuntimeException(e);
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new RuntimeException(e);
+ }
+ finally {
+ if (open != null) {
+ try {
+ open.close();
+ }
+ catch (SqlJetException e) {
+ e.printStackTrace();
+ throw new RuntimeException(e);
+ }
+ System.out.println("CLOSed FOR WRITE " + myName);
+ }
+ }
+ }
+
+ public boolean isInsideWrite() {
+ return myInsideWrite.get();
+ }
+
+ public void hang() throws SVNException {
+ System.out.println("starting " + myName);
+ mySemaphore.down();
+ myLocks.lockWrite(myWorkingCopyRoot);
+ myIsRunning.set(true);
+ System.out.println("started " + myName);
+ try {
+ operation();
+ } finally {
+ myLocks.unlockWrite(myWorkingCopyRoot);
+ myIsRunning.set(false);
+ }
+ }
+
+ public boolean isRunning() {
+ System.out.println("running " + myName + " " + myIsRunning.get());
+ return myIsRunning.get();
+ }
+
+ @Override
+ public void stop() {
+ myStopped = true;
+ }
+
+ public void go() {
+ System.out.println("going " + myName);
+ mySemaphore.up();
+ }
+ }
+}