/* (c) 2014 Open Source Geospatial Foundation - all rights reserved * (c) 2014 OpenPlans * This code is licensed under the GPL 2.0 license, available at the root * application directory. */ package org.geoserver.platform.resource; import java.io.File; import java.io.Serializable; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** * Notification of resource changes. * <p> * Notification is provided as a delta modified resources: * <ul> * <li>Listeners on a single resource will be notified on resource change to that resource. * * A listener to path="user_projections/epsg.properties" receive notification on change to the <b>epsg.properties</b> file. This notification will * consist of of delta=<code>user_projections/epsg.properties</code></li> * <li>Listeners on a directory will be notified on any resource change in the directory. The delta will include any modified directories. * A listener on path="style" is notified on change to <b>style/pophatch.sld</b> and <b>style/icons/city.png</b>. The change to these two files is * represented with delta consisting of delta=<code>style,style/icons,style/icons/city.png,style/pophatch.sld</code></li> * <li>Removed resources may be represented in notification, but will have reverted to {@link Resource.Type#UNDEFINED} since the content is no longer * present.</li> * </ul> * * @author Jody Garnett (Boundless) */ public class ResourceNotification implements Serializable { private static final long serialVersionUID = 1689657047251329584L; /** Event kind for the purpose of identification */ public enum Kind { /** Resource created */ ENTRY_CREATE, /** Resource deleted */ ENTRY_DELETE, /** Resource modified */ ENTRY_MODIFY } /** * Event for resource change notification. */ public static class Event implements Serializable { private static final long serialVersionUID = 2852962095949861322L; final String path; final Kind kind; public Event( String path, Kind kind ){ this.path = path; this.kind = kind; } /** * Nature of change * @return nature of change */ public Kind getKind() { return kind; } /** * Resource path changed * @return resource path changed */ public String getPath() { return path; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((kind == null) ? 0 : kind.hashCode()); result = prime * result + ((path == null) ? 0 : path.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Event other = (Event) obj; if (kind != other.kind) return false; if (path == null) { if (other.path != null) return false; } else if (!path.equals(other.path)) return false; return true; } @Override public String toString() { return "Event [path=" + path + ", kind=" + kind + "]"; } } /** * ResourceStore used for for resource lookup. */ //final private ResourceStore store; /** Notificaiton context */ final private String path; /** Notification kind */ final private Kind kind; /** * Delta of changes detected (since last check). */ final private List<Event> delta; final private long timestamp; public static List<Event> delta(File baseDirectory, List<File> created, List<File> removed, List<File> modified) { if( created == null ){ created = Collections.emptyList(); } if( removed == null ){ removed = Collections.emptyList(); } if( modified == null ){ modified = Collections.emptyList(); } int size = created.size()+removed.size()+modified.size(); if( size == 0 ) { return null; } List<Event> delta = new ArrayList<Event>( size ); for( File file : created ){ String newPath = Paths.convert( baseDirectory, file ); delta.add( new Event(newPath, Kind.ENTRY_CREATE ) ); } for( File file : removed ){ String deletePath = Paths.convert( baseDirectory, file ); delta.add( new Event(deletePath, Kind.ENTRY_DELETE ) ); } for( File file : modified ){ String changedPath = Paths.convert( baseDirectory, file ); delta.add( new Event(changedPath, Kind.ENTRY_MODIFY ) ); } return delta; } /** * Notification of a change to a single resource. * * @param path resource path changed * @param kind nature of change * @param timestamp local time stamp of change */ ResourceNotification(String path, Kind kind, long timestamp) { this.path = path; this.kind = kind; this.delta = Collections.emptyList(); this.timestamp = timestamp; } /** * Notification changes to directory contents. * * @param path resource path changed * @param kind nature of change * @param timestamp local time stamp of change * @param delta List of changes */ @SuppressWarnings("unchecked") public ResourceNotification( String path, Kind kind, long timestamp, List<Event> delta ){ this.path = path; this.kind = kind; this.delta = (List<Event>) (delta != null ? Collections.unmodifiableList(delta) : Collections.emptyList()); this.timestamp = timestamp; } public Kind getKind() { return kind; } public String getPath() { return path; } public long getTimestamp() { return timestamp; } /** * Paths of changed resources. * <p> * This list of changed resources is sorted and includes any relevant directories. * * @return paths of changed resources */ public List<Event> events() { return delta; // unmodifiable } @Override public String toString() { return "ResourceNotification [path=" + path + ", kind=" + kind + ", delta=" + delta + ", timestamp="+timestamp+"]"; } }