RegexFTPFileEntryParserImpl.java

  1. /*
  2.  * Licensed to the Apache Software Foundation (ASF) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * The ASF licenses this file to You under the Apache License, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License.  You may obtain a copy of the License at
  8.  *
  9.  *      http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */

  17. package org.apache.commons.net.ftp.parser;

  18. import java.util.regex.MatchResult;
  19. import java.util.regex.Matcher;
  20. import java.util.regex.Pattern;
  21. import java.util.regex.PatternSyntaxException;

  22. import org.apache.commons.net.ftp.FTPFileEntryParserImpl;

  23. /**
  24.  * This abstract class implements both the older FTPFileListParser and newer FTPFileEntryParser interfaces with default functionality. All the classes in the
  25.  * parser subpackage inherit from this.
  26.  *
  27.  * This is the base class for all regular expression based FTPFileEntryParser classes
  28.  */
  29. public abstract class RegexFTPFileEntryParserImpl extends FTPFileEntryParserImpl {
  30.     /**
  31.      * internal pattern the matcher tries to match, representing a file entry
  32.      */
  33.     private Pattern pattern;

  34.     /**
  35.      * internal match result used by the parser
  36.      */
  37.     private MatchResult result;

  38.     /**
  39.      * Internal PatternMatcher object used by the parser. It has protected scope in case subclasses want to make use of it for their own purposes.
  40.      */
  41.     protected Matcher _matcher_;

  42.     /**
  43.      * The constructor for a RegexFTPFileEntryParserImpl object. The expression is compiled with flags = 0.
  44.      *
  45.      * @param regex The regular expression with which this object is initialized.
  46.      *
  47.      * @throws IllegalArgumentException Thrown if the regular expression is unparseable. Should not be seen in normal conditions. If it is seen, this is a sign
  48.      *                                  that a subclass has been created with a bad regular expression. Since the parser must be created before use, this means
  49.      *                                  that any bad parser subclasses created from this will bomb very quickly, leading to easy detection.
  50.      */

  51.     public RegexFTPFileEntryParserImpl(final String regex) {
  52.         compileRegex(regex, 0);
  53.     }

  54.     /**
  55.      * The constructor for a RegexFTPFileEntryParserImpl object.
  56.      *
  57.      * @param regex The regular expression with which this object is initialized.
  58.      * @param flags the flags to apply, see {@link Pattern#compile(String, int)}. Use 0 for none.
  59.      *
  60.      * @throws IllegalArgumentException Thrown if the regular expression is unparseable. Should not be seen in normal conditions. If it is seen, this is a sign
  61.      *                                  that a subclass has been created with a bad regular expression. Since the parser must be created before use, this means
  62.      *                                  that any bad parser subclasses created from this will bomb very quickly, leading to easy detection.
  63.      * @since 3.4
  64.      */
  65.     public RegexFTPFileEntryParserImpl(final String regex, final int flags) {
  66.         compileRegex(regex, flags);
  67.     }

  68.     /**
  69.      * Compile the regex and store the {@link Pattern}.
  70.      *
  71.      * This is an internal method to do the work so the constructor does not have to call an overrideable method.
  72.      *
  73.      * @param regex the expression to compile
  74.      * @param flags the flags to apply, see {@link Pattern#compile(String, int)}. Use 0 for none.
  75.      * @throws IllegalArgumentException if the regex cannot be compiled
  76.      */
  77.     private void compileRegex(final String regex, final int flags) {
  78.         try {
  79.             pattern = Pattern.compile(regex, flags);
  80.         } catch (final PatternSyntaxException pse) {
  81.             throw new IllegalArgumentException("Unparseable regex supplied: " + regex);
  82.         }
  83.     }

  84.     /**
  85.      * Convenience method
  86.      *
  87.      * @return the number of groups() in the internal MatchResult.
  88.      */

  89.     public int getGroupCnt() {
  90.         if (this.result == null) {
  91.             return 0;
  92.         }
  93.         return this.result.groupCount();
  94.     }

  95.     /**
  96.      * For debugging purposes - returns a string shows each match group by number.
  97.      *
  98.      * @return a string shows each match group by number.
  99.      */

  100.     public String getGroupsAsString() {
  101.         final StringBuilder b = new StringBuilder();
  102.         for (int i = 1; i <= this.result.groupCount(); i++) {
  103.             b.append(i).append(") ").append(this.result.group(i)).append(System.lineSeparator());
  104.         }
  105.         return b.toString();
  106.     }

  107.     /**
  108.      * Convenience method delegates to the internal MatchResult's group() method.
  109.      *
  110.      * @param matchNum match group number to be retrieved
  111.      *
  112.      * @return the content of the <code>matchnum'th</code> group of the internal match or null if this method is called without a match having been made.
  113.      */
  114.     public String group(final int matchNum) {
  115.         if (this.result == null) {
  116.             return null;
  117.         }
  118.         return this.result.group(matchNum);
  119.     }

  120.     /**
  121.      * Convenience method delegates to the internal MatchResult's matches() method.
  122.      *
  123.      * @param s the String to be matched
  124.      * @return true if s matches this object's regular expression.
  125.      */

  126.     public boolean matches(final String s) {
  127.         this.result = null;
  128.         _matcher_ = pattern.matcher(s);
  129.         if (_matcher_.matches()) {
  130.             this.result = _matcher_.toMatchResult();
  131.         }
  132.         return null != this.result;
  133.     }

  134.     /**
  135.      * Alter the current regular expression being utilised for entry parsing and create a new {@link Pattern} instance.
  136.      *
  137.      * @param regex The new regular expression
  138.      * @return true
  139.      * @since 2.0
  140.      * @throws IllegalArgumentException if the regex cannot be compiled
  141.      */
  142.     public boolean setRegex(final String regex) {
  143.         compileRegex(regex, 0);
  144.         return true;
  145.     }

  146.     /**
  147.      * Alter the current regular expression being utilised for entry parsing and create a new {@link Pattern} instance.
  148.      *
  149.      * @param regex The new regular expression
  150.      * @param flags the flags to apply, see {@link Pattern#compile(String, int)}. Use 0 for none.
  151.      * @return true
  152.      * @since 3.4
  153.      * @throws IllegalArgumentException if the regex cannot be compiled
  154.      */
  155.     public boolean setRegex(final String regex, final int flags) {
  156.         compileRegex(regex, flags);
  157.         return true;
  158.     }
  159. }