blob: e715ad78340b0f82205d130b5e98972cbb0fcb25 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.netbeans.core.startup.layers;
import java.io.File;
import java.io.IOException;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import org.netbeans.core.startup.layers.LocalFileSystemEx;
import org.netbeans.junit.NbTestCase;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileSystem;
import org.openide.filesystems.FileUtil;
import org.openide.filesystems.MultiFileSystem;
import org.openide.filesystems.Repository;
import org.openide.filesystems.TestUtilHid;
import org.openide.util.Lookup;
import org.openide.util.lookup.InstanceContent;
/**
* Simulates deadlock in issue 133616.
*
* @author Jiri Skrivanek
*/
public class LocalFileSystemEx133616Test extends NbTestCase {
static {
System.setProperty("org.openide.util.Lookup", LocalFileSystemEx133616Test.class.getName() + "$Lkp");
}
/** Tested FileSystem to be registered in Lookup. */
private static FileSystem testedFS = null;
public LocalFileSystemEx133616Test(String name) {
super(name);
}
/** Simulates deadlock issue 133616
* - create MultiFileSystem
* - create lookup to set our MultiFileSystem and system filesystem
* - create handler to manage threads
* - put test FileObject to 'potentialLock' set
* - call hasLocks
* - it call LocalFileSystemEx.getInvalid which ends in our DeadlockHandler
* - it starts lockingThread which calls FileObject.lock which locks our FileObject
* - when we in LocalFileSystemEx.lock, we notify main thread which continues
* in getInvalid and tries to accuire lock on FileObject and it dead locks
*/
public void testLocalFileSystemEx133616() throws Exception {
System.setProperty("workdir", getWorkDirPath());
clearWorkDir();
FileSystem lfs = TestUtilHid.createLocalFileSystem("mfs1" + getName(), new String[]{"/fold/file1"});
LocalFileSystemEx exfs = new LocalFileSystemEx();
exfs.setRootDirectory(FileUtil.toFile(lfs.getRoot()));
FileSystem xfs = TestUtilHid.createXMLFileSystem(getName(), new String[]{});
FileSystem mfs = new MultiFileSystem(exfs, xfs);
testedFS = mfs;
Lookup l = Lookup.getDefault();
if (!(l instanceof Lkp)) {
fail("Wrong lookup: " + l);
}
((Lkp)l).init();
final FileObject file1FO = mfs.findResource("/fold/file1");
File file1File = FileUtil.toFile(file1FO);
Logger.getLogger(LocalFileSystemEx.class.getName()).setLevel(Level.FINEST);
Logger.getLogger(LocalFileSystemEx.class.getName()).addHandler(new DeadlockHandler(file1FO));
LocalFileSystemEx.potentialLock(file1FO.getPath());
LocalFileSystemEx.hasLocks();
}
class DeadlockHandler extends Handler {
private FileObject fileObject;
public DeadlockHandler(FileObject fo) {
super();
this.fileObject = fo;
}
public synchronized void publish(LogRecord rec) {
if ("133616 - checking invalid".equals(rec.getMessage())) {
Thread lockingThread = new Thread(new Runnable() {
public void run() {
try {
fileObject.lock().releaseLock();
} catch (IOException ex) {
fail(ex.getMessage());
}
}
}, "Locking");
lockingThread.start();
try {
wait();
} catch (InterruptedException ex) {
fail(ex.getMessage());
}
}
if ("133616 - in lock".equals(rec.getMessage())) {
notify();
}
}
@Override
public void flush() {
}
@Override
public void close() {
}
}
public static final class Lkp extends org.openide.util.lookup.AbstractLookup {
private final InstanceContent ic;
public Lkp() {
this(new org.openide.util.lookup.InstanceContent());
}
private Lkp(org.openide.util.lookup.InstanceContent ic) {
super(ic);
this.ic = ic;
}
public void init() {
ic.add(new Repository(testedFS));
}
}
}