1 /* 2 * Copyright 2009 Mike Cumings 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.kenai.jbosh; 18 19 import java.util.HashMap; 20 import java.util.Map; 21 22 /** 23 * Terminal binding conditions and their associated messages. 24 */ 25 final class TerminalBindingCondition { 26 27 /** 28 * Map of condition names to condition instances. 29 */ 30 private static final Map<String, TerminalBindingCondition> 31 COND_TO_INSTANCE = new HashMap<String, TerminalBindingCondition>(); 32 33 /** 34 * Map of HTTP response codes to condition instances. 35 */ 36 private static final Map<Integer, TerminalBindingCondition> 37 CODE_TO_INSTANCE = new HashMap<Integer, TerminalBindingCondition>(); 38 39 static final TerminalBindingCondition BAD_REQUEST = 40 createWithCode("bad-request", "The format of an HTTP header or " 41 + "binding element received from the client is unacceptable " 42 + "(e.g., syntax error).", Integer.valueOf(400)); 43 44 static final TerminalBindingCondition HOST_GONE = 45 create("host-gone", "The target domain specified in the 'to' " 46 + "attribute or the target host or port specified in the 'route' " 47 + "attribute is no longer serviced by the connection manager."); 48 49 static final TerminalBindingCondition HOST_UNKNOWN = 50 create("host-unknown", "The target domain specified in the 'to' " 51 + "attribute or the target host or port specified in the 'route' " 52 + "attribute is unknown to the connection manager."); 53 54 static final TerminalBindingCondition IMPROPER_ADDRESSING = 55 create("improper-addressing", "The initialization element lacks a " 56 + "'to' or 'route' attribute (or the attribute has no value) but " 57 + "the connection manager requires one."); 58 59 static final TerminalBindingCondition INTERNAL_SERVER_ERROR = 60 create("internal-server-error", "The connection manager has " 61 + "experienced an internal error that prevents it from servicing " 62 + "the request."); 63 64 static final TerminalBindingCondition ITEM_NOT_FOUND = 65 createWithCode("item-not-found", "(1) 'sid' is not valid, (2) " 66 + "'stream' is not valid, (3) 'rid' is larger than the upper limit " 67 + "of the expected window, (4) connection manager is unable to " 68 + "resend response, (5) 'key' sequence is invalid.", 69 Integer.valueOf(404)); 70 71 static final TerminalBindingCondition OTHER_REQUEST = 72 create("other-request", "Another request being processed at the " 73 + "same time as this request caused the session to terminate."); 74 75 static final TerminalBindingCondition POLICY_VIOLATION = 76 createWithCode("policy-violation", "The client has broken the " 77 + "session rules (polling too frequently, requesting too " 78 + "frequently, sending too many simultaneous requests).", 79 Integer.valueOf(403)); 80 81 static final TerminalBindingCondition REMOTE_CONNECTION_FAILED = 82 create("remote-connection-failed", "The connection manager was " 83 + "unable to connect to, or unable to connect securely to, or has " 84 + "lost its connection to, the server."); 85 86 static final TerminalBindingCondition REMOTE_STREAM_ERROR = 87 create("remote-stream-error", "Encapsulated transport protocol " 88 + "error."); 89 90 static final TerminalBindingCondition SEE_OTHER_URI = 91 create("see-other-uri", "The connection manager does not operate " 92 + "at this URI (e.g., the connection manager accepts only SSL or " 93 + "TLS connections at some https: URI rather than the http: URI " 94 + "requested by the client)."); 95 96 static final TerminalBindingCondition SYSTEM_SHUTDOWN = 97 create("system-shutdown", "The connection manager is being shut " 98 + "down. All active HTTP sessions are being terminated. No new " 99 + "sessions can be created."); 100 101 static final TerminalBindingCondition UNDEFINED_CONDITION = 102 create("undefined-condition", "Unknown or undefined error " 103 + "condition."); 104 105 /** 106 * Condition name. 107 */ 108 private final String cond; 109 110 /** 111 * Descriptive message. 112 */ 113 private final String msg; 114 115 /** 116 * Private constructor to pre 117 */ 118 private TerminalBindingCondition( 119 final String condition, 120 final String message) { 121 cond = condition; 122 msg = message; 123 } 124 125 /** 126 * Helper method to call the helper method to add entries. 127 */ 128 private static TerminalBindingCondition create( 129 final String condition, 130 final String message) { 131 return createWithCode(condition, message, null); 132 } 133 134 /** 135 * Helper method to add entries. 136 */ 137 private static TerminalBindingCondition createWithCode( 138 final String condition, 139 final String message, 140 final Integer code) { 141 if (condition == null) { 142 throw(new IllegalArgumentException( 143 "condition may not be null")); 144 } 145 if (message == null) { 146 throw(new IllegalArgumentException( 147 "message may not be null")); 148 } 149 if (COND_TO_INSTANCE.get(condition) != null) { 150 throw(new IllegalStateException( 151 "Multiple definitions of condition: " + condition)); 152 } 153 TerminalBindingCondition result = 154 new TerminalBindingCondition(condition, message); 155 COND_TO_INSTANCE.put(condition, result); 156 if (code != null) { 157 if (CODE_TO_INSTANCE.get(code) != null) { 158 throw(new IllegalStateException( 159 "Multiple definitions of code: " + code)); 160 } 161 CODE_TO_INSTANCE.put(code, result); 162 } 163 return result; 164 } 165 166 /** 167 * Lookup the terminal binding condition instance with the condition 168 * name specified. 169 * 170 * @param condStr condition name 171 * @return terminal binding condition instance, or {@code null} if no 172 * instance is known by the name specified 173 */ 174 static TerminalBindingCondition forString(final String condStr) { 175 return COND_TO_INSTANCE.get(condStr); 176 } 177 178 /** 179 * Lookup the terminal binding condition instance associated with the 180 * HTTP response code specified. 181 * 182 * @param httpRespCode HTTP response code 183 * @return terminal binding condition instance, or {@code null} if no 184 * instance is known by the response code specified 185 */ 186 static TerminalBindingCondition forHTTPResponseCode(final int httpRespCode) { 187 return CODE_TO_INSTANCE.get(Integer.valueOf(httpRespCode)); 188 } 189 190 /** 191 * Get the name of the condition. 192 * 193 * @return condition name 194 */ 195 String getCondition() { 196 return cond; 197 } 198 199 /** 200 * Get the human readable error message associated with this condition. 201 * 202 * @return error message 203 */ 204 String getMessage() { 205 return msg; 206 } 207 208 } 209