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="https://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 }