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.util;
018
019import java.lang.ref.WeakReference;
020
021import org.apache.commons.vfs2.FileChangeEvent;
022import org.apache.commons.vfs2.FileListener;
023import org.apache.commons.vfs2.FileName;
024import org.apache.commons.vfs2.FileObject;
025import org.apache.commons.vfs2.FileSystem;
026
027/**
028 * Wrap a listener with a WeakReference.
029 *
030 * @since 2.0
031 */
032public class WeakRefFileListener implements FileListener {
033    private final FileSystem fs;
034    private final FileName name;
035    private final WeakReference<FileListener> listener;
036
037    protected WeakRefFileListener(final FileObject file, final FileListener listener) {
038        this.fs = file.getFileSystem();
039        this.name = file.getName();
040        this.listener = new WeakReference<>(listener);
041    }
042
043    /**
044     * This will install the {@code listener} at the given {@code file}.
045     *
046     * @param file The FileObject to listen on.
047     * @param listener The FileListener
048     */
049    public static void installListener(final FileObject file, final FileListener listener) {
050        final WeakRefFileListener weakListener = new WeakRefFileListener(file, listener);
051
052        file.getFileSystem().addListener(file, new WeakRefFileListener(file, weakListener));
053    }
054
055    /**
056     * returns the wrapped listener. If it is gone, the WeakRefFileListener wrapper will remove itself from the list of
057     * listeners.
058     *
059     * @return The FileListener.
060     * @throws Exception if an error occurs.
061     */
062    protected FileListener getListener() throws Exception {
063        final FileListener listener = this.listener.get();
064        if (listener == null) {
065            final FileObject file = fs.resolveFile(name);
066            file.getFileSystem().removeListener(file, this);
067        }
068        return listener;
069    }
070
071    /**
072     * Called when a file is created.
073     *
074     * @param event The FileChangeEvent.
075     * @throws Exception if an error occurs.
076     */
077    @Override
078    public void fileCreated(final FileChangeEvent event) throws Exception {
079        final FileListener listener = getListener();
080        if (listener == null) {
081            return;
082        }
083        listener.fileCreated(event);
084    }
085
086    /**
087     * Called when a file is deleted.
088     *
089     * @param event The FileChangeEvent.
090     * @throws Exception if an error occurs.
091     */
092    @Override
093    public void fileDeleted(final FileChangeEvent event) throws Exception {
094        final FileListener listener = getListener();
095        if (listener == null) {
096            return;
097        }
098        listener.fileDeleted(event);
099    }
100
101    /**
102     * Called when a file is changed.
103     * <p>
104     * This will only happen if you monitor the file using {@link org.apache.commons.vfs2.FileMonitor}.
105     *
106     * @param event The FileChangeEvent.
107     * @throws Exception if an error occurs.
108     */
109    @Override
110    public void fileChanged(final FileChangeEvent event) throws Exception {
111        final FileListener listener = getListener();
112        if (listener == null) {
113            return;
114        }
115        listener.fileChanged(event);
116    }
117}