/* * Copyright 2010 Brian S O'Neill * * 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.cojen.dirmi.io; import java.io.Closeable; import java.io.IOException; import java.util.HashMap; import java.util.Map; import org.cojen.dirmi.ClosedException; /** * Set of Closeable objects which can be closed as a unit. Once the group is * closed, adding more members immediately closes them. * * @author Brian S O'Neill */ public class CloseableGroup<C extends Closeable> implements Closeable { private final Map<C, Object> mGroup; private boolean mClosed; public CloseableGroup() { mGroup = new HashMap<C, Object>(); } public synchronized boolean isClosed() { return mClosed; } /** * @throws ClosedException if group is closed */ public synchronized void checkClosed() throws ClosedException { if (mClosed) { throw new ClosedException(); } } /** * Add a Closeable member to the group, which is automatically closed when * group is closed. * * @param member group member to add * @return false if group is closed and member was immediately closed as a result */ public boolean add(C member) { synchronized (this) { if (!mClosed) { mGroup.put(member, ""); return true; } } try { member.close(); } catch (IOException e) { // Ignore. } return false; } /** * Removes a member from the group, but does not close it. */ public synchronized void remove(C member) { mGroup.remove(member); } /** * Closes the group and all group members. */ @Override public void close() { Map<C, Object> copy; synchronized (this) { mClosed = true; copy = new HashMap<C, Object>(mGroup); mGroup.clear(); } for (C c : copy.keySet()) { try { c.close(); } catch (IOException e) { // Ignore. } } } /** * Disconnects the group and all group members, which must be Channels. */ void disconnect() { Map<C, Object> copy; synchronized (this) { mClosed = true; copy = new HashMap<C, Object>(mGroup); mGroup.clear(); } for (C c : copy.keySet()) { ((Channel) c).disconnect(); } } @Override public synchronized String toString() { return "CloseableGroup: " + mGroup.keySet(); } }