File Source: IPBanList.java

         /* 
    P/P   *  Method: org.apache.roller.weblogger.util.IPBanList$ModifiedFile__static_init
          */
     1  /*
     2  * Licensed to the Apache Software Foundation (ASF) under one or more
     3  *  contributor license agreements.  The ASF licenses this file to You
     4  * under the Apache License, Version 2.0 (the "License"); you may not
     5  * use this file except in compliance with the License.
     6  * You may obtain a copy of the License at
     7  *
     8  *     http://www.apache.org/licenses/LICENSE-2.0
     9  *
    10  * Unless required by applicable law or agreed to in writing, software
    11  * distributed under the License is distributed on an "AS IS" BASIS,
    12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  * See the License for the specific language governing permissions and
    14  * limitations under the License.  For additional information regarding
    15  * copyright in this work, please see the NOTICE file in the top level
    16  * directory of this distribution.
    17  */
    18  
    19  package org.apache.roller.weblogger.util;
    20  
    21  import java.io.BufferedReader;
    22  import java.io.FileReader;
    23  import java.io.FileWriter;
    24  import java.io.PrintWriter;
    25  import java.util.HashSet;
    26  import java.util.Set;
    27  import org.apache.commons.logging.Log;
    28  import org.apache.commons.logging.LogFactory;
    29  import org.apache.roller.weblogger.config.WebloggerConfig;
    30  
    31  
    32  /**
    33   * Represents a list of banned ip addresses.
    34   *
    35   * This base implementation gets its list from a file on the filesystem.  We
    36   * are also aware of when the file changes via some outside source and we will
    37   * automatically re-read the file and update the list when that happens.
    38   */
    39  public class IPBanList {
    40      
             /* 
    P/P       *  Method: org.apache.roller.weblogger.util.IPBanList__static_init
              * 
              *  Presumptions:
              *    org.apache.commons.logging.LogFactory:getLog(...)@41 != null
              * 
              *  Postconditions:
              *    instance == &new IPBanList(IPBanList__static_init#1)
              *    (soft) log != null
              *    new HashSet(IPBanList#1) num objects == 1
              *    new IPBanList(IPBanList__static_init#1) num objects == 1
              *    new HashSet(loadBannedIps#1) num objects <= 1
              *    new IPBanList$ModifiedFile(IPBanList#2) num objects <= 1
              *    init'ed(new IPBanList$ModifiedFile(IPBanList#2).myLastModified)
              *    instance.bannedIps == One-of{&new HashSet(IPBanList#1), &new HashSet(loadBannedIps#1)}
              *    instance.bannedIps in Addr_Set{&new HashSet(IPBanList#1),&new HashSet(loadBannedIps#1)}
              *    init'ed(instance.bannedIpsFile)
              */
    41      private static Log log = LogFactory.getLog(IPBanList.class);
    42      
    43      // set of ips that are banned, use a set to ensure uniqueness
    44      private Set bannedIps = new HashSet();
    45      
    46      // file listing the ips that are banned
    47      private ModifiedFile bannedIpsFile = null;
    48      
    49      // reference to our singleton instance
    50      private static IPBanList instance = null;
    51      
    52      
    53      static {
    54          instance = new IPBanList();
    55      }
    56      
    57      
    58      // private because we are a singleton
             /* 
    P/P       *  Method: void org.apache.roller.weblogger.util.IPBanList()
              * 
              *  Preconditions:
              *    log != null
              * 
              *  Postconditions:
              *    this.bannedIps in Addr_Set{&new HashSet(IPBanList#1),&new HashSet(loadBannedIps#1)}
              *    init'ed(this.bannedIpsFile)
              *    new HashSet(IPBanList#1) num objects == 1
              *    new HashSet(loadBannedIps#1) num objects <= 1
              *    new IPBanList$ModifiedFile(IPBanList#2) num objects <= 1
              *    init'ed(new IPBanList$ModifiedFile(IPBanList#2).myLastModified)
              * 
              *  Test Vectors:
              *    org.apache.roller.weblogger.config.WebloggerConfig:getProperty(...)@64: Addr_Set{null}, Inverse{null}
              *    org.apache.roller.weblogger.util.IPBanList_ModifiedFile:canRead(...)@68: {0}, {1}
              *    org.apache.roller.weblogger.util.IPBanList_ModifiedFile:exists(...)@68: {0}, {1}
              */
    59      private IPBanList() {
    60          
    61          log.debug("INIT");
    62          
    63          // load up set of denied ips
    64          String banIpsFilePath = WebloggerConfig.getProperty("ipbanlist.file");
    65          if(banIpsFilePath != null) {
    66              ModifiedFile banIpsFile = new ModifiedFile(banIpsFilePath);
    67              
    68              if(banIpsFile.exists() && banIpsFile.canRead()) {
    69                  this.bannedIpsFile = banIpsFile;
    70                  this.loadBannedIps();
    71              }
    72          }
    73      }
    74      
    75      
    76      // access to the singleton instance
    77      public static IPBanList getInstance() {
                 /* 
    P/P           *  Method: IPBanList getInstance()
                  * 
                  *  Preconditions:
                  *    init'ed(instance)
                  * 
                  *  Postconditions:
                  *    return_value == instance
                  *    init'ed(return_value)
                  */
    78          return instance;
    79      }
    80      
    81      
    82      public boolean isBanned(String ip) {
    83          
    84          // update the banned ips list if needed
                 /* 
    P/P           *  Method: bool isBanned(String)
                  * 
                  *  Preconditions:
                  *    init'ed(this.bannedIpsFile)
                  *    (soft) log != null
                  *    (soft) init'ed(this.bannedIps)
                  *    (soft) init'ed(this.bannedIpsFile.myLastModified)
                  * 
                  *  Postconditions:
                  *    init'ed(return_value)
                  *    this.bannedIps == One-of{old this.bannedIps, &new HashSet(loadBannedIps#1)}
                  *    (soft) init'ed(this.bannedIps)
                  *    init'ed(this.bannedIpsFile.myLastModified)
                  *    new HashSet(loadBannedIps#1) num objects <= 1
                  * 
                  *  Test Vectors:
                  *    ip: Addr_Set{null}, Inverse{null}
                  */
    85          this.loadBannedIpsIfNeeded(false);
    86          
    87          if(ip != null) {
+   88              return this.bannedIps.contains(ip);
    89          } else {
    90              return false;
    91          }
    92      }
    93      
    94      
    95      public void addBannedIp(String ip) {
    96          
                 /* 
    P/P           *  Method: void addBannedIp(String)
                  * 
                  *  Preconditions:
                  *    (soft) log != null
                  *    (soft) init'ed(this.bannedIps)
                  *    (soft) init'ed(this.bannedIpsFile.myLastModified)
                  *    (soft) init'ed(this.bannedIpsFile)
                  * 
                  *  Postconditions:
                  *    this.bannedIps == One-of{old this.bannedIps, &new HashSet(loadBannedIps#1)}
                  *    (soft) init'ed(this.bannedIps)
                  *    (soft) init'ed(this.bannedIpsFile.myLastModified)
                  *    new HashSet(loadBannedIps#1) num objects <= 1
                  * 
                  *  Test Vectors:
                  *    ip: Inverse{null}, Addr_Set{null}
                  *    this.bannedIpsFile: Addr_Set{null}, Inverse{null}
                  *    java.util.Set:contains(...)@104: {1}, {0}
                  *    org.apache.roller.weblogger.util.IPBanList_ModifiedFile:canWrite(...)@104: {0}, {1}
                  */
    97          if(ip == null) {
    98              return;
    99          }
   100          
   101          // update the banned ips list if needed
   102          this.loadBannedIpsIfNeeded(false);
   103          
+  104          if(!this.bannedIps.contains(ip) && 
   105                  (bannedIpsFile != null && bannedIpsFile.canWrite())) {
   106              
   107              try {
   108                  synchronized(this) {
   109                      // add to file
   110                      PrintWriter out = new PrintWriter(new FileWriter(this.bannedIpsFile, true));
   111                      out.println(ip);
   112                      out.close();
   113                      this.bannedIpsFile.clearChanged();
   114                      
   115                      // add to Set
   116                      this.bannedIps.add(ip);
   117                  }
   118                  
   119                  log.debug("ADDED "+ip);
   120              } catch(Exception e) {
   121                  log.error("Error adding banned ip to file", e);
   122              }
   123          }
   124      }
   125      
   126      
   127      /**
   128       * Check if the banned ips file has changed and needs to be reloaded.
   129       */
   130      private void loadBannedIpsIfNeeded(boolean forceLoad) {
   131          
                 /* 
    P/P           *  Method: void loadBannedIpsIfNeeded(bool)
                  * 
                  *  Preconditions:
                  *    init'ed(this.bannedIpsFile)
                  *    (soft) log != null
                  *    (soft) init'ed(this.bannedIpsFile.myLastModified)
                  * 
                  *  Postconditions:
                  *    this.bannedIps == One-of{old this.bannedIps, &new HashSet(loadBannedIps#1)}
                  *    (soft) init'ed(this.bannedIpsFile.myLastModified)
                  *    new HashSet(loadBannedIps#1) num objects <= 1
                  * 
                  *  Test Vectors:
                  *    forceLoad: {0}, {1}
                  *    this.bannedIpsFile: Addr_Set{null}, Inverse{null}
                  */
   132          if(bannedIpsFile != null && 
   133                  (bannedIpsFile.hasChanged() || forceLoad)) {
   134              
   135              // need to reload
   136              this.loadBannedIps();
   137          }
   138      }
   139      
   140      
   141      /**
   142       * Load the list of banned ips from a file.  This clears the old list and
   143       * loads exactly what is in the file.
   144       */
   145      private synchronized void loadBannedIps() {
   146          
                 /* 
    P/P           *  Method: void loadBannedIps()
                  * 
                  *  Preconditions:
                  *    init'ed(this.bannedIpsFile)
                  *    (soft) log != null
                  * 
                  *  Postconditions:
                  *    this.bannedIps == One-of{old this.bannedIps, &new HashSet(loadBannedIps#1)}
                  *    possibly_updated(this.bannedIpsFile.myLastModified)
                  *    new HashSet(loadBannedIps#1) num objects <= 1
                  * 
                  *  Test Vectors:
                  *    this.bannedIpsFile: Addr_Set{null}, Inverse{null}
                  *    java.io.BufferedReader:readLine(...)@156: Addr_Set{null}, Inverse{null}
                  */
   147          if(bannedIpsFile != null) {
   148              
   149              try {
   150                  HashSet newBannedIpList = new HashSet();
   151                  
   152                  // TODO: optimize this
   153                  BufferedReader in = new BufferedReader(new FileReader(this.bannedIpsFile));
   154                  
   155                  String ip = null;
   156                  while((ip = in.readLine()) != null) {
   157                      newBannedIpList.add(ip);
   158                  }
   159                  
   160                  in.close();
   161                  
   162                  // list updated, reset modified file
   163                  this.bannedIps = newBannedIpList;
   164                  this.bannedIpsFile.clearChanged();
   165                  
   166                  log.info(this.bannedIps.size()+" banned ips loaded");
   167              } catch(Exception ex) {
   168                 log.error("Error loading banned ips from file", ex);
   169              }
   170              
   171          }
   172      }
   173      
   174      
   175      // a simple extension to the File class which tracks if the file has 
   176      // changed since the last time we checked
   177      private class ModifiedFile extends java.io.File {
   178          
   179          private long myLastModified = 0;
   180          
                 /* 
    P/P           *  Method: void org.apache.roller.weblogger.util.IPBanList$ModifiedFile(IPBanList, String)
                  * 
                  *  Postconditions:
                  *    init'ed(this.myLastModified)
                  */
   181          public ModifiedFile(String filePath) {
   182              super(filePath);
   183              
   184              this.myLastModified = lastModified();
   185          }
   186  
   187          public boolean hasChanged() {
                     /* 
    P/P               *  Method: bool hasChanged()
                      * 
                      *  Preconditions:
                      *    init'ed(this.myLastModified)
                      * 
                      *  Postconditions:
                      *    init'ed(return_value)
                      */
   188              if(lastModified() != myLastModified) {
   189                  return true;
   190              } else {
   191                  return false;
   192              }
   193          }
   194          
   195          public void clearChanged() {
                     /* 
    P/P               *  Method: void clearChanged()
                      * 
                      *  Postconditions:
                      *    init'ed(this.myLastModified)
                      */
   196              myLastModified = lastModified();
   197          }
   198      }
   199      
   200  }








SofCheck Inspector Build Version : 2.18479
IPBanList.java 2009-Jan-02 14:24:54
IPBanList.class 2009-Sep-04 03:12:32
IPBanList$ModifiedFile.class 2009-Sep-04 03:12:32