Save This Page
Home » j2ssh-0.2.9-src » com.sshtools.daemon.util » [javadoc | source]
    1   /*
    2    *  SSHTools - Java SSH2 API
    3    *
    4    *  Copyright (C) 2002-2003 Lee David Painter and Contributors.
    5    *
    6    *  Contributions made by:
    7    *
    8    *  Brett Smith
    9    *  Richard Pernavas
   10    *  Erwin Bolwidt
   11    *
   12    *  This program is free software; you can redistribute it and/or
   13    *  modify it under the terms of the GNU General Public License
   14    *  as published by the Free Software Foundation; either version 2
   15    *  of the License, or (at your option) any later version.
   16    *
   17    *  This program is distributed in the hope that it will be useful,
   18    *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   19    *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   20    *  GNU General Public License for more details.
   21    *
   22    *  You should have received a copy of the GNU General Public License
   23    *  along with this program; if not, write to the Free Software
   24    *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
   25    */
   26   // ===========================================================================
   27   // CONTENT  : CLASS StringPattern
   28   // AUTHOR   : Manfred Duchrow
   29   // VERSION  : 1.7 - 13/02/2003
   30   // HISTORY  :
   31   //  24/01/2000  duma  CREATED
   32   //  08/01/2002  duma  bugfix  -> Handle *xxx (equal characters after star) correctly
   33   //  16/01/2002  duma  changed -> Implements Serializable
   34   //	06/07/2002	duma	bugfix	-> Couldn't match "London" on "L*n"
   35   //	19/09/2002	duma	bugfix	-> Couldn't match "MA_DR_HRBLUB" on "*_HR*"
   36   //	19/09/2002	duma	changed	-> Using now StringExaminer instead of CharacterIterator
   37   //	29/09/2002	duma	changed	-> Refactored: Using StringExaminer instead of StringScanner
   38   //	26/12/2002	duma	changed	-> Comment of matches() was wrong / new hasWildcard()
   39   //	13/02/2003	duma	added		-> setDigitWildcardChar()
   40   //
   41   // Copyright (c) 2000-2003, by Manfred Duchrow. All rights reserved.
   42   // ===========================================================================
   43   package com.sshtools.daemon.util;
   44   
   45   
   46   // ===========================================================================
   47   // IMPORTS
   48   // ===========================================================================
   49   import java.io;
   50   
   51   
   52   /**
   53    * This class provides services for checking strings against string-patterns.
   54    * Currently it supports the wildcards<br>
   55    * '' for any number of any character and <br>
   56    * '?' for any one character. The API is very simple:<br>
   57    * <br>
   58    * There are only the two class methods <i>match()</i> and
   59    * <i>matchIgnoreCase()</i>. <br>
   60    * Example: <br>
   61    * StringPattern.match( 'Hello World", "H W" ) ;  --> evaluates to true  <br>
   62    * StringPattern.matchIgnoreCase( 'StringPattern", "str???pat" ) ;  -->
   63    * evaluates to true  <br>
   64    *
   65    * @author Manfred Duchrow
   66    * @version 1.7
   67    */
   68   public class StringPattern implements Serializable {
   69       // =========================================================================
   70       // CONSTANTS
   71       // =========================================================================
   72   
   73       /**  */
   74       protected final static String MULTI_WILDCARD = "*";
   75   
   76       /**  */
   77       protected final static char MULTICHAR_WILDCARD = '*';
   78   
   79       /**  */
   80       protected final static char SINGLECHAR_WILDCARD = '?';
   81   
   82       // =========================================================================
   83       // INSTANCE VARIABLES
   84       // =========================================================================
   85       private boolean ignoreCase = false;
   86       private String pattern = null;
   87   
   88       // -------------------------------------------------------------------------
   89       private Character digitWildcard = null;
   90   
   91       // -------------------------------------------------------------------------
   92       // =========================================================================
   93       // CONSTRUCTORS
   94       // =========================================================================
   95   
   96       /**
   97    * Initializes the new instance with the string pattern and the selecteion,
   98    * if case should be ignored when comparing characters.
   99    *
  100    * @param pattern The pattern to check against ( May contain '' and '?'
  101    *        wildcards )
  102    * @param ignoreCase Definition, if case sensitive character comparison or
  103    *        not.
  104    */
  105       public StringPattern(String pattern, boolean ignoreCase) {
  106           this.setPattern(pattern);
  107           this.setIgnoreCase(ignoreCase);
  108       }
  109   
  110       // StringPattern()
  111       // -------------------------------------------------------------------------
  112   
  113       /**
  114    * Initializes the new instance with the string pattern. The default is
  115    * case sensitive checking.
  116    *
  117    * @param pattern The pattern to check against ( May contain '' and '?'
  118    *        wildcards )
  119    */
  120       public StringPattern(String pattern) {
  121           this(pattern, false);
  122       }
  123   
  124       // StringPattern()
  125       // -------------------------------------------------------------------------
  126   
  127       /**
  128    * Initializes the new instance with the string pattern and a digit
  129    * wildcard  character. The default is case sensitive checking.
  130    *
  131    * @param pattern The pattern to check against ( May contain '', '?'
  132    *        wildcards and the digit wildcard )
  133    * @param digitWildcard A wildcard character that stands as placeholder for
  134    *        digits
  135    */
  136       public StringPattern(String pattern, char digitWildcard) {
  137           this(pattern, false, digitWildcard);
  138       }
  139   
  140       // StringPattern()
  141       // -------------------------------------------------------------------------
  142   
  143       /**
  144    * Initializes the new instance with the string pattern and the selecteion,
  145    * if case should be ignored when comparing characters plus a wildcard
  146    * character for digits.
  147    *
  148    * @param pattern The pattern to check against ( May contain '' and '?'
  149    *        wildcards )
  150    * @param ignoreCase Definition, if case sensitive character comparison or
  151    *        not.
  152    * @param digitWildcard A wildcard character that stands as placeholder for
  153    *        digits
  154    */
  155       public StringPattern(String pattern, boolean ignoreCase, char digitWildcard) {
  156           this.setPattern(pattern);
  157           this.setIgnoreCase(ignoreCase);
  158           this.setDigitWildcardChar(digitWildcard);
  159       }
  160   
  161       // StringPattern()
  162   
  163       /**
  164    * Returns whether or not the pattern matching ignores upper and lower case
  165    *
  166    * @return
  167    */
  168       public boolean getIgnoreCase() {
  169           return ignoreCase;
  170       }
  171   
  172       /**
  173    * Sets whether the pattern matching should ignore case or not
  174    *
  175    * @param newValue
  176    */
  177       public void setIgnoreCase(boolean newValue) {
  178           ignoreCase = newValue;
  179       }
  180   
  181       /**
  182    * Returns the pattern as string.
  183    *
  184    * @return
  185    */
  186       public String getPattern() {
  187           return pattern;
  188       }
  189   
  190       /**
  191    * Sets the pattern to a new value
  192    *
  193    * @param newValue
  194    */
  195       public void setPattern(String newValue) {
  196           pattern = newValue;
  197       }
  198   
  199       /**
  200    *
  201    *
  202    * @return
  203    */
  204       protected Character digitWildcard() {
  205           return digitWildcard;
  206       }
  207   
  208       /**
  209    *
  210    *
  211    * @param newValue
  212    */
  213       protected void digitWildcard(Character newValue) {
  214           digitWildcard = newValue;
  215       }
  216   
  217       // =========================================================================
  218       // CLASS METHODS
  219       // =========================================================================
  220   
  221       /**
  222    * Returns true, if the given probe string matches the given pattern.  <br>
  223    * The character comparison is done case sensitive.
  224    *
  225    * @param probe The string to check against the pattern.
  226    * @param pattern The patter, that probably contains wildcards ( '' or '?'
  227    *        )
  228    *
  229    * @return
  230    */
  231       public static boolean match(String probe, String pattern) {
  232           StringPattern stringPattern = new StringPattern(pattern, false);
  233   
  234           return (stringPattern.matches(probe));
  235       }
  236   
  237       // match()
  238       // -------------------------------------------------------------------------
  239   
  240       /**
  241    * Returns true, if the given probe string matches the given pattern.  <br>
  242    * The character comparison is done ignoring upper/lower-case.
  243    *
  244    * @param probe The string to check against the pattern.
  245    * @param pattern The patter, that probably contains wildcards ( '' or '?'
  246    *        )
  247    *
  248    * @return
  249    */
  250       public static boolean matchIgnoreCase(String probe, String pattern) {
  251           StringPattern stringPattern = new StringPattern(pattern, true);
  252   
  253           return (stringPattern.matches(probe));
  254       }
  255   
  256       // matchIgnoreCase()
  257       // -------------------------------------------------------------------------
  258       // =========================================================================
  259       // PUBLIC INSTANCE METHODS
  260       // =========================================================================
  261   
  262       /**
  263    * Tests if a specified string matches the pattern.
  264    *
  265    * @param probe The string to compare to the pattern
  266    *
  267    * @return true if and only if the probe matches the pattern, false
  268    *         otherwise.
  269    */
  270       public boolean matches(String probe) {
  271           StringExaminer patternIterator = null;
  272           StringExaminer probeIterator = null;
  273           char patternCh = '-';
  274           char probeCh = '-';
  275           String newPattern = null;
  276           String subPattern = null;
  277           int charIndex = 0;
  278   
  279           if (probe == null) {
  280               return false;
  281           }
  282   
  283           if (probe.length() == 0) {
  284               return false;
  285           }
  286   
  287           patternIterator = this.newExaminer(this.getPattern());
  288           probeIterator = this.newExaminer(probe);
  289           probeCh = probeIterator.nextChar();
  290           patternCh = this.getPatternChar(patternIterator, probeCh);
  291   
  292           while ((this.endNotReached(patternCh)) &&
  293                   (this.endNotReached(probeCh))) {
  294               if (patternCh == MULTICHAR_WILDCARD) {
  295                   patternCh = this.skipWildcards(patternIterator);
  296   
  297                   if (this.endReached(patternCh)) {
  298                       return true; // No more characters after multi wildcard - So everything matches
  299                   } else {
  300                       patternIterator.skip(-1);
  301                       newPattern = this.upToEnd(patternIterator);
  302                       charIndex = newPattern.indexOf(MULTICHAR_WILDCARD);
  303   
  304                       if (charIndex >= 0) {
  305                           subPattern = newPattern.substring(0, charIndex);
  306   
  307                           if (this.skipAfter(probeIterator, subPattern)) {
  308                               patternIterator = this.newExaminer(newPattern.substring(
  309                                           charIndex));
  310                               patternCh = probeCh;
  311                           } else {
  312                               return false;
  313                           }
  314                       } else {
  315                           probeIterator.skip(-1);
  316   
  317                           return this.matchReverse(newPattern, probeIterator);
  318                       }
  319                   }
  320               }
  321   
  322               if (this.charsAreEqual(probeCh, patternCh)) {
  323                   if (this.endNotReached(patternCh)) {
  324                       probeCh = probeIterator.nextChar();
  325                       patternCh = this.getPatternChar(patternIterator, probeCh);
  326                   }
  327               } else {
  328                   if (patternCh != MULTICHAR_WILDCARD) {
  329                       return false; // character is not matching - return immediately
  330                   }
  331               }
  332           }
  333   
  334           // while()
  335           return ((this.endReached(patternCh)) && (this.endReached(probeCh)));
  336       }
  337   
  338       // matches()
  339       // -------------------------------------------------------------------------
  340   
  341       /**
  342    * Returns the pattern string.
  343    *
  344    * @see java.lang.Object#toString()
  345    */
  346       public String toString() {
  347           if (this.getPattern() == null) {
  348               return super.toString();
  349           } else {
  350               return this.getPattern();
  351           }
  352       }
  353   
  354       // toString()
  355       // -------------------------------------------------------------------------
  356   
  357       /**
  358    * Returns true if the pattern contains any '' or '?' wildcard character.
  359    *
  360    * @return
  361    */
  362       public boolean hasWildcard() {
  363           if (this.getPattern() == null) {
  364               return false;
  365           }
  366   
  367           if (this.hasDigitWildcard()) {
  368               if (this.getPattern().indexOf(this.digitWildcardChar()) >= 0) {
  369                   return true;
  370               }
  371           }
  372   
  373           return (this.getPattern().indexOf(MULTI_WILDCARD) >= 0) ||
  374           (this.getPattern().indexOf(SINGLECHAR_WILDCARD) >= 0);
  375       }
  376   
  377       // hasWildcard()
  378       // -------------------------------------------------------------------------
  379   
  380       /**
  381    * Sets the given character as a wildcard character in this pattern to
  382    * match only digits ('0'-'9').   <br>
  383    *
  384    * @param digitWildcard The placeholder character for digits
  385    */
  386       public void setDigitWildcardChar(char digitWildcard) {
  387           if (digitWildcard <= 0) {
  388               this.digitWildcard(null);
  389           } else {
  390               this.digitWildcard(new Character(digitWildcard));
  391           }
  392       }
  393   
  394       // setDigitWildcardChar()
  395   
  396       /**
  397    *
  398    *
  399    * @return
  400    */
  401       protected boolean hasDigitWildcard() {
  402           return this.digitWildcard() != null;
  403       }
  404   
  405       // hasDigitWildcard()
  406       // -------------------------------------------------------------------------
  407       protected char digitWildcardChar() {
  408           if (this.hasDigitWildcard()) {
  409               return this.digitWildcard().charValue();
  410           } else {
  411               return '\0';
  412           }
  413       }
  414   
  415       // digitWildcardChar()
  416       // -------------------------------------------------------------------------
  417   
  418       /**
  419    * Moves the iterator position to the next character that is no wildcard.
  420    * Doesn't skip digit wildcards !
  421    *
  422    * @param iterator
  423    *
  424    * @return
  425    */
  426       protected char skipWildcards(StringExaminer iterator) {
  427           char result = '-';
  428   
  429           do {
  430               result = iterator.nextChar();
  431           } while ((result == MULTICHAR_WILDCARD) ||
  432                   (result == SINGLECHAR_WILDCARD));
  433   
  434           return result;
  435       }
  436   
  437       // skipWildcards()
  438       // -------------------------------------------------------------------------
  439   
  440       /**
  441    * Increments the given iterator up to the last character that matched the
  442    * character sequence in the given matchString. Returns true, if the
  443    * matchString was found, otherwise false.
  444    *
  445    * @param examiner
  446    * @param matchString The string to be found (must not contain )
  447    *
  448    * @return
  449    */
  450       protected boolean skipAfter(StringExaminer examiner, String matchString) {
  451           // Do not use the method of StringExaminer anymore, because digit wildcard
  452           // support is in the charsAreEqual() method which is unknown to the examiner.
  453           // return examiner.skipAfter( matchString ) ;
  454           char ch = '-';
  455           char matchChar = ' ';
  456           boolean found = false;
  457           int index = 0;
  458   
  459           if ((matchString == null) || (matchString.length() == 0)) {
  460               return false;
  461           }
  462   
  463           ch = examiner.nextChar();
  464   
  465           while ((examiner.endNotReached(ch)) && (!found)) {
  466               matchChar = matchString.charAt(index);
  467   
  468               if (this.charsAreEqual(ch, matchChar)) {
  469                   index++;
  470   
  471                   if (index >= matchString.length()) { // whole matchString checked ?
  472                       found = true;
  473                   } else {
  474                       ch = examiner.nextChar();
  475                   }
  476               } else {
  477                   if (index == 0) {
  478                       ch = examiner.nextChar();
  479                   } else {
  480                       index = 0;
  481                   }
  482               }
  483           }
  484   
  485           return found;
  486       }
  487   
  488       // skipAfter()
  489       // -------------------------------------------------------------------------
  490       protected String upToEnd(StringExaminer iterator) {
  491           return iterator.upToEnd();
  492       }
  493   
  494       // upToEnd()
  495       // -------------------------------------------------------------------------
  496       protected boolean matchReverse(String pattern, StringExaminer probeIterator) {
  497           String newPattern;
  498           String newProbe;
  499           StringPattern newMatcher;
  500           newPattern = MULTI_WILDCARD + pattern;
  501           newProbe = this.upToEnd(probeIterator);
  502           newPattern = this.strUtil().reverse(newPattern);
  503           newProbe = this.strUtil().reverse(newProbe);
  504           newMatcher = new StringPattern(newPattern, this.getIgnoreCase());
  505   
  506           if (this.hasDigitWildcard()) {
  507               newMatcher.setDigitWildcardChar(this.digitWildcardChar());
  508           }
  509   
  510           return newMatcher.matches(newProbe);
  511       }
  512   
  513       // matchReverse()
  514       // -------------------------------------------------------------------------
  515       protected boolean charsAreEqual(char probeChar, char patternChar) {
  516           if (this.hasDigitWildcard()) {
  517               if (patternChar == this.digitWildcardChar()) {
  518                   return Character.isDigit(probeChar);
  519               }
  520           }
  521   
  522           if (this.getIgnoreCase()) {
  523               return (Character.toUpperCase(probeChar) == Character.toUpperCase(patternChar));
  524           } else {
  525               return (probeChar == patternChar);
  526           }
  527       }
  528   
  529       // charsAreEqual()
  530       // -------------------------------------------------------------------------
  531       protected boolean endReached(char character) {
  532           return (character == StringExaminer.END_REACHED);
  533       }
  534   
  535       // endReached()
  536       // -------------------------------------------------------------------------
  537       protected boolean endNotReached(char character) {
  538           return (!endReached(character));
  539       }
  540   
  541       // endNotReached()
  542       // -------------------------------------------------------------------------
  543       protected char getPatternChar(StringExaminer patternIterator, char probeCh) {
  544           char patternCh;
  545           patternCh = patternIterator.nextChar();
  546   
  547           return ((patternCh == SINGLECHAR_WILDCARD) ? probeCh : patternCh);
  548       }
  549   
  550       // getPatternChar()
  551       // -------------------------------------------------------------------------
  552       protected StringExaminer newExaminer(String str) {
  553           return new StringExaminer(str, this.getIgnoreCase());
  554       }
  555   
  556       // newExaminer()
  557       // -------------------------------------------------------------------------
  558       protected StringUtil strUtil() {
  559           return StringUtil.current();
  560       }
  561   
  562       // strUtil()
  563       // -------------------------------------------------------------------------
  564   }
  565   
  566   
  567   // class StringPattern

Save This Page
Home » j2ssh-0.2.9-src » com.sshtools.daemon.util » [javadoc | source]