001: /*
002: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright
003: * notice. All rights reserved.
004: */
005: package com.tc.net.protocol.tcm;
006:
007: import com.tc.exception.TCRuntimeException;
008: import com.tc.logging.TCLogger;
009: import com.tc.logging.TCLogging;
010: import com.tc.util.Util;
011:
012: import gnu.trove.TIntObjectHashMap;
013:
014: import java.lang.reflect.Field;
015: import java.lang.reflect.Modifier;
016: import java.util.Arrays;
017: import java.util.Comparator;
018: import java.util.HashMap;
019: import java.util.Iterator;
020: import java.util.Map;
021:
022: /**
023: * Define all the various TC Message type numbers.
024: */
025:
026: public final class TCMessageType {
027: // //////////////////////////////////////////////
028: // NOTE: Never recycle these numbers, always add a new constant
029: // //////////////////////////////////////////////
030: public static final int TYPE_PING_MESSAGE = 1;
031: public static final int TYPE_PONG_MESSAGE = 2;
032: public static final int TYPE_REQUEST_ROOT_MESSAGE = 8;
033: public static final int TYPE_LOCK_REQUEST_MESSAGE = 9;
034: public static final int TYPE_COMMIT_TRANSACTION_MESSAGE = 10;
035: public static final int TYPE_REQUEST_ROOT_RESPONSE_MESSAGE = 11;
036: public static final int TYPE_REQUEST_MANAGED_OBJECT_MESSAGE = 12;
037: public static final int TYPE_REQUEST_MANAGED_OBJECT_RESPONSE_MESSAGE = 13;
038: public static final int TYPE_BROADCAST_TRANSACTION_MESSAGE = 14;
039: public static final int TYPE_OBJECT_ID_BATCH_REQUEST_MESSAGE = 18;
040: public static final int TYPE_OBJECT_ID_BATCH_REQUEST_RESPONSE_MESSAGE = 19;
041: public static final int TYPE_ACKNOWLEDGE_TRANSACTION_MESSAGE = 24;
042: public static final int TYPE_LOCK_RESPONSE_MESSAGE = 26;
043: public static final int TYPE_CLIENT_HANDSHAKE_MESSAGE = 28;
044: public static final int TYPE_BATCH_TRANSACTION_ACK_MESSAGE = 29;
045: public static final int TYPE_CLIENT_HANDSHAKE_ACK_MESSAGE = 30;
046: public static final int TYPE_CONFIG_PUSH_MESSAGE = 31;
047: public static final int TYPE_OVERRIDE_APPLICATION_CONFIG_MESSAGE = 32;
048: public static final int TYPE_LOCK_RECALL_MESSAGE = 33;
049: public static final int TYPE_JMX_MESSAGE = 34;
050: public static final int TYPE_LOCK_QUERY_RESPONSE_MESSAGE = 35;
051: public static final int TYPE_JMXREMOTE_MESSAGE_CONNECTION_MESSAGE = 36;
052: public static final int TYPE_MEMORY_DATA_STORE_REQUEST_MESSAGE = 37;
053: public static final int TYPE_MEMORY_DATA_STORE_RESPONSE_MESSAGE = 38;
054: public static final int TYPE_CLUSTER_MEMBERSHIP_EVENT_MESSAGE = 39;
055: public static final int TYPE_CLIENT_JMX_READY_MESSAGE = 40;
056: public static final int TYPE_OBJECTS_NOT_FOUND_RESPONSE_MESSAGE = 41;
057: public static final int TYPE_BENCH_MESSAGE = 42;
058: public static final int TYPE_LOCK_STAT_MESSAGE = 43;
059: public static final int TYPE_LOCK_STATISTICS_RESPONSE_MESSAGE = 44;
060: public static final int TYPE_COMPLETED_TRANSACTION_LOWWATERMARK_MESSAGE = 45;
061:
062: public static final TCMessageType PING_MESSAGE = new TCMessageType();
063: public static final TCMessageType PONG_MESSAGE = new TCMessageType();
064: public static final TCMessageType REQUEST_ROOT_MESSAGE = new TCMessageType();
065: public static final TCMessageType LOCK_REQUEST_MESSAGE = new TCMessageType();
066: public static final TCMessageType LOCK_RECALL_MESSAGE = new TCMessageType();
067: public static final TCMessageType LOCK_RESPONSE_MESSAGE = new TCMessageType();
068: public static final TCMessageType LOCK_QUERY_RESPONSE_MESSAGE = new TCMessageType();
069: public static final TCMessageType LOCK_STAT_MESSAGE = new TCMessageType();
070: public static final TCMessageType LOCK_STATISTICS_RESPONSE_MESSAGE = new TCMessageType();
071: public static final TCMessageType COMMIT_TRANSACTION_MESSAGE = new TCMessageType();
072: public static final TCMessageType REQUEST_ROOT_RESPONSE_MESSAGE = new TCMessageType();
073: public static final TCMessageType REQUEST_MANAGED_OBJECT_MESSAGE = new TCMessageType();
074: public static final TCMessageType REQUEST_MANAGED_OBJECT_RESPONSE_MESSAGE = new TCMessageType();
075: public static final TCMessageType BROADCAST_TRANSACTION_MESSAGE = new TCMessageType();
076: public static final TCMessageType OBJECT_ID_BATCH_REQUEST_MESSAGE = new TCMessageType();
077: public static final TCMessageType OBJECT_ID_BATCH_REQUEST_RESPONSE_MESSAGE = new TCMessageType();
078: public static final TCMessageType ACKNOWLEDGE_TRANSACTION_MESSAGE = new TCMessageType();
079: public static final TCMessageType CLIENT_HANDSHAKE_MESSAGE = new TCMessageType();
080: public static final TCMessageType CLIENT_HANDSHAKE_ACK_MESSAGE = new TCMessageType();
081: public static final TCMessageType BATCH_TRANSACTION_ACK_MESSAGE = new TCMessageType();
082: public static final TCMessageType CONFIG_PUSH_MESSAGE = new TCMessageType();
083: public static final TCMessageType OVERRIDE_APPLICATION_CONFIG_MESSAGE = new TCMessageType();
084: public static final TCMessageType JMX_MESSAGE = new TCMessageType();
085: public static final TCMessageType JMXREMOTE_MESSAGE_CONNECTION_MESSAGE = new TCMessageType();
086: public static final TCMessageType MEMORY_DATA_STORE_REQUEST_MESSAGE = new TCMessageType();
087: public static final TCMessageType MEMORY_DATA_STORE_RESPONSE_MESSAGE = new TCMessageType();
088: public static final TCMessageType CLUSTER_MEMBERSHIP_EVENT_MESSAGE = new TCMessageType();
089: public static final TCMessageType CLIENT_JMX_READY_MESSAGE = new TCMessageType();
090: public static final TCMessageType OBJECTS_NOT_FOUND_RESPONSE_MESSAGE = new TCMessageType();
091: public static final TCMessageType BENCH_MESSAGE = new TCMessageType();
092: public static final TCMessageType COMPLETED_TRANSACTION_LOWWATERMARK_MESSAGE = new TCMessageType();
093:
094: public static TCMessageType getInstance(int i) {
095: return (TCMessageType) typeMap.get(i);
096: }
097:
098: public static TCMessageType[] getAllMessageTypes() {
099: return (TCMessageType[]) allTypes.clone();
100: }
101:
102: public int getType() {
103: return type;
104: }
105:
106: public String getTypeName() {
107: return typeName;
108: }
109:
110: public String toString() {
111: return typeName + " (" + type + ")";
112: }
113:
114: // //////////////////////////////////////////////////////
115: //
116: // ******** You need not modify anything below *********
117: //
118: // //////////////////////////////////////////////////////
119: private static final TCLogger logger = TCLogging
120: .getLogger(TCMessageType.class);
121: private static final TIntObjectHashMap typeMap = new TIntObjectHashMap();
122: private static final TCMessageType[] allTypes;
123: private static final String typePrefix = "TYPE_";
124:
125: private int type;
126: private String typeName;
127:
128: private TCMessageType() {
129: // type and name are set automagically in init()
130: }
131:
132: private void setType(int type) {
133: this .type = type;
134: }
135:
136: private void setTypeName(String typeName) {
137: this .typeName = typeName;
138: }
139:
140: public int hashCode() {
141: return this .typeName.hashCode() + type;
142: }
143:
144: public boolean equals(Object obj) {
145: if (obj instanceof TCMessageType) {
146: TCMessageType other = (TCMessageType) obj;
147: return this .typeName.equals(other.typeName)
148: && (this .type == other.type);
149: }
150: return false;
151: }
152:
153: /**
154: * do some sanity checking on all the defined message types. Hopefully we'll catch duplicate message numbers early at
155: * development time. If somehow a compiler introduces funny public static final fields in this class, then one can add
156: * additional checks for naming conventions for the message types. Or maybe we shouldn't try to be smart about
157: * validating the message type numbers dynamically. Maybe I need more some coffee
158: */
159: private static TCMessageType[] init()
160: throws IllegalArgumentException, IllegalAccessException {
161: Field[] fields = TCMessageType.class.getDeclaredFields();
162:
163: Map mtFields = new HashMap();
164: Map intFields = new HashMap();
165:
166: for (int i = 0; i < fields.length; i++) {
167: final Field field = fields[i];
168: final String fName = field.getName();
169:
170: int modifiers = field.getModifiers();
171:
172: // disallow public non-final fields
173: if (Modifier.isPublic(modifiers)
174: && !Modifier.isFinal(modifiers)) {
175: throw new RuntimeException("TCMessageType: " + fName
176: + " must be final if public");
177: }
178:
179: boolean shouldInspect = Modifier.isPublic(modifiers)
180: && Modifier.isStatic(modifiers)
181: && Modifier.isFinal(modifiers);
182:
183: if (!shouldInspect) {
184: continue;
185: }
186:
187: if (field.getType().equals(TCMessageType.class)) {
188: if (!fName.toUpperCase().equals(fName)) {
189: // make formatter sane
190: throw new RuntimeException(
191: "TCMessageType: Message type names must be all UPPER CASE: "
192: + fName);
193: }
194:
195: if (fName.startsWith("_")) {
196: // make formatter sane
197: throw new RuntimeException(
198: "TCMessageType: Message type cannot start with underscore: "
199: + fName);
200: }
201:
202: mtFields.put(fName, field);
203: } else if (field.getType().equals(Integer.TYPE)) {
204: if (!fName.startsWith(typePrefix)) {
205: // <Hi there> If this is being thrown, you probably added an oddly
206: // named static final integer to this class
207: throw new RuntimeException(
208: "TCMessageType: Illegal integer field name: "
209: + fName);
210: }
211:
212: Integer value = (Integer) field
213: .get(TCMessageType.class);
214:
215: intFields.put(fName, value);
216: }
217: }
218:
219: for (final Iterator iter = mtFields.values().iterator(); iter
220: .hasNext();) {
221: final Field field = (Field) iter.next();
222: final String name = field.getName();
223: final TCMessageType type = (TCMessageType) field
224: .get(TCMessageType.class);
225:
226: final String intName = typePrefix + name;
227: if (!intFields.containsKey(intName)) {
228: // make formatter sane
229: throw new RuntimeException("TCMessageType: Missing "
230: + intName + " integer constant");
231: }
232:
233: final int val = ((Integer) intFields.remove(intName))
234: .intValue();
235:
236: type.setType(val);
237: type.setTypeName(name);
238:
239: Object prev = typeMap.put(type.getType(), type);
240: if (prev != null) {
241: // make formatter sane
242: throw new RuntimeException(
243: "TCMessageType: Duplicate message types defined for message number: "
244: + type.getType());
245: }
246:
247: iter.remove();
248: }
249:
250: if (!mtFields.isEmpty()) {
251: // make formatter sane
252: throw new RuntimeException(
253: "TCMessageType: internal error - not all message types filled in");
254: }
255:
256: if (!intFields.isEmpty()) {
257: String unused = Util.enumerateArray(intFields.keySet()
258: .toArray());
259: throw new RuntimeException(
260: "TCMessageType: Unused integer constants (please remove): "
261: + unused);
262: }
263:
264: final TCMessageType[] rv = new TCMessageType[typeMap.size()];
265: System.arraycopy(typeMap.getValues(), 0, rv, 0, rv.length);
266:
267: Arrays.sort(rv, new Comparator() {
268: public int compare(Object o1, Object o2) {
269: int i1 = ((TCMessageType) o1).getType();
270: int i2 = ((TCMessageType) o2).getType();
271:
272: if (i1 < i2) {
273: return -1;
274: } else if (i1 == i2) {
275: return 0;
276: } else if (i1 > i2) {
277: return 1;
278: } else {
279: throw new RuntimeException("internal error");
280: }
281: }
282: });
283:
284: if (logger.isDebugEnabled()) {
285: logger.debug(Util.enumerateArray(rv));
286: }
287:
288: return rv;
289: }
290:
291: static {
292: try {
293: allTypes = init();
294: } catch (Exception e) {
295: e.printStackTrace();
296: throw new TCRuntimeException(e);
297: }
298: }
299:
300: }
|