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.transport.stomp;
018
019import java.io.UnsupportedEncodingException;
020import java.util.Arrays;
021import java.util.HashMap;
022import java.util.Map;
023
024import org.apache.activemq.command.Command;
025import org.apache.activemq.command.Endpoint;
026import org.apache.activemq.command.Response;
027import org.apache.activemq.state.CommandVisitor;
028import org.apache.activemq.util.MarshallingSupport;
029
030/**
031 * Represents all the data in a STOMP frame.
032 *
033 * @author <a href="http://hiramchirino.com">chirino</a>
034 */
035public class StompFrame implements Command {
036
037    public static final byte[] NO_DATA = new byte[] {};
038
039    private String action;
040    private Map<String, String> headers = new HashMap<String, String>();
041    private byte[] content = NO_DATA;
042
043    public StompFrame(String command) {
044        this(command, null, null);
045    }
046
047    public StompFrame(String command, Map<String, String> headers) {
048        this(command, headers, null);
049    }
050
051    public StompFrame(String command, Map<String, String> headers, byte[] data) {
052        this.action = command;
053        if (headers != null)
054            this.headers = headers;
055        if (data != null)
056            this.content = data;
057    }
058
059    public StompFrame() {
060    }
061
062    public String getAction() {
063        return action;
064    }
065
066    public void setAction(String command) {
067        this.action = command;
068    }
069
070    public byte[] getContent() {
071        return content;
072    }
073
074    public String getBody() {
075        try {
076            return new String(content, "UTF-8");
077        } catch (UnsupportedEncodingException e) {
078            return new String(content);
079        }
080    }
081
082    public void setContent(byte[] data) {
083        this.content = data;
084    }
085
086    public Map<String, String> getHeaders() {
087        return headers;
088    }
089
090    public void setHeaders(Map<String, String> headers) {
091        this.headers = headers;
092    }
093
094    //
095    // Methods in the Command interface
096    //
097    public int getCommandId() {
098        return 0;
099    }
100
101    public Endpoint getFrom() {
102        return null;
103    }
104
105    public Endpoint getTo() {
106        return null;
107    }
108
109    public boolean isBrokerInfo() {
110        return false;
111    }
112
113    public boolean isMessage() {
114        return false;
115    }
116
117    public boolean isMessageAck() {
118        return false;
119    }
120
121    public boolean isMessageDispatch() {
122        return false;
123    }
124
125    public boolean isMessageDispatchNotification() {
126        return false;
127    }
128
129    public boolean isResponse() {
130        return false;
131    }
132
133    public boolean isResponseRequired() {
134        return false;
135    }
136
137    public boolean isShutdownInfo() {
138        return false;
139    }
140
141    public boolean isConnectionControl() {
142        return false;
143    }
144
145    public boolean isWireFormatInfo() {
146        return false;
147    }
148
149    public void setCommandId(int value) {
150    }
151
152    public void setFrom(Endpoint from) {
153    }
154
155    public void setResponseRequired(boolean responseRequired) {
156    }
157
158    public void setTo(Endpoint to) {
159    }
160
161    public Response visit(CommandVisitor visitor) throws Exception {
162        return null;
163    }
164
165    public byte getDataStructureType() {
166        return 0;
167    }
168
169    public boolean isMarshallAware() {
170        return false;
171    }
172
173    public String toString() {
174        return format(true);
175    }
176
177    public String format() {
178        return format(false);
179    }
180
181    public String format(boolean forLogging) {
182        StringBuilder buffer = new StringBuilder();
183        buffer.append(getAction());
184        buffer.append("\n");
185        Map<String, String> headers = getHeaders();
186        for (Map.Entry<String, String> entry : headers.entrySet()) {
187            buffer.append(entry.getKey());
188            buffer.append(":");
189            if (forLogging && entry.getKey().toString().toLowerCase().contains(Stomp.Headers.Connect.PASSCODE)) {
190                buffer.append("*****");
191            } else {
192                buffer.append(entry.getValue());
193            }
194            buffer.append("\n");
195        }
196        buffer.append("\n");
197        if (getContent() != null) {
198            try {
199                String contentString = new String(getContent(), "UTF-8");
200                if (forLogging) {
201                    contentString = MarshallingSupport.truncate64(contentString);
202                }
203                buffer.append(contentString);
204            } catch (Throwable e) {
205                buffer.append(Arrays.toString(getContent()));
206            }
207        }
208        // terminate the frame
209        buffer.append('\u0000');
210        return buffer.toString();
211    }
212}