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
018package org.apache.commons.net.ftp.parser;
019
020import org.apache.commons.net.ftp.Configurable;
021import org.apache.commons.net.ftp.FTPClientConfig;
022import 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 */
035public 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