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        public void startDocument() throws SAXException {}
067            
068        public void endDocument() throws SAXException {}
069            
070        public void startElement(String ns,
071                                 String sname,
072                                 String qname,
073                                 Attributes attrs) throws SAXException {
074          charsValid = false;
075          if ("boolean".equals(qname) ||
076              "i4".equals(qname) ||
077              "int".equals(qname) ||
078              "string".equals(qname) ||
079              "double".equals(qname) ||
080              "ex:i1".equals(qname) ||
081              "ex:i8".equals(qname) ||
082              "ex:float".equals(qname)) {
083            charsValid = true;
084            valList.add(new Value(qname));
085          } else if ("struct".equals(qname) ||
086                     "array".equals(qname)) {
087            valList.add(new Value(qname));
088          }
089        }
090            
091        public void endElement(String ns,
092                               String sname,
093                               String qname) throws SAXException {
094          charsValid = false;
095          if ("struct".equals(qname) ||
096              "array".equals(qname)) {
097            valList.add(new Value("/"+qname));
098          }
099        }
100            
101        public void characters(char buf[], int offset, int len)
102          throws SAXException {
103          if (charsValid) {
104            Value v = valList.get(valList.size()-1);
105            v.addChars(buf, offset, len);
106          }
107        }
108            
109      }
110        
111      private class XmlIndex implements Index {
112        public boolean done() {
113          Value v = valList.get(vIdx);
114          if ("/array".equals(v.getType())) {
115            valList.set(vIdx, null);
116            vIdx++;
117            return true;
118          } else {
119            return false;
120          }
121        }
122        public void incr() {}
123      }
124        
125      private ArrayList<Value> valList;
126      private int vLen;
127      private int vIdx;
128        
129      private Value next() throws IOException {
130        if (vIdx < vLen) {
131          Value v = valList.get(vIdx);
132          valList.set(vIdx, null);
133          vIdx++;
134          return v;
135        } else {
136          throw new IOException("Error in deserialization.");
137        }
138      }
139        
140      /** Creates a new instance of XmlRecordInput */
141      public XmlRecordInput(InputStream in) {
142        try{
143          valList = new ArrayList<Value>();
144          DefaultHandler handler = new XMLParser(valList);
145          SAXParserFactory factory = SAXParserFactory.newInstance();
146          SAXParser parser = factory.newSAXParser();
147          parser.parse(in, handler);
148          vLen = valList.size();
149          vIdx = 0;
150        } catch (Exception ex) {
151          throw new RuntimeException(ex);
152        }
153      }
154        
155      public byte readByte(String tag) throws IOException {
156        Value v = next();
157        if (!"ex:i1".equals(v.getType())) {
158          throw new IOException("Error deserializing "+tag+".");
159        }
160        return Byte.parseByte(v.getValue());
161      }
162        
163      public boolean readBool(String tag) throws IOException {
164        Value v = next();
165        if (!"boolean".equals(v.getType())) {
166          throw new IOException("Error deserializing "+tag+".");
167        }
168        return "1".equals(v.getValue());
169      }
170        
171      public int readInt(String tag) throws IOException {
172        Value v = next();
173        if (!"i4".equals(v.getType()) &&
174            !"int".equals(v.getType())) {
175          throw new IOException("Error deserializing "+tag+".");
176        }
177        return Integer.parseInt(v.getValue());
178      }
179        
180      public long readLong(String tag) throws IOException {
181        Value v = next();
182        if (!"ex:i8".equals(v.getType())) {
183          throw new IOException("Error deserializing "+tag+".");
184        }
185        return Long.parseLong(v.getValue());
186      }
187        
188      public float readFloat(String tag) throws IOException {
189        Value v = next();
190        if (!"ex:float".equals(v.getType())) {
191          throw new IOException("Error deserializing "+tag+".");
192        }
193        return Float.parseFloat(v.getValue());
194      }
195        
196      public double readDouble(String tag) throws IOException {
197        Value v = next();
198        if (!"double".equals(v.getType())) {
199          throw new IOException("Error deserializing "+tag+".");
200        }
201        return Double.parseDouble(v.getValue());
202      }
203        
204      public String readString(String tag) throws IOException {
205        Value v = next();
206        if (!"string".equals(v.getType())) {
207          throw new IOException("Error deserializing "+tag+".");
208        }
209        return Utils.fromXMLString(v.getValue());
210      }
211        
212      public Buffer readBuffer(String tag) throws IOException {
213        Value v = next();
214        if (!"string".equals(v.getType())) {
215          throw new IOException("Error deserializing "+tag+".");
216        }
217        return Utils.fromXMLBuffer(v.getValue());
218      }
219        
220      public void startRecord(String tag) throws IOException {
221        Value v = next();
222        if (!"struct".equals(v.getType())) {
223          throw new IOException("Error deserializing "+tag+".");
224        }
225      }
226        
227      public void endRecord(String tag) throws IOException {
228        Value v = next();
229        if (!"/struct".equals(v.getType())) {
230          throw new IOException("Error deserializing "+tag+".");
231        }
232      }
233        
234      public Index startVector(String tag) throws IOException {
235        Value v = next();
236        if (!"array".equals(v.getType())) {
237          throw new IOException("Error deserializing "+tag+".");
238        }
239        return new XmlIndex();
240      }
241        
242      public void endVector(String tag) throws IOException {}
243        
244      public Index startMap(String tag) throws IOException {
245        return startVector(tag);
246      }
247        
248      public void endMap(String tag) throws IOException { endVector(tag); }
249    
250    }