1bda3441225e0607b5ced8b538123fd7c7a417910chrismair/*
2bda3441225e0607b5ced8b538123fd7c7a417910chrismair * Copyright 2007 the original author or authors.
3bda3441225e0607b5ced8b538123fd7c7a417910chrismair *
4bda3441225e0607b5ced8b538123fd7c7a417910chrismair * Licensed under the Apache License, Version 2.0 (the "License");
5bda3441225e0607b5ced8b538123fd7c7a417910chrismair * you may not use this file except in compliance with the License.
6bda3441225e0607b5ced8b538123fd7c7a417910chrismair * You may obtain a copy of the License at
7bda3441225e0607b5ced8b538123fd7c7a417910chrismair *
8bda3441225e0607b5ced8b538123fd7c7a417910chrismair *      http://www.apache.org/licenses/LICENSE-2.0
9bda3441225e0607b5ced8b538123fd7c7a417910chrismair *
10bda3441225e0607b5ced8b538123fd7c7a417910chrismair * Unless required by applicable law or agreed to in writing, software
11bda3441225e0607b5ced8b538123fd7c7a417910chrismair * distributed under the License is distributed on an "AS IS" BASIS,
12bda3441225e0607b5ced8b538123fd7c7a417910chrismair * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13bda3441225e0607b5ced8b538123fd7c7a417910chrismair * See the License for the specific language governing permissions and
14bda3441225e0607b5ced8b538123fd7c7a417910chrismair * limitations under the License.
15bda3441225e0607b5ced8b538123fd7c7a417910chrismair */
16bda3441225e0607b5ced8b538123fd7c7a417910chrismairpackage org.mockftpserver.core.command;
17bda3441225e0607b5ced8b538123fd7c7a417910chrismair
18bda3441225e0607b5ced8b538123fd7c7a417910chrismairimport org.mockftpserver.core.util.Assert;
19bda3441225e0607b5ced8b538123fd7c7a417910chrismairimport org.mockftpserver.core.util.AssertFailedException;
20bda3441225e0607b5ced8b538123fd7c7a417910chrismair
21bda3441225e0607b5ced8b538123fd7c7a417910chrismairimport java.net.InetAddress;
22bda3441225e0607b5ced8b538123fd7c7a417910chrismairimport java.util.Collections;
23bda3441225e0607b5ced8b538123fd7c7a417910chrismairimport java.util.Date;
24bda3441225e0607b5ced8b538123fd7c7a417910chrismairimport java.util.HashMap;
25bda3441225e0607b5ced8b538123fd7c7a417910chrismairimport java.util.Map;
26bda3441225e0607b5ced8b538123fd7c7a417910chrismairimport java.util.Set;
27bda3441225e0607b5ced8b538123fd7c7a417910chrismair
28bda3441225e0607b5ced8b538123fd7c7a417910chrismair/**
29bda3441225e0607b5ced8b538123fd7c7a417910chrismair * Represents information about a single FTP Command invocation. Manages and provides access to
30bda3441225e0607b5ced8b538123fd7c7a417910chrismair * the Command, the host address (<code>InetAddress</code>) of the client that submitted the
31bda3441225e0607b5ced8b538123fd7c7a417910chrismair * Command and the timestamp of the Command submission.
32bda3441225e0607b5ced8b538123fd7c7a417910chrismair * <p>
33bda3441225e0607b5ced8b538123fd7c7a417910chrismair * This class also supports storing zero or more arbitrary mappings of <i>key</i> to value, where <i>key</i> is
34bda3441225e0607b5ced8b538123fd7c7a417910chrismair * a String and <i>value</i> is any Object. Convenience methods are provided that enable retrieving
35bda3441225e0607b5ced8b538123fd7c7a417910chrismair * type-specific data by its <i>key</i>. The data stored in an {@link InvocationRecord} is CommandHandler-specific.
36bda3441225e0607b5ced8b538123fd7c7a417910chrismair * <p>
37bda3441225e0607b5ced8b538123fd7c7a417910chrismair * The {@link #lock()} method makes an instance of this class immutable. After an instance is locked,
38bda3441225e0607b5ced8b538123fd7c7a417910chrismair * calling the {@link #set(String, Object)} method will throw an <code>AssertFailedException</code>.
39bda3441225e0607b5ced8b538123fd7c7a417910chrismair *
40bda3441225e0607b5ced8b538123fd7c7a417910chrismair * @author Chris Mair
41bda3441225e0607b5ced8b538123fd7c7a417910chrismair * @version $Revision$ - $Date$
42bda3441225e0607b5ced8b538123fd7c7a417910chrismair */
43bda3441225e0607b5ced8b538123fd7c7a417910chrismairpublic class InvocationRecord {
44bda3441225e0607b5ced8b538123fd7c7a417910chrismair
45bda3441225e0607b5ced8b538123fd7c7a417910chrismair    private Command command;
46bda3441225e0607b5ced8b538123fd7c7a417910chrismair    private Date time;
47bda3441225e0607b5ced8b538123fd7c7a417910chrismair    private InetAddress clientHost;
48bda3441225e0607b5ced8b538123fd7c7a417910chrismair    private Map data = new HashMap();
49bda3441225e0607b5ced8b538123fd7c7a417910chrismair    private boolean locked = false;
50bda3441225e0607b5ced8b538123fd7c7a417910chrismair
51bda3441225e0607b5ced8b538123fd7c7a417910chrismair    /**
52bda3441225e0607b5ced8b538123fd7c7a417910chrismair     * Create a new instance
53bda3441225e0607b5ced8b538123fd7c7a417910chrismair     *
54bda3441225e0607b5ced8b538123fd7c7a417910chrismair     * @param command    - the Command
55bda3441225e0607b5ced8b538123fd7c7a417910chrismair     * @param clientHost - the client host
56bda3441225e0607b5ced8b538123fd7c7a417910chrismair     */
57bda3441225e0607b5ced8b538123fd7c7a417910chrismair    public InvocationRecord(Command command, InetAddress clientHost) {
58bda3441225e0607b5ced8b538123fd7c7a417910chrismair        this.command = command;
59bda3441225e0607b5ced8b538123fd7c7a417910chrismair        this.time = new Date();
60bda3441225e0607b5ced8b538123fd7c7a417910chrismair        this.clientHost = clientHost;
61bda3441225e0607b5ced8b538123fd7c7a417910chrismair    }
62bda3441225e0607b5ced8b538123fd7c7a417910chrismair
63bda3441225e0607b5ced8b538123fd7c7a417910chrismair    /**
64bda3441225e0607b5ced8b538123fd7c7a417910chrismair     * Lock this instance, making it immutable. After an instance is locked,
65bda3441225e0607b5ced8b538123fd7c7a417910chrismair     * calling the {@link #set(String, Object)} method will throw an
66bda3441225e0607b5ced8b538123fd7c7a417910chrismair     * <code>AssertFailedException</code>.
67bda3441225e0607b5ced8b538123fd7c7a417910chrismair     */
68bda3441225e0607b5ced8b538123fd7c7a417910chrismair    public void lock() {
69bda3441225e0607b5ced8b538123fd7c7a417910chrismair        locked = true;
70bda3441225e0607b5ced8b538123fd7c7a417910chrismair    }
71bda3441225e0607b5ced8b538123fd7c7a417910chrismair
72bda3441225e0607b5ced8b538123fd7c7a417910chrismair    /**
73bda3441225e0607b5ced8b538123fd7c7a417910chrismair     * Return true if this object has been locked, false otherwise. See {@link #lock()}.
74bda3441225e0607b5ced8b538123fd7c7a417910chrismair     *
75bda3441225e0607b5ced8b538123fd7c7a417910chrismair     * @return true if this object has been locked, false otherwise.
76bda3441225e0607b5ced8b538123fd7c7a417910chrismair     */
77bda3441225e0607b5ced8b538123fd7c7a417910chrismair    public boolean isLocked() {
78bda3441225e0607b5ced8b538123fd7c7a417910chrismair        return locked;
79bda3441225e0607b5ced8b538123fd7c7a417910chrismair    }
80bda3441225e0607b5ced8b538123fd7c7a417910chrismair
81bda3441225e0607b5ced8b538123fd7c7a417910chrismair    /**
82bda3441225e0607b5ced8b538123fd7c7a417910chrismair     * @return the client host that submitted the command, as an InetAddress
83bda3441225e0607b5ced8b538123fd7c7a417910chrismair     */
84bda3441225e0607b5ced8b538123fd7c7a417910chrismair    public InetAddress getClientHost() {
85bda3441225e0607b5ced8b538123fd7c7a417910chrismair        return clientHost;
86bda3441225e0607b5ced8b538123fd7c7a417910chrismair    }
87bda3441225e0607b5ced8b538123fd7c7a417910chrismair
88bda3441225e0607b5ced8b538123fd7c7a417910chrismair    /**
89bda3441225e0607b5ced8b538123fd7c7a417910chrismair     * @return the Command
90bda3441225e0607b5ced8b538123fd7c7a417910chrismair     */
91bda3441225e0607b5ced8b538123fd7c7a417910chrismair    public Command getCommand() {
92bda3441225e0607b5ced8b538123fd7c7a417910chrismair        return command;
93bda3441225e0607b5ced8b538123fd7c7a417910chrismair    }
94bda3441225e0607b5ced8b538123fd7c7a417910chrismair
95bda3441225e0607b5ced8b538123fd7c7a417910chrismair    /**
96bda3441225e0607b5ced8b538123fd7c7a417910chrismair     * @return the time that the command was processed; this may differ slightly from when the command was received.
97bda3441225e0607b5ced8b538123fd7c7a417910chrismair     */
98bda3441225e0607b5ced8b538123fd7c7a417910chrismair    public Date getTime() {
99bda3441225e0607b5ced8b538123fd7c7a417910chrismair        // Return a copy of the Date object to preserve immutability
100bda3441225e0607b5ced8b538123fd7c7a417910chrismair        return new Date(time.getTime());
101bda3441225e0607b5ced8b538123fd7c7a417910chrismair    }
102bda3441225e0607b5ced8b538123fd7c7a417910chrismair
103bda3441225e0607b5ced8b538123fd7c7a417910chrismair    /**
104bda3441225e0607b5ced8b538123fd7c7a417910chrismair     * Store the value for the specified key. If this object already contained a mapping
105bda3441225e0607b5ced8b538123fd7c7a417910chrismair     * for this key, the old value is replaced by the specified value. This method throws
106bda3441225e0607b5ced8b538123fd7c7a417910chrismair     * an <code>AssertFailedException</code> if this object has been locked. See {@link #lock()}.
107bda3441225e0607b5ced8b538123fd7c7a417910chrismair     *
108bda3441225e0607b5ced8b538123fd7c7a417910chrismair     * @param key   - the key; must not be null
109bda3441225e0607b5ced8b538123fd7c7a417910chrismair     * @param value - the value to store for the specified key
110bda3441225e0607b5ced8b538123fd7c7a417910chrismair     * @throws AssertFailedException - if the key is null or this object has been locked.
111bda3441225e0607b5ced8b538123fd7c7a417910chrismair     */
112bda3441225e0607b5ced8b538123fd7c7a417910chrismair    public void set(String key, Object value) {
113bda3441225e0607b5ced8b538123fd7c7a417910chrismair        Assert.notNull(key, "key");
114bda3441225e0607b5ced8b538123fd7c7a417910chrismair        Assert.isFalse(locked, "The InvocationRecord is locked!");
115bda3441225e0607b5ced8b538123fd7c7a417910chrismair        data.put(key, value);
116bda3441225e0607b5ced8b538123fd7c7a417910chrismair    }
117bda3441225e0607b5ced8b538123fd7c7a417910chrismair
118bda3441225e0607b5ced8b538123fd7c7a417910chrismair    /**
119bda3441225e0607b5ced8b538123fd7c7a417910chrismair     * Returns <code>true</code> if this object contains a mapping for the specified key.
120bda3441225e0607b5ced8b538123fd7c7a417910chrismair     *
121bda3441225e0607b5ced8b538123fd7c7a417910chrismair     * @param key - the key; must not be null
122bda3441225e0607b5ced8b538123fd7c7a417910chrismair     * @return <code>true</code> if there is a mapping for the key
123bda3441225e0607b5ced8b538123fd7c7a417910chrismair     * @throws AssertFailedException - if the key is null
124bda3441225e0607b5ced8b538123fd7c7a417910chrismair     */
125bda3441225e0607b5ced8b538123fd7c7a417910chrismair    public boolean containsKey(String key) {
126bda3441225e0607b5ced8b538123fd7c7a417910chrismair        Assert.notNull(key, "key");
127bda3441225e0607b5ced8b538123fd7c7a417910chrismair        return data.containsKey(key);
128bda3441225e0607b5ced8b538123fd7c7a417910chrismair    }
129bda3441225e0607b5ced8b538123fd7c7a417910chrismair
130bda3441225e0607b5ced8b538123fd7c7a417910chrismair    /**
131bda3441225e0607b5ced8b538123fd7c7a417910chrismair     * Returns a Set view of the keys for the data stored in this object.
132bda3441225e0607b5ced8b538123fd7c7a417910chrismair     * Changes to the returned Set have no effect on the data stored within this object
133bda3441225e0607b5ced8b538123fd7c7a417910chrismair     * .
134bda3441225e0607b5ced8b538123fd7c7a417910chrismair     *
135bda3441225e0607b5ced8b538123fd7c7a417910chrismair     * @return the Set of keys for the data stored within this object
136bda3441225e0607b5ced8b538123fd7c7a417910chrismair     */
137bda3441225e0607b5ced8b538123fd7c7a417910chrismair    public Set keySet() {
138bda3441225e0607b5ced8b538123fd7c7a417910chrismair        return Collections.unmodifiableSet(data.keySet());
139bda3441225e0607b5ced8b538123fd7c7a417910chrismair    }
140bda3441225e0607b5ced8b538123fd7c7a417910chrismair
141bda3441225e0607b5ced8b538123fd7c7a417910chrismair    /**
142bda3441225e0607b5ced8b538123fd7c7a417910chrismair     * Get the String value associated with the specified key. Returns null if there is
143bda3441225e0607b5ced8b538123fd7c7a417910chrismair     * no mapping for this key. A return value of null does not necessarily indicate that
144bda3441225e0607b5ced8b538123fd7c7a417910chrismair     * this object contains no mapping for the key; it's also possible that the value was
145bda3441225e0607b5ced8b538123fd7c7a417910chrismair     * explicitly set to null for the key. The containsKey operation may be used to
146bda3441225e0607b5ced8b538123fd7c7a417910chrismair     * distinguish these two cases.
147bda3441225e0607b5ced8b538123fd7c7a417910chrismair     *
148bda3441225e0607b5ced8b538123fd7c7a417910chrismair     * @param key - the key; must not be null
149bda3441225e0607b5ced8b538123fd7c7a417910chrismair     * @return the String data stored at the specified key; may be null
150bda3441225e0607b5ced8b538123fd7c7a417910chrismair     * @throws ClassCastException    - if the object for the specified key is not a String
151bda3441225e0607b5ced8b538123fd7c7a417910chrismair     * @throws AssertFailedException - if the key is null
152bda3441225e0607b5ced8b538123fd7c7a417910chrismair     */
153bda3441225e0607b5ced8b538123fd7c7a417910chrismair    public String getString(String key) {
154bda3441225e0607b5ced8b538123fd7c7a417910chrismair        Assert.notNull(key, "key");
155bda3441225e0607b5ced8b538123fd7c7a417910chrismair        return (String) data.get(key);
156bda3441225e0607b5ced8b538123fd7c7a417910chrismair    }
157bda3441225e0607b5ced8b538123fd7c7a417910chrismair
158bda3441225e0607b5ced8b538123fd7c7a417910chrismair    /**
159bda3441225e0607b5ced8b538123fd7c7a417910chrismair     * Get the Object value associated with the specified key. Returns null if there is
160bda3441225e0607b5ced8b538123fd7c7a417910chrismair     * no mapping for this key. A return value of null does not necessarily indicate that
161bda3441225e0607b5ced8b538123fd7c7a417910chrismair     * this object contains no mapping for the key; it's also possible that the value was
162bda3441225e0607b5ced8b538123fd7c7a417910chrismair     * explicitly set to null for the key. The containsKey operation may be used to
163bda3441225e0607b5ced8b538123fd7c7a417910chrismair     * distinguish these two cases.
164bda3441225e0607b5ced8b538123fd7c7a417910chrismair     *
165bda3441225e0607b5ced8b538123fd7c7a417910chrismair     * @param key - the key; must not be null
166bda3441225e0607b5ced8b538123fd7c7a417910chrismair     * @return the data stored at the specified key, as an Object; may be null
167bda3441225e0607b5ced8b538123fd7c7a417910chrismair     * @throws AssertFailedException - if the key is null
168bda3441225e0607b5ced8b538123fd7c7a417910chrismair     */
169bda3441225e0607b5ced8b538123fd7c7a417910chrismair    public Object getObject(String key) {
170bda3441225e0607b5ced8b538123fd7c7a417910chrismair        Assert.notNull(key, "key");
171bda3441225e0607b5ced8b538123fd7c7a417910chrismair        return data.get(key);
172bda3441225e0607b5ced8b538123fd7c7a417910chrismair    }
173bda3441225e0607b5ced8b538123fd7c7a417910chrismair
174bda3441225e0607b5ced8b538123fd7c7a417910chrismair    /**
175bda3441225e0607b5ced8b538123fd7c7a417910chrismair     * Return the String representation of this object
176bda3441225e0607b5ced8b538123fd7c7a417910chrismair     *
177bda3441225e0607b5ced8b538123fd7c7a417910chrismair     * @see java.lang.Object#toString()
178bda3441225e0607b5ced8b538123fd7c7a417910chrismair     */
179bda3441225e0607b5ced8b538123fd7c7a417910chrismair    public String toString() {
180bda3441225e0607b5ced8b538123fd7c7a417910chrismair        return "InvocationRecord[time=" + time + " client-host=" + clientHost + " command=" + command + " data=" + data + "]";
181bda3441225e0607b5ced8b538123fd7c7a417910chrismair    }
182bda3441225e0607b5ced8b538123fd7c7a417910chrismair}
183