incubator-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ran...@apache.org
Subject cvs commit: incubator-ftpserver/src/doc/content/xdocs messages.xml
Date Thu, 22 Sep 2005 05:34:48 GMT
rana_b      2005/09/21 22:34:48

  Modified:    src/java/org/apache/ftpserver/message
                        MessageResourceImpl.java
               src/java/org/apache/ftpserver FtpWriter.java
                        RequestHandler.java
               src/java/org/apache/ftpserver/command HELP.java LANG.java
                        MKD.java OPTS_MLST.java PASS.java PORT.java
                        REIN.java REST.java RETR.java RMD.java RNTO.java
                        SITE_DESCUSER.java SIZE.java STOR.java STOU.java
                        USER.java
               src/java/org/apache/ftpserver/interfaces
                        IMessageResource.java
               src/java/org/apache/ftpserver/gui MessagePanel.java
               src/doc/content/xdocs messages.xml
  Added:       src/java/org/apache/ftpserver/message
                        FtpStatus_zh-tw.properties
  Log:
  i18n support - submitted by Birkir A. Barkarson
  
  Revision  Changes    Path
  1.2       +168 -75   incubator-ftpserver/src/java/org/apache/ftpserver/message/MessageResourceImpl.java
  
  Index: MessageResourceImpl.java
  ===================================================================
  RCS file: /home/cvs/incubator-ftpserver/src/java/org/apache/ftpserver/message/MessageResourceImpl.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- MessageResourceImpl.java	7 Sep 2005 05:02:57 -0000	1.1
  +++ MessageResourceImpl.java	22 Sep 2005 05:34:47 -0000	1.2
  @@ -16,39 +16,51 @@
    */
   package org.apache.ftpserver.message;
   
  -import org.apache.ftpserver.ftplet.Configuration;
  -import org.apache.ftpserver.ftplet.FtpException;
  -import org.apache.ftpserver.ftplet.Logger;
  -import org.apache.ftpserver.interfaces.IMessageResource;
  -import org.apache.ftpserver.util.IoUtils;
  -
   import java.io.File;
   import java.io.FileInputStream;
   import java.io.FileOutputStream;
   import java.io.IOException;
   import java.io.InputStream;
   import java.io.OutputStream;
  -import java.util.Enumeration;
  +import java.util.HashMap;
  +import java.util.Iterator;
   import java.util.Properties;
  +import java.util.StringTokenizer;
  +
  +import org.apache.ftpserver.ftplet.Configuration;
  +import org.apache.ftpserver.ftplet.FtpException;
  +import org.apache.ftpserver.ftplet.Logger;
  +import org.apache.ftpserver.interfaces.IMessageResource;
  +import org.apache.ftpserver.util.IoUtils;
  +
   
   /**
  - * Class to get ftp server reply messages.
  + * Class to get ftp server reply messages. This supports i18n.
  + * Basic message search path is: 
  + * 
  + * Custom Language Specific Messages -> Default Language Specific Messages ->
  + * Custom Common Messages -> Default Common Messages -> null (not found)
    * 
    * @author <a href="mailto:rana_b@yahoo.com">Rana Bhattacharyya</a>
    */
   public 
   class MessageResourceImpl implements IMessageResource {
   
  -    private final static String RESOURCE = "org/apache/ftpserver/message/FtpStatus.properties";
  +    private final static String RESOURCE_PATH = "org/apache/ftpserver/message/";
       
  -    private String m_customMessageFile;
  -    private Properties m_messages;
  -    private Properties m_customMessages;
  +    private String[] m_languages;
  +    private HashMap m_messages;
  +    private String m_customMessageDir;
       private Logger m_logger;
       
  +    private static class PropertiesPair {
  +        public Properties m_default = new Properties();
  +        public Properties m_custom = new Properties();
  +    } 
  +    
       
       /**
  -     * Set logger
  +     * Set logger.
        */
       public void setLogger(Logger logger) {
           m_logger = logger;
  @@ -59,85 +71,156 @@
        */
       public void configure(Configuration config) throws FtpException {
           
  -        // load default messages 
  +        // get the custom message directory
  +        m_customMessageDir = config.getString("custom-message-dir", "./res");
  +        
  +        // get all the languages
  +        String languages = config.getString("languages", null);
  +        if(languages != null) {
  +            StringTokenizer st = new StringTokenizer(languages, ",; \t");
  +            int tokenCount = st.countTokens();
  +            m_languages = new String[tokenCount];
  +            for(int i=0; i<tokenCount; ++i) {
  +                m_languages[i] = st.nextToken().toLowerCase();
  +            }
  +        }
  +        
  +        // populate different properties
  +        m_messages = new HashMap();
  +        if(m_languages != null) {
  +            for(int i=0; i<m_languages.length; ++i) {
  +                String lang = m_languages[i];
  +                PropertiesPair pair = createPropertiesPair(lang);
  +                m_messages.put(lang, pair);
  +            }
  +        }
  +        PropertiesPair pair = createPropertiesPair(null);
  +        m_messages.put(null, pair);
  +    }
  +    
  +    /**
  +     * Create Properties pair object. It stores the default 
  +     * and the custom messages.
  +     */
  +    private PropertiesPair createPropertiesPair(String lang) throws FtpException {
  +        PropertiesPair pair = new PropertiesPair();
  +        
  +        // load default resource
  +        String defaultResourceName;
  +        if(lang == null) {
  +            defaultResourceName = RESOURCE_PATH + "FtpStatus.properties";
  +        }
  +        else {
  +            defaultResourceName = RESOURCE_PATH + "FtpStatus_" + lang + ".properties";
  +        }
           InputStream in = null;
           try {
  -            in = getClass().getClassLoader().getResourceAsStream(RESOURCE);
  -            m_messages = new Properties();
  -            m_messages.load(in);
  +            in = getClass().getClassLoader().getResourceAsStream(defaultResourceName);
  +            if(in != null) {
  +                pair.m_default.load(in);
  +            }
           }
  -        catch(IOException ex) {
  -            m_logger.error("MessageResourceImpl.configure()", ex);
  -            throw new FtpException("MessageResourceImpl.configure()", ex);
  +        catch(Exception ex) {
  +            m_logger.warn("MessageResourceImpl.createPropertiesPair()", ex);
  +            throw new FtpException("MessageResourceImpl.createPropertiesPair()", ex);
           }
           finally {
               IoUtils.close(in);
           }
           
  -        // load custom messages
  -        m_customMessageFile = config.getString("custom-message-file", "./res/messages.gen");
  +        // load custom resource
  +        File resourceFile = null;
  +        if(lang == null) {
  +            resourceFile = new File(m_customMessageDir, "FtpStatus.gen");
  +        }
  +        else {
  +            resourceFile = new File(m_customMessageDir, "FtpStatus_" + lang + ".gen");
  +        }
           in = null;
           try {
  -            m_customMessages = new Properties();
  -            File file = new File(m_customMessageFile);
  -            if(file.isFile()) {
  -                in = new FileInputStream(m_customMessageFile);
  -                m_customMessages.load(in);
  +            if(resourceFile.exists()) {
  +                in = new FileInputStream(resourceFile);
  +                pair.m_custom.load(in);
               }
           }
  -        catch(IOException ex) {
  -            m_logger.error("MessageResourceImpl.configure()", ex);
  -            throw new FtpException("MessageResourceImpl.configure()", ex);
  +        catch(Exception ex) {
  +            m_logger.warn("MessageResourceImpl.createPropertiesPair()", ex);
  +            throw new FtpException("MessageResourceImpl.createPropertiesPair()", ex);
           }
           finally {
               IoUtils.close(in);
           }
  +        
  +        return pair;
       }
       
       /**
        * Get all the available languages.
        */
       public String[] getAvailableLanguages() {
  -        return null;
  +        return m_languages;
       }
       
       /**
  -     * Get the message.
  +     * Get the message. If the message not found, it will return null.
        */
       public String getMessage(int code, String subId, String language) {
  -        String msg = null;
  -        String codeStr = String.valueOf(code);
           
  -        // first try to get property for code.subId
  +        // find the message key
  +        String key = String.valueOf(code);
           if(subId != null) {
  -            String key = codeStr + '.' + subId;
  -            msg = m_customMessages.getProperty(key);
  -            if(msg == null) {
  -                msg = m_messages.getProperty(key);
  -            }
  +            key = key + '.' + subId;
           }
           
  -        // if not found get it for code
  -        if(msg == null) {
  -            msg = m_customMessages.getProperty(codeStr);
  -            if(msg == null) {
  -                msg = m_messages.getProperty(codeStr);
  +        // get language specific value
  +        String value = null;
  +        PropertiesPair pair = null;
  +        if(language != null) {
  +            language = language.toLowerCase();
  +            pair = (PropertiesPair)m_messages.get(language);
  +            if(pair != null) {
  +                value = pair.m_custom.getProperty(key);
  +                if(value == null) {
  +                    value = pair.m_default.getProperty(key);
  +                }
               }
           }
           
  -        // not found return empty string
  -        if(msg == null) {
  -            msg = "";
  +        // if not available get the default value
  +        if(value == null) {
  +            pair = (PropertiesPair)m_messages.get(null);
  +            if(pair != null) {
  +                value = pair.m_custom.getProperty(key);
  +                if(value == null) {
  +                    value = pair.m_default.getProperty(key);
  +                }
  +            }
           }
  -        return msg;
  +        
  +        return value;
       }
       
       /**
        * Get all messages.
        */
       public Properties getMessages(String language) {
  -        Properties messages = new Properties(m_messages);
  -        messages.putAll(m_customMessages);
  +        Properties messages = new Properties();
  +        
  +        // load properties sequentially 
  +        // (default,custom,default language,custom language)
  +        PropertiesPair pair = (PropertiesPair)m_messages.get(null);
  +        if(pair != null) {
  +            messages.putAll(pair.m_default);
  +            messages.putAll(pair.m_custom);
  +        }
  +        if(language != null) {
  +            language = language.toLowerCase();
  +            pair = (PropertiesPair)m_messages.get(language);
  +            if(pair != null) {
  +                messages.putAll(pair.m_default);
  +                messages.putAll(pair.m_custom);
  +            }
  +        }
           return messages;
       }
       
  @@ -145,27 +228,32 @@
        * Save properties in file.
        */
       public void save(Properties prop, String language) throws FtpException {
  +        
  +        // null properties - nothing to save
           if(prop == null) {
               return;
           }
           
  -        // get only the new or modified properties
  -        Properties customMessages = new Properties();
  -        Enumeration props = prop.propertyNames();
  -        while( props.hasMoreElements() ) {
  -            String key = (String)props.nextElement();
  -            String newVal = prop.getProperty(key);
  -            String val = m_messages.getProperty(key);
  -            if( (val == null) || (!val.equals(newVal)) ) {
  -                customMessages.setProperty(key, newVal);
  -            }
  +        // empty properties - nothing to save
  +        if(prop.isEmpty()) {
  +            return;
           }
           
  -        // save the newly created properties
  +        // get custom resource file name
  +        File resourceFile = null;
  +        if(language == null) {
  +            resourceFile = new File(m_customMessageDir, "FtpStatus.gen");
  +        }
  +        else {
  +            language = language.toLowerCase();
  +            resourceFile = new File(m_customMessageDir, "FtpStatus_" + language + ".gen");
  +        }
  +        
  +        // save resource file
           OutputStream out = null;
           try {
  -            out = new FileOutputStream(m_customMessageFile);
  -            customMessages.store(out, "Custom Messages");
  +            out = new FileOutputStream(resourceFile);
  +            prop.store(out, "Custom Messages");
           }
           catch(IOException ex) {
               m_logger.error("MessageResourceImpl.save()", ex);
  @@ -175,21 +263,26 @@
               IoUtils.close(out);
           }
           
  -        // assign the new custom properties
  -        m_customMessages = customMessages;
  +        // assign new messages
  +        PropertiesPair pair = (PropertiesPair)m_messages.get(language);
  +        if(pair == null) {
  +            pair = new PropertiesPair();
  +            m_messages.put(language, pair);
  +        }
  +        pair.m_custom = prop;
       }
       
       /**
  -     * Dispose component - clear properties.
  +     * Dispose component - clear all maps.
        */
       public void dispose() {
  -        if(m_messages != null) {
  -            m_messages.clear();
  -            m_messages = null;
  -        }
  -        if(m_customMessages != null) {
  -            m_customMessages.clear();
  -            m_customMessages = null;
  +        Iterator it = m_messages.keySet().iterator();
  +        while(it.hasNext()) {
  +            String language = (String)it.next();
  +            PropertiesPair pair = (PropertiesPair)m_messages.get(language);
  +            pair.m_custom.clear();
  +            pair.m_default.clear();
           }
  +        m_messages.clear();
       }
   }
  
  
  
  1.1                  incubator-ftpserver/src/java/org/apache/ftpserver/message/FtpStatus_zh-tw.properties
  
  Index: FtpStatus_zh-tw.properties
  ===================================================================
  \ufeff# Ftp server status properties
  # Traditional Chinese version 1.0.2, 2004-06-12
  # Translation by: \u7c21\u5982\u742a (Ju-Chi Chien)
  #
  
  550=\u6240\u9078\u5b9a\u7684\u64cd\u4f5c\u6c92\u88ab\u57f7\u884c
  
  502.not.implemented=\u300c{request.cmd}\u300d\u6307\u4ee4\u6c92\u88ab\u57f7\u884c
  530.permission=\u62d2\u7d55\u5b58\u53d6
  530.ip.restricted=\u62d2\u7d55\u5b58\u53d6
  530.connection.limit=\u62d2\u7d55\u5b58\u53d6
  220=\u4f60\u597d\u3001\u65b0\u5229\u7528\u8005\u7684\u6e96\u5099\u5b8c\u6210
  
  226.ABOR=ABOR\u7684\u6307\u4ee4\u6210\u529f
  
  202.ACCT=\u300c {request.cmd}\u300d\u7684\u6307\u4ee4\u6c92\u88ab\u57f7\u884c\u3001\u6b64\u7db2\u9801\u4e0d\u9700\u8981
  
  501.APPE=\u56e0\u5b50\u6216\u53c3\u6578\u69cb\u6210\u6709\u8aa4
  550.APPE.invalid=\u8cc7\u6599\u593e\u300c{output.msg}\u300d\u7981\u6b62\u4f7f\u7528
  550.APPE.permission=\u8cc7\u6599\u593e\u300c{output.msg}\u300d\u7981\u6b62\u4f7f\u7528
  150.APPE=\u8cc7\u6599\u72c0\u614b\u6b63\u5e38\u3001\u6b63\u5728\u958b\u555f\u6a94\u6848\u9023\u7dda
  425.APPE=\u7121\u6cd5\u958b\u555f\u6a94\u6848\u9023\u7d50
  426.APPE=\u95dc\u9589\u9023\u7d50\u3002\u50b3\u8f38\u4e2d\u65b7
  551.APPE=\u6240\u9078\u5b9a\u7684\u8cc7\u6599\u6c92\u88ab\u57f7\u884c
  226.APPE=\u6a94\u6848\u9023\u7d50\u95dc\u9589
  
  501.AUTH=\u56e0\u5b50\u6216\u53c3\u6578\u69cb\u6210\u6709\u8aa4
  234.AUTH.SSL={request.cmd}\u6307\u4ee4\u6210\u529f
  502.AUTH=\u300c{request.cmd}\u300d\u6307\u4ee4\u6c92\u88ab\u57f7\u884c
  
  250.CDUP=\u6240\u5132\u5b58\u7684\u8b8a\u66f4\u70ba\u300c{output.msg}\u300d
  550.CDUP=\u5176\u7db2\u5740\u7981\u6b62\u4f7f\u7528
  
  250.CWD=\u6240\u5132\u5b58\u7684\u8b8a\u66f4\u70ba\u300c{output.msg}\u300d
  550.CWD=\u5176\u7db2\u5740\u7981\u6b62\u4f7f\u7528
  
  501.DELE=\u56e0\u5b50\u6216\u53c3\u6578\u69cb\u6210\u6709\u8aa4
  550.DELE.invalid=\u8cc7\u6599\u593e\u300c{output.msg}\u300d\u7981\u6b62\u4f7f\u7528
  450.DELE.permission=\u6240\u9078\u5b9a\u7684\u8cc7\u6599\u6c92\u88ab\u57f7\u884c
  250.DELE=\u6240\u9078\u5b9a\u7684\u8cc7\u6599\u6307\u884c\u7121\u8aa4\u5b8c\u6210\u7d50\u675f
  450.DELE=\u6240\u9078\u5b9a\u7684\u8cc7\u6599\u6c92\u88ab\u57f7\u884c
  
  501.EPRT=\u56e0\u5b50\u6216\u53c3\u6578\u69cb\u6210\u6709\u8aa4
  200.EPRT={request.cmd}\u6307\u4ee4\u6210\u529f
  
  425.EPSV=\u7121\u6cd5\u958b\u555f\u6a94\u6848\u9023\u7d50
  229.EPSV=({output.msg})\u9032\u5165\u88ab\u52d5\u6a23\u5f0f
  
  211.FEAT=\u6240\u9078\u7528\u57f7\u884c\n SIZE\n MDTM\n MLST Size;Modify;Type;Perm\n UTF8\n LANG en;zh-tw\n REST STREAM\n TVFS\n \u5b8c\u6210
  
  214=\u57f7\u884c\u6307\u4ee4\nABOR  APPE  CDUP  CWD   DELE  FEAT  HELP  LIST\nMDTM  MKD   MODE  NLST  NOOP  PASS  PASV  PORT\nPWD   QUIT  REIN  REST  RETR  RMD   RNFR  RNTO\nSITE  SIZE  STAT  STOR  STOU  STRU  SYST  TYPE\nUSER\n\u5b8c\u6210
  214.ABOR=\u69cb\u6210\u7d50\u69cb: ABOR
  214.APPE=\u69cb\u6210\u7d50\u69cb: APPE <\u7a7a\u9694> <\u8def\u5f91\u540d>
  214.CDUP=\u69cb\u6210\u7d50\u69cb: CDUP
  214.CWD=\u69cb\u6210\u7d50\u69cb: CWD <\u7a7a\u9694> <\u8def\u5f91\u540d>
  214.DELE=\u69cb\u6210\u7d50\u69cb: DELE <\u7a7a\u9694> <\u8def\u5f91\u540d>
  214.FEAT=\u986f\u793a\u6240\u9078\u7528\u7684\u57f7\u884c\u540d\u55ae\n \u69cb\u6210\u7d50\u69cb: FEAT\n\u5b8c\u6210
  214.HELP=\u69cb\u6210\u7d50\u69cb: HELP [<\u7a7a\u9694> <\u6587\u5b57\u5217>]
  214.LIST=\u69cb\u6210\u7d50\u69cb: LIST [<\u7a7a\u9694> <\u8def\u5f91\u540d>]
  214.MDTM=\u69cb\u6210\u7d50\u69cb: MDTM <\u7a7a\u9694> <\u8def\u5f91\u540d>
  214.MKD=\u69cb\u6210\u7d50\u69cb: MKD <\u7a7a\u9694> <\u8def\u5f91\u540d>
  214.MODE=\u69cb\u6210\u7d50\u69cb: MODE <\u7a7a\u9694> <\u6a23\u5f0f\u7b26\u865f>
  214.NLST=\u69cb\u6210\u7d50\u69cb: NLST [<\u7a7a\u9694> <\u8def\u5f91\u540d>]
  214.NOOP=\u69cb\u6210\u7d50\u69cb: NOOP
  214.PASS=\u69cb\u6210\u7d50\u69cb: PASS <\u7a7a\u9694> <\u5bc6\u78bc>
  214.PASV=\u69cb\u6210\u7d50\u69cb: PASV
  214.PORT=\u69cb\u6210\u7d50\u69cb: PORT <\u7a7a\u9694> <host-port>
  214.PWD=\u69cb\u6210\u7d50\u69cb: PWD
  214.QUIT=\u69cb\u6210\u7d50\u69cb: QUIT
  214.REIN=\u69cb\u6210\u7d50\u69cb: REIN
  214.REST=\u69cb\u6210\u7d50\u69cb: RETR <\u7a7a\u9694> <\u6307\u4ee4>
  214.RETR=\u69cb\u6210\u7d50\u69cb: RETR <\u7a7a\u9694> <\u8def\u5f91\u540d>
  214.RMD=\u69cb\u6210\u7d50\u69cb: RMD <\u7a7a\u9694> <\u8def\u5f91\u540d>
  214.RNFR=\u69cb\u6210\u7d50\u69cb: RNFR <\u7a7a\u9694> <\u8def\u5f91\u540d>
  214.RNTO=\u69cb\u6210\u7d50\u69cb: RNTO <\u7a7a\u9694> <\u8def\u5f91\u540d>
  214.SITE=\u69cb\u6210\u7d50\u69cb: SITE <\u7a7a\u9694> <\u6587\u5b57\u5217>
  214.STOR=\u69cb\u6210\u7d50\u69cb: STOR <\u7a7a\u9694> <\u8def\u5f91\u540d>
  214.STOU=\u69cb\u6210\u7d50\u69cb: STOU
  214.SYST=\u69cb\u6210\u7d50\u69cb: SYST
  214.TYPE=\u69cb\u6210\u7d50\u69cb: TYPE <\u7a7a\u9694> <\u578b\u865f>
  214.USER=\u69cb\u6210\u7d50\u69cb: USER <\u7a7a\u9694> <\u4f7f\u7528\u8005\u540d\u7a31>
  
  504.LANG=\u300c{request.cmd}\u300d\u7684\u6307\u4ee4\u56e0\u5176\u53c3\u6578\u6c92\u88ab\u57f7\u884c
  200.LANG={request.cmd}\u6307\u4ee4\u6210\u529f
  
  501.LIST=\u56e0\u5b50\u6216\u53c3\u6578\u69cb\u6210\u6709\u8aa4
  150.LIST=\u8cc7\u6599\u72c0\u614b\u6b63\u5e38\u3001\u6b63\u5728\u958b\u555f\u6a94\u6848\u9023\u7dda
  425.LIST=\u7121\u6cd5\u958b\u555f\u6a94\u6848\u9023\u7d50
  226.LIST=\u6a94\u6848\u9023\u7d50\u95dc\u9589
  
  501.MDTM=\u56e0\u5b50\u6216\u53c3\u6578\u69cb\u6210\u6709\u8aa4
  550.MDTM=\u8cc7\u6599\u593e\u300c{output.msg}\u300d\u7981\u6b62\u4f7f\u7528
  
  150.MLSD=\u8cc7\u6599\u72c0\u614b\u6b63\u5e38\u3001\u6b63\u5728\u958b\u555f\u6a94\u6848\u9023\u7dda
  425.MLSD=\u7121\u6cd5\u958b\u555f\u6a94\u6848\u9023\u7d50
  501.MLSD=\u56e0\u5b50\u6216\u53c3\u6578\u69cb\u6210\u6709\u8aa4
  226.MLSD=\u6a94\u6848\u9023\u7d50\u95dc\u9589
  
  501.MKD=\u56e0\u5b50\u6216\u53c3\u6578\u69cb\u6210\u6709\u8aa4
  550.MKD.exists=\"{output.msg}\" \u5df2\u4f5c\u6210
  550.MKD.permission=\u62d2\u7d55\u5b58\u53d6
  257.MKD=\"{output.msg}\" \u4f5c\u6210
  
  501.MODE=\u56e0\u5b50\u6216\u53c3\u6578\u69cb\u6210\u6709\u8aa4
  200.MODE={request.cmd}\u6307\u4ee4\u6210\u529f
  504.MODE=\u300c{request.cmd}\u300d\u7684\u6307\u4ee4\u56e0\u5176\u53c3\u6578\u6c92\u88ab\u57f7\u884c
  
  150.NLST=\u8cc7\u6599\u72c0\u614b\u6b63\u5e38\u3001\u6b63\u5728\u958b\u555f\u6a94\u6848\u9023\u7dda
  425.NLST=\u7121\u6cd5\u958b\u555f\u6a94\u6848\u9023\u7d50
  501.NLST=\u56e0\u5b50\u6216\u53c3\u6578\u69cb\u6210\u6709\u8aa4
  226.NLST=\u6a94\u6848\u9023\u7d50\u95dc\u9589
  
  200.NOOP={request.cmd}\u6307\u4ee4\u6210\u529f
  
  501.OPTS=\u56e0\u5b50\u6216\u53c3\u6578\u69cb\u6210\u6709\u8aa4
  
  501.PASS=\u56e0\u5b50\u6216\u53c3\u6578\u69cb\u6210\u6709\u8aa4
  230.PASS=\u4f7f\u7528\u8005\u8acb\u5148\u767b\u9304
  
  425.PASV=\u7121\u6cd5\u958b\u555f\u6a94\u6848\u9023\u7d50
  227.PASV=({output.msg})\u9032\u5165\u88ab\u52d5\u6a23\u5f0f
  
  200.PBSZ={request.cmd}\u6307\u4ee4\u6210\u529f
  
  501.PORT=\u56e0\u5b50\u6216\u53c3\u6578\u69cb\u6210\u6709\u8aa4
  200.PORT={request.cmd}\u6307\u4ee4\u6210\u529f
  
  501.PROT=\u56e0\u5b50\u6216\u53c3\u6578\u69cb\u6210\u6709\u8aa4
  200.PROT={request.cmd}\u6307\u4ee4\u6210\u529f
  
  257.PWD=\"{output.msg}\" \u662f\u73fe\u5728\u7684\u5132\u6a94
  
  221.QUIT=\u518d\u898b
  
  220.REIN=\u4f60\u597d\u3001\u65b0\u5229\u7528\u8005\u7684\u6e96\u5099\u5b8c\u6210
  
  501.REST=\u56e0\u5b50\u6216\u53c3\u6578\u69cb\u6210\u6709\u8aa4
  501.REST.invalid=\"{request.arg}\" \u662f\u7121\u6cd5\u8fa8\u8b58\u7684\u53c3\u6578
  501.REST.negetive=\"{request.arg}\" \u662f\u7121\u6cd5\u8fa8\u8b58\u7684\u53c3\u6578
  350.REST=\u4ee5{request.arg}\u518d\u958b\u3002 \u4ee5STOR\u6216RETR\u958b\u59cb\u50b3\u9001
  
  501.RETR=\u56e0\u5b50\u6216\u53c3\u6578\u69cb\u6210\u6709\u8aa4
  550.RETR.missing=\u8cc7\u6599\u593e\u300c{output.msg}\u300d\u7981\u6b62\u4f7f\u7528
  550.RETR.permission=\u62d2\u7d55\u5b58\u53d6
  150.RETR=\u8cc7\u6599\u72c0\u614b\u6b63\u5e38\u3001\u6b63\u5728\u958b\u555f\u6a94\u6848\u9023\u7dda
  425.RETR=\u7121\u6cd5\u958b\u555f\u6a94\u6848\u9023\u7d50
  226.RETR=\u6a94\u6848\u9023\u7d50\u95dc\u9589
  
  501.RMD=\u56e0\u5b50\u6216\u53c3\u6578\u69cb\u6210\u6709\u8aa4
  550.RMD.permission=\u62d2\u7d55\u5b58\u53d6
  250.RMD=\"{output.msg}\" \u522a\u9664\u6240\u5132\u5b58\u7684
  
  501.RNFR=\u56e0\u5b50\u6216\u53c3\u6578\u69cb\u6210\u6709\u8aa4
  350.RNFR=\u6240\u9078\u5b9a\u7684\u9078\u9805\u9084\u6709\u5176\u4ed6\u8cc7\u8a0a
  
  501.RNTO=\u56e0\u5b50\u6216\u53c3\u6578\u69cb\u6210\u6709\u8aa4
  553.RNTO.permission=\u62d2\u7d55\u5b58\u53d6
  250.RNTO=\u6240\u9078\u5b9a\u7684\u8cc7\u6599\u6307\u884c\u7121\u8aa4\u5b8c\u6210\u7d50\u675f
  
  200.SITE={request.cmd}\u6307\u4ee4\u6210\u529f
  530.SITE.permission=\u62d2\u7d55\u5b58\u53d6
  
  501.SIZE=\u56e0\u5b50\u6216\u53c3\u6578\u69cb\u6210\u6709\u8aa4
  550.SIZE.missing=\u8cc7\u6599\u593e\u300c{output.msg}\u300d\u7981\u6b62\u4f7f\u7528
  550.SIZE.invalid=\u8cc7\u6599\u593e\u300c{output.msg}\u300d\u7981\u6b62\u4f7f\u7528
  
  211.STAT=Apache FTP Server\n\u8207\u300c{server.ip}\u300d\u9023\u7d50\u4e2d\n\u5f9e\u300c{client.ip}\u300d\u9023\u7d50\u4e2d\n\u4ee5\u300c{client.login}\u300d\u767b\u9304\u9023\u7dda\n\u8cc7\u8a0a\u5b8c\u6210
  
  501.STOR=\u56e0\u5b50\u6216\u53c3\u6578\u69cb\u6210\u6709\u8aa4
  550.STOR.permission=\u62d2\u7d55\u5b58\u53d6
  150.STOR=\u8cc7\u6599\u72c0\u614b\u6b63\u5e38\u3001\u6b63\u5728\u958b\u555f\u6a94\u6848\u9023\u7dda
  425.STOR=\u7121\u6cd5\u958b\u555f\u6a94\u6848\u9023\u7d50
  226.STOR=\u6a94\u6848\u9023\u7d50\u95dc\u9589
  
  550.STOU.permission=\u62d2\u7d55\u5b58\u53d6
  150.STOU=\u8cc7\u6599\u72c0\u614b\u6b63\u5e38\u3001\u6b63\u5728\u958b\u555f\u6a94\u6848\u9023\u7dda
  425.STOU=\u7121\u6cd5\u958b\u555f\u6a94\u6848\u9023\u7d50
  226.STOU=\u6240\u9078\u5b9a\u7684\u8cc7\u6599\u6307\u884c\u7121\u8aa4\u5b8c\u6210\u7d50\u675f\u3002\u6240\u4f5c\u6210\u7684\u8cc7\u6599\u662f: {output.msg}
  
  501.STRU=\u56e0\u5b50\u6216\u53c3\u6578\u69cb\u6210\u6709\u8aa4
  200.STRU={request.cmd}\u6307\u4ee4\u6210\u529f
  504.STRU=\u300c{request.cmd}\u300d\u7684\u6307\u4ee4\u56e0\u5176\u53c3\u6578\u6c92\u88ab\u57f7\u884c
  
  501.TYPE=\u56e0\u5b50\u6216\u53c3\u6578\u69cb\u6210\u6709\u8aa4
  200.TYPE={request.cmd}\u6307\u4ee4\u6210\u529f
  504.TYPE=\u300c{request.cmd}\u300d\u7684\u6307\u4ee4\u56e0\u5176\u53c3\u6578\u6c92\u88ab\u57f7\u884c
  
  501.USER=\u56e0\u5b50\u6216\u53c3\u6578\u69cb\u6210\u6709\u8aa4
  331.USER.anonymous=\u53ef\u533f\u540d\u700f\u89bd\u8acb\u8f38\u5165\u96fb\u5b50\u4fe1\u7bb1
  331.USER=\u4f7f\u7528\u8005\u540d\u7a31\u7121\u8aa4\u300c{client.login.name}\u300d\u9808\u8981\u5bc6\u78bc
  
  
  
  1.7       +19 -10    incubator-ftpserver/src/java/org/apache/ftpserver/FtpWriter.java
  
  Index: FtpWriter.java
  ===================================================================
  RCS file: /home/cvs/incubator-ftpserver/src/java/org/apache/ftpserver/FtpWriter.java,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- FtpWriter.java	7 Sep 2005 05:00:32 -0000	1.6
  +++ FtpWriter.java	22 Sep 2005 05:34:47 -0000	1.7
  @@ -16,23 +16,25 @@
    */
   package org.apache.ftpserver;
   
  +import java.io.BufferedReader;
  +import java.io.IOException;
  +import java.io.OutputStreamWriter;
  +import java.io.StringReader;
  +import java.io.Writer;
  +import java.net.InetAddress;
  +import java.net.Socket;
  +
   import org.apache.ftpserver.ftplet.FileSystemView;
   import org.apache.ftpserver.ftplet.FtpRequest;
   import org.apache.ftpserver.ftplet.FtpResponse;
   import org.apache.ftpserver.ftplet.FtpStatistics;
  +import org.apache.ftpserver.ftplet.Logger;
   import org.apache.ftpserver.interfaces.ConnectionObserver;
   import org.apache.ftpserver.interfaces.IFtpConfig;
  +import org.apache.ftpserver.interfaces.IMessageResource;
   import org.apache.ftpserver.util.DateUtils;
   import org.apache.ftpserver.util.IoUtils;
   
  -import java.io.BufferedReader;
  -import java.io.IOException;
  -import java.io.OutputStreamWriter;
  -import java.io.StringReader;
  -import java.io.Writer;
  -import java.net.InetAddress;
  -import java.net.Socket;
  -
   /**
    * FTP response object. The server uses this to send server messages
    *
  @@ -134,7 +136,14 @@
        * Generate and send ftp server response.
        */
       public void send(int code, String subId, String basicMsg) throws IOException {
  -        String msg = m_fconfig.getMessageResource().getMessage(code, subId, m_request.getLanguage());
  +        IMessageResource resource = m_fconfig.getMessageResource();
  +        String lang = m_request.getLanguage();
  +        String msg = resource.getMessage(code, subId, lang);
  +        if(msg == null) {
  +            Logger logger = m_fconfig.getLogger();
  +            logger.warn("Message not found : " + code + ',' + subId + ',' + lang);
  +            msg = "";
  +        }
           msg = replaceVariables(code, basicMsg, msg);
           write(code, msg);
       }
  
  
  
  1.4       +3 -3      incubator-ftpserver/src/java/org/apache/ftpserver/RequestHandler.java
  
  Index: RequestHandler.java
  ===================================================================
  RCS file: /home/cvs/incubator-ftpserver/src/java/org/apache/ftpserver/RequestHandler.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- RequestHandler.java	9 Sep 2005 11:27:38 -0000	1.3
  +++ RequestHandler.java	22 Sep 2005 05:34:47 -0000	1.4
  @@ -209,7 +209,7 @@
                   }
                   
                   // everything is fine - go ahead 
  -                m_writer.send(220, "connection.welcome", null);
  +                m_writer.send(220, null, null);
               }
               
               m_reader = new BufferedReader(new InputStreamReader(m_controlSocket.getInputStream(), "UTF-8"));
  @@ -228,7 +228,7 @@
                   // parse and check permission
                   m_request.parse(commandLine);
                   if(!hasPermission()) {
  -                    m_writer.send(530, "permission.denied", null);
  +                    m_writer.send(530, "permission", null);
                       continue;
                   }
   
  
  
  
  1.2       +10 -6     incubator-ftpserver/src/java/org/apache/ftpserver/command/HELP.java
  
  Index: HELP.java
  ===================================================================
  RCS file: /home/cvs/incubator-ftpserver/src/java/org/apache/ftpserver/command/HELP.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- HELP.java	7 Sep 2005 05:06:22 -0000	1.1
  +++ HELP.java	22 Sep 2005 05:34:47 -0000	1.2
  @@ -16,12 +16,13 @@
    */
   package org.apache.ftpserver.command;
   
  +import java.io.IOException;
  +
   import org.apache.ftpserver.Command;
   import org.apache.ftpserver.FtpRequestImpl;
   import org.apache.ftpserver.FtpWriter;
   import org.apache.ftpserver.RequestHandler;
  -
  -import java.io.IOException;
  +import org.apache.ftpserver.interfaces.IMessageResource;
   
   /**
    * <code>HELP [&lt;SP&gt; <string>] &lt;CRLF&gt;</code><br>
  @@ -38,7 +39,7 @@
   class HELP implements Command {
       
       /**
  -     * Execute command
  +     * Execute command.
        */
       public void execute(RequestHandler handler,
                           FtpRequestImpl request, 
  @@ -53,9 +54,12 @@
               return;
           }
           
  -        // print command specific help
  +        // print command specific help if available
           String ftpCmd = request.getArgument().toUpperCase();
  +        IMessageResource resource = handler.getConfig().getMessageResource();
  +        if(resource.getMessage(214, ftpCmd, request.getLanguage()) == null) {
  +            ftpCmd = null;
  +        }
           out.send(214, ftpCmd, null);
  -        return;
       }
   }
  
  
  
  1.2       +29 -4     incubator-ftpserver/src/java/org/apache/ftpserver/command/LANG.java
  
  Index: LANG.java
  ===================================================================
  RCS file: /home/cvs/incubator-ftpserver/src/java/org/apache/ftpserver/command/LANG.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- LANG.java	7 Sep 2005 05:06:22 -0000	1.1
  +++ LANG.java	22 Sep 2005 05:34:47 -0000	1.2
  @@ -23,6 +23,7 @@
   import org.apache.ftpserver.FtpWriter;
   import org.apache.ftpserver.RequestHandler;
   import org.apache.ftpserver.ftplet.FtpException;
  +import org.apache.ftpserver.interfaces.IMessageResource;
   
   /**
    * A new command "LANG" is added to the FTP command set to allow
  @@ -41,8 +42,32 @@
                           FtpRequestImpl request, 
                           FtpWriter out) throws IOException, FtpException {
           
  -        // not yet supported
  -        out.send(502, "LANG", null);
  +        // reset state
  +        request.resetState();
  +        
  +        // default language
  +        String language = request.getArgument();
  +        if(language == null) {
  +            request.setLanguage(null);
  +            out.send(200, "LANG", null);
  +            return;
  +        }
  +        
  +        // check and set language
  +        language = language.toLowerCase();
  +        IMessageResource msgResource = handler.getConfig().getMessageResource();
  +        String[] availableLanguages = msgResource.getAvailableLanguages();
  +        if(availableLanguages != null) {
  +            for(int i=0; i<availableLanguages.length; ++i) {
  +                if(availableLanguages[i].equals(language)) {
  +                    request.setLanguage(language);
  +                    out.send(200, "LANG", null);
  +                    return;
  +                }
  +            }
  +        }
  +        
  +        // not found - send error message
  +        out.send(504, "LANG", null);
       }
  -    
   }
  
  
  
  1.3       +3 -3      incubator-ftpserver/src/java/org/apache/ftpserver/command/MKD.java
  
  Index: MKD.java
  ===================================================================
  RCS file: /home/cvs/incubator-ftpserver/src/java/org/apache/ftpserver/command/MKD.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- MKD.java	9 Sep 2005 11:21:20 -0000	1.2
  +++ MKD.java	22 Sep 2005 05:34:47 -0000	1.3
  @@ -80,14 +80,14 @@
           catch(Exception ex) {
           }
           if(file == null) {
  -            out.send(550, "MKD.invalid.file", fileName);
  +            out.send(550, "MKD.invalid", fileName);
               return;
           }
           
           // check permission
           fileName = file.getFullName();
           if( !file.hasWritePermission() ) {
  -            out.send(550, "MKD.no.permission", fileName);
  +            out.send(550, "MKD.permission", fileName);
               return;
           }
           
  
  
  
  1.2       +10 -2     incubator-ftpserver/src/java/org/apache/ftpserver/command/OPTS_MLST.java
  
  Index: OPTS_MLST.java
  ===================================================================
  RCS file: /home/cvs/incubator-ftpserver/src/java/org/apache/ftpserver/command/OPTS_MLST.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- OPTS_MLST.java	9 Sep 2005 11:19:46 -0000	1.1
  +++ OPTS_MLST.java	22 Sep 2005 05:34:47 -0000	1.2
  @@ -17,6 +17,7 @@
   package org.apache.ftpserver.command;
   
   import java.io.IOException;
  +import java.util.StringTokenizer;
   
   import org.apache.ftpserver.Command;
   import org.apache.ftpserver.DirectoryLister;
  @@ -54,9 +55,16 @@
           }
           String listTypes = argument.substring(spIndex + 1);
           
  +        // parse all the type tokens
  +        StringTokenizer st = new StringTokenizer(listTypes, ";");
  +        String types[] = new String[st.countTokens()];
  +        for(int i=0; i<types.length; ++i) {
  +            types[i] = st.nextToken();
  +        }
  +        
           // set the list types
           DirectoryLister dirLister = handler.getDirectoryLister();
  -        if(dirLister.setSelectedTypes(listTypes)) {
  +        if(dirLister.setSelectedTypes(types)) {
               out.send(200, "OPTS.MLST", listTypes);
           }
           else {
  
  
  
  1.2       +3 -3      incubator-ftpserver/src/java/org/apache/ftpserver/command/PASS.java
  
  Index: PASS.java
  ===================================================================
  RCS file: /home/cvs/incubator-ftpserver/src/java/org/apache/ftpserver/command/PASS.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- PASS.java	7 Sep 2005 05:06:22 -0000	1.1
  +++ PASS.java	22 Sep 2005 05:34:47 -0000	1.2
  @@ -91,7 +91,7 @@
               int currAnonLogin = stat.getCurrentAnonymousLoginNumber();
               int maxAnonLogin = conManager.getMaxAnonymousLogins();
               if( bAnonymous && (currAnonLogin >= maxAnonLogin) ) {
  -                out.send(421, "PASS.anonymous.limit", null);
  +                out.send(421, "PASS.anonymous", null);
                   return;
               }
               
  @@ -99,7 +99,7 @@
               int currLogin = stat.getCurrentLoginNumber();
               int maxLogin = conManager.getMaxLogins();
               if(currLogin >= maxLogin) {
  -                out.send(421, "PASS.login.limit", null);
  +                out.send(421, "PASS.login", null);
                   return;
               }
               
  
  
  
  1.2       +4 -4      incubator-ftpserver/src/java/org/apache/ftpserver/command/PORT.java
  
  Index: PORT.java
  ===================================================================
  RCS file: /home/cvs/incubator-ftpserver/src/java/org/apache/ftpserver/command/PORT.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- PORT.java	7 Sep 2005 05:06:22 -0000	1.1
  +++ PORT.java	22 Sep 2005 05:34:47 -0000	1.2
  @@ -85,7 +85,7 @@
               dataAddr = InetAddress.getByName(dataSrvName);
           }
           catch(UnknownHostException ex) {
  -            out.send(553, "PORT.host.unknown", null);
  +            out.send(553, "PORT.host", null);
               return;
           }
           
  @@ -93,7 +93,7 @@
           if(handler.getConfig().getDataConnectionConfig().isPortIpCheck()) {
               InetAddress clientAddr = handler.getRequest().getRemoteAddress();
               if(!dataAddr.equals(clientAddr)) {
  -                out.send(510, "PORT.IP.mismatch", null);
  +                out.send(510, "PORT.mismatch", null);
                   return;
               }
           }
  @@ -106,7 +106,7 @@
               dataPort = (hi << 8) | lo;     
           }
           catch(NumberFormatException ex) {
  -            out.send(552, "PORT.number.valid", null); 
  +            out.send(552, "PORT.invalid", null); 
               return; 
           }
           
  
  
  
  1.2       +2 -1      incubator-ftpserver/src/java/org/apache/ftpserver/command/REIN.java
  
  Index: REIN.java
  ===================================================================
  RCS file: /home/cvs/incubator-ftpserver/src/java/org/apache/ftpserver/command/REIN.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- REIN.java	9 Sep 2005 11:19:46 -0000	1.1
  +++ REIN.java	22 Sep 2005 05:34:47 -0000	1.2
  @@ -42,6 +42,7 @@
                           FtpWriter out) throws IOException {
           
           request.reinitialize();
  +        request.setLanguage(null);
           out.send(220, "REIN", null);
       }   
   }
  
  
  
  1.2       +3 -3      incubator-ftpserver/src/java/org/apache/ftpserver/command/REST.java
  
  Index: REST.java
  ===================================================================
  RCS file: /home/cvs/incubator-ftpserver/src/java/org/apache/ftpserver/command/REST.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- REST.java	7 Sep 2005 05:06:22 -0000	1.1
  +++ REST.java	22 Sep 2005 05:34:47 -0000	1.2
  @@ -61,14 +61,14 @@
               // check offset number
               if(skipLen < 0L) {
                   skipLen = 0L;
  -                out.send(501, "REST.number.negetive", null);
  +                out.send(501, "REST.negetive", null);
               }
               else {
                   out.send(350, "REST", null);
               }
           }
           catch(NumberFormatException ex) {
  -            out.send(501, "REST.number.invalid", null); 
  +            out.send(501, "REST.invalid", null); 
           }
           
           request.setFileOffset(skipLen);
  
  
  
  1.3       +5 -5      incubator-ftpserver/src/java/org/apache/ftpserver/command/RETR.java
  
  Index: RETR.java
  ===================================================================
  RCS file: /home/cvs/incubator-ftpserver/src/java/org/apache/ftpserver/command/RETR.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- RETR.java	9 Sep 2005 11:21:20 -0000	1.2
  +++ RETR.java	22 Sep 2005 05:34:47 -0000	1.3
  @@ -88,26 +88,26 @@
               catch(Exception ex) {
               }
               if(file == null) {
  -                out.send(550, "RETR.file.not.exist", fileName);
  +                out.send(550, "RETR.missing", fileName);
                   return;
               }
               fileName = file.getFullName();
               
               // check file existance
               if(!file.doesExist()) {
  -                out.send(550, "RETR.file.not.exist", fileName);
  +                out.send(550, "RETR.missing", fileName);
                   return;
               }
               
               // check valid file
               if(!file.isFile()) {
  -                out.send(550, "RETR.file.invalid", fileName);
  +                out.send(550, "RETR.invalid", fileName);
                   return;
               }
               
               // check permission
               if(!file.hasReadPermission()) {
  -                out.send(550, "RETR.no.permission", fileName);
  +                out.send(550, "RETR.permission", fileName);
                   return;
               }
               
  
  
  
  1.3       +4 -4      incubator-ftpserver/src/java/org/apache/ftpserver/command/RMD.java
  
  Index: RMD.java
  ===================================================================
  RCS file: /home/cvs/incubator-ftpserver/src/java/org/apache/ftpserver/command/RMD.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- RMD.java	9 Sep 2005 11:21:20 -0000	1.2
  +++ RMD.java	22 Sep 2005 05:34:47 -0000	1.3
  @@ -80,20 +80,20 @@
           catch(Exception ex) {
           }
           if(file == null) {
  -            out.send(550, "RMD.no.permission", fileName);
  +            out.send(550, "RMD.permission", fileName);
               return;
           }
           
           // check permission
           fileName = file.getFullName();
           if( !file.hasDeletePermission() ) {
  -            out.send(450, "RMD.no.permission", fileName);
  +            out.send(550, "RMD.permission", fileName);
               return;
           }
           
           // check file
           if(!file.isDirectory()) {
  -            out.send(450, "RMD.directory.invalid", fileName);
  +            out.send(550, "RMD.invalid", fileName);
               return;
           }
           
  
  
  
  1.2       +4 -4      incubator-ftpserver/src/java/org/apache/ftpserver/command/RNTO.java
  
  Index: RNTO.java
  ===================================================================
  RCS file: /home/cvs/incubator-ftpserver/src/java/org/apache/ftpserver/command/RNTO.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- RNTO.java	7 Sep 2005 05:06:22 -0000	1.1
  +++ RNTO.java	22 Sep 2005 05:34:47 -0000	1.2
  @@ -83,20 +83,20 @@
               catch(Exception ex) {
               }
               if(toFile == null) {
  -                out.send(553, "RNTO.not.valid", null);
  +                out.send(553, "RNTO.invalid", null);
                   return;
               }
               toFileStr = toFile.getFullName();
               
               // check permission
               if( !toFile.hasWritePermission() ) {
  -                out.send(553, "RNTO.no.permission", null);
  +                out.send(553, "RNTO.permission", null);
                   return;
               }
               
               // check file existance
               if( !frFile.doesExist() ) {
  -                out.send(553, "RNTO.file.not.exist", null);
  +                out.send(553, "RNTO.missing", null);
                   return;
               }
               
  
  
  
  1.2       +2 -2      incubator-ftpserver/src/java/org/apache/ftpserver/command/SITE_DESCUSER.java
  
  Index: SITE_DESCUSER.java
  ===================================================================
  RCS file: /home/cvs/incubator-ftpserver/src/java/org/apache/ftpserver/command/SITE_DESCUSER.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- SITE_DESCUSER.java	7 Sep 2005 05:06:22 -0000	1.1
  +++ SITE_DESCUSER.java	22 Sep 2005 05:34:47 -0000	1.2
  @@ -74,7 +74,7 @@
           catch(FtpException ex) {
           }
           if(user == null) {
  -            out.send(501, "SITE.DESCUSER.not.exist", userName);
  +            out.send(501, "SITE.DESCUSER", userName);
               return;
           }
           
  
  
  
  1.2       +4 -4      incubator-ftpserver/src/java/org/apache/ftpserver/command/SIZE.java
  
  Index: SIZE.java
  ===================================================================
  RCS file: /home/cvs/incubator-ftpserver/src/java/org/apache/ftpserver/command/SIZE.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- SIZE.java	7 Sep 2005 05:06:22 -0000	1.1
  +++ SIZE.java	22 Sep 2005 05:34:47 -0000	1.2
  @@ -60,17 +60,17 @@
           catch(Exception ex) {
           }
           if(file == null) {
  -            out.send(550, "SIZE.file.not.exist", fileName);
  +            out.send(550, "SIZE.missing", fileName);
               return;
           }
           
           // print file size
           fileName = file.getFullName();
           if(!file.doesExist()) {
  -            out.send(550, "SIZE.file.not.exist", fileName);
  +            out.send(550, "SIZE.missing", fileName);
           }
           else if(!file.isFile()) {
  -            out.send(550, "SIZE.file.invalid", fileName);
  +            out.send(550, "SIZE.invalid", fileName);
           }
           else {
               String fileLen = String.valueOf(file.getSize());             
  
  
  
  1.3       +3 -3      incubator-ftpserver/src/java/org/apache/ftpserver/command/STOR.java
  
  Index: STOR.java
  ===================================================================
  RCS file: /home/cvs/incubator-ftpserver/src/java/org/apache/ftpserver/command/STOR.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- STOR.java	9 Sep 2005 11:21:20 -0000	1.2
  +++ STOR.java	22 Sep 2005 05:34:47 -0000	1.3
  @@ -90,14 +90,14 @@
               catch(Exception ex) {
               }
               if(file == null) {
  -                out.send(550, "STOR.path.invalid", fileName);
  +                out.send(550, "STOR.invalid", fileName);
                   return;
               }
               fileName = file.getFullName();
               
               // get permission
               if( !file.hasWritePermission() ) {
  -                out.send(550, "STOR.no.permission", fileName);
  +                out.send(550, "STOR.permission", fileName);
                   return;
               }
               
  
  
  
  1.3       +2 -2      incubator-ftpserver/src/java/org/apache/ftpserver/command/STOU.java
  
  Index: STOU.java
  ===================================================================
  RCS file: /home/cvs/incubator-ftpserver/src/java/org/apache/ftpserver/command/STOU.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- STOU.java	9 Sep 2005 11:21:20 -0000	1.2
  +++ STOU.java	22 Sep 2005 05:34:47 -0000	1.3
  @@ -89,7 +89,7 @@
               
               // check permission
               if(!file.hasWritePermission()) {
  -                out.send(550, "STOU.no.permission", fileName);
  +                out.send(550, "STOU.permission", fileName);
                   return;
               }
               
  
  
  
  1.2       +5 -5      incubator-ftpserver/src/java/org/apache/ftpserver/command/USER.java
  
  Index: USER.java
  ===================================================================
  RCS file: /home/cvs/incubator-ftpserver/src/java/org/apache/ftpserver/command/USER.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- USER.java	7 Sep 2005 05:06:22 -0000	1.1
  +++ USER.java	22 Sep 2005 05:34:47 -0000	1.2
  @@ -73,7 +73,7 @@
                       bSuccess = true;
                   }
                   else {
  -                    out.send(530, "USER.user.invalid", null);
  +                    out.send(530, "USER.invalid", null);
                   }
                   return;
               }
  @@ -81,7 +81,7 @@
               // anonymous login is not enabled
               boolean bAnonymous = userName.equals("anonymous");
               if( bAnonymous && (!conManager.isAnonymousLoginEnabled()) ) {
  -                out.send(530, "USER.no.anonymous.support", null);
  +                out.send(530, "USER.anonymous", null);
                   return;
               }
               
  @@ -89,7 +89,7 @@
               int currAnonLogin = stat.getCurrentAnonymousLoginNumber();
               int maxAnonLogin = conManager.getMaxAnonymousLogins();
               if( bAnonymous && (currAnonLogin >= maxAnonLogin) ) {
  -                out.send(421, "USER.anonymous.limit", null);
  +                out.send(421, "USER.anonymous", null);
                   return;
               }
               
  @@ -97,7 +97,7 @@
               int currLogin = stat.getCurrentLoginNumber();
               int maxLogin = conManager.getMaxLogins();
               if(currLogin >= maxLogin) {
  -                out.send(421, "USER.login.limit", null);
  +                out.send(421, "USER.login", null);
                   return;
               }
               
  
  
  
  1.2       +3 -5      incubator-ftpserver/src/java/org/apache/ftpserver/interfaces/IMessageResource.java
  
  Index: IMessageResource.java
  ===================================================================
  RCS file: /home/cvs/incubator-ftpserver/src/java/org/apache/ftpserver/interfaces/IMessageResource.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- IMessageResource.java	7 Sep 2005 05:04:03 -0000	1.1
  +++ IMessageResource.java	22 Sep 2005 05:34:47 -0000	1.2
  @@ -35,21 +35,19 @@
       String[] getAvailableLanguages();
       
       /**
  -     * Get the message for the corresponding code and sub id.
  +     * Get the message for the corresponding code and sub id. 
  +     * If not found it will return null. 
        */
       String getMessage(int code, String subId, String language);
       
  -    
       /**
        * Save properties. This properties object contain all the
        * available messages. Old properties will not be overwritten.
        */
       void save(Properties prop, String language) throws FtpException;
       
  -    
       /**
        * Get all the messages.
        */
       Properties getMessages(String language);
  -    
   }
  
  
  
  1.2       +135 -60   incubator-ftpserver/src/java/org/apache/ftpserver/gui/MessagePanel.java
  
  Index: MessagePanel.java
  ===================================================================
  RCS file: /home/cvs/incubator-ftpserver/src/java/org/apache/ftpserver/gui/MessagePanel.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- MessagePanel.java	7 Sep 2005 05:04:45 -0000	1.1
  +++ MessagePanel.java	22 Sep 2005 05:34:47 -0000	1.2
  @@ -21,17 +21,22 @@
   import java.awt.FlowLayout;
   import java.awt.event.ActionEvent;
   import java.awt.event.ActionListener;
  -import java.util.ArrayList;
   import java.util.Collections;
   import java.util.Enumeration;
  -import java.util.Iterator;
   import java.util.Properties;
  +import java.util.Vector;
   
   import javax.swing.JButton;
   import javax.swing.JComboBox;
  +import javax.swing.JLabel;
  +import javax.swing.JList;
   import javax.swing.JPanel;
   import javax.swing.JScrollPane;
  +import javax.swing.JSplitPane;
   import javax.swing.JTextArea;
  +import javax.swing.ListSelectionModel;
  +import javax.swing.event.ListSelectionEvent;
  +import javax.swing.event.ListSelectionListener;
   
   import org.apache.ftpserver.ftplet.FtpException;
   import org.apache.ftpserver.interfaces.IFtpConfig;
  @@ -43,17 +48,20 @@
    * @author <a href="mailto:rana_b@yahoo.com">Rana Bhattacharyya</a>
    */
   public 
  -class MessagePanel extends PluginPanel implements ActionListener {
  +class MessagePanel extends PluginPanel {
   
       private static final long serialVersionUID = -68038181884794057L;
       
       private IFtpConfig m_fconfig;
  -    private JTextArea m_txtArea;
       private JComboBox m_comboBox;
       
  -    private ArrayList m_messageKeys = new ArrayList();
  -    private Properties m_messageProps = new Properties();
  -    private int m_oldSelIndex = -1;
  +    private JList m_list;
  +    private JTextArea m_txtArea;
  +    
  +    private String[] m_languages;
  +    private Vector m_messageKeys;
  +    private Properties m_messageProps;
  +    private int m_oldKeySelIndex = -1;
       
       /**
        * Constructor - set the container.
  @@ -70,22 +78,48 @@
           
           setLayout(new BorderLayout());
           
  +        // top panel
           JPanel comboPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
           add(comboPanel, BorderLayout.NORTH);
           
  -        // all replies
  +        // Language label
  +        JLabel label = new JLabel("Language : ");
  +        comboPanel.add(label);
  +        
  +        // all languages
           m_comboBox = new JComboBox();
  -        m_comboBox.setPreferredSize(new Dimension(250, 22));
  -        m_comboBox.addActionListener(this);
  +        m_comboBox.setPreferredSize(new Dimension(100, 22));
  +        m_comboBox.addActionListener(new ActionListener() {
  +            public void actionPerformed(ActionEvent evt) {
  +                changeLanguage();
  +            }
  +        });
           comboPanel.add(m_comboBox);
           
  +        // split pane
  +        JSplitPane splitPane = new JSplitPane();
  +        splitPane.setDividerSize(0);
  +        add(splitPane, BorderLayout.CENTER);
  +        
  +        // message list keys
  +        m_list = new JList();
  +        m_list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
  +        m_list.addListSelectionListener(new ListSelectionListener() {
  +            public void valueChanged(ListSelectionEvent evt) {
  +                changeKey();
  +            }
  +        });
  +        JScrollPane listScroller = new JScrollPane(m_list);
  +        splitPane.setLeftComponent(listScroller);
  +        
           // message text
           m_txtArea = new JTextArea();
           JScrollPane txtPane = new JScrollPane(m_txtArea, 
                       JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
                       JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
  -        add(txtPane, BorderLayout.CENTER);
  +        splitPane.setRightComponent(txtPane);
           
  +        // button panel
           JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
           add(buttonPanel, BorderLayout.SOUTH);
           
  @@ -102,49 +136,96 @@
           JButton reloadBtn = new JButton("Reload");
           reloadBtn.addActionListener(new ActionListener() {
               public void actionPerformed(ActionEvent evt) {
  -                refresh(m_fconfig);
  +                changeLanguage();
               }
           });
           buttonPanel.add(reloadBtn);
       }
       
       /**
  -     * List selection changed. 
  +     * Combo selection changed. 
        */
  -    public void actionPerformed(ActionEvent e) {
  +    public void changeLanguage() {
  +        
  +        // get selected language
  +        m_oldKeySelIndex = -1;
           int selIdx = m_comboBox.getSelectedIndex();
  -        if(selIdx != -1) {
  -            Object selVal = m_messageKeys.get(selIdx);
  -            String val = m_messageProps.getProperty((String)selVal);
  -            if(val == null) {
  -                val = "";
  -            }
  -            
  -            // save the last text area value
  -            if(m_oldSelIndex != -1) {
  -                String oldKey = (String)m_messageKeys.get(m_oldSelIndex);
  -                String oldTxt = m_txtArea.getText();
  -                m_messageProps.setProperty(oldKey, oldTxt);
  -            }
  -            
  -            // update text area
  -            m_txtArea.setText(val);
  +        if(selIdx == -1) {
  +            return;
           }
  -    } 
  -
  +        String language = null;
  +        if(selIdx >= 1) {
  +            language = m_languages[selIdx - 1];
  +        }
  +        
  +        // get properties
  +        IMessageResource msgRes = m_fconfig.getMessageResource();
  +        Properties prop = msgRes.getMessages(language);
  +        Vector keyList = new Vector();
  +        for(Enumeration keys = prop.propertyNames(); keys.hasMoreElements();) {
  +            String key = (String)keys.nextElement();
  +            keyList.add(key);
  +        }
  +        Collections.sort(keyList);
  +        m_messageKeys = keyList;
  +        m_messageProps = prop;
  +        
  +        // load list
  +        m_list.removeAll();
  +        m_list.setListData(keyList);
  +        m_list.setSelectedIndex(0);
  +    }
  +    
  +    /**
  +     * List selection changed.
  +     */
  +    public void changeKey() {
  +        
  +        // get key selection index
  +        int selIdx = m_list.getSelectedIndex();
  +        if(selIdx == -1) {
  +            return;
  +        }
  +        
  +        // save the last text area value
  +        if(m_oldKeySelIndex != -1) {
  +            String oldKey = (String)m_messageKeys.get(m_oldKeySelIndex);
  +            String oldTxt = m_txtArea.getText();
  +            m_messageProps.setProperty(oldKey, oldTxt);
  +        }
  +        m_oldKeySelIndex = selIdx;
  +        
  +        // update text area
  +        String key = (String)m_messageKeys.get(selIdx);
  +        String val = m_messageProps.getProperty(key);
  +        m_txtArea.setText(val);
  +        m_txtArea.setCaretPosition(0);
  +    }
  +    
       /**
        * Save entered properties 
        */
       private void save() {
           
  +        // get the selected language
  +        int selIdx = m_comboBox.getSelectedIndex();
  +        if(selIdx == -1) {
  +            return;
  +        }
  +        String language = null;
  +        if(selIdx >= 1) {
  +            language = m_languages[selIdx - 1];
  +        }
  +        
  +        // store existing text value
  +        String key = (String)m_comboBox.getSelectedItem();
  +        String val = m_txtArea.getText();
  +        m_messageProps.setProperty(key, val);
  +        
  +        
  +        // save custom messages
           try {
  -            // save the text value
  -            String key = (String)m_comboBox.getSelectedItem();
  -            String val = m_txtArea.getText();
  -            m_messageProps.setProperty(key, val);
  -            
  -            // save messages
  -            getContainer().getFtpConfig().getMessageResource().save(m_messageProps, null);
  +            m_fconfig.getMessageResource().save(m_messageProps, language);
           }
           catch(FtpException ex) {
               GuiUtils.showErrorMessage(this, "Cannot save messages.");
  @@ -157,28 +238,22 @@
       public void refresh(IFtpConfig ftpConfig) {
           m_fconfig = ftpConfig;
           m_comboBox.removeAllItems();
  -        m_txtArea.setText("");
  -        m_messageKeys.clear();
  -        m_oldSelIndex = -1;
  -        
  -        if(m_fconfig != null) {
  -            IMessageResource msgRes = m_fconfig.getMessageResource();
  -            m_messageProps = msgRes.getMessages(null);
  -            Enumeration props = m_messageProps.propertyNames();
  -            while(props.hasMoreElements()) {
  -                String key = (String)props.nextElement();
  -                m_messageKeys.add(key);
  -            }
  -            
  -            Collections.sort(m_messageKeys);
  -            Iterator it = m_messageKeys.iterator();
  -            while(it.hasNext()) {
  -                m_comboBox.addItem(it.next());
  -            }
  -            if(!m_messageKeys.isEmpty()) {
  -                m_comboBox.setSelectedIndex(0);
  +        m_list.removeAll();
  +        m_oldKeySelIndex = -1;
  +        if(m_fconfig == null) {
  +            return;
  +        }
  +        
  +        // populate language list
  +        IMessageResource msgRes = m_fconfig.getMessageResource();
  +        m_languages = msgRes.getAvailableLanguages();
  +        m_comboBox.addItem("<default>");
  +        if(m_languages != null) {
  +            for(int i=0; i<m_languages.length; ++i) {
  +                m_comboBox.addItem(m_languages[i]);
               }
           }
  +        m_comboBox.setSelectedIndex(0);
       }
   
       /** 
  
  
  
  1.2       +25 -13    incubator-ftpserver/src/doc/content/xdocs/messages.xml
  
  Index: messages.xml
  ===================================================================
  RCS file: /home/cvs/incubator-ftpserver/src/doc/content/xdocs/messages.xml,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- messages.xml	7 Sep 2005 05:07:43 -0000	1.1
  +++ messages.xml	22 Sep 2005 05:34:48 -0000	1.2
  @@ -16,17 +16,17 @@
     limitations under the License.
   -->
   <!DOCTYPE document PUBLIC "-//APACHE//DTD Documentation V2.0//EN" "http://forrest.apache.org/dtd/document-v20.dtd">
  -<document> 
  -    <header> 
  -        <title>FTP Server Messages</title> 
  +<document>
  +    <header>
  +        <title>FTP Server Messages</title>
           <authors>
               <person id="RB" name="Rana Bhattacharyya" email="rana_b@yahoo.com"/>
           </authors>
  -    </header> 
  -  <body> 
  +    </header>
  +  <body>
         <section id="messages">
             <title>FTP Server Messages</title>
  -          <p>This document explains how to customize all the Apache FTP Server 
  +          <p>This document explains how to customize all the Apache FTP Server
                reply messages.
             </p>
             <p>All the server messages are customizable. The default reply messages
  @@ -43,15 +43,27 @@
                     <td>org.apache.ftpserver.message.MessageResourceImpl</td>
                 </tr>
                 <tr>
  -                  <td>config.message.custom-message-file</td>
  -                  <td>The custom message file location. The default value is ./res/messages.gen</td>
  +                  <td>config.message.custom-message-dir</td>
  +                  <td>The directory where custom message files will be stored.
  +                      The default value is ./res
  +                  </td>
  +              </tr>
  +              <tr>
  +                  <td>config.message.languages</td>
  +                  <td>Comma separated values of all the languages supported.
  +                      The default value is null. The currently supported values are
  +                      <ul>
  +                          <li>en</li>
  +                          <li>zh-tw</li>
  +                      </ul>
  +                  </td>
                 </tr>
             </table>
  -          
  +
             <section>
                 <title>Dynamic Values</title>
  -              <p>Dynamic values can be embedded in the server message replies. User can 
  -                 specify different variables in message strings. Variables are represented 
  +              <p>Dynamic values can be embedded in the server message replies. User can
  +                 specify different variables in message strings. Variables are represented
                    by <em>{variable}</em> in the string.
                 </p>
                 <table>
  @@ -173,12 +185,12 @@
                     </tr>
                 </table>
             </section>
  -          
  +
             <section>
                 <title>Message UI</title>
                 <p>User can customize server replies using FTP server UI.</p>
                 <img src="images/ftp_messages.jpg"/>
  -          </section>  
  +          </section>
         </section>
     </body>
   </document>
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: cvs-unsubscribe@incubator.apache.org
For additional commands, e-mail: cvs-help@incubator.apache.org


Mime
View raw message