001 /*
002 *
003 * Licensed to the Apache Software Foundation (ASF) under one
004 * or more contributor license agreements. See the NOTICE file
005 * distributed with this work for additional information
006 * regarding copyright ownership. The ASF licenses this file
007 * to you under the Apache License, Version 2.0 (the
008 * "License"); you may not use this file except in compliance
009 * with the License. You may obtain a copy of the License at
010 *
011 * http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing,
014 * software distributed under the License is distributed on an
015 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
016 * KIND, either express or implied. See the License for the
017 * specific language governing permissions and limitations
018 * under the License.
019 *
020 */
021 package org.apache.qpid.framing;
022
023 import org.apache.mina.common.ByteBuffer;
024
025 import org.apache.qpid.framing.abstraction.ProtocolVersionMethodConverter;
026
027 import org.slf4j.Logger;
028 import org.slf4j.LoggerFactory;
029
030 public class VersionSpecificRegistry
031 {
032 private static final Logger _log = LoggerFactory.getLogger(VersionSpecificRegistry.class);
033
034 private final byte _protocolMajorVersion;
035 private final byte _protocolMinorVersion;
036
037 private static final int DEFAULT_MAX_CLASS_ID = 200;
038 private static final int DEFAULT_MAX_METHOD_ID = 50;
039
040 private AMQMethodBodyInstanceFactory[][] _registry = new AMQMethodBodyInstanceFactory[DEFAULT_MAX_CLASS_ID][];
041
042 private ProtocolVersionMethodConverter _protocolVersionConverter;
043
044 public VersionSpecificRegistry(byte major, byte minor)
045 {
046 _protocolMajorVersion = major;
047 _protocolMinorVersion = minor;
048
049 _protocolVersionConverter = loadProtocolVersionConverters(major, minor);
050 }
051
052 private static ProtocolVersionMethodConverter loadProtocolVersionConverters(byte protocolMajorVersion,
053 byte protocolMinorVersion)
054 {
055 try
056 {
057 Class<ProtocolVersionMethodConverter> versionMethodConverterClass =
058 (Class<ProtocolVersionMethodConverter>) Class.forName("org.apache.qpid.framing.MethodConverter_"
059 + protocolMajorVersion + "_" + protocolMinorVersion);
060
061 return versionMethodConverterClass.newInstance();
062
063 }
064 catch (ClassNotFoundException e)
065 {
066 _log.warn("Could not find protocol conversion classes for " + protocolMajorVersion + "-" + protocolMinorVersion);
067 if (protocolMinorVersion != 0)
068 {
069 protocolMinorVersion--;
070
071 return loadProtocolVersionConverters(protocolMajorVersion, protocolMinorVersion);
072 }
073 else if (protocolMajorVersion != 0)
074 {
075 protocolMajorVersion--;
076
077 return loadProtocolVersionConverters(protocolMajorVersion, protocolMinorVersion);
078 }
079 else
080 {
081 return null;
082 }
083
084 }
085 catch (IllegalAccessException e)
086 {
087 throw new IllegalStateException("Unable to load protocol version converter: ", e);
088 }
089 catch (InstantiationException e)
090 {
091 throw new IllegalStateException("Unable to load protocol version converter: ", e);
092 }
093 }
094
095 public byte getProtocolMajorVersion()
096 {
097 return _protocolMajorVersion;
098 }
099
100 public byte getProtocolMinorVersion()
101 {
102 return _protocolMinorVersion;
103 }
104
105 public AMQMethodBodyInstanceFactory getMethodBody(final short classID, final short methodID)
106 {
107 try
108 {
109 return _registry[classID][methodID];
110 }
111 catch (IndexOutOfBoundsException e)
112 {
113 return null;
114 }
115 catch (NullPointerException e)
116 {
117 return null;
118 }
119 }
120
121 public void registerMethod(final short classID, final short methodID, final AMQMethodBodyInstanceFactory instanceFactory)
122 {
123 if (_registry.length <= classID)
124 {
125 AMQMethodBodyInstanceFactory[][] oldRegistry = _registry;
126 _registry = new AMQMethodBodyInstanceFactory[classID + 1][];
127 System.arraycopy(oldRegistry, 0, _registry, 0, oldRegistry.length);
128 }
129
130 if (_registry[classID] == null)
131 {
132 _registry[classID] =
133 new AMQMethodBodyInstanceFactory[(methodID > DEFAULT_MAX_METHOD_ID) ? (methodID + 1)
134 : (DEFAULT_MAX_METHOD_ID + 1)];
135 }
136 else if (_registry[classID].length <= methodID)
137 {
138 AMQMethodBodyInstanceFactory[] oldMethods = _registry[classID];
139 _registry[classID] = new AMQMethodBodyInstanceFactory[methodID + 1];
140 System.arraycopy(oldMethods, 0, _registry[classID], 0, oldMethods.length);
141 }
142
143 _registry[classID][methodID] = instanceFactory;
144
145 }
146
147 public AMQMethodBody get(short classID, short methodID, ByteBuffer in, long size) throws AMQFrameDecodingException
148 {
149 AMQMethodBodyInstanceFactory bodyFactory;
150 try
151 {
152 bodyFactory = _registry[classID][methodID];
153 }
154 catch (NullPointerException e)
155 {
156 throw new AMQFrameDecodingException(null, "Class " + classID + " unknown in AMQP version "
157 + _protocolMajorVersion + "-" + _protocolMinorVersion + " (while trying to decode class " + classID
158 + " method " + methodID + ".", e);
159 }
160 catch (IndexOutOfBoundsException e)
161 {
162 if (classID >= _registry.length)
163 {
164 throw new AMQFrameDecodingException(null, "Class " + classID + " unknown in AMQP version "
165 + _protocolMajorVersion + "-" + _protocolMinorVersion + " (while trying to decode class " + classID
166 + " method " + methodID + ".", e);
167
168 }
169 else
170 {
171 throw new AMQFrameDecodingException(null, "Method " + methodID + " unknown in AMQP version "
172 + _protocolMajorVersion + "-" + _protocolMinorVersion + " (while trying to decode class " + classID
173 + " method " + methodID + ".", e);
174
175 }
176 }
177
178 if (bodyFactory == null)
179 {
180 throw new AMQFrameDecodingException(null, "Method " + methodID + " unknown in AMQP version "
181 + _protocolMajorVersion + "-" + _protocolMinorVersion + " (while trying to decode class " + classID
182 + " method " + methodID + ".", null);
183 }
184
185 return bodyFactory.newInstance( in, size);
186
187 }
188
189 public ProtocolVersionMethodConverter getProtocolVersionMethodConverter()
190 {
191 return _protocolVersionConverter;
192 }
193
194 public void configure()
195 {
196 _protocolVersionConverter.configure();
197 }
198 }
|