package er.indexing.storage;
import java.io.IOException;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.IndexInput;
import org.apache.lucene.store.IndexOutput;
import org.apache.lucene.store.Lock;
import org.apache.lucene.store.LockFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.webobjects.eocontrol.EOEditingContext;
import com.webobjects.foundation.NSArray;
import com.webobjects.foundation.NSMutableDictionary;
import er.extensions.eof.ERXEOControlUtilities;
public class ERIDirectory extends _ERIDirectory {
/**
* Do I need to update serialVersionUID?
* See section 5.6 <cite>Type Changes Affecting Serialization</cite> on page 51 of the
* <a href="http://java.sun.com/j2se/1.4/pdf/serial-spec.pdf">Java Object Serialization Spec</a>
*/
private static final long serialVersionUID = 1L;
private static final Logger log = LoggerFactory.getLogger(ERIDirectory.class);
public static final ERIDirectoryClazz clazz = new ERIDirectoryClazz();
private class LockingDirectory extends Directory {
private Directory _wrapped;
LockingDirectory(Directory wrapped) {
_wrapped = wrapped;
setLockFactory(_wrapped.getLockFactory());
}
@Override
public void close() throws IOException {
editingContext().lock();
try {
_wrapped.close();
} finally {
editingContext().unlock();
}
}
@Override
public IndexOutput createOutput(String name) throws IOException {
editingContext().lock();
try {
return _wrapped.createOutput(name);
} finally {
editingContext().unlock();
}
}
@Override
public void deleteFile(String name) throws IOException {
editingContext().lock();
try {
_wrapped.deleteFile(name);
} finally {
editingContext().unlock();
}
}
@Override
public boolean fileExists(String name) throws IOException {
editingContext().lock();
try {
return _wrapped.fileExists(name);
} finally {
editingContext().unlock();
}
}
@Override
public long fileLength(String name) throws IOException {
editingContext().lock();
try {
return _wrapped.fileLength(name);
} finally {
editingContext().unlock();
}
}
@Override
public long fileModified(String name) throws IOException {
editingContext().lock();
try {
return _wrapped.fileModified(name);
} finally {
editingContext().unlock();
}
}
@Override
public String[] list() throws IOException {
editingContext().lock();
try {
return _wrapped.list();
} finally {
editingContext().unlock();
}
}
@Override
public IndexInput openInput(String name) throws IOException {
editingContext().lock();
try {
return _wrapped.openInput(name);
} finally {
editingContext().unlock();
}
}
@Override
public void renameFile(String from, String to) throws IOException {
editingContext().lock();
try {
_wrapped.renameFile(from, to);
} finally {
editingContext().unlock();
}
}
@Override
public void touchFile(String name) throws IOException {
editingContext().lock();
try {
_wrapped.touchFile(name);
} finally {
editingContext().unlock();
}
}
}
private class EOFDirectory extends Directory {
private class EOFLockFactory extends LockFactory {
private class EOFLock extends Lock {
private String _name;
private EOFLock(String name) {
_name = name;
}
@Override
public boolean isLocked() {
editingContext().lock();
try {
return fileForName(name()) != null;
} finally {
editingContext().unlock();
}
}
@Override
public boolean obtain() throws IOException {
editingContext().lock();
try {
return createFile(name()) != null;
} finally {
editingContext().unlock();
}
}
@Override
public void release() throws IOException {
editingContext().lock();
try {
deleteFile(name());
} finally {
editingContext().unlock();
}
}
public String name() {
return _name;
}
}
private NSMutableDictionary<String, EOFLock> locks = new NSMutableDictionary();
@Override
public void clearLock(String s) throws IOException {
synchronized (locks) {
locks.removeObjectForKey(s);
}
}
@Override
public Lock makeLock(String s) {
synchronized (locks) {
EOFLock lock = new EOFLock(s);
locks.setObjectForKey(lock, s);
return lock;
}
}
}
public EOFDirectory() {
setLockFactory(new EOFLockFactory());
}
@Override
public void close() throws IOException {
editingContext().saveChanges();
}
@Override
public IndexOutput createOutput(String s) throws IOException {
log.debug("createOutput: {}", s);
ERIFile file = fileForName(s);
if (file == null) {
file = createFile(s);
}
return fileForName(s).createOutput();
}
public ERIFile createFile(String s) {
ERIFile file;
file = ERIFile.clazz.createAndInsertObject(editingContext());
file.setName(s);
file.setDirectory(ERIDirectory.this);
addToFiles(file);
editingContext().saveChanges();
return file;
}
@Override
public void deleteFile(String s) throws IOException {
log.debug("deleteFile: {}", s);
ERIFile file = fileForName(s);
if (file != null) {
file.delete();
editingContext().saveChanges();
}
}
@Override
public boolean fileExists(String s) throws IOException {
return fileForName(s) != null;
}
@Override
public long fileLength(String s) throws IOException {
return fileForName(s).length();
}
@Override
public long fileModified(String s) throws IOException {
return fileForName(s).timestamp();
}
@Override
public String[] list() throws IOException {
return ((NSArray<String>) files().valueForKeyPath(ERIFile.Key.NAME)).toArray(new String[0]);
}
@Override
public IndexInput openInput(String s) throws IOException {
ERIFile file = fileForName(s);
if (file == null) {
throw new IOException("File not found: " + s);
}
try {
return file.openInput();
} catch (Exception ex) {
ERXEOControlUtilities.refaultObject(ERIDirectory.this);
ERXEOControlUtilities.clearSnapshotForRelationshipNamed(ERIDirectory.this, Key.FILES);
throw new IOException("File not found: " + s);
}
}
@Override
public void renameFile(String s, String s1) throws IOException {
fileForName(s).setName(s1);
editingContext().saveChanges();
}
@Override
public void touchFile(String s) throws IOException {
ERIFile file = fileForName(s);
if (file == null) {
file = createFile(s);
}
file.touch();
editingContext().saveChanges();
}
}
public static class ERIDirectoryClazz extends _ERIDirectory._ERIDirectoryClazz {
public Directory directoryForName(EOEditingContext ec, String store) {
ERIDirectory directory = objectMatchingKeyAndValue(ec, Key.NAME, store);
if (directory == null) {
directory = createAndInsertObject(ec);
directory.setName(store);
ec.saveChanges();
}
return directory.directory();
}
}
public interface Key extends _ERIDirectory.Key {
}
@Override
public void init(EOEditingContext ec) {
super.init(ec);
}
public ERIFile fileForName(String name) {
for (ERIFile file : files()) {
if (file.name().equals(name)) {
return file;
}
}
return null;
}
private Directory _directory;
public Directory directory() {
if (_directory == null) {
_directory = new LockingDirectory(new EOFDirectory());
}
return _directory;
}
}