/* * $Id$ * * Copyright 2010 Glencoe Software, Inc. All rights reserved. * Use is subject to license terms supplied in LICENSE.txt */ package ome.services.blitz.repo; import java.util.concurrent.atomic.AtomicReference; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import Ice.Current; import ome.api.RawFileStore; import ome.services.blitz.impl.RawFileStoreI; import ome.services.blitz.util.BlitzExecutor; import omero.ServerError; import omero.api.AMD_RawFileStore_read; import omero.api.AMD_RawFileStore_setFileId; import omero.api.AMD_RawFileStore_write; /** * An implementation of the RepoRawFileStore interface * * @author Josh Moore, josh at glencoesoftware.com */ public class RepoRawFileStoreI extends RawFileStoreI { private final static Logger log = LoggerFactory.getLogger(RepoRawFileStoreI.class); /** * Interface which can be implemented in order to inject logic into various * {@link RepoRawFileStoreI} methods. These are only called if the callback * instance is set via {@link RepoRawFileStoreI#setCallback(Callback)}. * */ interface Callback { /** * Called if and only if the write method is successful. */ void onWrite(byte[] buf, long position, long length); /** * Called in a finally block after * {@link RepoRawFileStoreI#postClose(Current)} completes. */ void onPreClose(); /** * Called in a finally block after * {@link RepoRawFileStoreI#postClose(Current)} completes. */ void onPostClose(); } /** * Implementation of {@link Callback} which does nothing for each of the * methods. Each method can be easily overridden in order to provide a * subset of the callback methods. */ static class NoOpCallback implements Callback { @Override public void onWrite(byte[] buf, long position, long length) { // no-op } @Override public void onPreClose() { // no-op } @Override public void onPostClose() { // no-op } } private AtomicReference<Callback> cb = new AtomicReference<Callback>(); public RepoRawFileStoreI(BlitzExecutor be, RawFileStore service, Ice.Current curr) { super(service, be); } public void setCallback(Callback cb) { this.cb.set(cb); } @Override public void setFileId_async(AMD_RawFileStore_setFileId __cb, long fileId, Current __current) throws ServerError { omero.ApiUsageException aue = new omero.ApiUsageException(); aue.message = "Cannot reset id to " + fileId; __cb.ice_exception(aue); } @Override public void read_async(AMD_RawFileStore_read __cb, long position, int length, Current __current) throws ServerError { if (length > 64 * 1000 * 1000) { __cb.ice_exception(new omero.ApiUsageException(null, null, "Too big: " + length)); return; // EARLY EXIT! } super.read_async(__cb, position, length, __current); } @Override public void write_async(AMD_RawFileStore_write __cb, byte[] buf, long position, int length, Current __current) throws ServerError { super.write_async(__cb, buf, position, length, __current); Callback cb = this.cb.get(); if (cb != null) { cb.onWrite(buf, position, length); } } @Override protected void preClose(Current current) throws Throwable { try { super.preClose(current); } finally { Callback cb = this.cb.get(); if (cb != null) { cb.onPreClose(); } } } @Override protected void postClose(Ice.Current c) { try { super.postClose(c); } finally { Callback cb = this.cb.get(); if (cb != null) { cb.onPostClose(); } } } }