mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
+1
-1
@@ -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;
|
||||
|
||||
|
||||
+9
-5
@@ -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;
|
||||
|
||||
+6
@@ -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 {
|
||||
|
||||
+42
@@ -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) {
|
||||
<error descr="'A1.S' is not an inner class">c</error>.super();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class C2 {
|
||||
C2(String c){
|
||||
<error descr="'java.lang.Object' is not an inner class">c</error>.super();
|
||||
}
|
||||
}
|
||||
|
||||
class A3 {
|
||||
class S {
|
||||
}
|
||||
|
||||
class C extends S {
|
||||
C(String c) {
|
||||
<error descr="Incompatible types. Found: 'java.lang.String', required: 'A3'">c</error>.super();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,4 +11,6 @@ abstract class C {
|
||||
|
||||
@Anno(nested = {@Anno, @Anno})
|
||||
void notWrong() { }
|
||||
}
|
||||
}
|
||||
|
||||
class B extends <error descr="Annotations are not allowed here">@Deprecated</error> Object{}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
abstract class A {
|
||||
abstract <S, T extends Iterable<S>> void foo();
|
||||
|
||||
{
|
||||
foo();
|
||||
}
|
||||
}
|
||||
|
||||
class X{
|
||||
<T extends Enum<T>> void foo(){
|
||||
foo();
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
interface IA {
|
||||
<T extends Cloneable & Iterable> void foo(T x);
|
||||
<T extends Iterable & Cloneable> void foo(T x);
|
||||
}
|
||||
|
||||
abstract class A<T extends Throwable> {
|
||||
abstract <T extends Comparable<?> & Iterable> void foo(T x, A<?> y);
|
||||
abstract <T extends Iterable & Comparable<?>> void foo(T x, A<? extends Throwable> y);
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
class C<T extends C<? extends C<? extends T>>>{
|
||||
void foo(C<?> x){
|
||||
<error descr="Inferred type '? extends C<? extends C<capture<?>>>' for type parameter 'T' is not within its bound; should extend 'C<? extends C<? extends C<capture<?>>>>'">bar(x)</error>;
|
||||
}
|
||||
<T extends C<? extends T>> void bar(C<T> x){}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
abstract class A {
|
||||
abstract void foo(Enum<?> x);
|
||||
}
|
||||
|
||||
class B extends A {
|
||||
void foo(Enum<? extends Enum<?>> x) { }
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
class C {
|
||||
void foo(){}
|
||||
}
|
||||
|
||||
class D extends C{
|
||||
static <T> void foo(){}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
abstract class A {
|
||||
abstract <T> T foo();
|
||||
|
||||
{
|
||||
int x = foo();
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
class A {
|
||||
<T> A(T x) {}
|
||||
|
||||
{
|
||||
new <<error descr="Actual type argument and inferred type contradict each other">String</error>>A(1);
|
||||
}
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
class A {
|
||||
<T> A() {}
|
||||
|
||||
{
|
||||
new <<error descr="Type argument cannot be of primitive type">int</error>>A();
|
||||
}
|
||||
}
|
||||
|
||||
class B<T> {
|
||||
{
|
||||
new B<<error descr="Type argument cannot be of primitive type">int</error>>();
|
||||
B.<<error descr="Type argument cannot be of primitive type">int</error>>m();
|
||||
}
|
||||
|
||||
<S> void m(){}
|
||||
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
abstract class A<T, S extends T>
|
||||
{
|
||||
abstract S bar();
|
||||
void foo(A<Cloneable[], ? extends Throwable[]> a)
|
||||
{
|
||||
int x = a.bar().length;
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
class C
|
||||
{
|
||||
Object x = new <error descr="Anonymous class implements interface; cannot have type arguments"><Integer></error> D() { };
|
||||
Object x1 = new <Integer> P() { };
|
||||
Object x2 = new <Integer> U() { };
|
||||
Object x3 = new <error descr="Anonymous class implements interface; cannot have type arguments"><Integer></error> I() { };
|
||||
interface D{}
|
||||
abstract class P {}
|
||||
}
|
||||
|
||||
interface I {}
|
||||
class U {}
|
||||
@@ -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()));
|
||||
|
||||
@@ -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); }
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ import java.util.*;
|
||||
* Date: 10/19/12
|
||||
* Time: 12:42 PM
|
||||
*/
|
||||
public abstract class LearningProxy<T> implements InvocationHandler {
|
||||
public abstract class LearningProxy<T, E extends Throwable> {
|
||||
private final static Map<String, Object> ourDefaultValues = new HashMap<String, Object>();
|
||||
static {
|
||||
ourDefaultValues.put("byte", new Byte((byte) 0));
|
||||
@@ -42,13 +42,25 @@ public abstract class LearningProxy<T> implements InvocationHandler {
|
||||
ourDefaultValues.put("void", null);
|
||||
}
|
||||
private final Set<MethodDescriptor> myTrackedMethods;
|
||||
private final InvocationHandler myLearn;
|
||||
|
||||
public LearningProxy() {
|
||||
myTrackedMethods = new HashSet<MethodDescriptor>();
|
||||
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> T create(Class<T> clazz, final T t) {
|
||||
return (T) Proxy.newProxyInstance(clazz.getClassLoader(), new Class[]{clazz}, new InvocationHandler() {
|
||||
@@ -58,6 +70,7 @@ public abstract class LearningProxy<T> 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<T> implements InvocationHandler {
|
||||
}
|
||||
|
||||
public <T> T learn(Class<T> 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 {
|
||||
|
||||
@@ -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, Impl> T create(final Class<T> 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 <T, Impl> void checkMethodsExist(Class<T> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@@ -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;
|
||||
|
||||
@@ -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<String, Lock> myLockMap = new HashMap<String, Lock>();
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<LearningProxy<SVNChangelistClientI, SVNException>> myChangelist;
|
||||
private final AtomicReference<LearningProxy<SvnUpdateClientI, SVNException>> myUpdate;
|
||||
|
||||
public SvnProxies(SvnAbstractWriteOperationLocks locks) {
|
||||
myLocks = locks;
|
||||
myChangelist = new AtomicReference<LearningProxy<SVNChangelistClientI, SVNException>>();
|
||||
myUpdate = new AtomicReference<LearningProxy<SvnUpdateClientI, SVNException>>();
|
||||
}
|
||||
|
||||
public LearningProxy<SVNChangelistClientI, SVNException> getChangelistsProfessor(final File file) {
|
||||
if (myChangelist.get() == null) {
|
||||
final MyLearningProxy<SVNChangelistClientI> proxy = new MyLearningProxy<SVNChangelistClientI>(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<SvnUpdateClientI, SVNException> getUpdateProfessor(final File file) {
|
||||
if (myUpdate.get() == null) {
|
||||
final MyLearningProxy<SvnUpdateClientI> proxy = new MyLearningProxy<SvnUpdateClientI>(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<T> extends LearningProxy<T, SVNException> {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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<String, Lock> 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<String, Lock>();
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
}
|
||||
}
|
||||
@@ -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 {
|
||||
}
|
||||
@@ -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<String> changeLists, SVNDepth depth, ISVNChangelistHandler handler) throws SVNException;
|
||||
|
||||
void getChangeListPaths(Collection<String> changeLists, Collection<File> 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<String> changeLists, Collection<File> targets, SVNDepth depth, ISVNChangelistHandler handler) throws SVNException;
|
||||
|
||||
void doGetChangeLists(File path, Collection<String> changeLists, SVNDepth depth, ISVNChangelistHandler handler) throws SVNException;
|
||||
}
|
||||
@@ -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 {
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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<String> changeLists, SVNDepth depth, ISVNChangelistHandler handler) throws SVNException {
|
||||
myClient.getChangeLists(path, changeLists, depth, handler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getChangeListPaths(Collection<String> changeLists,
|
||||
Collection<File> 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<String> changeLists,
|
||||
Collection<File> targets,
|
||||
SVNDepth depth,
|
||||
ISVNChangelistHandler handler) throws SVNException {
|
||||
myClient.doGetChangeListPaths(changeLists, targets, depth, handler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doGetChangeLists(File path, Collection<String> changeLists, SVNDepth depth, ISVNChangelistHandler handler)
|
||||
throws SVNException {
|
||||
myClient.doGetChangeLists(path, changeLists, depth, handler);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -27,6 +27,15 @@
|
||||
<orderEntry type="module" module-name="lang-api" />
|
||||
<orderEntry type="module" module-name="platform-resources" scope="TEST" />
|
||||
<orderEntry type="module" module-name="dom-impl" scope="TEST" />
|
||||
<orderEntry type="module-library">
|
||||
<library>
|
||||
<CLASSES>
|
||||
<root url="jar://$MODULE_DIR$/lib/sqljet.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</orderEntry>
|
||||
</component>
|
||||
</module>
|
||||
|
||||
|
||||
@@ -51,7 +51,13 @@
|
||||
<root url="jar://$MODULE_DIR$/lib/sqljet.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
<SOURCES>
|
||||
<root url="jar://$MODULE_DIR$/lib/sqljetsrc.zip!/src/test/compatibility" />
|
||||
<root url="jar://$MODULE_DIR$/lib/sqljetsrc.zip!/src/test/benchmark" />
|
||||
<root url="jar://$MODULE_DIR$/lib/sqljetsrc.zip!/src/test/stress" />
|
||||
<root url="jar://$MODULE_DIR$/lib/sqljetsrc.zip!/src/test/java" />
|
||||
<root url="jar://$MODULE_DIR$/lib/sqljetsrc.zip!/src/main/java" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
</orderEntry>
|
||||
<orderEntry type="module-library" scope="RUNTIME">
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user