001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.commons.vfs2.provider;
018
019import java.util.ArrayList;
020
021import org.apache.commons.vfs2.FileSystemException;
022
023/**
024 * A {@link VfsComponent} that contains a set of sub-components.
025 */
026public abstract class AbstractVfsContainer extends AbstractVfsComponent {
027    /**
028     * The components contained by this component.
029     */
030    private final ArrayList<Object> components = new ArrayList<>(); // @GuardedBy("self")
031
032    /**
033     * Adds a sub-component to this component.
034     * <p>
035     * If the sub-component implements {@link VfsComponent}, it is initialised. All sub-components are closed when this
036     * component is closed.
037     *
038     * @param component the component to add.
039     * @throws FileSystemException if any error occurs.
040     */
041    protected void addComponent(final Object component) throws FileSystemException {
042        synchronized (components) {
043            if (!components.contains(component)) {
044                // Initialise
045                if (component instanceof VfsComponent) {
046                    final VfsComponent vfsComponent = (VfsComponent) component;
047                    vfsComponent.setLogger(getLogger());
048                    vfsComponent.setContext(getContext());
049                    vfsComponent.init();
050                }
051
052                // Keep track of component, to close it later
053                components.add(component);
054            }
055        } // synchronized
056    }
057
058    /**
059     * Removes a sub-component from this component.
060     *
061     * @param component the component to remove.
062     */
063    protected void removeComponent(final Object component) {
064        synchronized (components) {
065            // multiple instances should not happen
066            components.remove(component);
067        }
068    }
069
070    /**
071     * Closes the sub-components of this component.
072     */
073    @Override
074    public void close() {
075        final Object[] toclose;
076        synchronized (components) {
077            toclose = components.toArray();
078            components.clear();
079        }
080
081        // Close all components
082        for (final Object component : toclose) {
083            if (component instanceof VfsComponent) {
084                final VfsComponent vfsComponent = (VfsComponent) component;
085                vfsComponent.close();
086            }
087        }
088    }
089}