1087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor/*
2087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor * Copyright (C) 2006 The Android Open Source Project
3087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor *
4087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor * Licensed under the Apache License, Version 2.0 (the "License");
5087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor * you may not use this file except in compliance with the License.
6087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor * You may obtain a copy of the License at
7087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor *
8087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor *      http://www.apache.org/licenses/LICENSE-2.0
9087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor *
10087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor * Unless required by applicable law or agreed to in writing, software
11087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor * distributed under the License is distributed on an "AS IS" BASIS,
12087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor * See the License for the specific language governing permissions and
14087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor * limitations under the License.
15087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor */
16087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor
172269d1572e5fcfb725ea55f5764d8c3280d69f6dDianne Hackbornpackage com.android.internal.util;
18087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor
19087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylorimport org.xmlpull.v1.XmlSerializer;
20087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor
21087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylorimport java.io.IOException;
22087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylorimport java.io.OutputStream;
23087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylorimport java.io.OutputStreamWriter;
24087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylorimport java.io.UnsupportedEncodingException;
25087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylorimport java.io.Writer;
26087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylorimport java.nio.ByteBuffer;
27087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylorimport java.nio.CharBuffer;
28087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylorimport java.nio.charset.Charset;
29087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylorimport java.nio.charset.CharsetEncoder;
30087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylorimport java.nio.charset.CoderResult;
313ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onukiimport java.nio.charset.CodingErrorAction;
32087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylorimport java.nio.charset.IllegalCharsetNameException;
33087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylorimport java.nio.charset.UnsupportedCharsetException;
34087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor
35087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor/**
36087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor * This is a quick and dirty implementation of XmlSerializer that isn't horribly
37087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor * painfully slow like the normal one.  It only does what is needed for the
38087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor * specific XML files being written with it.
39087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor */
40087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylorpublic class FastXmlSerializer implements XmlSerializer {
41087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor    private static final String ESCAPE_TABLE[] = new String[] {
423ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki        "�",   "",   "",   "",  "",    "",   "",  "",  // 0-7
433ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki        "",   "	",   "
",  "", "",   "
",  "", "", // 8-15
443ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki        "",  "",  "",  "", "",   "",  "", "", // 16-23
453ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki        "",  "",  "",  "", "",   "",  "", "", // 24-31
463ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki        null,     null,     """, null,     null,     null,     "&",  null,   // 32-39
473ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki        null,     null,     null,     null,     null,     null,     null,     null,   // 40-47
483ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki        null,     null,     null,     null,     null,     null,     null,     null,   // 48-55
493ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki        null,     null,     null,     null,     "<",   null,     ">",   null,   // 56-63
50087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor    };
51087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor
5213e11e83f66c374637839548f3c871f6df3b6868Christopher Tate    private static final int DEFAULT_BUFFER_LEN = 32*1024;
53087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor
548a2ed1d7c0c4f6476e39cc37d9ebd29c7562ce01Dianne Hackborn    private static String sSpace = "                                                              ";
558a2ed1d7c0c4f6476e39cc37d9ebd29c7562ce01Dianne Hackborn
5613e11e83f66c374637839548f3c871f6df3b6868Christopher Tate    private final int mBufferLen;
5713e11e83f66c374637839548f3c871f6df3b6868Christopher Tate    private final char[] mText;
58087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor    private int mPos;
59087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor
60087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor    private Writer mWriter;
61087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor
62087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor    private OutputStream mOutputStream;
63087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor    private CharsetEncoder mCharset;
6413e11e83f66c374637839548f3c871f6df3b6868Christopher Tate    private ByteBuffer mBytes;
65087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor
668a2ed1d7c0c4f6476e39cc37d9ebd29c7562ce01Dianne Hackborn    private boolean mIndent = false;
67087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor    private boolean mInTag;
68087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor
698a2ed1d7c0c4f6476e39cc37d9ebd29c7562ce01Dianne Hackborn    private int mNesting = 0;
708a2ed1d7c0c4f6476e39cc37d9ebd29c7562ce01Dianne Hackborn    private boolean mLineStart = true;
718a2ed1d7c0c4f6476e39cc37d9ebd29c7562ce01Dianne Hackborn
7213e11e83f66c374637839548f3c871f6df3b6868Christopher Tate    public FastXmlSerializer() {
7313e11e83f66c374637839548f3c871f6df3b6868Christopher Tate        this(DEFAULT_BUFFER_LEN);
7413e11e83f66c374637839548f3c871f6df3b6868Christopher Tate    }
7513e11e83f66c374637839548f3c871f6df3b6868Christopher Tate
7613e11e83f66c374637839548f3c871f6df3b6868Christopher Tate    /**
7713e11e83f66c374637839548f3c871f6df3b6868Christopher Tate     * Allocate a FastXmlSerializer with the given internal output buffer size.  If the
7813e11e83f66c374637839548f3c871f6df3b6868Christopher Tate     * size is zero or negative, then the default buffer size will be used.
7913e11e83f66c374637839548f3c871f6df3b6868Christopher Tate     *
8013e11e83f66c374637839548f3c871f6df3b6868Christopher Tate     * @param bufferSize Size in bytes of the in-memory output buffer that the writer will use.
8113e11e83f66c374637839548f3c871f6df3b6868Christopher Tate     */
8213e11e83f66c374637839548f3c871f6df3b6868Christopher Tate    public FastXmlSerializer(int bufferSize) {
8313e11e83f66c374637839548f3c871f6df3b6868Christopher Tate        mBufferLen = (bufferSize > 0) ? bufferSize : DEFAULT_BUFFER_LEN;
8413e11e83f66c374637839548f3c871f6df3b6868Christopher Tate        mText = new char[mBufferLen];
8513e11e83f66c374637839548f3c871f6df3b6868Christopher Tate        mBytes = ByteBuffer.allocate(mBufferLen);
8613e11e83f66c374637839548f3c871f6df3b6868Christopher Tate    }
8713e11e83f66c374637839548f3c871f6df3b6868Christopher Tate
88087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor    private void append(char c) throws IOException {
89087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        int pos = mPos;
9013e11e83f66c374637839548f3c871f6df3b6868Christopher Tate        if (pos >= (mBufferLen-1)) {
91087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            flush();
92087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            pos = mPos;
93087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        }
94087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        mText[pos] = c;
95087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        mPos = pos+1;
96087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor    }
97087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor
98087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor    private void append(String str, int i, final int length) throws IOException {
9913e11e83f66c374637839548f3c871f6df3b6868Christopher Tate        if (length > mBufferLen) {
100087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            final int end = i + length;
101087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            while (i < end) {
10213e11e83f66c374637839548f3c871f6df3b6868Christopher Tate                int next = i + mBufferLen;
10313e11e83f66c374637839548f3c871f6df3b6868Christopher Tate                append(str, i, next<end ? mBufferLen : (end-i));
104087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor                i = next;
105087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            }
106087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            return;
107087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        }
108087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        int pos = mPos;
10913e11e83f66c374637839548f3c871f6df3b6868Christopher Tate        if ((pos+length) > mBufferLen) {
110087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            flush();
111087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            pos = mPos;
112087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        }
113087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        str.getChars(i, i+length, mText, pos);
114087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        mPos = pos + length;
115087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor    }
116087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor
117087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor    private void append(char[] buf, int i, final int length) throws IOException {
11813e11e83f66c374637839548f3c871f6df3b6868Christopher Tate        if (length > mBufferLen) {
119087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            final int end = i + length;
120087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            while (i < end) {
12113e11e83f66c374637839548f3c871f6df3b6868Christopher Tate                int next = i + mBufferLen;
12213e11e83f66c374637839548f3c871f6df3b6868Christopher Tate                append(buf, i, next<end ? mBufferLen : (end-i));
123087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor                i = next;
124087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            }
125087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            return;
126087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        }
127087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        int pos = mPos;
12813e11e83f66c374637839548f3c871f6df3b6868Christopher Tate        if ((pos+length) > mBufferLen) {
129087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            flush();
130087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            pos = mPos;
131087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        }
132087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        System.arraycopy(buf, i, mText, pos, length);
133087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        mPos = pos + length;
134087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor    }
135087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor
136087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor    private void append(String str) throws IOException {
137087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        append(str, 0, str.length());
138087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor    }
139087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor
1408a2ed1d7c0c4f6476e39cc37d9ebd29c7562ce01Dianne Hackborn    private void appendIndent(int indent) throws IOException {
1418a2ed1d7c0c4f6476e39cc37d9ebd29c7562ce01Dianne Hackborn        indent *= 4;
1428a2ed1d7c0c4f6476e39cc37d9ebd29c7562ce01Dianne Hackborn        if (indent > sSpace.length()) {
1438a2ed1d7c0c4f6476e39cc37d9ebd29c7562ce01Dianne Hackborn            indent = sSpace.length();
1448a2ed1d7c0c4f6476e39cc37d9ebd29c7562ce01Dianne Hackborn        }
1458a2ed1d7c0c4f6476e39cc37d9ebd29c7562ce01Dianne Hackborn        append(sSpace, 0, indent);
1468a2ed1d7c0c4f6476e39cc37d9ebd29c7562ce01Dianne Hackborn    }
1478a2ed1d7c0c4f6476e39cc37d9ebd29c7562ce01Dianne Hackborn
148087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor    private void escapeAndAppendString(final String string) throws IOException {
149087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        final int N = string.length();
150087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        final char NE = (char)ESCAPE_TABLE.length;
151087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        final String[] escapes = ESCAPE_TABLE;
152087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        int lastPos = 0;
153087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        int pos;
154087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        for (pos=0; pos<N; pos++) {
155087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            char c = string.charAt(pos);
156087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            if (c >= NE) continue;
157087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            String escape = escapes[c];
158087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            if (escape == null) continue;
159087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            if (lastPos < pos) append(string, lastPos, pos-lastPos);
160087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            lastPos = pos + 1;
161087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            append(escape);
162087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        }
163087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        if (lastPos < pos) append(string, lastPos, pos-lastPos);
164087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor    }
165087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor
166087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor    private void escapeAndAppendString(char[] buf, int start, int len) throws IOException {
167087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        final char NE = (char)ESCAPE_TABLE.length;
168087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        final String[] escapes = ESCAPE_TABLE;
169087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        int end = start+len;
170087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        int lastPos = start;
171087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        int pos;
172087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        for (pos=start; pos<end; pos++) {
173087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            char c = buf[pos];
174087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            if (c >= NE) continue;
175087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            String escape = escapes[c];
176087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            if (escape == null) continue;
177087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            if (lastPos < pos) append(buf, lastPos, pos-lastPos);
178087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            lastPos = pos + 1;
179087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            append(escape);
180087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        }
181087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        if (lastPos < pos) append(buf, lastPos, pos-lastPos);
182087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor    }
183087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor
184087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor    public XmlSerializer attribute(String namespace, String name, String value) throws IOException,
185087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            IllegalArgumentException, IllegalStateException {
186087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        append(' ');
187087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        if (namespace != null) {
188087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            append(namespace);
189087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            append(':');
190087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        }
191087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        append(name);
192087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        append("=\"");
193087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor
194087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        escapeAndAppendString(value);
195087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        append('"');
1968a2ed1d7c0c4f6476e39cc37d9ebd29c7562ce01Dianne Hackborn        mLineStart = false;
197087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        return this;
198087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor    }
199087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor
200087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor    public void cdsect(String text) throws IOException, IllegalArgumentException,
201087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            IllegalStateException {
202087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        throw new UnsupportedOperationException();
203087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor    }
204087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor
205087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor    public void comment(String text) throws IOException, IllegalArgumentException,
206087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            IllegalStateException {
207087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        throw new UnsupportedOperationException();
208087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor    }
209087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor
210087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor    public void docdecl(String text) throws IOException, IllegalArgumentException,
211087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            IllegalStateException {
212087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        throw new UnsupportedOperationException();
213087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor    }
214087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor
215087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor    public void endDocument() throws IOException, IllegalArgumentException, IllegalStateException {
216087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        flush();
217087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor    }
218087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor
219087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor    public XmlSerializer endTag(String namespace, String name) throws IOException,
220087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            IllegalArgumentException, IllegalStateException {
2218a2ed1d7c0c4f6476e39cc37d9ebd29c7562ce01Dianne Hackborn        mNesting--;
222087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        if (mInTag) {
223087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            append(" />\n");
224087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        } else {
2258a2ed1d7c0c4f6476e39cc37d9ebd29c7562ce01Dianne Hackborn            if (mIndent && mLineStart) {
2268a2ed1d7c0c4f6476e39cc37d9ebd29c7562ce01Dianne Hackborn                appendIndent(mNesting);
2278a2ed1d7c0c4f6476e39cc37d9ebd29c7562ce01Dianne Hackborn            }
228087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            append("</");
229087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            if (namespace != null) {
230087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor                append(namespace);
231087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor                append(':');
232087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            }
233087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            append(name);
234087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            append(">\n");
235087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        }
2368a2ed1d7c0c4f6476e39cc37d9ebd29c7562ce01Dianne Hackborn        mLineStart = true;
237087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        mInTag = false;
238087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        return this;
239087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor    }
240087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor
241087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor    public void entityRef(String text) throws IOException, IllegalArgumentException,
242087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            IllegalStateException {
243087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        throw new UnsupportedOperationException();
244087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor    }
245087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor
246087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor    private void flushBytes() throws IOException {
247087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        int position;
248087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        if ((position = mBytes.position()) > 0) {
249087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            mBytes.flip();
250087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            mOutputStream.write(mBytes.array(), 0, position);
251087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            mBytes.clear();
252087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        }
253087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor    }
254087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor
255087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor    public void flush() throws IOException {
256087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        //Log.i("PackageManager", "flush mPos=" + mPos);
257087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        if (mPos > 0) {
258087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            if (mOutputStream != null) {
259087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor                CharBuffer charBuffer = CharBuffer.wrap(mText, 0, mPos);
260087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor                CoderResult result = mCharset.encode(charBuffer, mBytes, true);
261087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor                while (true) {
262087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor                    if (result.isError()) {
263087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor                        throw new IOException(result.toString());
264087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor                    } else if (result.isOverflow()) {
265087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor                        flushBytes();
266087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor                        result = mCharset.encode(charBuffer, mBytes, true);
267087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor                        continue;
268087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor                    }
269087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor                    break;
270087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor                }
271087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor                flushBytes();
272087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor                mOutputStream.flush();
273087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            } else {
274087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor                mWriter.write(mText, 0, mPos);
275087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor                mWriter.flush();
276087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            }
277087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            mPos = 0;
278087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        }
279087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor    }
280087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor
281087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor    public int getDepth() {
282087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        throw new UnsupportedOperationException();
283087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor    }
284087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor
285087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor    public boolean getFeature(String name) {
286087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        throw new UnsupportedOperationException();
287087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor    }
288087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor
289087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor    public String getName() {
290087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        throw new UnsupportedOperationException();
291087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor    }
292087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor
293087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor    public String getNamespace() {
294087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        throw new UnsupportedOperationException();
295087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor    }
296087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor
297087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor    public String getPrefix(String namespace, boolean generatePrefix)
298087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            throws IllegalArgumentException {
299087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        throw new UnsupportedOperationException();
300087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor    }
301087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor
302087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor    public Object getProperty(String name) {
303087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        throw new UnsupportedOperationException();
304087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor    }
305087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor
306087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor    public void ignorableWhitespace(String text) throws IOException, IllegalArgumentException,
307087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            IllegalStateException {
308087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        throw new UnsupportedOperationException();
309087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor    }
310087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor
311087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor    public void processingInstruction(String text) throws IOException, IllegalArgumentException,
312087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            IllegalStateException {
313087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        throw new UnsupportedOperationException();
314087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor    }
315087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor
316087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor    public void setFeature(String name, boolean state) throws IllegalArgumentException,
317087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            IllegalStateException {
318087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        if (name.equals("http://xmlpull.org/v1/doc/features.html#indent-output")) {
3198a2ed1d7c0c4f6476e39cc37d9ebd29c7562ce01Dianne Hackborn            mIndent = true;
320087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            return;
321087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        }
322087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        throw new UnsupportedOperationException();
323087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor    }
324087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor
325087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor    public void setOutput(OutputStream os, String encoding) throws IOException,
326087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            IllegalArgumentException, IllegalStateException {
327087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        if (os == null)
328087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            throw new IllegalArgumentException();
329087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        if (true) {
330087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            try {
3313ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki                mCharset = Charset.forName(encoding).newEncoder()
3323ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki                        .onMalformedInput(CodingErrorAction.REPLACE)
3333ae3557ea3a9ad8429de9db14de62a4214a07cdcMakoto Onuki                        .onUnmappableCharacter(CodingErrorAction.REPLACE);
334087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            } catch (IllegalCharsetNameException e) {
335087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor                throw (UnsupportedEncodingException) (new UnsupportedEncodingException(
336087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor                        encoding).initCause(e));
337087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            } catch (UnsupportedCharsetException e) {
338087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor                throw (UnsupportedEncodingException) (new UnsupportedEncodingException(
339087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor                        encoding).initCause(e));
340087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            }
341087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            mOutputStream = os;
342087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        } else {
343087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            setOutput(
344087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor                encoding == null
345087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor                    ? new OutputStreamWriter(os)
346087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor                    : new OutputStreamWriter(os, encoding));
347087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        }
348087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor    }
349087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor
350087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor    public void setOutput(Writer writer) throws IOException, IllegalArgumentException,
351087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            IllegalStateException {
352087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        mWriter = writer;
353087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor    }
354087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor
355087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor    public void setPrefix(String prefix, String namespace) throws IOException,
356087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            IllegalArgumentException, IllegalStateException {
357087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        throw new UnsupportedOperationException();
358087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor    }
359087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor
360087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor    public void setProperty(String name, Object value) throws IllegalArgumentException,
361087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            IllegalStateException {
362087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        throw new UnsupportedOperationException();
363087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor    }
364087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor
365087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor    public void startDocument(String encoding, Boolean standalone) throws IOException,
366087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            IllegalArgumentException, IllegalStateException {
367087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        append("<?xml version='1.0' encoding='utf-8' standalone='"
368087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor                + (standalone ? "yes" : "no") + "' ?>\n");
3698a2ed1d7c0c4f6476e39cc37d9ebd29c7562ce01Dianne Hackborn        mLineStart = true;
370087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor    }
371087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor
372087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor    public XmlSerializer startTag(String namespace, String name) throws IOException,
373087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            IllegalArgumentException, IllegalStateException {
374087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        if (mInTag) {
375087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            append(">\n");
376087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        }
3778a2ed1d7c0c4f6476e39cc37d9ebd29c7562ce01Dianne Hackborn        if (mIndent) {
3788a2ed1d7c0c4f6476e39cc37d9ebd29c7562ce01Dianne Hackborn            appendIndent(mNesting);
3798a2ed1d7c0c4f6476e39cc37d9ebd29c7562ce01Dianne Hackborn        }
3808a2ed1d7c0c4f6476e39cc37d9ebd29c7562ce01Dianne Hackborn        mNesting++;
381087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        append('<');
382087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        if (namespace != null) {
383087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            append(namespace);
384087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            append(':');
385087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        }
386087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        append(name);
387087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        mInTag = true;
3888a2ed1d7c0c4f6476e39cc37d9ebd29c7562ce01Dianne Hackborn        mLineStart = false;
389087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        return this;
390087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor    }
391087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor
392087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor    public XmlSerializer text(char[] buf, int start, int len) throws IOException,
393087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            IllegalArgumentException, IllegalStateException {
394087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        if (mInTag) {
395087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            append(">");
396087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            mInTag = false;
397087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        }
398087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        escapeAndAppendString(buf, start, len);
3998a2ed1d7c0c4f6476e39cc37d9ebd29c7562ce01Dianne Hackborn        if (mIndent) {
4008a2ed1d7c0c4f6476e39cc37d9ebd29c7562ce01Dianne Hackborn            mLineStart = buf[start+len-1] == '\n';
4018a2ed1d7c0c4f6476e39cc37d9ebd29c7562ce01Dianne Hackborn        }
402087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        return this;
403087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor    }
404087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor
405087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor    public XmlSerializer text(String text) throws IOException, IllegalArgumentException,
406087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            IllegalStateException {
407087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        if (mInTag) {
408087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            append(">");
409087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor            mInTag = false;
410087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        }
411087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        escapeAndAppendString(text);
4128a2ed1d7c0c4f6476e39cc37d9ebd29c7562ce01Dianne Hackborn        if (mIndent) {
4133029bf225cfa2c4b5b6e76303b0eba0d91c21026Jeff Sharkey            mLineStart = text.length() > 0 && (text.charAt(text.length()-1) == '\n');
4148a2ed1d7c0c4f6476e39cc37d9ebd29c7562ce01Dianne Hackborn        }
415087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor        return this;
416087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor    }
417087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor
418087ff0b93580760bf0c5dd36a0081289224b1cdeTom Taylor}
419