1c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair/* 2c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * Copyright 20078 the original author or authors. 3c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * 4c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * Licensed under the Apache License, Version 2.0 (the "License"); 5c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * you may not use this file except in compliance with the License. 6c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * You may obtain a copy of the License at 7c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * 8c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * http://www.apache.org/licenses/LICENSE-2.0 9c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * 10c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * Unless required by applicable law or agreed to in writing, software 11c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * distributed under the License is distributed on an "AS IS" BASIS, 12c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * See the License for the specific language governing permissions and 14c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * limitations under the License. 15c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair */ 16c1de24f1bfa6699e54b069e300af5e4246b34a34chrismairpackage org.mockftpserver.core.command; 17c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair 18c1de24f1bfa6699e54b069e300af5e4246b34a34chrismairimport org.mockftpserver.core.CommandSyntaxException; 19c1de24f1bfa6699e54b069e300af5e4246b34a34chrismairimport org.mockftpserver.core.util.Assert; 20c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair 21c1de24f1bfa6699e54b069e300af5e4246b34a34chrismairimport java.util.Arrays; 22c1de24f1bfa6699e54b069e300af5e4246b34a34chrismairimport java.util.List; 23c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair 24c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair/** 25c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * Represents a command received from an FTP client, containing a command name and parameters. 26c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * Objects of this class are immutable. 27c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * 28c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * @author Chris Mair 29c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * @version $Revision$ - $Date$ 30c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair */ 31c1de24f1bfa6699e54b069e300af5e4246b34a34chrismairpublic final class Command { 32c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair 33c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair private String name; 34c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair private String[] parameters; 35c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair 36c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair /** 37c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * Construct a new immutable instance with the specified command name and parameters 38c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * 39c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * @param name - the command name; may not be null 40c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * @param parameters - the command parameters; may be empty; may not be null 41c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair */ 42c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair public Command(String name, String[] parameters) { 43c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair Assert.notNull(name, "name"); 44c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair Assert.notNull(parameters, "parameters"); 45c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair this.name = name; 46c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair this.parameters = copy(parameters); 47c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair } 48c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair 49c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair /** 50c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * Construct a new immutable instance with the specified command name and parameters 51c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * 52c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * @param name - the command name; may not be null 53c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * @param parameters - the command parameters; may be empty; may not be null 54c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair */ 55c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair public Command(String name, List parameters) { 56c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair this(name, (String[]) parameters.toArray(new String[parameters.size()])); 57c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair } 58c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair 59c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair /** 60c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * @return the name 61c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair */ 62c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair public String getName() { 63c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair return name; 64c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair } 65c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair 66c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair /** 67c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * @return the parameters 68c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair */ 69c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair public String[] getParameters() { 70c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair return copy(parameters); 71c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair } 72c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair 73c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair /** 74c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * Get the String value of the parameter at the specified index 75c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * 76c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * @param index - the index 77c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * @return the parameter value as a String 78c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * @throws org.mockftpserver.core.util.AssertFailedException 79c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * if the parameter index is invalid or the value is not a valid String 80c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair */ 81c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair public String getRequiredParameter(int index) { 82c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair assertValidIndex(index); 83c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair return parameters[index]; 84c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair } 85c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair 86c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair /** 87c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * Get the String value of the parameter at the specified index; return null if no parameter exists for the index 88c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * 89c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * @param index - the index 90c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * @return the parameter value as a String, or null if this Command does not have a parameter for that index 91c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair */ 92c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair public String getParameter(int index) { 93c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair return (parameters.length > index) ? parameters[index] : null; 94c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair } 95c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair 96c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair /** 97c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * Get the String value of the parameter at the specified index; return null if no 98c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * parameter exists for the index. This is an alias for {@link #getParameter(int)}. 99c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * 100c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * @param index - the index 101c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * @return the parameter value as a String, or null if this Command does not have a parameter for that index 102c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair */ 103c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair public String getOptionalString(int index) { 104c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair return getParameter(index); 105c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair } 106c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair 107c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair /** 108c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * @see java.lang.Object#equals(java.lang.Object) 109c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair */ 110c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair public boolean equals(Object obj) { 111c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair if (this == obj) { 112c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair return true; 113c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair } 114c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair if (obj == null || !(obj instanceof Command)) { 115c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair return false; 116c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair } 117c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair return this.hashCode() == obj.hashCode(); 118c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair } 119c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair 120c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair /** 121c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * @see java.lang.Object#hashCode() 122c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair */ 123c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair public int hashCode() { 124c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair String str = name + Arrays.asList(parameters); 125c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair return str.hashCode(); 126c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair } 127c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair 128c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair /** 129c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * Return the String representation of this object 130c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * 131c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * @see java.lang.Object#toString() 132c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair */ 133c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair public String toString() { 134c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair return "Command[" + name + ":" + Arrays.asList(parameters) + "]"; 135c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair } 136c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair 137c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair /** 138c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * Return the name, normalized to a common format - convert to upper case. 139c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * 140c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * @return the name converted to upper case 141c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair */ 142c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair public static String normalizeName(String name) { 143c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair return name.toUpperCase(); 144c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair } 145c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair 146c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair /** 147c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * Construct a shallow copy of the specified array 148c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * 149c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * @param array - the array to copy 150c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * @return a new array with the same contents 151c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair */ 152c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair private static String[] copy(String[] array) { 153c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair String[] newArray = new String[array.length]; 154c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair System.arraycopy(array, 0, newArray, 0, array.length); 155c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair return newArray; 156c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair } 157c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair 158c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair /** 159c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * Assert that the index is valid 160c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * 161c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * @param index - the index 162c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * @throws org.mockftpserver.core.CommandSyntaxException 163c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * - if the parameter index is invalid 164c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair */ 165c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair private void assertValidIndex(int index) { 166c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair if (index < 0 || index >= parameters.length) { 167c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair throw new CommandSyntaxException("The parameter index " + index + " is not valid for " + this); 168c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair } 169c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair } 170c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair 171c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair} 172