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;
026import org.apache.activemq.state.CommandVisitor;
027import org.apache.activemq.util.ByteArrayInputStream;
028import org.apache.activemq.util.ByteArrayOutputStream;
029import org.apache.activemq.util.ByteSequence;
030import org.apache.activemq.util.MarshallingSupport;
031import org.apache.activemq.wireformat.WireFormat;
032
033/**
034 * @openwire:marshaller code="1"
035 * 
036 */
037public 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    public long getMaxFrameSize() throws IOException {
275        Long l = (Long)getProperty("MaxFrameSize");
276        return l == null ? 0 : l.longValue();
277    }
278
279    public void setMaxFrameSize(long maxFrameSize) throws IOException {
280        setProperty("MaxFrameSize", new Long(maxFrameSize));
281    }
282    
283   
284
285    /**
286     * @throws IOException
287     */
288    public int getCacheSize() throws IOException {
289        Integer i = (Integer)getProperty("CacheSize");
290        return i == null ? 0 : i.intValue();
291    }
292
293    public void setCacheSize(int cacheSize) throws IOException {
294        setProperty("CacheSize", new Integer(cacheSize));
295    }
296
297    public Response visit(CommandVisitor visitor) throws Exception {
298        return visitor.processWireFormat(this);
299    }
300
301    @Override
302    public String toString() {
303        Map<String, Object> p = null;
304        try {
305            p = getProperties();
306        } catch (IOException ignore) {
307        }
308        return "WireFormatInfo { version=" + version + ", properties=" + p + ", magic=" + toString(magic) + "}";
309    }
310
311    private String toString(byte[] data) {
312        StringBuffer sb = new StringBuffer();
313        sb.append('[');
314        for (int i = 0; i < data.length; i++) {
315            if (i != 0) {
316                sb.append(',');
317            }
318            sb.append((char)data[i]);
319        }
320        sb.append(']');
321        return sb.toString();
322    }
323
324    // /////////////////////////////////////////////////////////////
325    //
326    // This are not implemented.
327    //
328    // /////////////////////////////////////////////////////////////
329
330    public void setCommandId(int value) {
331    }
332
333    public int getCommandId() {
334        return 0;
335    }
336
337    public boolean isResponseRequired() {
338        return false;
339    }
340
341    public boolean isResponse() {
342        return false;
343    }
344
345    public boolean isBrokerInfo() {
346        return false;
347    }
348
349    public boolean isMessageDispatch() {
350        return false;
351    }
352
353    public boolean isMessage() {
354        return false;
355    }
356
357    public boolean isMessageAck() {
358        return false;
359    }
360
361    public boolean isMessageDispatchNotification() {
362        return false;
363    }
364
365    public boolean isShutdownInfo() {
366        return false;
367    }
368    
369    public boolean isConnectionControl() {
370        return false;
371    }
372
373    public void setCachedMarshalledForm(WireFormat wireFormat, ByteSequence data) {
374    }
375
376    public ByteSequence getCachedMarshalledForm(WireFormat wireFormat) {
377        return null;
378    }
379
380}