All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.openide.filesystems.FileEvent Maven / Gradle / Ivy

There is a newer version: RELEASE240
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.openide.filesystems;

import java.io.IOException;
import java.util.Collection;
import java.util.Date;
import java.util.EventObject;
import java.util.logging.Level;
import java.util.logging.Logger;

/** Event for listening on filesystem changes.
* 

* By calling {@link #getFile} the original file where the action occurred * can be obtained. * * @author Jaroslav Tulach, Petr Hamernik */ public class FileEvent extends EventObject { /** generated Serialized Version UID */ private static final long serialVersionUID = 1028087432345400108L; private static final Logger LOG = Logger.getLogger(FileEvent.class.getName()); /** Original file object where the action took place. */ private FileObject file; /** time when this event has been fired */ private long time; /** is expected? */ private boolean expected; /***/ private EventControl.AtomicActionLink atomActionID; private transient Collection postNotify; /** Creates new FileEvent. The FileObject where the action occurred * is assumed to be the same as the source object. * Delegates to {@link #FileEvent(org.openide.filesystems.FileObject, org.openide.filesystems.FileObject, boolean, long) * FileEvent(src, src, false, -1)}. * @param src source file which sent this event */ public FileEvent(FileObject src) { this(src, src, false, -1); } /** Creates new FileEvent, specifying the action object. * Delegates to {@link #FileEvent(org.openide.filesystems.FileObject, org.openide.filesystems.FileObject, boolean, long) * FileEvent(src, file, false, -1)}. * * @param src source file which sent this event * @param file FileObject where the action occurred */ public FileEvent(FileObject src, FileObject file) { this(src, file, false, -1); } /** Creates new FileEvent. * Delegates to {@link #FileEvent(org.openide.filesystems.FileObject, org.openide.filesystems.FileObject, boolean, long) * FileEvent(src, file, false, time)}. */ FileEvent(FileObject src, FileObject file, long time) { this(src, file, false, time); } /** Creates new FileEvent, specifying the action object. * Delegates to {@link #FileEvent(org.openide.filesystems.FileObject, org.openide.filesystems.FileObject, boolean, long) * FileEvent(src, file, expected, -1)}. * * @param src source file which sent this event * @param file FileObject where the action occurred * @param expected sets flag whether the value was expected*/ public FileEvent(FileObject src, FileObject file, boolean expected) { this(src, file, expected, -1); } /** Creates new FileEvent, specifying all its details. *

* Note that the two arguments of this method need not be identical * in cases where it is reasonable that a different file object from * the one affected would be listened to by other components. E.g., * in the case of a file creation event, the event source (which * listeners are attached to) would be the containing folder, while * the action object would be the newly created file object. *

* The time is usually {@link System#currentTimeMillis()} (which is the one * used if the parameter value is lower or equal to zero), but it may * be any other suitable time. For example when a file was changed, it * may be reasonable to use the timestamp of the file after its stream * has been closed. * * @param src source file which sends this event * @param file {@link FileObject} where the action occured * @param expected whether the change has been expected or not * @param time the time when the change happened * @since 7.54 */ public FileEvent(FileObject src, FileObject file, boolean expected, long time) { super(src); this.file = file; this.time = time <= 0L ? System.currentTimeMillis() : time; this.expected = expected; if (LOG.isLoggable(Level.FINEST)) { LOG.log(Level.FINEST, "FileEvent({0}, {1}, {2}, {3})", new Object[]{src, file, expected, this.time}); } MIMESupport.freeCaches(); FileUtil.freeCaches(); } /** @return the original file where action occurred */ public final FileObject getFile() { return file; } /** The time when this event has been created. * @return the milliseconds */ public final long getTime() { return time; } /** Getter to test whether the change has been expected or not. */ public final boolean isExpected() { return expected; } /** Support for batch processing of events. In some situations * you may want to delay processing of received events until the last * known one is delivered. For example if there is a lot of operations * done inside {@link FileUtil#runAtomicAction(java.lang.Runnable)} * action, there can be valid reason to do the processing only after * all of them are delivered. In such situation attach your {@link Runnable} * to provided event. Such {@link Runnable} is then guaranteed to be called once. * Either immediately (if there is no batch delivery in progress) * or some time later (if there is a batch delivery). You can attach * single runnable multiple times, even to different events in the * same batch section and its {@link Runnable#run()} method will still be * called just once. {@link Object#equals(java.lang.Object)} is used * to check equality of two {@link Runnable}s. * * @since 7.24 * @param r the runnable to execute when batch event deliver is over * (can be even executed immediately) */ public final void runWhenDeliveryOver(Runnable r) { Collection to = postNotify; if (to != null) { to.add(r); } else { r.run(); } } @Override public String toString() { StringBuilder b = new StringBuilder(); b.append(getClass().getName().replaceFirst(".+\\.", "")); b.append('['); FileObject src = (FileObject) getSource(); if (src != file) { b.append("src="); b.append(FileUtil.getFileDisplayName(src)); b.append(','); } b.append("file="); b.append(FileUtil.getFileDisplayName(file)); b.append(",time="); b.append(new Date(time)); b.append(",expected="); b.append(expected); insertIntoToString(b); b.append(']'); return b.toString(); } void insertIntoToString(StringBuilder b) {} /** */ void setAtomicActionLink(EventControl.AtomicActionLink atomActionID) { this.atomActionID = atomActionID; } /** Tests if this event has been generated from given atomic action. This can * be used to filter out own changes - when one modifies a file * that one also observes, one can use following trick: *

     * class MyAction implements {@link FileSystem.AtomicAction} {
     *   public void run() throws {@link IOException} {
     *     // change a file
     *   }
     * 
     *   public boolean equals(Object obj) {
     *     return obj != null && obj.getClass() == {@link #getClass()};
     *   }
     * 
     *   public int hashCode() {
     *     return getClass().{@link #hashCode()};
     *   }
     * }
     * 
     * // later when an event is delivered to {@link FileChangeListener your listener} one can check:
     * public void fileChangedEvent({@link FileEvent} ev) {
     *   if (!ev.firedFrom(new MyAction()) {
     *     // the event is not caused by my action, so react somehow
     *   }
     * }
     * 
     * 
* * @param run is tested atomic action. * @return true if fired from run. * @since 1.35 */ public boolean firedFrom(FileSystem.AtomicAction run) { EventControl.AtomicActionLink currentPropID = this.atomActionID; if (run == null) { return false; } while (currentPropID != null) { final Object aa = currentPropID.getAtomicAction(); if (aa != null && aa.equals(run)) { return true; } currentPropID = currentPropID.getPreviousLink(); } return false; } final boolean isAsynchronous() { EventControl.AtomicActionLink currentPropID = this.atomActionID; while (currentPropID != null) { final Object atomicAction = currentPropID.getAtomicAction(); if (atomicAction != null && atomicAction.getClass().getName().indexOf("AsyncRefreshAtomicAction") != -1) { return true; } if (atomicAction instanceof FileSystem.AsyncAtomicAction) { if (((FileSystem.AsyncAtomicAction)atomicAction).isAsynchronous()) { return true; } } currentPropID = currentPropID.getPreviousLink(); } return false; } void setPostNotify(Collection runs) { // cannot try to set the postNotify field twiced assert postNotify == null || runs == null; this.postNotify = runs; } void inheritPostNotify(FileEvent ev) { // cannot try to set the postNotify field twiced assert postNotify == null; this.postNotify = ev.postNotify; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy