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    
027    import org.apache.activemq.state.CommandVisitor;
028    import org.apache.activemq.util.ByteArrayInputStream;
029    import org.apache.activemq.util.ByteArrayOutputStream;
030    import org.apache.activemq.util.ByteSequence;
031    import org.apache.activemq.util.MarshallingSupport;
032    import org.apache.activemq.wireformat.WireFormat;
033    
034    /**
035     * @openwire:marshaller code="1"
036     * @version $Revision$
037     */
038    public class WireFormatInfo implements Command, MarshallAware {
039    
040        public static final byte DATA_STRUCTURE_TYPE = CommandTypes.WIREFORMAT_INFO;
041        private static final int MAX_PROPERTY_SIZE = 1024 * 4;
042        private static final byte MAGIC[] = new byte[] {'A', 'c', 't', 'i', 'v', 'e', 'M', 'Q'};
043    
044        protected byte magic[] = MAGIC;
045        protected int version;
046        protected ByteSequence marshalledProperties;
047    
048        protected transient Map<String, Object> properties;
049        private transient Endpoint from;
050        private transient Endpoint to;
051    
052        public byte getDataStructureType() {
053            return DATA_STRUCTURE_TYPE;
054        }
055    
056        public boolean isWireFormatInfo() {
057            return true;
058        }
059    
060        public boolean isMarshallAware() {
061            return true;
062        }
063    
064        /**
065         * @openwire:property version=1 size=8 testSize=-1
066         */
067        public byte[] getMagic() {
068            return magic;
069        }
070    
071        public void setMagic(byte[] magic) {
072            this.magic = magic;
073        }
074    
075        /**
076         * @openwire:property version=1
077         */
078        public int getVersion() {
079            return version;
080        }
081    
082        public void setVersion(int version) {
083            this.version = version;
084        }
085    
086        /**
087         * @openwire:property version=1
088         */
089        public ByteSequence getMarshalledProperties() {
090            return marshalledProperties;
091        }
092    
093        public void setMarshalledProperties(ByteSequence marshalledProperties) {
094            this.marshalledProperties = marshalledProperties;
095        }
096    
097        /**
098         * The endpoint within the transport where this message came from.
099         */
100        public Endpoint getFrom() {
101            return from;
102        }
103    
104        public void setFrom(Endpoint from) {
105            this.from = from;
106        }
107    
108        /**
109         * The endpoint within the transport where this message is going to - null
110         * means all endpoints.
111         */
112        public Endpoint getTo() {
113            return to;
114        }
115    
116        public void setTo(Endpoint to) {
117            this.to = to;
118        }
119    
120        // ////////////////////
121        // 
122        // Implementation Methods.
123        //
124        // ////////////////////
125    
126        public Object getProperty(String name) throws IOException {
127            if (properties == null) {
128                if (marshalledProperties == null) {
129                    return null;
130                }
131                properties = unmarsallProperties(marshalledProperties);
132            }
133            return properties.get(name);
134        }
135    
136        @SuppressWarnings("unchecked")
137        public Map<String, Object> getProperties() throws IOException {
138            if (properties == null) {
139                if (marshalledProperties == null) {
140                    return Collections.EMPTY_MAP;
141                }
142                properties = unmarsallProperties(marshalledProperties);
143            }
144            return Collections.unmodifiableMap(properties);
145        }
146    
147        public void clearProperties() {
148            marshalledProperties = null;
149            properties = null;
150        }
151    
152        public void setProperty(String name, Object value) throws IOException {
153            lazyCreateProperties();
154            properties.put(name, value);
155        }
156    
157        protected void lazyCreateProperties() throws IOException {
158            if (properties == null) {
159                if (marshalledProperties == null) {
160                    properties = new HashMap<String, Object>();
161                } else {
162                    properties = unmarsallProperties(marshalledProperties);
163                    marshalledProperties = null;
164                }
165            }
166        }
167    
168        private Map<String, Object> unmarsallProperties(ByteSequence marshalledProperties) throws IOException {
169            return MarshallingSupport.unmarshalPrimitiveMap(new DataInputStream(new ByteArrayInputStream(marshalledProperties)), MAX_PROPERTY_SIZE);
170        }
171    
172        public void beforeMarshall(WireFormat wireFormat) throws IOException {
173            // Need to marshal the properties.
174            if (marshalledProperties == null && properties != null) {
175                ByteArrayOutputStream baos = new ByteArrayOutputStream();
176                DataOutputStream os = new DataOutputStream(baos);
177                MarshallingSupport.marshalPrimitiveMap(properties, os);
178                os.close();
179                marshalledProperties = baos.toByteSequence();
180            }
181        }
182    
183        public void afterMarshall(WireFormat wireFormat) throws IOException {
184        }
185    
186        public void beforeUnmarshall(WireFormat wireFormat) throws IOException {
187        }
188    
189        public void afterUnmarshall(WireFormat wireFormat) throws IOException {
190        }
191    
192        public boolean isValid() {
193            return magic != null && Arrays.equals(magic, MAGIC);
194        }
195    
196        public void setResponseRequired(boolean responseRequired) {
197        }
198    
199        /**
200         * @throws IOException
201         */
202        public boolean isCacheEnabled() throws IOException {
203            return Boolean.TRUE == getProperty("CacheEnabled");
204        }
205    
206        public void setCacheEnabled(boolean cacheEnabled) throws IOException {
207            setProperty("CacheEnabled", cacheEnabled ? Boolean.TRUE : Boolean.FALSE);
208        }
209    
210        /**
211         * @throws IOException
212         */
213        public boolean isStackTraceEnabled() throws IOException {
214            return Boolean.TRUE == getProperty("StackTraceEnabled");
215        }
216    
217        public void setStackTraceEnabled(boolean stackTraceEnabled) throws IOException {
218            setProperty("StackTraceEnabled", stackTraceEnabled ? Boolean.TRUE : Boolean.FALSE);
219        }
220    
221        /**
222         * @throws IOException
223         */
224        public boolean isTcpNoDelayEnabled() throws IOException {
225            return Boolean.TRUE == getProperty("TcpNoDelayEnabled");
226        }
227    
228        public void setTcpNoDelayEnabled(boolean tcpNoDelayEnabled) throws IOException {
229            setProperty("TcpNoDelayEnabled", tcpNoDelayEnabled ? Boolean.TRUE : Boolean.FALSE);
230        }
231    
232        /**
233         * @throws IOException
234         */
235        public boolean isSizePrefixDisabled() throws IOException {
236            return Boolean.TRUE == getProperty("SizePrefixDisabled");
237        }
238    
239        public void setSizePrefixDisabled(boolean prefixPacketSize) throws IOException {
240            setProperty("SizePrefixDisabled", prefixPacketSize ? Boolean.TRUE : Boolean.FALSE);
241        }
242    
243        /**
244         * @throws IOException
245         */
246        public boolean isTightEncodingEnabled() throws IOException {
247            return Boolean.TRUE == getProperty("TightEncodingEnabled");
248        }
249    
250        public void setTightEncodingEnabled(boolean tightEncodingEnabled) throws IOException {
251            setProperty("TightEncodingEnabled", tightEncodingEnabled ? Boolean.TRUE : Boolean.FALSE);
252        }
253    
254        /**
255         * @throws IOException
256         */
257        public long getMaxInactivityDuration() throws IOException {
258            Long l = (Long)getProperty("MaxInactivityDuration");
259            return l == null ? 0 : l.longValue();
260        }
261    
262        public void setMaxInactivityDuration(long maxInactivityDuration) throws IOException {
263            setProperty("MaxInactivityDuration", new Long(maxInactivityDuration));
264        }
265        
266        public long getMaxInactivityDurationInitalDelay() throws IOException {
267            Long l = (Long)getProperty("MaxInactivityDurationInitalDelay");
268            return l == null ? 0 : l.longValue();
269        }
270    
271        public void setMaxInactivityDurationInitalDelay(long maxInactivityDurationInitalDelay) throws IOException {
272            setProperty("MaxInactivityDurationInitalDelay", new Long(maxInactivityDurationInitalDelay));
273        }
274        
275       
276    
277        /**
278         * @throws IOException
279         */
280        public int getCacheSize() throws IOException {
281            Integer i = (Integer)getProperty("CacheSize");
282            return i == null ? 0 : i.intValue();
283        }
284    
285        public void setCacheSize(int cacheSize) throws IOException {
286            setProperty("CacheSize", new Integer(cacheSize));
287        }
288    
289        public Response visit(CommandVisitor visitor) throws Exception {
290            return visitor.processWireFormat(this);
291        }
292    
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 void setCachedMarshalledForm(WireFormat wireFormat, ByteSequence data) {
361        }
362    
363        public ByteSequence getCachedMarshalledForm(WireFormat wireFormat) {
364            return null;
365        }
366    
367    }