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 */
017package org.apache.activemq.command;
018
019import java.io.DataInputStream;
020import java.io.DataOutputStream;
021import java.io.IOException;
022import java.util.Arrays;
023import java.util.Collections;
024import java.util.HashMap;
025import java.util.Map;
026
027import org.apache.activemq.state.CommandVisitor;
028import org.apache.activemq.util.ByteArrayInputStream;
029import org.apache.activemq.util.ByteArrayOutputStream;
030import org.apache.activemq.util.ByteSequence;
031import org.apache.activemq.util.MarshallingSupport;
032import org.apache.activemq.wireformat.WireFormat;
033import org.fusesource.hawtbuf.UTF8Buffer;
034
035/**
036 * @openwire:marshaller code="1"
037 *
038 */
039public class WireFormatInfo implements Command, MarshallAware {
040
041    public static final byte DATA_STRUCTURE_TYPE = CommandTypes.WIREFORMAT_INFO;
042    private static final int MAX_PROPERTY_SIZE = 1024 * 4;
043    private static final byte MAGIC[] = new byte[] {'A', 'c', 't', 'i', 'v', 'e', 'M', 'Q'};
044
045    protected byte magic[] = MAGIC;
046    protected int version;
047    protected ByteSequence marshalledProperties;
048
049    protected transient Map<String, Object> properties;
050    private transient Endpoint from;
051    private transient Endpoint to;
052
053    @Override
054    public byte getDataStructureType() {
055        return DATA_STRUCTURE_TYPE;
056    }
057
058    @Override
059    public boolean isWireFormatInfo() {
060        return true;
061    }
062
063    @Override
064    public boolean isMarshallAware() {
065        return true;
066    }
067
068    /**
069     * @openwire:property version=1 size=8 testSize=-1
070     */
071    public byte[] getMagic() {
072        return magic;
073    }
074
075    public void setMagic(byte[] magic) {
076        this.magic = magic;
077    }
078
079    /**
080     * @openwire:property version=1
081     */
082    public int getVersion() {
083        return version;
084    }
085
086    public void setVersion(int version) {
087        this.version = version;
088    }
089
090    /**
091     * @openwire:property version=1
092     */
093    public ByteSequence getMarshalledProperties() {
094        return marshalledProperties;
095    }
096
097    public void setMarshalledProperties(ByteSequence marshalledProperties) {
098        this.marshalledProperties = marshalledProperties;
099    }
100
101    /**
102     * The endpoint within the transport where this message came from.
103     */
104    @Override
105    public Endpoint getFrom() {
106        return from;
107    }
108
109    @Override
110    public void setFrom(Endpoint from) {
111        this.from = from;
112    }
113
114    /**
115     * The endpoint within the transport where this message is going to - null
116     * means all endpoints.
117     */
118    @Override
119    public Endpoint getTo() {
120        return to;
121    }
122
123    @Override
124    public void setTo(Endpoint to) {
125        this.to = to;
126    }
127
128    // ////////////////////
129    //
130    // Implementation Methods.
131    //
132    // ////////////////////
133
134    public Object getProperty(String name) throws IOException {
135        if (properties == null) {
136            if (marshalledProperties == null) {
137                return null;
138            }
139            properties = unmarsallProperties(marshalledProperties);
140        }
141        return properties.get(name);
142    }
143
144    @SuppressWarnings("unchecked")
145    public Map<String, Object> getProperties() throws IOException {
146        if (properties == null) {
147            if (marshalledProperties == null) {
148                return Collections.EMPTY_MAP;
149            }
150            properties = unmarsallProperties(marshalledProperties);
151        }
152        return Collections.unmodifiableMap(properties);
153    }
154
155    public void clearProperties() {
156        marshalledProperties = null;
157        properties = null;
158    }
159
160    public void setProperty(String name, Object value) throws IOException {
161        lazyCreateProperties();
162        properties.put(name, value);
163    }
164
165    protected void lazyCreateProperties() throws IOException {
166        if (properties == null) {
167            if (marshalledProperties == null) {
168                properties = new HashMap<String, Object>();
169            } else {
170                properties = unmarsallProperties(marshalledProperties);
171                marshalledProperties = null;
172            }
173        }
174    }
175
176    private Map<String, Object> unmarsallProperties(ByteSequence marshalledProperties) throws IOException {
177        return MarshallingSupport.unmarshalPrimitiveMap(new DataInputStream(new ByteArrayInputStream(marshalledProperties)), MAX_PROPERTY_SIZE);
178    }
179
180    @Override
181    public void beforeMarshall(WireFormat wireFormat) throws IOException {
182        // Need to marshal the properties.
183        if (marshalledProperties == null && properties != null) {
184            ByteArrayOutputStream baos = new ByteArrayOutputStream();
185            DataOutputStream os = new DataOutputStream(baos);
186            MarshallingSupport.marshalPrimitiveMap(properties, os);
187            os.close();
188            marshalledProperties = baos.toByteSequence();
189        }
190    }
191
192    @Override
193    public void afterMarshall(WireFormat wireFormat) throws IOException {
194    }
195
196    @Override
197    public void beforeUnmarshall(WireFormat wireFormat) throws IOException {
198    }
199
200    @Override
201    public void afterUnmarshall(WireFormat wireFormat) throws IOException {
202    }
203
204    public boolean isValid() {
205        return magic != null && Arrays.equals(magic, MAGIC);
206    }
207
208    @Override
209    public void setResponseRequired(boolean responseRequired) {
210    }
211
212    /**
213     * @throws IOException
214     */
215    public boolean isCacheEnabled() throws IOException {
216        return Boolean.TRUE == getProperty("CacheEnabled");
217    }
218
219    public void setCacheEnabled(boolean cacheEnabled) throws IOException {
220        setProperty("CacheEnabled", cacheEnabled ? Boolean.TRUE : Boolean.FALSE);
221    }
222
223    /**
224     * @throws IOException
225     */
226    public boolean isStackTraceEnabled() throws IOException {
227        return Boolean.TRUE == getProperty("StackTraceEnabled");
228    }
229
230    public void setStackTraceEnabled(boolean stackTraceEnabled) throws IOException {
231        setProperty("StackTraceEnabled", stackTraceEnabled ? Boolean.TRUE : Boolean.FALSE);
232    }
233
234    /**
235     * @throws IOException
236     */
237    public boolean isTcpNoDelayEnabled() throws IOException {
238        return Boolean.TRUE == getProperty("TcpNoDelayEnabled");
239    }
240
241    public void setTcpNoDelayEnabled(boolean tcpNoDelayEnabled) throws IOException {
242        setProperty("TcpNoDelayEnabled", tcpNoDelayEnabled ? Boolean.TRUE : Boolean.FALSE);
243    }
244
245    /**
246     * @throws IOException
247     */
248    public boolean isSizePrefixDisabled() throws IOException {
249        return Boolean.TRUE == getProperty("SizePrefixDisabled");
250    }
251
252    public void setSizePrefixDisabled(boolean prefixPacketSize) throws IOException {
253        setProperty("SizePrefixDisabled", prefixPacketSize ? Boolean.TRUE : Boolean.FALSE);
254    }
255
256    /**
257     * @throws IOException
258     */
259    public boolean isTightEncodingEnabled() throws IOException {
260        return Boolean.TRUE == getProperty("TightEncodingEnabled");
261    }
262
263    public void setTightEncodingEnabled(boolean tightEncodingEnabled) throws IOException {
264        setProperty("TightEncodingEnabled", tightEncodingEnabled ? Boolean.TRUE : Boolean.FALSE);
265    }
266
267    public String getHost() throws IOException {
268        UTF8Buffer buff = (UTF8Buffer) getProperty("Host");
269        if( buff == null ) {
270            return null;
271        }
272        return buff.toString();
273    }
274
275    public void setHost(String hostname) throws IOException {
276        setProperty("Host", hostname);
277    }
278
279    /**
280     * @throws IOException
281     */
282    public long getMaxInactivityDuration() throws IOException {
283        Long l = (Long)getProperty("MaxInactivityDuration");
284        return l == null ? 0 : l.longValue();
285    }
286
287    public void setMaxInactivityDuration(long maxInactivityDuration) throws IOException {
288        setProperty("MaxInactivityDuration", new Long(maxInactivityDuration));
289    }
290
291    public long getMaxInactivityDurationInitalDelay() throws IOException {
292        Long l = (Long)getProperty("MaxInactivityDurationInitalDelay");
293        return l == null ? 0 : l.longValue();
294    }
295
296    public void setMaxInactivityDurationInitalDelay(long maxInactivityDurationInitalDelay) throws IOException {
297        setProperty("MaxInactivityDurationInitalDelay", new Long(maxInactivityDurationInitalDelay));
298    }
299
300    public long getMaxFrameSize() throws IOException {
301        Long l = (Long)getProperty("MaxFrameSize");
302        return l == null ? 0 : l.longValue();
303    }
304
305    public void setMaxFrameSize(long maxFrameSize) throws IOException {
306        setProperty("MaxFrameSize", new Long(maxFrameSize));
307    }
308
309    /**
310     * @throws IOException
311     */
312    public int getCacheSize() throws IOException {
313        Integer i = (Integer)getProperty("CacheSize");
314        return i == null ? 0 : i.intValue();
315    }
316
317    public void setCacheSize(int cacheSize) throws IOException {
318        setProperty("CacheSize", new Integer(cacheSize));
319    }
320
321    @Override
322    public Response visit(CommandVisitor visitor) throws Exception {
323        return visitor.processWireFormat(this);
324    }
325
326    @Override
327    public String toString() {
328        Map<String, Object> p = null;
329        try {
330            p = getProperties();
331        } catch (IOException ignore) {
332        }
333        return "WireFormatInfo { version=" + version + ", properties=" + p + ", magic=" + toString(magic) + "}";
334    }
335
336    private String toString(byte[] data) {
337        StringBuffer sb = new StringBuffer();
338        sb.append('[');
339        for (int i = 0; i < data.length; i++) {
340            if (i != 0) {
341                sb.append(',');
342            }
343            sb.append((char)data[i]);
344        }
345        sb.append(']');
346        return sb.toString();
347    }
348
349    // /////////////////////////////////////////////////////////////
350    //
351    // This are not implemented.
352    //
353    // /////////////////////////////////////////////////////////////
354
355    @Override
356    public void setCommandId(int value) {
357    }
358
359    @Override
360    public int getCommandId() {
361        return 0;
362    }
363
364    @Override
365    public boolean isResponseRequired() {
366        return false;
367    }
368
369    @Override
370    public boolean isResponse() {
371        return false;
372    }
373
374    @Override
375    public boolean isBrokerInfo() {
376        return false;
377    }
378
379    @Override
380    public boolean isMessageDispatch() {
381        return false;
382    }
383
384    @Override
385    public boolean isMessage() {
386        return false;
387    }
388
389    @Override
390    public boolean isMessageAck() {
391        return false;
392    }
393
394    @Override
395    public boolean isMessageDispatchNotification() {
396        return false;
397    }
398
399    @Override
400    public boolean isShutdownInfo() {
401        return false;
402    }
403
404    @Override
405    public boolean isConnectionControl() {
406        return false;
407    }
408
409    @Override
410    public boolean isConsumerControl() {
411        return false;
412    }
413
414    public void setCachedMarshalledForm(WireFormat wireFormat, ByteSequence data) {
415    }
416
417    public ByteSequence getCachedMarshalledForm(WireFormat wireFormat) {
418        return null;
419    }
420}