177391c2a01ce1fed085906743cc240a4d58edd92chrismair/* 277391c2a01ce1fed085906743cc240a4d58edd92chrismair * Copyright 2007 the original author or authors. 377391c2a01ce1fed085906743cc240a4d58edd92chrismair * 477391c2a01ce1fed085906743cc240a4d58edd92chrismair * Licensed under the Apache License, Version 2.0 (the "License"); 577391c2a01ce1fed085906743cc240a4d58edd92chrismair * you may not use this file except in compliance with the License. 677391c2a01ce1fed085906743cc240a4d58edd92chrismair * You may obtain a copy of the License at 777391c2a01ce1fed085906743cc240a4d58edd92chrismair * 877391c2a01ce1fed085906743cc240a4d58edd92chrismair * http://www.apache.org/licenses/LICENSE-2.0 977391c2a01ce1fed085906743cc240a4d58edd92chrismair * 1077391c2a01ce1fed085906743cc240a4d58edd92chrismair * Unless required by applicable law or agreed to in writing, software 1177391c2a01ce1fed085906743cc240a4d58edd92chrismair * distributed under the License is distributed on an "AS IS" BASIS, 1277391c2a01ce1fed085906743cc240a4d58edd92chrismair * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1377391c2a01ce1fed085906743cc240a4d58edd92chrismair * See the License for the specific language governing permissions and 1477391c2a01ce1fed085906743cc240a4d58edd92chrismair * limitations under the License. 1577391c2a01ce1fed085906743cc240a4d58edd92chrismair */ 1677391c2a01ce1fed085906743cc240a4d58edd92chrismairpackage org.mockftpserver.core.command; 1777391c2a01ce1fed085906743cc240a4d58edd92chrismair 1877391c2a01ce1fed085906743cc240a4d58edd92chrismairimport java.net.InetAddress; 1977391c2a01ce1fed085906743cc240a4d58edd92chrismairimport java.util.Collections; 2077391c2a01ce1fed085906743cc240a4d58edd92chrismairimport java.util.Date; 2177391c2a01ce1fed085906743cc240a4d58edd92chrismairimport java.util.HashMap; 2277391c2a01ce1fed085906743cc240a4d58edd92chrismairimport java.util.Map; 2377391c2a01ce1fed085906743cc240a4d58edd92chrismairimport java.util.Set; 2477391c2a01ce1fed085906743cc240a4d58edd92chrismair 2577391c2a01ce1fed085906743cc240a4d58edd92chrismairimport org.mockftpserver.core.util.Assert; 2677391c2a01ce1fed085906743cc240a4d58edd92chrismairimport org.mockftpserver.core.util.AssertFailedException; 2777391c2a01ce1fed085906743cc240a4d58edd92chrismair 2877391c2a01ce1fed085906743cc240a4d58edd92chrismair/** 2977391c2a01ce1fed085906743cc240a4d58edd92chrismair * Represents information about a single FTP Command invocation. Manages and provides access to 3077391c2a01ce1fed085906743cc240a4d58edd92chrismair * the Command, the host address (<code>InetAddress</code>) of the client that submitted the 3177391c2a01ce1fed085906743cc240a4d58edd92chrismair * Command and the timestamp of the Command submission. 3277391c2a01ce1fed085906743cc240a4d58edd92chrismair * <p> 3377391c2a01ce1fed085906743cc240a4d58edd92chrismair * This class also supports storing zero or more arbitrary mappings of <i>key</i> to value, where <i>key</i> is 3477391c2a01ce1fed085906743cc240a4d58edd92chrismair * a String and <i>value</i> is any Object. Convenience methods are provided that enable retrieving 3577391c2a01ce1fed085906743cc240a4d58edd92chrismair * type-specific data by its <i>key</i>. The data stored in an {@link InvocationRecord} is CommandHandler-specific. 3677391c2a01ce1fed085906743cc240a4d58edd92chrismair * <p> 3777391c2a01ce1fed085906743cc240a4d58edd92chrismair * The {@link #lock()} method makes an instance of this class immutable. After an instance is locked, 3877391c2a01ce1fed085906743cc240a4d58edd92chrismair * calling the {@link #set(String, Object)} method will throw an <code>AssertFailedException</code>. 3977391c2a01ce1fed085906743cc240a4d58edd92chrismair * 4077391c2a01ce1fed085906743cc240a4d58edd92chrismair * @version $Revision$ - $Date$ 4177391c2a01ce1fed085906743cc240a4d58edd92chrismair * 4277391c2a01ce1fed085906743cc240a4d58edd92chrismair * @author Chris Mair 4377391c2a01ce1fed085906743cc240a4d58edd92chrismair */ 4477391c2a01ce1fed085906743cc240a4d58edd92chrismairpublic class InvocationRecord { 4577391c2a01ce1fed085906743cc240a4d58edd92chrismair 4677391c2a01ce1fed085906743cc240a4d58edd92chrismair private Command command; 4777391c2a01ce1fed085906743cc240a4d58edd92chrismair private Date time; 4877391c2a01ce1fed085906743cc240a4d58edd92chrismair private InetAddress clientHost; 4977391c2a01ce1fed085906743cc240a4d58edd92chrismair private Map data = new HashMap(); 5077391c2a01ce1fed085906743cc240a4d58edd92chrismair private boolean locked = false; 5177391c2a01ce1fed085906743cc240a4d58edd92chrismair 5277391c2a01ce1fed085906743cc240a4d58edd92chrismair /** 5377391c2a01ce1fed085906743cc240a4d58edd92chrismair * Create a new instance 5477391c2a01ce1fed085906743cc240a4d58edd92chrismair * @param command - the Command 5577391c2a01ce1fed085906743cc240a4d58edd92chrismair * @param clientHost - the client host 5677391c2a01ce1fed085906743cc240a4d58edd92chrismair */ 5777391c2a01ce1fed085906743cc240a4d58edd92chrismair public InvocationRecord(Command command, InetAddress clientHost) { 5877391c2a01ce1fed085906743cc240a4d58edd92chrismair this.command = command; 5977391c2a01ce1fed085906743cc240a4d58edd92chrismair this.time = new Date(); 6077391c2a01ce1fed085906743cc240a4d58edd92chrismair this.clientHost = clientHost; 6177391c2a01ce1fed085906743cc240a4d58edd92chrismair } 6277391c2a01ce1fed085906743cc240a4d58edd92chrismair 6377391c2a01ce1fed085906743cc240a4d58edd92chrismair /** 6477391c2a01ce1fed085906743cc240a4d58edd92chrismair * Lock this instance, making it immutable. After an instance is locked, 6577391c2a01ce1fed085906743cc240a4d58edd92chrismair * calling the {@link #set(String, Object)} method will throw an 6677391c2a01ce1fed085906743cc240a4d58edd92chrismair * <code>AssertFailedException</code>. 6777391c2a01ce1fed085906743cc240a4d58edd92chrismair */ 6877391c2a01ce1fed085906743cc240a4d58edd92chrismair public void lock() { 6977391c2a01ce1fed085906743cc240a4d58edd92chrismair locked = true; 7077391c2a01ce1fed085906743cc240a4d58edd92chrismair } 7177391c2a01ce1fed085906743cc240a4d58edd92chrismair 7277391c2a01ce1fed085906743cc240a4d58edd92chrismair /** 7377391c2a01ce1fed085906743cc240a4d58edd92chrismair * Return true if this object has been locked, false otherwise. See {@link #lock()}. 7477391c2a01ce1fed085906743cc240a4d58edd92chrismair * @return true if this object has been locked, false otherwise. 7577391c2a01ce1fed085906743cc240a4d58edd92chrismair */ 7677391c2a01ce1fed085906743cc240a4d58edd92chrismair public boolean isLocked() { 7777391c2a01ce1fed085906743cc240a4d58edd92chrismair return locked; 7877391c2a01ce1fed085906743cc240a4d58edd92chrismair } 7977391c2a01ce1fed085906743cc240a4d58edd92chrismair 8077391c2a01ce1fed085906743cc240a4d58edd92chrismair /** 8177391c2a01ce1fed085906743cc240a4d58edd92chrismair * @return the client host that submitted the command, as an InetAddress 8277391c2a01ce1fed085906743cc240a4d58edd92chrismair */ 8377391c2a01ce1fed085906743cc240a4d58edd92chrismair public InetAddress getClientHost() { 8477391c2a01ce1fed085906743cc240a4d58edd92chrismair return clientHost; 8577391c2a01ce1fed085906743cc240a4d58edd92chrismair } 8677391c2a01ce1fed085906743cc240a4d58edd92chrismair 8777391c2a01ce1fed085906743cc240a4d58edd92chrismair /** 8877391c2a01ce1fed085906743cc240a4d58edd92chrismair * @return the Command 8977391c2a01ce1fed085906743cc240a4d58edd92chrismair */ 9077391c2a01ce1fed085906743cc240a4d58edd92chrismair public Command getCommand() { 9177391c2a01ce1fed085906743cc240a4d58edd92chrismair return command; 9277391c2a01ce1fed085906743cc240a4d58edd92chrismair } 9377391c2a01ce1fed085906743cc240a4d58edd92chrismair 9477391c2a01ce1fed085906743cc240a4d58edd92chrismair /** 9577391c2a01ce1fed085906743cc240a4d58edd92chrismair * @return the time that the command was processed; this may differ slightly from when the command was received. 9677391c2a01ce1fed085906743cc240a4d58edd92chrismair */ 9777391c2a01ce1fed085906743cc240a4d58edd92chrismair public Date getTime() { 9877391c2a01ce1fed085906743cc240a4d58edd92chrismair // Return a copy of the Date object to preserve immutability 9977391c2a01ce1fed085906743cc240a4d58edd92chrismair return new Date(time.getTime()); 10077391c2a01ce1fed085906743cc240a4d58edd92chrismair } 10177391c2a01ce1fed085906743cc240a4d58edd92chrismair 10277391c2a01ce1fed085906743cc240a4d58edd92chrismair /** 10377391c2a01ce1fed085906743cc240a4d58edd92chrismair * Store the value for the specified key. If this object already contained a mapping 10477391c2a01ce1fed085906743cc240a4d58edd92chrismair * for this key, the old value is replaced by the specified value. This method throws 10577391c2a01ce1fed085906743cc240a4d58edd92chrismair * an <code>AssertFailedException</code> if this object has been locked. See {@link #lock()}. 10677391c2a01ce1fed085906743cc240a4d58edd92chrismair * 10777391c2a01ce1fed085906743cc240a4d58edd92chrismair * @param key - the key; must not be null 10877391c2a01ce1fed085906743cc240a4d58edd92chrismair * @param value - the value to store for the specified key 10977391c2a01ce1fed085906743cc240a4d58edd92chrismair * 11077391c2a01ce1fed085906743cc240a4d58edd92chrismair * @throws AssertFailedException - if the key is null or this object has been locked. 11177391c2a01ce1fed085906743cc240a4d58edd92chrismair */ 11277391c2a01ce1fed085906743cc240a4d58edd92chrismair public void set(String key, Object value) { 11377391c2a01ce1fed085906743cc240a4d58edd92chrismair Assert.notNull(key, "key"); 11477391c2a01ce1fed085906743cc240a4d58edd92chrismair Assert.isFalse(locked, "The InvocationRecord is locked!"); 11577391c2a01ce1fed085906743cc240a4d58edd92chrismair data.put(key, value); 11677391c2a01ce1fed085906743cc240a4d58edd92chrismair } 11777391c2a01ce1fed085906743cc240a4d58edd92chrismair 11877391c2a01ce1fed085906743cc240a4d58edd92chrismair /** 11977391c2a01ce1fed085906743cc240a4d58edd92chrismair * Returns <code>true</code> if this object contains a mapping for the specified key. 12077391c2a01ce1fed085906743cc240a4d58edd92chrismair * 12177391c2a01ce1fed085906743cc240a4d58edd92chrismair * @param key - the key; must not be null 12277391c2a01ce1fed085906743cc240a4d58edd92chrismair * @return <code>true</code> if there is a mapping for the key 12377391c2a01ce1fed085906743cc240a4d58edd92chrismair * 12477391c2a01ce1fed085906743cc240a4d58edd92chrismair * @throws AssertFailedException - if the key is null 12577391c2a01ce1fed085906743cc240a4d58edd92chrismair */ 12677391c2a01ce1fed085906743cc240a4d58edd92chrismair public boolean containsKey(String key) { 12777391c2a01ce1fed085906743cc240a4d58edd92chrismair Assert.notNull(key, "key"); 12877391c2a01ce1fed085906743cc240a4d58edd92chrismair return data.containsKey(key); 12977391c2a01ce1fed085906743cc240a4d58edd92chrismair } 13077391c2a01ce1fed085906743cc240a4d58edd92chrismair 13177391c2a01ce1fed085906743cc240a4d58edd92chrismair /** 13277391c2a01ce1fed085906743cc240a4d58edd92chrismair * Returns a Set view of the keys for the data stored in this object. 13377391c2a01ce1fed085906743cc240a4d58edd92chrismair * Changes to the returned Set have no effect on the data stored within this object 13477391c2a01ce1fed085906743cc240a4d58edd92chrismair * . 13577391c2a01ce1fed085906743cc240a4d58edd92chrismair * @return the Set of keys for the data stored within this object 13677391c2a01ce1fed085906743cc240a4d58edd92chrismair */ 13777391c2a01ce1fed085906743cc240a4d58edd92chrismair public Set keySet() { 13877391c2a01ce1fed085906743cc240a4d58edd92chrismair return Collections.unmodifiableSet(data.keySet()); 13977391c2a01ce1fed085906743cc240a4d58edd92chrismair } 14077391c2a01ce1fed085906743cc240a4d58edd92chrismair 14177391c2a01ce1fed085906743cc240a4d58edd92chrismair /** 14277391c2a01ce1fed085906743cc240a4d58edd92chrismair * Get the String value associated with the specified key. Returns null if there is 14377391c2a01ce1fed085906743cc240a4d58edd92chrismair * no mapping for this key. A return value of null does not necessarily indicate that 14477391c2a01ce1fed085906743cc240a4d58edd92chrismair * this object contains no mapping for the key; it's also possible that the value was 14577391c2a01ce1fed085906743cc240a4d58edd92chrismair * explicitly set to null for the key. The containsKey operation may be used to 14677391c2a01ce1fed085906743cc240a4d58edd92chrismair * distinguish these two cases. 14777391c2a01ce1fed085906743cc240a4d58edd92chrismair * 14877391c2a01ce1fed085906743cc240a4d58edd92chrismair * @param key - the key; must not be null 14977391c2a01ce1fed085906743cc240a4d58edd92chrismair * @return the String data stored at the specified key; may be null 15077391c2a01ce1fed085906743cc240a4d58edd92chrismair * 15177391c2a01ce1fed085906743cc240a4d58edd92chrismair * @throws ClassCastException - if the object for the specified key is not a String 15277391c2a01ce1fed085906743cc240a4d58edd92chrismair * @throws AssertFailedException - if the key is null 15377391c2a01ce1fed085906743cc240a4d58edd92chrismair */ 15477391c2a01ce1fed085906743cc240a4d58edd92chrismair public String getString(String key) { 15577391c2a01ce1fed085906743cc240a4d58edd92chrismair Assert.notNull(key, "key"); 15677391c2a01ce1fed085906743cc240a4d58edd92chrismair return (String) data.get(key); 15777391c2a01ce1fed085906743cc240a4d58edd92chrismair } 15877391c2a01ce1fed085906743cc240a4d58edd92chrismair 15977391c2a01ce1fed085906743cc240a4d58edd92chrismair /** 16077391c2a01ce1fed085906743cc240a4d58edd92chrismair * Get the Object value associated with the specified key. Returns null if there is 16177391c2a01ce1fed085906743cc240a4d58edd92chrismair * no mapping for this key. A return value of null does not necessarily indicate that 16277391c2a01ce1fed085906743cc240a4d58edd92chrismair * this object contains no mapping for the key; it's also possible that the value was 16377391c2a01ce1fed085906743cc240a4d58edd92chrismair * explicitly set to null for the key. The containsKey operation may be used to 16477391c2a01ce1fed085906743cc240a4d58edd92chrismair * distinguish these two cases. 16577391c2a01ce1fed085906743cc240a4d58edd92chrismair * 16677391c2a01ce1fed085906743cc240a4d58edd92chrismair * @param key - the key; must not be null 16777391c2a01ce1fed085906743cc240a4d58edd92chrismair * @return the data stored at the specified key, as an Object; may be null 16877391c2a01ce1fed085906743cc240a4d58edd92chrismair * 16977391c2a01ce1fed085906743cc240a4d58edd92chrismair * @throws AssertFailedException - if the key is null 17077391c2a01ce1fed085906743cc240a4d58edd92chrismair */ 17177391c2a01ce1fed085906743cc240a4d58edd92chrismair public Object getObject(String key) { 17277391c2a01ce1fed085906743cc240a4d58edd92chrismair Assert.notNull(key, "key"); 17377391c2a01ce1fed085906743cc240a4d58edd92chrismair return data.get(key); 17477391c2a01ce1fed085906743cc240a4d58edd92chrismair } 17577391c2a01ce1fed085906743cc240a4d58edd92chrismair 17677391c2a01ce1fed085906743cc240a4d58edd92chrismair /** 17777391c2a01ce1fed085906743cc240a4d58edd92chrismair * Return the String representation of this object 17877391c2a01ce1fed085906743cc240a4d58edd92chrismair * @see java.lang.Object#toString() 17977391c2a01ce1fed085906743cc240a4d58edd92chrismair */ 18077391c2a01ce1fed085906743cc240a4d58edd92chrismair public String toString() { 18177391c2a01ce1fed085906743cc240a4d58edd92chrismair return "InvocationRecord[time=" + time + " client-host=" + clientHost + " command=" + command + " data="+ data + "]"; 18277391c2a01ce1fed085906743cc240a4d58edd92chrismair } 18377391c2a01ce1fed085906743cc240a4d58edd92chrismair} 184