1d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/*
2d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Copyright 2009 Mike Cumings
3d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen *
4d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Licensed under the Apache License, Version 2.0 (the "License");
5d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * you may not use this file except in compliance with the License.
6d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * You may obtain a copy of the License at
7d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen *
8d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen *   http://www.apache.org/licenses/LICENSE-2.0
9d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen *
10d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Unless required by applicable law or agreed to in writing, software
11d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * distributed under the License is distributed on an "AS IS" BASIS,
12d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * See the License for the specific language governing permissions and
14d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * limitations under the License.
15d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
16d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
17d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpackage com.kenai.jbosh;
18d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
19d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.io.ByteArrayOutputStream;
20d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.io.IOException;
21d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.io.InputStream;
22d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.util.Collections;
23d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.util.Map;
24d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
25d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
26d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Implementation of the {@code AbstractBody} class which allows for the
27d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * definition of messages from pre-existing message content.  Instances of
28d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * this class are based on the underlying data and therefore cannot be
29d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * modified.  In order to obtain the wrapper element namespace and
30d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * attribute information, the body content is partially parsed.
31d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <p/>
32d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * This class does only minimal syntactic and semantic checking with respect
33d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * to what the generated XML will look like.  It is up to the developer to
34d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * protect against the definition of malformed XML messages when building
35d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * instances of this class.
36d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <p/>
37d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Instances of this class are immutable and thread-safe.
38d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
39d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenfinal class StaticBody extends AbstractBody {
40d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
41d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
42d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Selected parser to be used to process raw XML messages.
43d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
44d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    private static final BodyParser PARSER =
45d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            new BodyParserXmlPull();
46d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
47d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
48d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Size of the internal buffer when copying from a stream.
49d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
50d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    private static final int BUFFER_SIZE = 1024;
51d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
52d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
53d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Map of all attributes to their values.
54d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
55d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    private final Map<BodyQName, String> attrs;
56d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
57d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
58d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * This body message in raw XML form.
59d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
60d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    private final String raw;
61d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
62d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    ///////////////////////////////////////////////////////////////////////////
63d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    // Constructors:
64d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
65d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
66d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Prevent direct construction.
67d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
68d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    private StaticBody(
69d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            final Map<BodyQName, String> attrMap,
70d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            final String rawXML) {
71d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        attrs = attrMap;
72d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        raw = rawXML;
73d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
74d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
75d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
76d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Creates an instance which is initialized by reading a body
77d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * message from the provided stream.
78d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
79d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @param inStream stream to read message XML from
80d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @return body instance
81d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @throws BOSHException on parse error
82d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
83d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public static StaticBody fromStream(
84d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            final InputStream inStream)
85d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            throws BOSHException {
86d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
87d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        try {
88d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            byte[] buffer = new byte[BUFFER_SIZE];
89d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            int read;
90d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            do {
91d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                read = inStream.read(buffer);
92d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                if (read > 0) {
93d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                    byteOut.write(buffer, 0, read);
94d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                }
95d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            } while (read >= 0);
96d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        } catch (IOException iox) {
97d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            throw(new BOSHException(
98d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                    "Could not read body data", iox));
99d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
100d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        return fromString(byteOut.toString());
101d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
102d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
103d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
104d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Creates an instance which is initialized by reading a body
105d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * message from the provided raw XML string.
106d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
107d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @param rawXML raw message XML in string form
108d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @return body instance
109d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @throws BOSHException on parse error
110d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
111d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public static StaticBody fromString(
112d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            final String rawXML)
113d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            throws BOSHException {
114d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        BodyParserResults results = PARSER.parse(rawXML);
115d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        return new StaticBody(results.getAttributes(), rawXML);
116d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
117d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
118d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
119d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
120d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * {@inheritDoc}
121d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
122d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public Map<BodyQName, String> getAttributes() {
123d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        return Collections.unmodifiableMap(attrs);
124d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
125d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
126d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
127d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * {@inheritDoc}
128d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
129d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public String toXML() {
130d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        return raw;
131d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
132d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
133d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
134