185efb15529d45e32fea8de03c38a968c157c8262chrismair/*
285efb15529d45e32fea8de03c38a968c157c8262chrismair * Copyright 2007 the original author or authors.
385efb15529d45e32fea8de03c38a968c157c8262chrismair *
485efb15529d45e32fea8de03c38a968c157c8262chrismair * Licensed under the Apache License, Version 2.0 (the "License");
585efb15529d45e32fea8de03c38a968c157c8262chrismair * you may not use this file except in compliance with the License.
685efb15529d45e32fea8de03c38a968c157c8262chrismair * You may obtain a copy of the License at
785efb15529d45e32fea8de03c38a968c157c8262chrismair *
885efb15529d45e32fea8de03c38a968c157c8262chrismair *      http://www.apache.org/licenses/LICENSE-2.0
985efb15529d45e32fea8de03c38a968c157c8262chrismair *
1085efb15529d45e32fea8de03c38a968c157c8262chrismair * Unless required by applicable law or agreed to in writing, software
1185efb15529d45e32fea8de03c38a968c157c8262chrismair * distributed under the License is distributed on an "AS IS" BASIS,
1285efb15529d45e32fea8de03c38a968c157c8262chrismair * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1385efb15529d45e32fea8de03c38a968c157c8262chrismair * See the License for the specific language governing permissions and
1485efb15529d45e32fea8de03c38a968c157c8262chrismair * limitations under the License.
1585efb15529d45e32fea8de03c38a968c157c8262chrismair */
1685efb15529d45e32fea8de03c38a968c157c8262chrismairpackage org.mockftpserver.core.command;
1785efb15529d45e32fea8de03c38a968c157c8262chrismair
1885efb15529d45e32fea8de03c38a968c157c8262chrismairimport java.text.MessageFormat;
1985efb15529d45e32fea8de03c38a968c157c8262chrismairimport java.util.ArrayList;
2085efb15529d45e32fea8de03c38a968c157c8262chrismairimport java.util.List;
2185efb15529d45e32fea8de03c38a968c157c8262chrismairimport java.util.MissingResourceException;
2285efb15529d45e32fea8de03c38a968c157c8262chrismairimport java.util.ResourceBundle;
2385efb15529d45e32fea8de03c38a968c157c8262chrismair
2485efb15529d45e32fea8de03c38a968c157c8262chrismairimport org.apache.log4j.Logger;
2585efb15529d45e32fea8de03c38a968c157c8262chrismairimport org.mockftpserver.core.session.Session;
2685efb15529d45e32fea8de03c38a968c157c8262chrismairimport org.mockftpserver.core.util.Assert;
2785efb15529d45e32fea8de03c38a968c157c8262chrismairimport org.mockftpserver.core.util.AssertFailedException;
2885efb15529d45e32fea8de03c38a968c157c8262chrismair
2985efb15529d45e32fea8de03c38a968c157c8262chrismair/**
3085efb15529d45e32fea8de03c38a968c157c8262chrismair * The abstract superclass for CommandHandler classes. This class manages the List of
3185efb15529d45e32fea8de03c38a968c157c8262chrismair * InvocationRecord objects corresponding to each invocation of the command handler,
3285efb15529d45e32fea8de03c38a968c157c8262chrismair * and provides helper methods for subclasses.
3385efb15529d45e32fea8de03c38a968c157c8262chrismair *
3485efb15529d45e32fea8de03c38a968c157c8262chrismair * @version $Revision$ - $Date$
3585efb15529d45e32fea8de03c38a968c157c8262chrismair *
3685efb15529d45e32fea8de03c38a968c157c8262chrismair * @author Chris Mair
3785efb15529d45e32fea8de03c38a968c157c8262chrismair */
3885efb15529d45e32fea8de03c38a968c157c8262chrismairpublic abstract class AbstractCommandHandler implements CommandHandler, ReplyTextBundleAware, InvocationHistory {
3985efb15529d45e32fea8de03c38a968c157c8262chrismair
4085efb15529d45e32fea8de03c38a968c157c8262chrismair    private static final Logger LOG = Logger.getLogger(AbstractCommandHandler.class);
4185efb15529d45e32fea8de03c38a968c157c8262chrismair
4285efb15529d45e32fea8de03c38a968c157c8262chrismair    private ResourceBundle replyTextBundle;
4385efb15529d45e32fea8de03c38a968c157c8262chrismair    private List invocations = new ArrayList();
4485efb15529d45e32fea8de03c38a968c157c8262chrismair
4585efb15529d45e32fea8de03c38a968c157c8262chrismair    // -------------------------------------------------------------------------
4685efb15529d45e32fea8de03c38a968c157c8262chrismair    // Template Method
4785efb15529d45e32fea8de03c38a968c157c8262chrismair    // -------------------------------------------------------------------------
4885efb15529d45e32fea8de03c38a968c157c8262chrismair
4985efb15529d45e32fea8de03c38a968c157c8262chrismair    /**
5085efb15529d45e32fea8de03c38a968c157c8262chrismair     * Handle the specified command for the session. This method is declared to throw Exception,
5185efb15529d45e32fea8de03c38a968c157c8262chrismair     * allowing CommandHandler implementations to avoid unnecessary exception-handling. All checked
5285efb15529d45e32fea8de03c38a968c157c8262chrismair     * exceptions are expected to be wrapped and handled by the caller.
5385efb15529d45e32fea8de03c38a968c157c8262chrismair     *
5485efb15529d45e32fea8de03c38a968c157c8262chrismair     * @param command - the Command to be handled
5585efb15529d45e32fea8de03c38a968c157c8262chrismair     * @param session - the session on which the Command was submitted
5685efb15529d45e32fea8de03c38a968c157c8262chrismair     *
5785efb15529d45e32fea8de03c38a968c157c8262chrismair     * @throws Exception
5885efb15529d45e32fea8de03c38a968c157c8262chrismair     * @throws AssertFailedException - if the command or session is null
5985efb15529d45e32fea8de03c38a968c157c8262chrismair     *
6085efb15529d45e32fea8de03c38a968c157c8262chrismair     * @see org.mockftpserver.core.command.CommandHandler#handleCommand(org.mockftpserver.core.command.Command,
6185efb15529d45e32fea8de03c38a968c157c8262chrismair     *      org.mockftpserver.core.session.Session)
6285efb15529d45e32fea8de03c38a968c157c8262chrismair     */
6385efb15529d45e32fea8de03c38a968c157c8262chrismair    public final void handleCommand(Command command, Session session) throws Exception {
6485efb15529d45e32fea8de03c38a968c157c8262chrismair        Assert.notNull(command, "command");
6585efb15529d45e32fea8de03c38a968c157c8262chrismair        Assert.notNull(session, "session");
6685efb15529d45e32fea8de03c38a968c157c8262chrismair        InvocationRecord invocationRecord = new InvocationRecord(command, session.getClientHost());
6785efb15529d45e32fea8de03c38a968c157c8262chrismair        invocations.add(invocationRecord);
6885efb15529d45e32fea8de03c38a968c157c8262chrismair        handleCommand(command, session, invocationRecord);
6985efb15529d45e32fea8de03c38a968c157c8262chrismair        invocationRecord.lock();
7085efb15529d45e32fea8de03c38a968c157c8262chrismair    }
7185efb15529d45e32fea8de03c38a968c157c8262chrismair
7285efb15529d45e32fea8de03c38a968c157c8262chrismair    /**
7385efb15529d45e32fea8de03c38a968c157c8262chrismair     * Handle the specified command for the session. This method is declared to throw Exception,
7485efb15529d45e32fea8de03c38a968c157c8262chrismair     * allowing CommandHandler implementations to avoid unnecessary exception-handling. All checked
7585efb15529d45e32fea8de03c38a968c157c8262chrismair     * exceptions are expected to be wrapped and handled by the caller.
7685efb15529d45e32fea8de03c38a968c157c8262chrismair     *
7785efb15529d45e32fea8de03c38a968c157c8262chrismair     * @param command - the Command to be handled
7885efb15529d45e32fea8de03c38a968c157c8262chrismair     * @param session - the session on which the Command was submitted
7985efb15529d45e32fea8de03c38a968c157c8262chrismair     * @param invocationRecord - the InvocationRecord; CommandHandlers are expected to add
8085efb15529d45e32fea8de03c38a968c157c8262chrismair     *        handler-specific data to the InvocationRecord, as appropriate
8185efb15529d45e32fea8de03c38a968c157c8262chrismair     * @throws Exception
8285efb15529d45e32fea8de03c38a968c157c8262chrismair     */
8385efb15529d45e32fea8de03c38a968c157c8262chrismair    protected abstract void handleCommand(Command command, Session session, InvocationRecord invocationRecord)
8485efb15529d45e32fea8de03c38a968c157c8262chrismair            throws Exception;
8585efb15529d45e32fea8de03c38a968c157c8262chrismair
8685efb15529d45e32fea8de03c38a968c157c8262chrismair    //-------------------------------------------------------------------------
8785efb15529d45e32fea8de03c38a968c157c8262chrismair    // Support for reply text ResourceBundle
8885efb15529d45e32fea8de03c38a968c157c8262chrismair    //-------------------------------------------------------------------------
8985efb15529d45e32fea8de03c38a968c157c8262chrismair
9085efb15529d45e32fea8de03c38a968c157c8262chrismair    /**
9185efb15529d45e32fea8de03c38a968c157c8262chrismair     * Return the ResourceBundle containing the reply text messages
9285efb15529d45e32fea8de03c38a968c157c8262chrismair     * @return the replyTextBundle
9385efb15529d45e32fea8de03c38a968c157c8262chrismair     *
9485efb15529d45e32fea8de03c38a968c157c8262chrismair     * @see org.mockftpserver.core.command.ReplyTextBundleAware#getReplyTextBundle()
9585efb15529d45e32fea8de03c38a968c157c8262chrismair     */
9685efb15529d45e32fea8de03c38a968c157c8262chrismair    public ResourceBundle getReplyTextBundle() {
9785efb15529d45e32fea8de03c38a968c157c8262chrismair        return replyTextBundle;
9885efb15529d45e32fea8de03c38a968c157c8262chrismair    }
9985efb15529d45e32fea8de03c38a968c157c8262chrismair
10085efb15529d45e32fea8de03c38a968c157c8262chrismair    /**
10185efb15529d45e32fea8de03c38a968c157c8262chrismair     * Set the ResourceBundle containing the reply text messages
10285efb15529d45e32fea8de03c38a968c157c8262chrismair     * @param replyTextBundle - the replyTextBundle to set
10385efb15529d45e32fea8de03c38a968c157c8262chrismair     *
10485efb15529d45e32fea8de03c38a968c157c8262chrismair     * @see org.mockftpserver.core.command.ReplyTextBundleAware#setReplyTextBundle(java.util.ResourceBundle)
10585efb15529d45e32fea8de03c38a968c157c8262chrismair     */
10685efb15529d45e32fea8de03c38a968c157c8262chrismair    public void setReplyTextBundle(ResourceBundle replyTextBundle) {
10785efb15529d45e32fea8de03c38a968c157c8262chrismair        this.replyTextBundle = replyTextBundle;
10885efb15529d45e32fea8de03c38a968c157c8262chrismair    }
10985efb15529d45e32fea8de03c38a968c157c8262chrismair
11085efb15529d45e32fea8de03c38a968c157c8262chrismair    // -------------------------------------------------------------------------
11185efb15529d45e32fea8de03c38a968c157c8262chrismair    // Utility methods for subclasses
11285efb15529d45e32fea8de03c38a968c157c8262chrismair    // -------------------------------------------------------------------------
11385efb15529d45e32fea8de03c38a968c157c8262chrismair
11485efb15529d45e32fea8de03c38a968c157c8262chrismair    /**
11585efb15529d45e32fea8de03c38a968c157c8262chrismair     * Send a reply for this command on the control connection.
11685efb15529d45e32fea8de03c38a968c157c8262chrismair     *
11785efb15529d45e32fea8de03c38a968c157c8262chrismair     * The reply code is designated by the <code>replyCode</code> property, and the reply text
11885efb15529d45e32fea8de03c38a968c157c8262chrismair     * is determined by the following rules:
11985efb15529d45e32fea8de03c38a968c157c8262chrismair     * <ol>
12085efb15529d45e32fea8de03c38a968c157c8262chrismair     *   <li>If the <code>replyText</code> property is non-null, then use that.</li>
12185efb15529d45e32fea8de03c38a968c157c8262chrismair     *   <li>Otherwise, if <code>replyMessageKey</code> is non-null, the use that to retrieve a
12285efb15529d45e32fea8de03c38a968c157c8262chrismair     *      localized message from the <code>replyText</code> ResourceBundle.</li>
12385efb15529d45e32fea8de03c38a968c157c8262chrismair     *   <li>Otherwise, retrieve the reply text from the <code>replyText</code> ResourceBundle,
12485efb15529d45e32fea8de03c38a968c157c8262chrismair     *      using the reply code as the key.</li>
12585efb15529d45e32fea8de03c38a968c157c8262chrismair     * </ol>
12685efb15529d45e32fea8de03c38a968c157c8262chrismair     * If the arguments Object[] is not null, then these arguments are substituted within the
12785efb15529d45e32fea8de03c38a968c157c8262chrismair     * reply text using the {@link MessageFormat} class.
12885efb15529d45e32fea8de03c38a968c157c8262chrismair     *
12985efb15529d45e32fea8de03c38a968c157c8262chrismair     * @param session - the Session
13085efb15529d45e32fea8de03c38a968c157c8262chrismair     * @param replyCode - the reply code
13185efb15529d45e32fea8de03c38a968c157c8262chrismair     * @param replyMessageKey - if not null (and replyText is null), this is used as the ResourceBundle
13285efb15529d45e32fea8de03c38a968c157c8262chrismair     *      message key instead of the reply code.
13385efb15529d45e32fea8de03c38a968c157c8262chrismair     * @param replyText - if non-null, this is used as the reply text
13485efb15529d45e32fea8de03c38a968c157c8262chrismair     * @param arguments - the array of arguments to be formatted and substituted within the reply
13585efb15529d45e32fea8de03c38a968c157c8262chrismair     *        text; may be null
13685efb15529d45e32fea8de03c38a968c157c8262chrismair     *
13785efb15529d45e32fea8de03c38a968c157c8262chrismair     * @throws AssertFailedException - if session is null
13885efb15529d45e32fea8de03c38a968c157c8262chrismair     *
13985efb15529d45e32fea8de03c38a968c157c8262chrismair     * @see MessageFormat
14085efb15529d45e32fea8de03c38a968c157c8262chrismair     */
14185efb15529d45e32fea8de03c38a968c157c8262chrismair    protected void sendReply(Session session, int replyCode, String replyMessageKey, String replyText,
14285efb15529d45e32fea8de03c38a968c157c8262chrismair            Object[] arguments) {
14385efb15529d45e32fea8de03c38a968c157c8262chrismair
14485efb15529d45e32fea8de03c38a968c157c8262chrismair        Assert.notNull(session, "session");
14585efb15529d45e32fea8de03c38a968c157c8262chrismair        assertValidReplyCode(replyCode);
14685efb15529d45e32fea8de03c38a968c157c8262chrismair
14785efb15529d45e32fea8de03c38a968c157c8262chrismair        final Logger HANDLER_LOG = Logger.getLogger(getClass());
14885efb15529d45e32fea8de03c38a968c157c8262chrismair        String key = (replyMessageKey != null) ? replyMessageKey : Integer.toString(replyCode);
14985efb15529d45e32fea8de03c38a968c157c8262chrismair        String text = getTextForReplyCode(replyCode, key, replyText, arguments);
15085efb15529d45e32fea8de03c38a968c157c8262chrismair        String replyTextToLog = (text == null) ? "" : " " + text;
15185efb15529d45e32fea8de03c38a968c157c8262chrismair        HANDLER_LOG.debug("Sending reply [" + replyCode + replyTextToLog + "]");
15285efb15529d45e32fea8de03c38a968c157c8262chrismair        session.sendReply(replyCode, text);
15385efb15529d45e32fea8de03c38a968c157c8262chrismair    }
15485efb15529d45e32fea8de03c38a968c157c8262chrismair
15585efb15529d45e32fea8de03c38a968c157c8262chrismair    /**
15685efb15529d45e32fea8de03c38a968c157c8262chrismair     * Return the specified text surrounded with double quotes
15785efb15529d45e32fea8de03c38a968c157c8262chrismair     *
15885efb15529d45e32fea8de03c38a968c157c8262chrismair     * @param text - the text to surround with quotes
15985efb15529d45e32fea8de03c38a968c157c8262chrismair     * @return the text with leading and trailing double quotes
16085efb15529d45e32fea8de03c38a968c157c8262chrismair     *
16185efb15529d45e32fea8de03c38a968c157c8262chrismair     * @throws AssertFailedException - if text is null
16285efb15529d45e32fea8de03c38a968c157c8262chrismair     */
16385efb15529d45e32fea8de03c38a968c157c8262chrismair    protected static String quotes(String text) {
16485efb15529d45e32fea8de03c38a968c157c8262chrismair        Assert.notNull(text, "text");
16585efb15529d45e32fea8de03c38a968c157c8262chrismair        final String QUOTES = "\"";
16685efb15529d45e32fea8de03c38a968c157c8262chrismair        return QUOTES + text + QUOTES;
16785efb15529d45e32fea8de03c38a968c157c8262chrismair    }
16885efb15529d45e32fea8de03c38a968c157c8262chrismair
16985efb15529d45e32fea8de03c38a968c157c8262chrismair    /**
17085efb15529d45e32fea8de03c38a968c157c8262chrismair     * Assert that the specified number is a valid reply code
17185efb15529d45e32fea8de03c38a968c157c8262chrismair     * @param replyCode - the reply code to check
17285efb15529d45e32fea8de03c38a968c157c8262chrismair     *
17385efb15529d45e32fea8de03c38a968c157c8262chrismair     * @throws AssertFailedException - if the replyCode is invalid
17485efb15529d45e32fea8de03c38a968c157c8262chrismair     */
17585efb15529d45e32fea8de03c38a968c157c8262chrismair    protected void assertValidReplyCode(int replyCode) {
17685efb15529d45e32fea8de03c38a968c157c8262chrismair        Assert.isTrue(replyCode > 0, "The number [" + replyCode + "] is not a valid reply code");
17785efb15529d45e32fea8de03c38a968c157c8262chrismair    }
17885efb15529d45e32fea8de03c38a968c157c8262chrismair
17985efb15529d45e32fea8de03c38a968c157c8262chrismair    // -------------------------------------------------------------------------
18085efb15529d45e32fea8de03c38a968c157c8262chrismair    // InvocationHistory - Support for command history
18185efb15529d45e32fea8de03c38a968c157c8262chrismair    // -------------------------------------------------------------------------
18285efb15529d45e32fea8de03c38a968c157c8262chrismair
18385efb15529d45e32fea8de03c38a968c157c8262chrismair    /**
18485efb15529d45e32fea8de03c38a968c157c8262chrismair     * @return the number of invocation records stored for this command handler instance
18585efb15529d45e32fea8de03c38a968c157c8262chrismair     *
18685efb15529d45e32fea8de03c38a968c157c8262chrismair     * @see org.mockftpserver.core.command.InvocationHistory#numberOfInvocations()
18785efb15529d45e32fea8de03c38a968c157c8262chrismair     */
18885efb15529d45e32fea8de03c38a968c157c8262chrismair    public int numberOfInvocations() {
18985efb15529d45e32fea8de03c38a968c157c8262chrismair        return invocations.size();
19085efb15529d45e32fea8de03c38a968c157c8262chrismair    }
19185efb15529d45e32fea8de03c38a968c157c8262chrismair
19285efb15529d45e32fea8de03c38a968c157c8262chrismair    /**
19385efb15529d45e32fea8de03c38a968c157c8262chrismair     * Return the InvocationRecord representing the command invoction data for the nth invocation
19485efb15529d45e32fea8de03c38a968c157c8262chrismair     * for this command handler instance. One InvocationRecord should be stored for each invocation
19585efb15529d45e32fea8de03c38a968c157c8262chrismair     * of the CommandHandler.
19685efb15529d45e32fea8de03c38a968c157c8262chrismair     *
19785efb15529d45e32fea8de03c38a968c157c8262chrismair     * @param index - the index of the invocation record to return. The first record is at index zero.
19885efb15529d45e32fea8de03c38a968c157c8262chrismair     * @return the InvocationRecord for the specified index
19985efb15529d45e32fea8de03c38a968c157c8262chrismair     *
20085efb15529d45e32fea8de03c38a968c157c8262chrismair     * @throws AssertFailedException - if there is no invocation record corresponding to the specified index
20185efb15529d45e32fea8de03c38a968c157c8262chrismair     *
20285efb15529d45e32fea8de03c38a968c157c8262chrismair     * @see org.mockftpserver.core.command.InvocationHistory#getInvocation(int)
20385efb15529d45e32fea8de03c38a968c157c8262chrismair     */
20485efb15529d45e32fea8de03c38a968c157c8262chrismair    public InvocationRecord getInvocation(int index) {
20585efb15529d45e32fea8de03c38a968c157c8262chrismair        return (InvocationRecord) invocations.get(index);
20685efb15529d45e32fea8de03c38a968c157c8262chrismair    }
20785efb15529d45e32fea8de03c38a968c157c8262chrismair
20885efb15529d45e32fea8de03c38a968c157c8262chrismair    /**
20985efb15529d45e32fea8de03c38a968c157c8262chrismair     * Clear out the invocation history for this CommandHandler. After invoking this method, the
21085efb15529d45e32fea8de03c38a968c157c8262chrismair     * <code>numberOfInvocations()</code> method will return zero.
21185efb15529d45e32fea8de03c38a968c157c8262chrismair     *
21285efb15529d45e32fea8de03c38a968c157c8262chrismair     * @see org.mockftpserver.core.command.InvocationHistory#clearInvocations()
21385efb15529d45e32fea8de03c38a968c157c8262chrismair     */
21485efb15529d45e32fea8de03c38a968c157c8262chrismair    public void clearInvocations() {
21585efb15529d45e32fea8de03c38a968c157c8262chrismair        invocations.clear();
21685efb15529d45e32fea8de03c38a968c157c8262chrismair    }
21785efb15529d45e32fea8de03c38a968c157c8262chrismair
21885efb15529d45e32fea8de03c38a968c157c8262chrismair    // -------------------------------------------------------------------------
21985efb15529d45e32fea8de03c38a968c157c8262chrismair    // Internal Helper Methods
22085efb15529d45e32fea8de03c38a968c157c8262chrismair    // -------------------------------------------------------------------------
22185efb15529d45e32fea8de03c38a968c157c8262chrismair
22285efb15529d45e32fea8de03c38a968c157c8262chrismair    /**
22385efb15529d45e32fea8de03c38a968c157c8262chrismair     * Return the text for the specified reply code, formatted using the message arguments, if
22485efb15529d45e32fea8de03c38a968c157c8262chrismair     * supplied. If overrideText is not null, then return that. Otherwise, return the text mapped to
22585efb15529d45e32fea8de03c38a968c157c8262chrismair     * the code from the replyText ResourceBundle. If the ResourceBundle contains no mapping, then
22685efb15529d45e32fea8de03c38a968c157c8262chrismair     * return null.
22785efb15529d45e32fea8de03c38a968c157c8262chrismair     * <p>
22885efb15529d45e32fea8de03c38a968c157c8262chrismair     * If arguments is not null, then the returned reply text if formatted using the
22985efb15529d45e32fea8de03c38a968c157c8262chrismair     * {@link MessageFormat} class.
23085efb15529d45e32fea8de03c38a968c157c8262chrismair     *
23185efb15529d45e32fea8de03c38a968c157c8262chrismair     * @param code - the reply code
23285efb15529d45e32fea8de03c38a968c157c8262chrismair     * @param messageKey - the key used to retrieve the reply text from the replyTextBundle
23385efb15529d45e32fea8de03c38a968c157c8262chrismair     * @param overrideText - if not null, this is used instead of the text from the replyTextBundle.
23485efb15529d45e32fea8de03c38a968c157c8262chrismair     * @param arguments - the array of arguments to be formatted and substituted within the reply
23585efb15529d45e32fea8de03c38a968c157c8262chrismair     *        text; may be null
23685efb15529d45e32fea8de03c38a968c157c8262chrismair     * @return the text for the reply code; may be null
23785efb15529d45e32fea8de03c38a968c157c8262chrismair     */
23885efb15529d45e32fea8de03c38a968c157c8262chrismair    private String getTextForReplyCode(int code, String messageKey, String overrideText, Object[] arguments) {
23985efb15529d45e32fea8de03c38a968c157c8262chrismair        try {
24085efb15529d45e32fea8de03c38a968c157c8262chrismair            String t = (overrideText == null) ? replyTextBundle.getString(messageKey) : overrideText;
24185efb15529d45e32fea8de03c38a968c157c8262chrismair            String formattedMessage = MessageFormat.format(t, arguments);
24285efb15529d45e32fea8de03c38a968c157c8262chrismair            return (formattedMessage == null) ? null : formattedMessage.trim();
24385efb15529d45e32fea8de03c38a968c157c8262chrismair        }
24485efb15529d45e32fea8de03c38a968c157c8262chrismair        catch (MissingResourceException e) {
24585efb15529d45e32fea8de03c38a968c157c8262chrismair            // No reply text is mapped for the specified key
24685efb15529d45e32fea8de03c38a968c157c8262chrismair            LOG.warn("No reply text defined for reply code [" + code + "]");
24785efb15529d45e32fea8de03c38a968c157c8262chrismair            return null;
24885efb15529d45e32fea8de03c38a968c157c8262chrismair        }
24985efb15529d45e32fea8de03c38a968c157c8262chrismair    }
25085efb15529d45e32fea8de03c38a968c157c8262chrismair
25185efb15529d45e32fea8de03c38a968c157c8262chrismair}
252