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   
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}