Home | History | Annotate | Download | only in config
      1 /*
      2  * Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  *
      8  *   - Redistributions of source code must retain the above copyright
      9  *     notice, this list of conditions and the following disclaimer.
     10  *
     11  *   - Redistributions in binary form must reproduce the above copyright
     12  *     notice, this list of conditions and the following disclaimer in the
     13  *     documentation and/or other materials provided with the distribution.
     14  *
     15  *   - Neither the name of Oracle nor the names of its
     16  *     contributors may be used to endorse or promote products derived
     17  *     from this software without specific prior written permission.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
     20  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     21  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     23  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     24  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     26  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
     27  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
     28  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     29  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 /*
     33  * This source code is provided to illustrate the usage of a given feature
     34  * or technique and has been deliberately simplified. Additional steps
     35  * required for a production-quality application, such as security checks,
     36  * input validation and proper error handling, might not be present in
     37  * this sample code.
     38  */
     39 
     40 
     41 package com.sun.jmx.examples.scandir.config;
     42 
     43 import java.io.File;
     44 import java.io.FileFilter;
     45 import java.util.ArrayList;
     46 import java.util.Arrays;
     47 import java.util.List;
     48 import java.util.logging.Logger;
     49 import javax.xml.bind.annotation.XmlAttribute;
     50 import javax.xml.bind.annotation.XmlElement;
     51 import javax.xml.bind.annotation.XmlElementRef;
     52 import javax.xml.bind.annotation.XmlElementWrapper;
     53 import javax.xml.bind.annotation.XmlList;
     54 import javax.xml.bind.annotation.XmlRootElement;
     55 
     56 /**
     57  * The <code>DirectoryScannerConfig</code> Java Bean is used to model
     58  * the configuration of a {@link
     59  * com.sun.jmx.examples.scandir.DirectoryScannerMXBean}.
     60  * <p>
     61  * This class is annotated for XML binding.
     62  * </p>
     63  * @author Sun Microsystems, 2006 - All rights reserved.
     64  */
     65 @XmlRootElement(name="DirectoryScanner",
     66         namespace=XmlConfigUtils.NAMESPACE)
     67 public class DirectoryScannerConfig {
     68 
     69     //
     70     // A logger for this class.
     71     //
     72     // private static final Logger LOG =
     73     //        Logger.getLogger(DirectoryScannerConfig.class.getName());
     74 
     75     /**
     76      * This enumeration is used to model the actions that a {@link
     77      * com.sun.jmx.examples.scandir.DirectoryScannerMXBean
     78      * DirectoryScannerMXBean} should take when a file matches its set
     79      * of matching criteria.
     80      **/
     81     public enum Action {
     82         /**
     83          * Indicates that the {@code DirectoryScannerMXBean} should
     84          * emit a {@code Notification} when a matching file is found.
     85          */
     86         NOTIFY,
     87         /**
     88          * Indicates that the {@code DirectoryScannerMXBean} should
     89          * delete the matching files.
     90          */
     91         DELETE,
     92         /**
     93          * Indicates that the {@code DirectoryScannerMXBean} should
     94          * log the actions that were taken on the matching files.
     95          */
     96         LOGRESULT };
     97 
     98     // A short name for the Directory Scanner
     99     // This name is used for the value of the {@code name=} key in the
    100     // {@code DirectoryScannerMXBean} ObjectName.
    101     private String name;
    102 
    103     // The root directory of the Directory Scanner
    104     private String rootDirectory;
    105 
    106     // List of filters identifying files that should be selected.
    107     // A file is selected if at least one filter matches.
    108     //
    109     private final List<FileMatch> includeFiles =
    110             new ArrayList<FileMatch>();
    111 
    112     // List of filters identifying files that should be excluded.
    113     // A file is excluded if at least one filter matches.
    114     //
    115     private final List<FileMatch> excludeFiles =
    116             new ArrayList<FileMatch>();
    117 
    118 
    119     // The actions that this Directory Scanner should carry out when a
    120     // file is selected. Default is NOTIFY and LOGRESULT.
    121     //
    122     private Action[] actions = { Action.NOTIFY, Action.LOGRESULT };
    123 
    124     /**
    125      * Creates a new instance of {@code DirectoryScannerConfig}.
    126      * We keep this empty constructor to make XML binding easier.
    127      * You shouldn't use this constructor directly:
    128      * use {@link #DirectoryScannerConfig(String)
    129      * DirectoryScannerConfig(String name)} instead.
    130      * @deprecated <p>Tagged deprecated so that a compiler warning is issued.
    131      *             Use {@link #DirectoryScannerConfig(String)
    132      *                  DirectoryScannerConfig(String name)} instead.
    133      *             </p>
    134      **/
    135     public DirectoryScannerConfig() {
    136         this(null);
    137     }
    138 
    139     /**
    140      * Creates a new instance of {@code DirectoryScannerConfig}.
    141      * @param name A short name for the Directory Scanner. This name is used for
    142      *        the value of the {@code name=} key in the
    143      *        {@code DirectoryScannerMXBean} ObjectName.
    144      **/
    145     public DirectoryScannerConfig(String name) {
    146         this.name = name;
    147         rootDirectory = null;
    148     }
    149 
    150     /**
    151      * Gets the root directory configured for that Directory Scanner.
    152      * @return the root directory at which the directory scanner should start
    153      *         scanning.
    154      **/
    155     @XmlElement(name="RootDirectory",namespace=XmlConfigUtils.NAMESPACE)
    156     public String getRootDirectory() {
    157         return rootDirectory;
    158     }
    159 
    160     /**
    161      * Configures a root directory for that Directory Scanner.
    162      * @param root The root directory at which the directory scanner should
    163      *        start scanning.
    164      **/
    165     public void setRootDirectory(String root) {
    166         rootDirectory=root;
    167     }
    168 
    169 
    170     /**
    171      * Gets the short name of this directory scanner.
    172      *
    173      * <p>
    174      * This name is used for the value of the {@code name=} key in the
    175      * {@code DirectoryScannerMXBean} ObjectName.
    176      * </p>
    177      *
    178      * @return the short name of this directory scanner.
    179      **/
    180     @XmlAttribute(name="name",required=true)
    181     public String getName() {
    182         return this.name;
    183     }
    184 
    185     /**
    186      * Setter for property {@link #getName() name}.
    187      * Once set its value cannot change.
    188      * @param name New value of property name.
    189      * @throws IllegalArgumentException if {@code name} is already set to a
    190      *         different non null value.
    191      */
    192     public void setName(String name) {
    193         if (this.name == null)
    194             this.name = name;
    195         else if (name == null)
    196             throw new IllegalArgumentException("name=null");
    197         else if (!name.equals(this.name))
    198             throw new IllegalArgumentException("name="+name);
    199     }
    200 
    201     /**
    202      * Getter for property includeFiles.
    203      * This is an array of filters identifying files that should be selected.
    204      * A file is selected if at least one filter matches.
    205      * @return Value of property includeFiles.
    206      */
    207     @XmlElementWrapper(name="IncludeFiles",
    208             namespace=XmlConfigUtils.NAMESPACE)
    209     @XmlElementRef
    210     public FileMatch[] getIncludeFiles() {
    211         synchronized(includeFiles) {
    212             return includeFiles.toArray(new FileMatch[0]);
    213         }
    214     }
    215 
    216     /**
    217      * Adds a filter to the includeFiles property.
    218      * A file is selected if at least one filter matches.
    219      * @param include A filter identifying files that should be selected.
    220      */
    221     public void addIncludeFiles(FileMatch include) {
    222         if (include == null)
    223             throw new IllegalArgumentException("null");
    224         synchronized (includeFiles) {
    225             includeFiles.add(include);
    226         }
    227     }
    228 
    229     /**
    230      * Setter for property includeFiles.
    231      * @param includeFiles New value of property includeFiles.
    232      *        This is an array of filters identifying files
    233      *        that should be selected. A file is selected if at least
    234      *        one filter matches.
    235      */
    236     public void setIncludeFiles(FileMatch[] includeFiles) {
    237         synchronized (this.includeFiles) {
    238             this.includeFiles.clear();
    239             if (includeFiles == null) return;
    240             this.includeFiles.addAll(Arrays.asList(includeFiles));
    241         }
    242     }
    243 
    244     /**
    245      * Getter for property excludeFiles.
    246      * This is an array of filters identifying files that should be excluded.
    247      * A file is excluded if at least one filter matches.
    248      * @return Value of property excludeFiles.
    249      */
    250     @XmlElementWrapper(name="ExcludeFiles",
    251             namespace=XmlConfigUtils.NAMESPACE)
    252     @XmlElementRef
    253     public FileMatch[] getExcludeFiles() {
    254         synchronized(excludeFiles) {
    255             return excludeFiles.toArray(new FileMatch[0]);
    256         }
    257     }
    258 
    259     /**
    260      * Setter for property excludeFiles.
    261      * @param excludeFiles New value of property excludeFiles.
    262      *        This is an array of filters identifying files
    263      *        that should be excluded. A file is excluded if at least
    264      *        one filter matches.
    265      */
    266     public void setExcludeFiles(FileMatch[] excludeFiles) {
    267         synchronized (this.excludeFiles) {
    268             this.excludeFiles.clear();
    269             if (excludeFiles == null) return;
    270             this.excludeFiles.addAll(Arrays.asList(excludeFiles));
    271         }
    272     }
    273 
    274     /**
    275      * Adds a filter to the excludeFiles property.
    276      * A file is excluded if at least one filter matches.
    277      * @param exclude A filter identifying files that should be excluded.
    278      */
    279     public void addExcludeFiles(FileMatch exclude) {
    280         if (exclude == null)
    281             throw new IllegalArgumentException("null");
    282         synchronized (excludeFiles) {
    283             this.excludeFiles.add(exclude);
    284         }
    285     }
    286 
    287     /**
    288      * Gets the list of actions that this Directory Scanner should carry
    289      * out when a file is selected. Default is NOTIFY and LOGRESULT.
    290 
    291      * @return The list of actions that this Directory Scanner should carry
    292      * out when a file is selected.
    293      */
    294     @XmlElement(name="Actions",namespace=XmlConfigUtils.NAMESPACE)
    295     @XmlList
    296     public Action[] getActions() {
    297        return  (actions == null)?null:actions.clone();
    298     }
    299 
    300     /**
    301      * Sets the list of actions that this Directory Scanner should carry
    302      * out when a file is selected. Default is NOTIFY and LOGRESULT.
    303 
    304      * @param actions The list of actions that this Directory Scanner should
    305      * carry out when a file is selected.
    306      */
    307     public void setActions(Action[] actions) {
    308         this.actions = (actions == null)?null:actions.clone();
    309     }
    310 
    311     /**
    312      * Builds a {@code FileFilter} from the {@link #getIncludeFiles
    313      * includeFiles} and {@link #getExcludeFiles excludeFiles} lists.
    314      * A file will be accepted if it is selected by at least one of
    315      * the filters in {@link #getIncludeFiles includeFiles}, and is
    316      * not excluded by any of the filters in {@link
    317      * #getExcludeFiles excludeFiles}. If there's no filter in
    318      * {@link #getIncludeFiles includeFiles}, then a file is accepted
    319      * simply if it is not excluded by any of the filters in {@link
    320      * #getExcludeFiles excludeFiles}.
    321      *
    322      * @return A new {@code FileFilter}  created from the current snapshot
    323      *         of the {@link #getIncludeFiles
    324      * includeFiles} and {@link #getExcludeFiles excludeFiles} lists.
    325      *         Later modification of these lists will not affect the
    326      *         returned {@code FileFilter}.
    327      **/
    328     public FileFilter buildFileFilter() {
    329         final FileFilter[] ins = getIncludeFiles();
    330         final FileFilter[] outs = getExcludeFiles();
    331         final FileFilter filter = new FileFilter() {
    332             public boolean accept(File f) {
    333                 boolean result = false;
    334                 // If no include filter, all files are included.
    335                 if (ins != null) {
    336                     for (FileFilter in: ins) {
    337                         // if one filter accepts it, file is included
    338                         if (!in.accept(f)) continue;
    339 
    340                         // file is accepted, include it
    341                         result=true;
    342                         break;
    343                     }
    344                 } else result= true;
    345                 if (result == false) return false;
    346 
    347                 // The file is in the include list. Let's see if it's not
    348                 // in the exclude list...
    349                 //
    350                 if (outs != null) {
    351                     for (FileFilter out: outs) {
    352                         // if one filter accepts it, file is excluded
    353                         if (!out.accept(f)) continue;
    354 
    355                         // file is accepted, exclude it.
    356                         result=false;
    357                         break;
    358                     }
    359                 }
    360                 return result;
    361             }
    362         };
    363         return filter;
    364     }
    365 
    366     // Used for equality - see equals().
    367     private Object[] toArray() {
    368         final Object[] thisconfig = {
    369             name,rootDirectory,actions,excludeFiles,includeFiles
    370         };
    371         return thisconfig;
    372     }
    373 
    374     @Override
    375     public boolean equals(Object o) {
    376         if (o == this) return true;
    377         if (!(o instanceof DirectoryScannerConfig)) return false;
    378         final DirectoryScannerConfig other = (DirectoryScannerConfig)o;
    379         final Object[] thisconfig = toArray();
    380         final Object[] otherconfig = other.toArray();
    381         return Arrays.deepEquals(thisconfig,otherconfig);
    382     }
    383 
    384     @Override
    385     public int hashCode() {
    386         final String key = name;
    387         if (key == null) return 0;
    388         else return key.hashCode();
    389     }
    390 
    391 
    392 }
    393