Merge remote-tracking branch 'origin/master'

This commit is contained in:
Konstantin Bulenkov
2012-10-23 18:37:22 +02:00
46 changed files with 1225 additions and 113 deletions
@@ -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;
@@ -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;
@@ -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 {
@@ -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{}
@@ -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();
}
}
@@ -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);
}
@@ -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){}
}
@@ -0,0 +1,7 @@
abstract class A {
abstract void foo(Enum<?> x);
}
class B extends A {
void foo(Enum<? extends Enum<?>> x) { }
}
@@ -0,0 +1,7 @@
class C {
void foo(){}
}
class D extends C{
static <T> void foo(){}
}
@@ -0,0 +1,7 @@
abstract class A {
abstract <T> T foo();
{
int x = foo();
}
}
@@ -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);
}
}
@@ -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(){}
}
@@ -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;
}
}
@@ -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);
+9
View File
@@ -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>
+7 -1
View File
@@ -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();
}
}
}