001    /**
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.activemq.command;
018    
019    import java.io.DataInputStream;
020    import java.io.DataOutputStream;
021    import java.io.IOException;
022    import java.util.Arrays;
023    import java.util.Collections;
024    import java.util.HashMap;
025    import java.util.Map;
026    import org.apache.activemq.state.CommandVisitor;
027    import org.apache.activemq.util.ByteArrayInputStream;
028    import org.apache.activemq.util.ByteArrayOutputStream;
029    import org.apache.activemq.util.ByteSequence;
030    import org.apache.activemq.util.MarshallingSupport;
031    import org.apache.activemq.wireformat.WireFormat;
032    
033    /**
034     * @openwire:marshaller code="1"
035     * 
036     */
037    public class WireFormatInfo implements Command, MarshallAware {
038    
039        public static final byte DATA_STRUCTURE_TYPE = CommandTypes.WIREFORMAT_INFO;
040        private static final int MAX_PROPERTY_SIZE = 1024 * 4;
041        private static final byte MAGIC[] = new byte[] {'A', 'c', 't', 'i', 'v', 'e', 'M', 'Q'};
042    
043        protected byte magic[] = MAGIC;
044        protected int version;
045        protected ByteSequence marshalledProperties;
046    
047        protected transient Map<String, Object> properties;
048        private transient Endpoint from;
049        private transient Endpoint to;
050    
051        public byte getDataStructureType() {
052            return DATA_STRUCTURE_TYPE;
053        }
054    
055        public boolean isWireFormatInfo() {
056            return true;
057        }
058    
059        public boolean isMarshallAware() {
060            return true;
061        }
062    
063        /**
064         * @openwire:property version=1 size=8 testSize=-1
065         */
066        public byte[] getMagic() {
067            return magic;
068        }
069    
070        public void setMagic(byte[] magic) {
071            this.magic = magic;
072        }
073    
074        /**
075         * @openwire:property version=1
076         */
077        public int getVersion() {
078            return version;
079        }
080    
081        public void setVersion(int version) {
082            this.version = version;
083        }
084    
085        /**
086         * @openwire:property version=1
087         */
088        public ByteSequence getMarshalledProperties() {
089            return marshalledProperties;
090        }
091    
092        public void setMarshalledProperties(ByteSequence marshalledProperties) {
093            this.marshalledProperties = marshalledProperties;
094        }
095    
096        /**
097         * The endpoint within the transport where this message came from.
098         */
099        public Endpoint getFrom() {
100            return from;
101        }
102    
103        public void setFrom(Endpoint from) {
104            this.from = from;
105        }
106    
107        /**
108         * The endpoint within the transport where this message is going to - null
109         * means all endpoints.
110         */
111        public Endpoint getTo() {
112            return to;
113        }
114    
115        public void setTo(Endpoint to) {
116            this.to = to;
117        }
118    
119        // ////////////////////
120        // 
121        // Implementation Methods.
122        //
123        // ////////////////////
124    
125        public Object getProperty(String name) throws IOException {
126            if (properties == null) {
127                if (marshalledProperties == null) {
128                    return null;
129                }
130                properties = unmarsallProperties(marshalledProperties);
131            }
132            return properties.get(name);
133        }
134    
135        @SuppressWarnings("unchecked")
136        public Map<String, Object> getProperties() throws IOException {
137            if (properties == null) {
138                if (marshalledProperties == null) {
139                    return Collections.EMPTY_MAP;
140                }
141                properties = unmarsallProperties(marshalledProperties);
142            }
143            return Collections.unmodifiableMap(properties);
144        }
145    
146        public void clearProperties() {
147            marshalledProperties = null;
148            properties = null;
149        }
150    
151        public void setProperty(String name, Object value) throws IOException {
152            lazyCreateProperties();
153            properties.put(name, value);
154        }
155    
156        protected void lazyCreateProperties() throws IOException {
157            if (properties == null) {
158                if (marshalledProperties == null) {
159                    properties = new HashMap<String, Object>();
160                } else {
161                    properties = unmarsallProperties(marshalledProperties);
162                    marshalledProperties = null;
163                }
164            }
165        }
166    
167        private Map<String, Object> unmarsallProperties(ByteSequence marshalledProperties) throws IOException {
168            return MarshallingSupport.unmarshalPrimitiveMap(new DataInputStream(new ByteArrayInputStream(marshalledProperties)), MAX_PROPERTY_SIZE);
169        }
170    
171        public void beforeMarshall(WireFormat wireFormat) throws IOException {
172            // Need to marshal the properties.
173            if (marshalledProperties == null && properties != null) {
174                ByteArrayOutputStream baos = new ByteArrayOutputStream();
175                DataOutputStream os = new DataOutputStream(baos);
176                MarshallingSupport.marshalPrimitiveMap(properties, os);
177                os.close();
178                marshalledProperties = baos.toByteSequence();
179            }
180        }
181    
182        public void afterMarshall(WireFormat wireFormat) throws IOException {
183        }
184    
185        public void beforeUnmarshall(WireFormat wireFormat) throws IOException {
186        }
187    
188        public void afterUnmarshall(WireFormat wireFormat) throws IOException {
189        }
190    
191        public boolean isValid() {
192            return magic != null && Arrays.equals(magic, MAGIC);
193        }
194    
195        public void setResponseRequired(boolean responseRequired) {
196        }
197    
198        /**
199         * @throws IOException
200         */
201        public boolean isCacheEnabled() throws IOException {
202            return Boolean.TRUE == getProperty("CacheEnabled");
203        }
204    
205        public void setCacheEnabled(boolean cacheEnabled) throws IOException {
206            setProperty("CacheEnabled", cacheEnabled ? Boolean.TRUE : Boolean.FALSE);
207        }
208    
209        /**
210         * @throws IOException
211         */
212        public boolean isStackTraceEnabled() throws IOException {
213            return Boolean.TRUE == getProperty("StackTraceEnabled");
214        }
215    
216        public void setStackTraceEnabled(boolean stackTraceEnabled) throws IOException {
217            setProperty("StackTraceEnabled", stackTraceEnabled ? Boolean.TRUE : Boolean.FALSE);
218        }
219    
220        /**
221         * @throws IOException
222         */
223        public boolean isTcpNoDelayEnabled() throws IOException {
224            return Boolean.TRUE == getProperty("TcpNoDelayEnabled");
225        }
226    
227        public void setTcpNoDelayEnabled(boolean tcpNoDelayEnabled) throws IOException {
228            setProperty("TcpNoDelayEnabled", tcpNoDelayEnabled ? Boolean.TRUE : Boolean.FALSE);
229        }
230    
231        /**
232         * @throws IOException
233         */
234        public boolean isSizePrefixDisabled() throws IOException {
235            return Boolean.TRUE == getProperty("SizePrefixDisabled");
236        }
237    
238        public void setSizePrefixDisabled(boolean prefixPacketSize) throws IOException {
239            setProperty("SizePrefixDisabled", prefixPacketSize ? Boolean.TRUE : Boolean.FALSE);
240        }
241    
242        /**
243         * @throws IOException
244         */
245        public boolean isTightEncodingEnabled() throws IOException {
246            return Boolean.TRUE == getProperty("TightEncodingEnabled");
247        }
248    
249        public void setTightEncodingEnabled(boolean tightEncodingEnabled) throws IOException {
250            setProperty("TightEncodingEnabled", tightEncodingEnabled ? Boolean.TRUE : Boolean.FALSE);
251        }
252    
253        /**
254         * @throws IOException
255         */
256        public long getMaxInactivityDuration() throws IOException {
257            Long l = (Long)getProperty("MaxInactivityDuration");
258            return l == null ? 0 : l.longValue();
259        }
260    
261        public void setMaxInactivityDuration(long maxInactivityDuration) throws IOException {
262            setProperty("MaxInactivityDuration", new Long(maxInactivityDuration));
263        }
264        
265        public long getMaxInactivityDurationInitalDelay() throws IOException {
266            Long l = (Long)getProperty("MaxInactivityDurationInitalDelay");
267            return l == null ? 0 : l.longValue();
268        }
269    
270        public void setMaxInactivityDurationInitalDelay(long maxInactivityDurationInitalDelay) throws IOException {
271            setProperty("MaxInactivityDurationInitalDelay", new Long(maxInactivityDurationInitalDelay));
272        }
273        
274       
275    
276        /**
277         * @throws IOException
278         */
279        public int getCacheSize() throws IOException {
280            Integer i = (Integer)getProperty("CacheSize");
281            return i == null ? 0 : i.intValue();
282        }
283    
284        public void setCacheSize(int cacheSize) throws IOException {
285            setProperty("CacheSize", new Integer(cacheSize));
286        }
287    
288        public Response visit(CommandVisitor visitor) throws Exception {
289            return visitor.processWireFormat(this);
290        }
291    
292        @Override
293        public String toString() {
294            Map<String, Object> p = null;
295            try {
296                p = getProperties();
297            } catch (IOException ignore) {
298            }
299            return "WireFormatInfo { version=" + version + ", properties=" + p + ", magic=" + toString(magic) + "}";
300        }
301    
302        private String toString(byte[] data) {
303            StringBuffer sb = new StringBuffer();
304            sb.append('[');
305            for (int i = 0; i < data.length; i++) {
306                if (i != 0) {
307                    sb.append(',');
308                }
309                sb.append((char)data[i]);
310            }
311            sb.append(']');
312            return sb.toString();
313        }
314    
315        // /////////////////////////////////////////////////////////////
316        //
317        // This are not implemented.
318        //
319        // /////////////////////////////////////////////////////////////
320    
321        public void setCommandId(int value) {
322        }
323    
324        public int getCommandId() {
325            return 0;
326        }
327    
328        public boolean isResponseRequired() {
329            return false;
330        }
331    
332        public boolean isResponse() {
333            return false;
334        }
335    
336        public boolean isBrokerInfo() {
337            return false;
338        }
339    
340        public boolean isMessageDispatch() {
341            return false;
342        }
343    
344        public boolean isMessage() {
345            return false;
346        }
347    
348        public boolean isMessageAck() {
349            return false;
350        }
351    
352        public boolean isMessageDispatchNotification() {
353            return false;
354        }
355    
356        public boolean isShutdownInfo() {
357            return false;
358        }
359        
360        public boolean isConnectionControl() {
361            return false;
362        }
363    
364        public void setCachedMarshalledForm(WireFormat wireFormat, ByteSequence data) {
365        }
366    
367        public ByteSequence getCachedMarshalledForm(WireFormat wireFormat) {
368            return null;
369        }
370    
371    }