117f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair/*
217f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair * Copyright 2007 the original author or authors.
317f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair *
417f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair * Licensed under the Apache License, Version 2.0 (the "License");
517f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair * you may not use this file except in compliance with the License.
617f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair * You may obtain a copy of the License at
717f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair *
817f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair *      http://www.apache.org/licenses/LICENSE-2.0
917f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair *
1017f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair * Unless required by applicable law or agreed to in writing, software
1117f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair * distributed under the License is distributed on an "AS IS" BASIS,
1217f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1317f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair * See the License for the specific language governing permissions and
1417f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair * limitations under the License.
1517f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair */
1617f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismairpackage org.mockftpserver.core.command;
1717f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair
1817f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismairimport java.net.InetAddress;
1917f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismairimport java.util.Collections;
2017f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismairimport java.util.Date;
2117f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismairimport java.util.HashMap;
2217f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismairimport java.util.Map;
2317f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismairimport java.util.Set;
2417f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair
2517f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismairimport org.mockftpserver.core.util.Assert;
2617f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismairimport org.mockftpserver.core.util.AssertFailedException;
2717f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair
2817f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair/**
2917f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair * Represents information about a single FTP Command invocation. Manages and provides access to
3017f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair * the Command, the host address (<code>InetAddress</code>) of the client that submitted the
3117f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair * Command and the timestamp of the Command submission.
3217f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair * <p>
3317f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair * This class also supports storing zero or more arbitrary mappings of <i>key</i> to value, where <i>key</i> is
3417f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair * a String and <i>value</i> is any Object. Convenience methods are provided that enable retrieving
3517f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair * type-specific data by its <i>key</i>. The data stored in an {@link InvocationRecord} is CommandHandler-specific.
3617f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair * <p>
3717f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair * The {@link #lock()} method makes an instance of this class immutable. After an instance is locked,
3817f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair * calling the {@link #set(String, Object)} method will throw an <code>AssertFailedException</code>.
3917f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair *
4017f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair * @version $Revision$ - $Date$
4117f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair *
4217f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair * @author Chris Mair
4317f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair */
4417f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismairpublic class InvocationRecord {
4517f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair
4617f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair    private Command command;
4717f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair    private Date time;
4817f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair    private InetAddress clientHost;
4917f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair    private Map data = new HashMap();
5017f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair    private boolean locked = false;
5117f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair
5217f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair    /**
5317f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair     * Create a new instance
5417f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair     * @param command - the Command
5517f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair     * @param clientHost - the client host
5617f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair     */
5717f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair    public InvocationRecord(Command command, InetAddress clientHost) {
5817f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair        this.command = command;
5917f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair        this.time = new Date();
6017f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair        this.clientHost = clientHost;
6117f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair    }
6217f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair
6317f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair    /**
6417f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair     * Lock this instance, making it immutable. After an instance is locked,
6517f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair     * calling the {@link #set(String, Object)} method will throw an
6617f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair     * <code>AssertFailedException</code>.
6717f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair     */
6817f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair    public void lock() {
6917f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair        locked = true;
7017f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair    }
7117f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair
7217f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair    /**
7317f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair     * Return true if this object has been locked, false otherwise. See {@link #lock()}.
7417f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair     * @return true if this object has been locked, false otherwise.
7517f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair     */
7617f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair    public boolean isLocked() {
7717f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair        return locked;
7817f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair    }
7917f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair
8017f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair    /**
8117f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair     * @return the client host that submitted the command, as an InetAddress
8217f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair     */
8317f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair    public InetAddress getClientHost() {
8417f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair        return clientHost;
8517f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair    }
8617f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair
8717f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair    /**
8817f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair     * @return the Command
8917f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair     */
9017f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair    public Command getCommand() {
9117f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair        return command;
9217f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair    }
9317f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair
9417f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair    /**
9517f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair     * @return the time that the command was processed; this may differ slightly from when the command was received.
9617f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair     */
9717f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair    public Date getTime() {
9817f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair        // Return a copy of the Date object to preserve immutability
9917f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair        return new Date(time.getTime());
10017f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair    }
10117f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair
10217f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair    /**
10317f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair     * Store the value for the specified key. If this object already contained a mapping
10417f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair     * for this key, the old value is replaced by the specified value. This method throws
10517f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair     * an <code>AssertFailedException</code> if this object has been locked. See {@link #lock()}.
10617f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair     *
10717f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair     * @param key - the key; must not be null
10817f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair     * @param value - the value to store for the specified key
10917f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair     *
11017f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair     * @throws AssertFailedException - if the key is null or this object has been locked.
11117f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair     */
11217f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair    public void set(String key, Object value) {
11317f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair        Assert.notNull(key, "key");
11417f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair        Assert.isFalse(locked, "The InvocationRecord is locked!");
11517f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair        data.put(key, value);
11617f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair    }
11717f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair
11817f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair    /**
11917f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair     * Returns <code>true</code> if this object contains a mapping for the specified key.
12017f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair     *
12117f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair     * @param key - the key; must not be null
12217f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair     * @return <code>true</code> if there is a mapping for the key
12317f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair     *
12417f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair     * @throws AssertFailedException - if the key is null
12517f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair     */
12617f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair    public boolean containsKey(String key) {
12717f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair        Assert.notNull(key, "key");
12817f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair        return data.containsKey(key);
12917f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair    }
13017f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair
13117f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair    /**
13217f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair     * Returns a Set view of the keys for the data stored in this object.
13317f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair     * Changes to the returned Set have no effect on the data stored within this object
13417f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair     * .
13517f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair     * @return the Set of keys for the data stored within this object
13617f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair     */
13717f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair    public Set keySet() {
13817f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair        return Collections.unmodifiableSet(data.keySet());
13917f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair    }
14017f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair
14117f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair    /**
14217f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair     * Get the String value associated with the specified key. Returns null if there is
14317f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair     * no mapping for this key. A return value of null does not necessarily indicate that
14417f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair     * this object contains no mapping for the key; it's also possible that the value was
14517f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair     * explicitly set to null for the key. The containsKey operation may be used to
14617f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair     * distinguish these two cases.
14717f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair     *
14817f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair     * @param key - the key; must not be null
14917f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair     * @return the String data stored at the specified key; may be null
15017f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair     *
15117f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair     * @throws ClassCastException - if the object for the specified key is not a String
15217f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair     * @throws AssertFailedException - if the key is null
15317f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair     */
15417f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair    public String getString(String key) {
15517f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair        Assert.notNull(key, "key");
15617f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair        return (String) data.get(key);
15717f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair    }
15817f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair
15917f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair    /**
16017f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair     * Get the Object value associated with the specified key. Returns null if there is
16117f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair     * no mapping for this key. A return value of null does not necessarily indicate that
16217f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair     * this object contains no mapping for the key; it's also possible that the value was
16317f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair     * explicitly set to null for the key. The containsKey operation may be used to
16417f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair     * distinguish these two cases.
16517f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair     *
16617f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair     * @param key - the key; must not be null
16717f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair     * @return the data stored at the specified key, as an Object; may be null
16817f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair     *
16917f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair     * @throws AssertFailedException - if the key is null
17017f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair     */
17117f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair    public Object getObject(String key) {
17217f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair        Assert.notNull(key, "key");
17317f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair        return data.get(key);
17417f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair    }
17517f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair
17617f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair    /**
17717f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair     * Return the String representation of this object
17817f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair     * @see java.lang.Object#toString()
17917f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair     */
18017f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair    public String toString() {
18117f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair        return "InvocationRecord[time=" + time + " client-host=" + clientHost + " command=" + command + " data="+ data + "]";
18217f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair    }
18317f899cea435aaf91624af2a93bc24bcfcd5fc2dchrismair}
184