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    package org.apache.commons.net.ftp.parser;
019    
020    import org.apache.commons.net.ftp.Configurable;
021    import org.apache.commons.net.ftp.FTPClientConfig;
022    import org.apache.commons.net.ftp.FTPFileEntryParser;
023    
024    
025    /**
026     * This is the default implementation of the
027     * FTPFileEntryParserFactory interface.  This is the
028     * implementation that will be used by
029     * org.apache.commons.net.ftp.FTPClient.listFiles()
030     * if no other implementation has been specified.
031     *
032     * @see org.apache.commons.net.ftp.FTPClient#listFiles
033     * @see org.apache.commons.net.ftp.FTPClient#setParserFactory
034     */
035    public class DefaultFTPFileEntryParserFactory
036        implements FTPFileEntryParserFactory
037    {
038            private FTPClientConfig config = null;
039    
040            /**
041         * This default implementation of the FTPFileEntryParserFactory
042         * interface works according to the following logic:
043         * First it attempts to interpret the supplied key as a fully
044         * qualified classname of a class implementing the
045         * FTPFileEntryParser interface.  If that succeeds, a parser
046         * object of this class is instantiated and is returned; 
047         * otherwise it attempts to interpret the key as an identirier
048         * commonly used by the FTP SYST command to identify systems.
049         * <p/>
050         * If <code>key</code> is not recognized as a fully qualified
051         * classname known to the system, this method will then attempt
052         * to see whether it <b>contains</b> a string identifying one of
053         * the known parsers.  This comparison is <b>case-insensitive</b>.
054         * The intent here is where possible, to select as keys strings
055         * which are returned by the SYST command on the systems which
056         * the corresponding parser successfully parses.  This enables
057         * this factory to be used in the auto-detection system.
058         * <p/>
059         *
060         * @param key    should be a fully qualified classname corresponding to
061         *               a class implementing the FTPFileEntryParser interface<br/>
062         *               OR<br/>
063         *               a string containing (case-insensitively) one of the
064         *               following keywords:
065         *               <ul>
066         *               <li>{@link FTPClientConfig#SYST_UNIX UNIX}</li>
067         *               <li>{@link FTPClientConfig#SYST_NT WINDOWS}</li>
068         *               <li>{@link FTPClientConfig#SYST_OS2 OS/2}</li>
069         *               <li>{@link FTPClientConfig#SYST_OS400 OS/400}</li>
070         *               <li>{@link FTPClientConfig#SYST_VMS VMS}</li>
071         *               <li>{@link FTPClientConfig#SYST_MVS MVS}</li>
072         *               <li>{@link FTPClientConfig#SYST_NETWARE}</li>
073         *               </ul>
074         * @return the FTPFileEntryParser corresponding to the supplied key.
075         * @throws ParserInitializationException thrown if for any reason the factory cannot resolve
076         *                   the supplied key into an FTPFileEntryParser.
077         * @see FTPFileEntryParser
078         */
079        public FTPFileEntryParser createFileEntryParser(String key)
080        {
081            if (key == null)
082                    throw new ParserInitializationException("Parser key cannot be null");
083                    
084            Class<?> parserClass = null;
085            FTPFileEntryParser parser = null;
086            try
087            {
088                parserClass = Class.forName(key);
089                parser = (FTPFileEntryParser) parserClass.newInstance();
090            }
091            catch (ClassNotFoundException e)
092            {
093                try 
094                {
095                        String ukey = null;
096                        if (null != key)
097                        {
098                            ukey = key.toUpperCase(java.util.Locale.ENGLISH);
099                        }
100                        if ((ukey.indexOf(FTPClientConfig.SYST_UNIX) >= 0) 
101                                    || (ukey.indexOf(FTPClientConfig.SYST_L8) >= 0))
102                        {
103                            parser = createUnixFTPEntryParser();
104                        }
105                        else if (ukey.indexOf(FTPClientConfig.SYST_VMS) >= 0)
106                        {
107                            parser = createVMSVersioningFTPEntryParser();
108                        }
109                        else if (ukey.indexOf(FTPClientConfig.SYST_NT) >= 0)
110                        {
111                            parser = createNTFTPEntryParser();
112                        }
113                        else if (ukey.indexOf(FTPClientConfig.SYST_OS2) >= 0)
114                        {
115                            parser = createOS2FTPEntryParser();
116                        }
117                        else if (ukey.indexOf(FTPClientConfig.SYST_OS400) >= 0 ||
118                                    ukey.indexOf(FTPClientConfig.SYST_AS400) >= 0)
119                        {
120                            parser = createOS400FTPEntryParser();
121                        }
122                        else if (ukey.indexOf(FTPClientConfig.SYST_MVS) >= 0)
123                        {
124                            parser = createMVSEntryParser();
125                            }
126                        else if (ukey.indexOf(FTPClientConfig.SYST_NETWARE) >= 0) 
127                        {
128                            parser = createNetwareFTPEntryParser();
129                        }
130                        else
131                        {
132                            throw new ParserInitializationException("Unknown parser type: " + key);
133                        }
134                } 
135                catch (NoClassDefFoundError nf) {
136                        throw new ParserInitializationException("Error initializing parser", nf);
137                }
138    
139            }
140            catch (NoClassDefFoundError e)
141            {       
142                throw new ParserInitializationException("Error initializing parser", e);
143            }
144            catch (ClassCastException e)
145            {
146                throw new ParserInitializationException(parserClass.getName()
147                    + " does not implement the interface "
148                    + "org.apache.commons.net.ftp.FTPFileEntryParser.", e);
149            }
150            catch (Throwable e)
151            {
152                throw new ParserInitializationException("Error initializing parser", e);
153            }
154    
155            if (parser instanceof Configurable) {
156                ((Configurable)parser).configure(this.config);
157            }    
158            return parser;
159        }
160        
161        /**
162         * <p>Implementation extracts a key from the supplied 
163         * {@link  FTPClientConfig FTPClientConfig}
164         * parameter and creates an object implementing the
165         * interface FTPFileEntryParser and uses the supplied configuration
166         * to configure it.
167         * </p><p>
168         * Note that this method will generally not be called in scenarios
169         * that call for autodetection of parser type but rather, for situations
170         * where the user knows that the server uses a non-default configuration
171         * and knows what that configuration is.
172         * </p>
173         * @param config  A {@link  FTPClientConfig FTPClientConfig}  
174         * used to configure the parser created
175         *
176         * @return the @link  FTPFileEntryParser FTPFileEntryParser} so created.
177         * @exception ParserInitializationException
178         *                   Thrown on any exception in instantiation
179         * @since 1.4
180         */
181            public FTPFileEntryParser createFileEntryParser(FTPClientConfig config) 
182            throws ParserInitializationException 
183            {
184                this.config = config;
185                    String key = config.getServerSystemKey();
186                    return createFileEntryParser(key);
187            }
188    
189    
190        public FTPFileEntryParser createUnixFTPEntryParser()
191        {
192            return new UnixFTPEntryParser();
193        }
194    
195        public FTPFileEntryParser createVMSVersioningFTPEntryParser()
196        {
197            return new VMSVersioningFTPEntryParser();
198        }
199        
200        public FTPFileEntryParser createNetwareFTPEntryParser() {
201            return new NetwareFTPEntryParser();
202        }
203    
204        public FTPFileEntryParser createNTFTPEntryParser()
205        {
206            if (config != null && FTPClientConfig.SYST_NT.equals(
207                    config.getServerSystemKey())) 
208            {
209                return new NTFTPEntryParser();
210            } else {
211                return new CompositeFileEntryParser(new FTPFileEntryParser[]
212                            {
213                                new NTFTPEntryParser(),
214                                new UnixFTPEntryParser()
215                            });
216            }
217        }
218        
219         public FTPFileEntryParser createOS2FTPEntryParser()
220        {
221            return new OS2FTPEntryParser();
222        }
223    
224        public FTPFileEntryParser createOS400FTPEntryParser()
225        {
226            if (config != null && 
227                    FTPClientConfig.SYST_OS400.equals(config.getServerSystemKey())) 
228            {
229                return new OS400FTPEntryParser();
230            } else {
231                    return new CompositeFileEntryParser(new FTPFileEntryParser[]
232                        {
233                            new OS400FTPEntryParser(),
234                            new UnixFTPEntryParser()
235                        });
236            }
237        }
238    
239        public FTPFileEntryParser createMVSEntryParser()
240        {
241            return new MVSFTPEntryParser();
242        }
243    
244    
245            
246    }
247