001    /*
002     * Copyright 2004-2005 The Apache Software Foundation
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     *     http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    
017    package org.apache.commons.net.ftp.parser;
018    import org.apache.commons.net.ftp.FTPFileEntryParserImpl;
019    import org.apache.oro.text.regex.MalformedPatternException;
020    import org.apache.oro.text.regex.MatchResult;
021    import org.apache.oro.text.regex.Pattern;
022    import org.apache.oro.text.regex.PatternMatcher;
023    import org.apache.oro.text.regex.Perl5Compiler;
024    import org.apache.oro.text.regex.Perl5Matcher;
025    
026    
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 for all regular based FTPFileEntryParser
034     *
035     * @author Steve Cohen <scohen@apache.org>
036     */
037    public abstract class RegexFTPFileEntryParserImpl extends FTPFileEntryParserImpl
038    {
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 PatternMatcher _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        {
072            super();
073            try
074            {
075                _matcher_ = new Perl5Matcher();
076                pattern   = new Perl5Compiler().compile(regex);
077            }
078            catch (MalformedPatternException e)
079            {
080                throw new IllegalArgumentException (
081                   "Unparseable regex supplied:  " + regex);
082            }
083        }
084    
085        /**
086         * Convenience method delegates to the internal MatchResult's matches()
087         * method.
088         *
089         * @param s the String to be matched
090         * @return true if s matches this object's regular expression.
091         */
092    
093        public boolean matches(String s)
094        {
095            this.result = null;
096            if (_matcher_.matches(s.trim(), this.pattern))
097            {
098                this.result = _matcher_.getMatch();
099            }
100            return null != this.result;
101        }
102    
103    
104    
105        /**
106         * Convenience method delegates to the internal MatchResult's groups()
107         * method.
108         *
109         * @return the number of groups() in the internal MatchResult.
110         */
111    
112        public int getGroupCnt()
113        {
114            if (this.result == null)
115            {
116                return 0;
117            }
118            return this.result.groups();
119        }
120    
121    
122    
123        /**
124         * Convenience method delegates to the internal MatchResult's group()
125         * method.
126         *
127         * @param matchnum match group number to be retrieved
128         *
129         * @return the content of the <code>matchnum'th<code> group of the internal
130         *         match or null if this method is called without a match having
131         *         been made.
132         */
133        public String group(int matchnum)
134        {
135            if (this.result == null)
136            {
137                return null;
138            }
139            return this.result.group(matchnum);
140        }
141    
142        /**
143         * For debugging purposes - returns a string shows each match group by
144         * number.
145         *
146         * @return a string shows each match group by number.
147         */
148    
149        public String getGroupsAsString()
150        {
151            StringBuffer b = new StringBuffer();
152            for (int i = 1; i <= this.result.groups(); i++)
153            {
154                b.append(i).append(") ").append(this.result.group(i))
155                    .append(System.getProperty("line.separator"));
156            }
157            return b.toString();
158        }
159        
160    }
161    
162