177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair/* 277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * Copyright 2007 the original author or authors. 377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * 477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * Licensed under the Apache License, Version 2.0 (the "License"); 577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * you may not use this file except in compliance with the License. 677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * You may obtain a copy of the License at 777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * 877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * http://www.apache.org/licenses/LICENSE-2.0 977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * 1077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * Unless required by applicable law or agreed to in writing, software 1177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * distributed under the License is distributed on an "AS IS" BASIS, 1277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * See the License for the specific language governing permissions and 1477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * limitations under the License. 1577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair */ 1677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismairpackage org.mockftpserver.core.command; 1777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 1877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismairimport org.mockftpserver.core.util.Assert; 1977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismairimport org.mockftpserver.core.util.AssertFailedException; 2077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 2177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismairimport java.net.InetAddress; 2277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismairimport java.util.Collections; 2377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismairimport java.util.Date; 2477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismairimport java.util.HashMap; 2577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismairimport java.util.Map; 2677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismairimport java.util.Set; 2777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 2877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair/** 2977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * Represents information about a single FTP Command invocation. Manages and provides access to 3077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * the Command, the host address (<code>InetAddress</code>) of the client that submitted the 3177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * Command and the timestamp of the Command submission. 3277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * <p> 3377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * This class also supports storing zero or more arbitrary mappings of <i>key</i> to value, where <i>key</i> is 3477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * a String and <i>value</i> is any Object. Convenience methods are provided that enable retrieving 3577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * type-specific data by its <i>key</i>. The data stored in an {@link InvocationRecord} is CommandHandler-specific. 3677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * <p> 3777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * The {@link #lock()} method makes an instance of this class immutable. After an instance is locked, 3877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * calling the {@link #set(String, Object)} method will throw an <code>AssertFailedException</code>. 3977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * 4077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @author Chris Mair 4177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @version $Revision$ - $Date$ 4277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair */ 4377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismairpublic class InvocationRecord { 4477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 4577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair private Command command; 4677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair private Date time; 4777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair private InetAddress clientHost; 4877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair private Map data = new HashMap(); 4977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair private boolean locked = false; 5077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 5177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair /** 5277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * Create a new instance 5377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * 5477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @param command - the Command 5577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @param clientHost - the client host 5677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair */ 5777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair public InvocationRecord(Command command, InetAddress clientHost) { 5877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair this.command = command; 5977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair this.time = new Date(); 6077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair this.clientHost = clientHost; 6177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 6277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 6377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair /** 6477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * Lock this instance, making it immutable. After an instance is locked, 6577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * calling the {@link #set(String, Object)} method will throw an 6677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * <code>AssertFailedException</code>. 6777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair */ 6877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair public void lock() { 6977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair locked = true; 7077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 7177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 7277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair /** 7377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * Return true if this object has been locked, false otherwise. See {@link #lock()}. 7477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * 7577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @return true if this object has been locked, false otherwise. 7677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair */ 7777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair public boolean isLocked() { 7877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair return locked; 7977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 8077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 8177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair /** 8277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @return the client host that submitted the command, as an InetAddress 8377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair */ 8477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair public InetAddress getClientHost() { 8577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair return clientHost; 8677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 8777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 8877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair /** 8977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @return the Command 9077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair */ 9177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair public Command getCommand() { 9277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair return command; 9377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 9477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 9577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair /** 9677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @return the time that the command was processed; this may differ slightly from when the command was received. 9777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair */ 9877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair public Date getTime() { 9977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair // Return a copy of the Date object to preserve immutability 10077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair return new Date(time.getTime()); 10177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 10277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 10377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair /** 10477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * Store the value for the specified key. If this object already contained a mapping 10577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * for this key, the old value is replaced by the specified value. This method throws 10677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * an <code>AssertFailedException</code> if this object has been locked. See {@link #lock()}. 10777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * 10877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @param key - the key; must not be null 10977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @param value - the value to store for the specified key 11077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @throws AssertFailedException - if the key is null or this object has been locked. 11177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair */ 11277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair public void set(String key, Object value) { 11377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair Assert.notNull(key, "key"); 11477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair Assert.isFalse(locked, "The InvocationRecord is locked!"); 11577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair data.put(key, value); 11677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 11777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 11877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair /** 11977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * Returns <code>true</code> if this object contains a mapping for the specified key. 12077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * 12177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @param key - the key; must not be null 12277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @return <code>true</code> if there is a mapping for the key 12377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @throws AssertFailedException - if the key is null 12477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair */ 12577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair public boolean containsKey(String key) { 12677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair Assert.notNull(key, "key"); 12777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair return data.containsKey(key); 12877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 12977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 13077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair /** 13177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * Returns a Set view of the keys for the data stored in this object. 13277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * Changes to the returned Set have no effect on the data stored within this object 13377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * . 13477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * 13577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @return the Set of keys for the data stored within this object 13677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair */ 13777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair public Set keySet() { 13877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair return Collections.unmodifiableSet(data.keySet()); 13977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 14077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 14177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair /** 14277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * Get the String value associated with the specified key. Returns null if there is 14377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * no mapping for this key. A return value of null does not necessarily indicate that 14477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * this object contains no mapping for the key; it's also possible that the value was 14577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * explicitly set to null for the key. The containsKey operation may be used to 14677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * distinguish these two cases. 14777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * 14877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @param key - the key; must not be null 14977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @return the String data stored at the specified key; may be null 15077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @throws ClassCastException - if the object for the specified key is not a String 15177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @throws AssertFailedException - if the key is null 15277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair */ 15377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair public String getString(String key) { 15477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair Assert.notNull(key, "key"); 15577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair return (String) data.get(key); 15677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 15777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 15877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair /** 15977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * Get the Object value associated with the specified key. Returns null if there is 16077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * no mapping for this key. A return value of null does not necessarily indicate that 16177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * this object contains no mapping for the key; it's also possible that the value was 16277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * explicitly set to null for the key. The containsKey operation may be used to 16377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * distinguish these two cases. 16477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * 16577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @param key - the key; must not be null 16677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @return the data stored at the specified key, as an Object; may be null 16777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @throws AssertFailedException - if the key is null 16877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair */ 16977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair public Object getObject(String key) { 17077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair Assert.notNull(key, "key"); 17177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair return data.get(key); 17277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 17377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 17477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair /** 17577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * Return the String representation of this object 17677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * 17777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @see java.lang.Object#toString() 17877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair */ 17977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair public String toString() { 18077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair return "InvocationRecord[time=" + time + " client-host=" + clientHost + " command=" + command + " data=" + data + "]"; 18177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 18277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair} 183