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; 020import java.util.stream.Stream; 021 022import org.apache.commons.vfs2.FileSystemException; 023 024/** 025 * A {@link VfsComponent} that contains a set of subcomponents. 026 */ 027public abstract class AbstractVfsContainer extends AbstractVfsComponent { 028 029 /** 030 * The components contained by this component. 031 */ 032 private final ArrayList<Object> components = new ArrayList<>(); // @GuardedBy("self") 033 034 /** 035 * Constructs a new instance for subclasses. 036 */ 037 public AbstractVfsContainer() { 038 // empty 039 } 040 041 /** 042 * Adds a subcomponent to this component. 043 * <p> 044 * If the sub-component implements {@link VfsComponent}, it is initialized. All sub-components are closed when this 045 * component is closed. 046 * </p> 047 * 048 * @param component the component to add. 049 * @throws FileSystemException if any error occurs. 050 */ 051 protected void addComponent(final Object component) throws FileSystemException { 052 synchronized (components) { 053 if (!components.contains(component)) { 054 // Initialize 055 if (component instanceof VfsComponent) { 056 final VfsComponent vfsComponent = (VfsComponent) component; 057 vfsComponent.setLogger(getLogger()); 058 vfsComponent.setContext(getContext()); 059 vfsComponent.init(); 060 } 061 // Keep track of component, to close it later 062 components.add(component); 063 } 064 } 065 } 066 067 /** 068 * Closes the subcomponents of this component. 069 */ 070 @Override 071 public void close() { 072 final Object[] toclose; 073 synchronized (components) { 074 toclose = components.toArray(); 075 components.clear(); 076 } 077 // Close all components 078 Stream.of(toclose).filter(VfsComponent.class::isInstance) 079 .forEach(component -> ((VfsComponent) component).close()); 080 } 081 082 /** 083 * Removes a subcomponent from this component. 084 * 085 * @param component the component to remove. 086 */ 087 protected void removeComponent(final Object component) { 088 synchronized (components) { 089 // multiple instances should not happen 090 components.remove(component); 091 } 092 } 093}