001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    
018    
019    package org.apache.commons.net.ftp.parser;
020    
021    import java.util.regex.MatchResult;
022    import java.util.regex.Matcher;
023    import java.util.regex.Pattern;
024    import java.util.regex.PatternSyntaxException;
025    
026    import org.apache.commons.net.ftp.FTPFileEntryParserImpl;
027    
028    /**
029     * This abstract class implements both the older FTPFileListParser and
030     * newer FTPFileEntryParser interfaces with default functionality.
031     * All the classes in the parser subpackage inherit from this.
032     *
033     * This is the base class for all regular expression based FTPFileEntryParser classes
034     *
035     * @author Steve Cohen <scohen@apache.org>
036     */
037    public abstract class RegexFTPFileEntryParserImpl extends
038            FTPFileEntryParserImpl {
039        /**
040         * internal pattern the matcher tries to match, representing a file
041         * entry
042         */
043        private Pattern pattern = null;
044    
045        /**
046         * internal match result used by the parser
047         */
048        private MatchResult result = null;
049    
050        /**
051         * Internal PatternMatcher object used by the parser.  It has protected
052         * scope in case subclasses want to make use of it for their own purposes.
053         */
054        protected Matcher _matcher_ = null;
055    
056        /**
057         * The constructor for a RegexFTPFileEntryParserImpl object.
058         *
059         * @param regex  The regular expression with which this object is
060         * initialized.
061         *
062         * @exception IllegalArgumentException
063         * Thrown if the regular expression is unparseable.  Should not be seen in
064         * normal conditions.  It it is seen, this is a sign that a subclass has
065         * been created with a bad regular expression.   Since the parser must be
066         * created before use, this means that any bad parser subclasses created
067         * from this will bomb very quickly,  leading to easy detection.
068         */
069    
070        public RegexFTPFileEntryParserImpl(String regex) {
071            super();
072            setRegex(regex);
073        }
074    
075        /**
076         * Convenience method delegates to the internal MatchResult's matches()
077         * method.
078         *
079         * @param s the String to be matched
080         * @return true if s matches this object's regular expression.
081         */
082    
083        public boolean matches(String s) {
084            this.result = null;
085            _matcher_ = pattern.matcher(s);
086            if (_matcher_.matches()) {
087                this.result = _matcher_.toMatchResult();
088            }
089            return null != this.result;
090        }
091    
092        /**
093         * Convenience method
094         *
095         * @return the number of groups() in the internal MatchResult.
096         */
097    
098        public int getGroupCnt() {
099            if (this.result == null) {
100                return 0;
101            }
102            return this.result.groupCount();
103        }
104    
105        /**
106         * Convenience method delegates to the internal MatchResult's group()
107         * method.
108         *
109         * @param matchnum match group number to be retrieved
110         *
111         * @return the content of the <code>matchnum'th</code> group of the internal
112         *         match or null if this method is called without a match having
113         *         been made.
114         */
115        public String group(int matchnum) {
116            if (this.result == null) {
117                return null;
118            }
119            return this.result.group(matchnum);
120        }
121    
122        /**
123         * For debugging purposes - returns a string shows each match group by
124         * number.
125         *
126         * @return a string shows each match group by number.
127         */
128    
129        public String getGroupsAsString() {
130            StringBuilder b = new StringBuilder();
131            for (int i = 1; i <= this.result.groupCount(); i++) {
132                b.append(i).append(") ").append(this.result.group(i)).append(
133                        System.getProperty("line.separator"));
134            }
135            return b.toString();
136        }
137    
138        /**
139         * Alter the current regular expression being utilised for entry parsing
140         * and create a new {@link Pattern} instance.
141         * @param regex The new regular expression
142         * @return  true if the compiled pattern is not null
143         * @since 2.0
144         */
145        public boolean setRegex(String regex) {
146            try {
147                pattern = Pattern.compile(regex);
148            } catch (PatternSyntaxException pse) {
149                throw new IllegalArgumentException("Unparseable regex supplied: "
150                        + regex);
151            }
152            return (pattern != null);
153        }
154    
155    }