001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018
019 package org.apache.hadoop.record;
020
021 import java.io.InputStream;
022 import java.io.IOException;
023 import java.util.ArrayList;
024
025 import org.apache.hadoop.classification.InterfaceAudience;
026 import org.apache.hadoop.classification.InterfaceStability;
027 import org.xml.sax.*;
028 import org.xml.sax.helpers.DefaultHandler;
029 import javax.xml.parsers.SAXParserFactory;
030 import javax.xml.parsers.SAXParser;
031
032 /**
033 * XML Deserializer.
034 *
035 * @deprecated Replaced by <a href="http://hadoop.apache.org/avro/">Avro</a>.
036 */
037 @Deprecated
038 @InterfaceAudience.Public
039 @InterfaceStability.Stable
040 public class XmlRecordInput implements RecordInput {
041
042 static private class Value {
043 private String type;
044 private StringBuffer sb;
045
046 public Value(String t) {
047 type = t;
048 sb = new StringBuffer();
049 }
050 public void addChars(char[] buf, int offset, int len) {
051 sb.append(buf, offset, len);
052 }
053 public String getValue() { return sb.toString(); }
054 public String getType() { return type; }
055 }
056
057 private static class XMLParser extends DefaultHandler {
058 private boolean charsValid = false;
059
060 private ArrayList<Value> valList;
061
062 private XMLParser(ArrayList<Value> vlist) {
063 valList = vlist;
064 }
065
066 @Override
067 public void startDocument() throws SAXException {}
068
069 @Override
070 public void endDocument() throws SAXException {}
071
072 @Override
073 public void startElement(String ns,
074 String sname,
075 String qname,
076 Attributes attrs) throws SAXException {
077 charsValid = false;
078 if ("boolean".equals(qname) ||
079 "i4".equals(qname) ||
080 "int".equals(qname) ||
081 "string".equals(qname) ||
082 "double".equals(qname) ||
083 "ex:i1".equals(qname) ||
084 "ex:i8".equals(qname) ||
085 "ex:float".equals(qname)) {
086 charsValid = true;
087 valList.add(new Value(qname));
088 } else if ("struct".equals(qname) ||
089 "array".equals(qname)) {
090 valList.add(new Value(qname));
091 }
092 }
093
094 @Override
095 public void endElement(String ns,
096 String sname,
097 String qname) throws SAXException {
098 charsValid = false;
099 if ("struct".equals(qname) ||
100 "array".equals(qname)) {
101 valList.add(new Value("/"+qname));
102 }
103 }
104
105 @Override
106 public void characters(char buf[], int offset, int len)
107 throws SAXException {
108 if (charsValid) {
109 Value v = valList.get(valList.size()-1);
110 v.addChars(buf, offset, len);
111 }
112 }
113
114 }
115
116 private class XmlIndex implements Index {
117 @Override
118 public boolean done() {
119 Value v = valList.get(vIdx);
120 if ("/array".equals(v.getType())) {
121 valList.set(vIdx, null);
122 vIdx++;
123 return true;
124 } else {
125 return false;
126 }
127 }
128 @Override
129 public void incr() {}
130 }
131
132 private ArrayList<Value> valList;
133 private int vLen;
134 private int vIdx;
135
136 private Value next() throws IOException {
137 if (vIdx < vLen) {
138 Value v = valList.get(vIdx);
139 valList.set(vIdx, null);
140 vIdx++;
141 return v;
142 } else {
143 throw new IOException("Error in deserialization.");
144 }
145 }
146
147 /** Creates a new instance of XmlRecordInput */
148 public XmlRecordInput(InputStream in) {
149 try{
150 valList = new ArrayList<Value>();
151 DefaultHandler handler = new XMLParser(valList);
152 SAXParserFactory factory = SAXParserFactory.newInstance();
153 SAXParser parser = factory.newSAXParser();
154 parser.parse(in, handler);
155 vLen = valList.size();
156 vIdx = 0;
157 } catch (Exception ex) {
158 throw new RuntimeException(ex);
159 }
160 }
161
162 @Override
163 public byte readByte(String tag) throws IOException {
164 Value v = next();
165 if (!"ex:i1".equals(v.getType())) {
166 throw new IOException("Error deserializing "+tag+".");
167 }
168 return Byte.parseByte(v.getValue());
169 }
170
171 @Override
172 public boolean readBool(String tag) throws IOException {
173 Value v = next();
174 if (!"boolean".equals(v.getType())) {
175 throw new IOException("Error deserializing "+tag+".");
176 }
177 return "1".equals(v.getValue());
178 }
179
180 @Override
181 public int readInt(String tag) throws IOException {
182 Value v = next();
183 if (!"i4".equals(v.getType()) &&
184 !"int".equals(v.getType())) {
185 throw new IOException("Error deserializing "+tag+".");
186 }
187 return Integer.parseInt(v.getValue());
188 }
189
190 @Override
191 public long readLong(String tag) throws IOException {
192 Value v = next();
193 if (!"ex:i8".equals(v.getType())) {
194 throw new IOException("Error deserializing "+tag+".");
195 }
196 return Long.parseLong(v.getValue());
197 }
198
199 @Override
200 public float readFloat(String tag) throws IOException {
201 Value v = next();
202 if (!"ex:float".equals(v.getType())) {
203 throw new IOException("Error deserializing "+tag+".");
204 }
205 return Float.parseFloat(v.getValue());
206 }
207
208 @Override
209 public double readDouble(String tag) throws IOException {
210 Value v = next();
211 if (!"double".equals(v.getType())) {
212 throw new IOException("Error deserializing "+tag+".");
213 }
214 return Double.parseDouble(v.getValue());
215 }
216
217 @Override
218 public String readString(String tag) throws IOException {
219 Value v = next();
220 if (!"string".equals(v.getType())) {
221 throw new IOException("Error deserializing "+tag+".");
222 }
223 return Utils.fromXMLString(v.getValue());
224 }
225
226 @Override
227 public Buffer readBuffer(String tag) throws IOException {
228 Value v = next();
229 if (!"string".equals(v.getType())) {
230 throw new IOException("Error deserializing "+tag+".");
231 }
232 return Utils.fromXMLBuffer(v.getValue());
233 }
234
235 @Override
236 public void startRecord(String tag) throws IOException {
237 Value v = next();
238 if (!"struct".equals(v.getType())) {
239 throw new IOException("Error deserializing "+tag+".");
240 }
241 }
242
243 @Override
244 public void endRecord(String tag) throws IOException {
245 Value v = next();
246 if (!"/struct".equals(v.getType())) {
247 throw new IOException("Error deserializing "+tag+".");
248 }
249 }
250
251 @Override
252 public Index startVector(String tag) throws IOException {
253 Value v = next();
254 if (!"array".equals(v.getType())) {
255 throw new IOException("Error deserializing "+tag+".");
256 }
257 return new XmlIndex();
258 }
259
260 @Override
261 public void endVector(String tag) throws IOException {}
262
263 @Override
264 public Index startMap(String tag) throws IOException {
265 return startVector(tag);
266 }
267
268 @Override
269 public void endMap(String tag) throws IOException { endVector(tag); }
270
271 }