Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * JBoss, Home of Professional Open Source
   * Copyright 2010, JBoss Inc., and individual contributors as indicated
   * by the @authors tag. See the copyright.txt in the distribution for a
   * full listing of individual contributors.
   *
   * This is free software; you can redistribute it and/or modify it
   * under the terms of the GNU Lesser General Public License as
   * published by the Free Software Foundation; either version 2.1 of
  * the License, or (at your option) any later version.
  *
  * This software is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this software; if not, write to the Free
  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
  */
 
 package org.jboss.remoting3.spi;
 
 import java.util.Map;
A basic implementation of a closeable resource. Use as a convenient base class for your closeable resources. Ensures that the close() method is idempotent; implements the registry of close handlers.

Parameters:
<T> the type of the closeable resource
 
 public abstract class AbstractHandleableCloseable<T extends HandleableCloseable<T>> implements HandleableCloseable<T> {
 
     private static final Logger log = Logger.getLogger("org.jboss.remoting.resource");
     private static final boolean LEAK_DEBUGGING;
 
     private final Executor executor;
     private final StackTraceElement[] backtrace;
     private final boolean autoClose;
 
     private final Object closeLock = new Object();
     private State state = .;
     private IOException failure = null;
     private Map<KeyCloseHandler<? super T>> closeHandlers = null;
 
     enum State {
         OPEN,
         CLOSING,
         CLOSED,
     }
 
     static {
         boolean b;
         try {
             b = Boolean.parseBoolean(AccessController.doPrivileged(new PrivilegedAction<String>() {
                 public String run() {
                     return System.getProperty("jboss.remoting.leakdebugging""false");
                 }
             }));
         } catch (SecurityException se) {
             b = false;
         }
          = b;
     }

    
Basic constructor.

Parameters:
executor the executor used to execute the close notification handlers
 
     protected AbstractHandleableCloseable(final Executor executor) {
         this(executortrue);
     }

    
Basic constructor.

Parameters:
executor the executor used to execute the close notification handlers
autoClose true if this instance should automatically close on finalize
 
     protected AbstractHandleableCloseable(final Executor executorfinal boolean autoClose) {
         if (executor == null) {
             throw new NullPointerException("executor is null");
         }
        this. = executor;
         =  ? Thread.currentThread().getStackTrace() : null;
        this. = autoClose;
    }

    
Read the status of this resource. This is just a snapshot in time; there is no guarantee that the resource will remain open for any amount of time, even if this method returns true.

Returns:
true if the resource is still open
    protected boolean isOpen() {
        synchronized () {
            return  == .;
        }
    }

    
Called exactly once when the close() method is invoked; the actual close operation should take place here. This method must call closeComplete(), directly or indirectly, for the close operation to finish (it may happen in another thread but it must happen). This method should not expect the closeComplete() call to be made from another thread from the same thread pool that may cause close(). As close will block, this can result in situations where all threads in the pool are blocked on close() method calls, which means the closeComplete() will never be run.

Throws:
org.jboss.remoting3.RemotingException if the close failed
    protected void closeAction() throws IOException {
        closeComplete();
    }

    
    public void close() throws IOException {
        .tracef("Closing %s synchronously"this);
        boolean first = false;
        synchronized () {
            switch () {
                case : {
                    first = true;
                     = .;
                    break;
                }
                case : {
                    break;
                }
                case return;
                defaultthrow new IllegalStateException();
            }
        }
        if (firsttry {
            closeAction();
        } catch (IOException e) {
            .tracef(e"Close of %s failed"this);
            final Map<KeyCloseHandler<? super T>> closeHandlers;
            synchronized () {
                 = .;
                closeHandlers = this.;
                this. = null;
                .notifyAll();
            }
            if (closeHandlers != null) {
                for (final CloseHandler<? super T> handler : closeHandlers.values()) {
                    runCloseTask(new CloseHandlerTask(handlere));
                }
            }
            throw e;
        } catch (Throwable t) {
            .errorf(t"Close action for %s failed to execute (resource may be left in an indeterminate state)"this);
            throw new IllegalStateException(t);
        }
        final IOException failure;
        synchronized () {
            while ( != .try {
                .wait();
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                throw new InterruptedIOException("Interrupted while waiting for close to complete");
            }
            failure = this.;
            this. = null;
        }
        if (failure != null) {
            final IOException clone = clone(failure);
            if (failure != clone) {
                SpiUtils.glueStackTraces(failure, Thread.currentThread().getStackTrace(), 1, "asynchronous close");
            }
            throw clone;
        }
    }
    private static <T extends IOException> T clone(T original) {
        final Throwable cause = original.getCause();
        @SuppressWarnings("unchecked")
        final Class<T> originalClass = (Class<T>) original.getClass();
        // try a few constructors
        Constructor<T> constructor;
        try {
            constructor = originalClass.getConstructor(String.classThrowable.class);
            final T clone = constructor.newInstance(original.getMessage(), cause);
            clone.setStackTrace(original.getStackTrace());
            return clone;
        } catch (NoSuchMethodException e) {
            // nope
        } catch (InvocationTargetException e) {
            // nope
        } catch (InstantiationException e) {
            // nope
        } catch (IllegalAccessException e) {
            // nope
        }
        try {
            constructor = originalClass.getConstructor(String.class);
            final T clone = constructor.newInstance(original.getMessage());
            clone.initCause(cause);
            clone.setStackTrace(original.getStackTrace());
            return clone;
        } catch (NoSuchMethodException e) {
            // nope
        } catch (InvocationTargetException e) {
            // nope
        } catch (InstantiationException e) {
            // nope
        } catch (IllegalAccessException e) {
            // nope
        }
        try {
            constructor = originalClass.getConstructor();
            final T clone = constructor.newInstance();
            clone.initCause(cause);
            clone.setStackTrace(original.getStackTrace());
            return clone;
        } catch (NoSuchMethodException e) {
            // nope
        } catch (InvocationTargetException e) {
            // nope
        } catch (InstantiationException e) {
            // nope
        } catch (IllegalAccessException e) {
            // nope
        }
        // we tried!
        return original;
    }

    
Call when close is complete.
    protected void closeComplete() {
        final Map<KeyCloseHandler<? super T>> closeHandlers;
        synchronized () {
            switch () {
                case : {
                    .tracef("Closing %s asynchronously"this);
                    // fall thru
                }
                case : {
                    .tracef("Completed close of %s"this);
                     = .;
                    closeHandlers = this.;
                    this. = null;
                    break;
                }
                case : {
                    // idempotent
                    return;
                }
                default:
                    throw new IllegalStateException();
            }
            .notifyAll();
        }
        if (closeHandlers != null) {
            for (final CloseHandler<? super T> handler : closeHandlers.values()) {
                runCloseTask(new CloseHandlerTask(handlernull));
            }
        }
    }

    
Call if an async close has failed.

Parameters:
cause the failure cause
    protected void closeFailed(IOException cause) {
        final Map<KeyCloseHandler<? super T>> closeHandlers;
        synchronized () {
            switch () {
                case : {
                    .tracef(cause"Completed close of %s with failure"this);
                     = .;
                     = cause;
                    closeHandlers = this.;
                    this. = null;
                    break;
                }
                case : {
                    // idempotent
                    return;
                }
                default:
                    throw new IllegalStateException();
            }
            .notifyAll();
        }
        if (closeHandlers != null) {
            for (final CloseHandler<? super T> handler : closeHandlers.values()) {
                runCloseTask(new CloseHandlerTask(handlercause));
            }
        }
    }

    
    public void awaitClosed() throws InterruptedException {
        synchronized () {
            while ( != .) {
                .wait();
            }
        }
    }

    
    public void awaitClosedUninterruptibly() {
        boolean intr = false;
        try {
            synchronized () {
                while ( != .) {
                    try {
                        .wait();
                    } catch (InterruptedException e) {
                        intr = true;
                    }
                }
            }
        } finally {
            if (intr) Thread.currentThread().interrupt();
        }
    }

    
    public void closeAsync() {
        .tracef("Closing %s asynchronously"this);
        boolean first;
        synchronized () {
            switch () {
                case : {
                    first = true;
                     = .;
                    break;
                }
                case :
                case return;
                defaultthrow new IllegalStateException();
            }
        }
        if (firsttry {
            closeAction();
        } catch (IOException e) {
            .tracef(e"Close of %s failed"this);
            final Map<KeyCloseHandler<? super T>> closeHandlers;
            synchronized () {
                 = .;
                closeHandlers = this.;
                this. = null;
                .notifyAll();
            }
            if (closeHandlers != null) {
                for (final CloseHandler<? super T> handler : closeHandlers.values()) {
                    runCloseTask(new CloseHandlerTask(handlere));
                }
            }
        } catch (Throwable t) {
            .errorf(t"Close action for %s failed to execute (resource may be left in an indeterminate state)"this);
        }
    }

    
    public Key addCloseHandler(final CloseHandler<? super T> handler) {
        if (handler == null) {
            throw new NullPointerException("handler is null");
        }
        synchronized () {
            if ( == . ||  == .) {
                final Key key = new KeyImpl<T>(this);
                final Map<KeyCloseHandler<? super T>> closeHandlers = this.;
                if (closeHandlers == null) {
                    final IdentityHashMap<KeyCloseHandler<? super T>> newMap = new IdentityHashMap<KeyCloseHandler<? super T>>();
                    this. = newMap;
                    newMap.put(keyhandler);
                } else {
                    closeHandlers.put(keyhandler);
                }
                return key;
            }
        }
        runCloseTask(new CloseHandlerTask(handlernull));
        return new NullKey();
    }
    private static void runCloseTask(final Runnable task) {
        try {
            task.run();
        } catch (Throwable t) {
            .tracef(t"Got exception running close task %s"task);
        }
    }
    private static final class NullKey implements Key {
        public void remove() {
        }
    }
    private static final class KeyImpl<T extends HandleableCloseable<T>> implements Key {
        private final AbstractHandleableCloseable<T> instance;
        private KeyImpl(final AbstractHandleableCloseable<T> instance) {
            this. = instance;
        }
        public void remove() {
            synchronized (.) {
                final Map<KeyCloseHandler<? super T>> closeHandlers = .;
                if (closeHandlers != null) {
                    closeHandlers.remove(this);
                }
            }
        }
    }

    
Get the executor to use for handler invocation.

Returns:
the executor
    protected Executor getExecutor() {
        return ;
    }

    
Finalize this closeable instance. If the instance hasn't been closed, it is closed and a warning is logged.
    protected void finalize() throws Throwable {
        try {
            super.finalize();
        } finally {
            if ( && isOpen()) {
                if () {
                    final Throwable t = new LeakThrowable();
                    t.setStackTrace();
                    .warnf(t"Leaked a %s instance: %s"getClass().getName(), this);
                } else {
                    .tracef("Leaked a %s instance: %s"getClass().getName(), this);
                }
                closeAsync();
            }
        }
    }

    
Check if open, throwing an exception if it is not.

    protected void checkOpen() throws NotOpenException {
        synchronized () {
            if ( != .) {
                throw new NotOpenException(toString() + " is not open");
            }
        }
    }
    @SuppressWarnings({ "serial" })
    static final class LeakThrowable extends Throwable {
        LeakThrowable() {
        }
        public String toString() {
            return "a leaked reference";
        }
    }
    final class CloseHandlerTask implements Runnable {
        private final CloseHandler<? super T> handler;
        private final IOException exception;
        CloseHandlerTask(final CloseHandler<? super T> handlerfinal IOException exception) {
            this. = handler;
            this. = exception;
        }
        @SuppressWarnings("unchecked")
        public void run() {
            SpiUtils.safeHandleClose(, (T) AbstractHandleableCloseable.this);
        }
    }
New to GrepCode? Check out our FAQ X