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 * Wraps a listener with a WeakReference. 029 * 030 * @since 2.0 031 */ 032public class WeakRefFileListener implements FileListener { 033 034 /** 035 * Install the {@code listener} at the given {@code file}. 036 * <p> 037 * This installs a wrapper with a weak reference, so the listener can 038 * be collected. The reference to the listener is removed when the 039 * first event can't be delivered. 040 * <p> 041 * Warning: you cannot remove the listener with 042 * {@code fs.removeListener(file, listener)} as you do'nt have the wrapper 043 * instance at hand. 044 * <p> 045 * Method is used by {@link org.apache.commons.vfs2.provider.DelegateFileObject}, 046 * as used for {@link org.apache.commons.vfs2.impl.VirtualFileSystem}. 047 * 048 * @param file The FileObject to listen on. 049 * @param listener The FileListener 050 */ 051 public static void installListener(final FileObject file, final FileListener listener) { 052 file.getFileSystem().addListener(file, new WeakRefFileListener(file, listener)); 053 } 054 055 private final FileSystem fs; 056 private final FileName name; 057 058 private final WeakReference<FileListener> listener; 059 060 /** 061 * Constructs a new instance. 062 * 063 * @param file the file object. 064 * @param listener the file listener. 065 */ 066 protected WeakRefFileListener(final FileObject file, final FileListener listener) { 067 fs = file.getFileSystem(); 068 name = file.getName(); 069 this.listener = new WeakReference<>(listener); 070 } 071 072 /** 073 * Called when a file is changed. 074 * <p> 075 * This will only happen if you monitor the file using {@link org.apache.commons.vfs2.FileMonitor}. 076 * </p> 077 * 078 * @param event The FileChangeEvent. 079 * @throws Exception if an error occurs. 080 */ 081 @Override 082 public void fileChanged(final FileChangeEvent event) throws Exception { 083 final FileListener listener = getListener(); 084 if (listener != null) { 085 listener.fileChanged(event); 086 } 087 } 088 089 /** 090 * Called when a file is created. 091 * 092 * @param event The FileChangeEvent. 093 * @throws Exception if an error occurs. 094 */ 095 @Override 096 public void fileCreated(final FileChangeEvent event) throws Exception { 097 final FileListener listener = getListener(); 098 if (listener != null) { 099 listener.fileCreated(event); 100 } 101 } 102 103 /** 104 * Called when a file is deleted. 105 * 106 * @param event The FileChangeEvent. 107 * @throws Exception if an error occurs. 108 */ 109 @Override 110 public void fileDeleted(final FileChangeEvent event) throws Exception { 111 final FileListener listener = getListener(); 112 if (listener != null) { 113 listener.fileDeleted(event); 114 } 115 } 116 117 /** 118 * Gets the wrapped listener. If it is gone, the WeakRefFileListener wrapper will remove itself from the list of 119 * listeners. 120 * 121 * @return The FileListener. 122 * @throws Exception if an error occurs. 123 */ 124 protected FileListener getListener() throws Exception { 125 final FileListener listener = this.listener.get(); 126 if (listener == null) { 127 try (FileObject fileObject = fs.resolveFile(name)) { 128 fileObject.getFileSystem().removeListener(fileObject, this); 129 } 130 } 131 return listener; 132 } 133}