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