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;
032import org.fusesource.hawtbuf.UTF8Buffer;
033
034/**
035 * @openwire:marshaller code="1"
036 * 
037 */
038public 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    public String getHost() throws IOException {
255        UTF8Buffer buff = (UTF8Buffer) getProperty("Host");
256        if( buff == null ) {
257            return null;
258        }
259        return (String) buff.toString();
260    }
261
262    public void setHost(String hostname) throws IOException {
263        setProperty("Host", hostname);
264    }
265
266    /**
267     * @throws IOException
268     */
269    public long getMaxInactivityDuration() throws IOException {
270        Long l = (Long)getProperty("MaxInactivityDuration");
271        return l == null ? 0 : l.longValue();
272    }
273
274    public void setMaxInactivityDuration(long maxInactivityDuration) throws IOException {
275        setProperty("MaxInactivityDuration", new Long(maxInactivityDuration));
276    }
277    
278    public long getMaxInactivityDurationInitalDelay() throws IOException {
279        Long l = (Long)getProperty("MaxInactivityDurationInitalDelay");
280        return l == null ? 0 : l.longValue();
281    }
282
283    public void setMaxInactivityDurationInitalDelay(long maxInactivityDurationInitalDelay) throws IOException {
284        setProperty("MaxInactivityDurationInitalDelay", new Long(maxInactivityDurationInitalDelay));
285    }
286
287    public long getMaxFrameSize() throws IOException {
288        Long l = (Long)getProperty("MaxFrameSize");
289        return l == null ? 0 : l.longValue();
290    }
291
292    public void setMaxFrameSize(long maxFrameSize) throws IOException {
293        setProperty("MaxFrameSize", new Long(maxFrameSize));
294    }
295    
296   
297
298    /**
299     * @throws IOException
300     */
301    public int getCacheSize() throws IOException {
302        Integer i = (Integer)getProperty("CacheSize");
303        return i == null ? 0 : i.intValue();
304    }
305
306    public void setCacheSize(int cacheSize) throws IOException {
307        setProperty("CacheSize", new Integer(cacheSize));
308    }
309
310    public Response visit(CommandVisitor visitor) throws Exception {
311        return visitor.processWireFormat(this);
312    }
313
314    @Override
315    public String toString() {
316        Map<String, Object> p = null;
317        try {
318            p = getProperties();
319        } catch (IOException ignore) {
320        }
321        return "WireFormatInfo { version=" + version + ", properties=" + p + ", magic=" + toString(magic) + "}";
322    }
323
324    private String toString(byte[] data) {
325        StringBuffer sb = new StringBuffer();
326        sb.append('[');
327        for (int i = 0; i < data.length; i++) {
328            if (i != 0) {
329                sb.append(',');
330            }
331            sb.append((char)data[i]);
332        }
333        sb.append(']');
334        return sb.toString();
335    }
336
337    // /////////////////////////////////////////////////////////////
338    //
339    // This are not implemented.
340    //
341    // /////////////////////////////////////////////////////////////
342
343    public void setCommandId(int value) {
344    }
345
346    public int getCommandId() {
347        return 0;
348    }
349
350    public boolean isResponseRequired() {
351        return false;
352    }
353
354    public boolean isResponse() {
355        return false;
356    }
357
358    public boolean isBrokerInfo() {
359        return false;
360    }
361
362    public boolean isMessageDispatch() {
363        return false;
364    }
365
366    public boolean isMessage() {
367        return false;
368    }
369
370    public boolean isMessageAck() {
371        return false;
372    }
373
374    public boolean isMessageDispatchNotification() {
375        return false;
376    }
377
378    public boolean isShutdownInfo() {
379        return false;
380    }
381    
382    public boolean isConnectionControl() {
383        return false;
384    }
385
386    public void setCachedMarshalledForm(WireFormat wireFormat, ByteSequence data) {
387    }
388
389    public ByteSequence getCachedMarshalledForm(WireFormat wireFormat) {
390        return null;
391    }
392
393}