001/*
002 * Copyright (C) 2012 eXo Platform SAS.
003 *
004 * This is free software; you can redistribute it and/or modify it
005 * under the terms of the GNU Lesser General Public License as
006 * published by the Free Software Foundation; either version 2.1 of
007 * the License, or (at your option) any later version.
008 *
009 * This software is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * You should have received a copy of the GNU Lesser General Public
015 * License along with this software; if not, write to the Free
016 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
017 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
018 */
019package org.crsh.jcr;
020
021import org.crsh.util.Safe;
022import org.xml.sax.Attributes;
023import org.xml.sax.ContentHandler;
024import org.xml.sax.SAXException;
025import org.xml.sax.helpers.DefaultHandler;
026
027import javax.xml.parsers.SAXParser;
028import javax.xml.parsers.SAXParserFactory;
029import java.io.IOException;
030import java.io.InputStream;
031import java.util.ArrayList;
032import java.util.LinkedList;
033import java.util.List;
034import java.util.logging.Level;
035import java.util.logging.Logger;
036
037public class Importer implements FileSystem {
038
039  /** . */
040  private static final Logger log = Logger.getLogger(Importer.class.getName());
041
042  /** . */
043  private final ContentHandler handler;
044
045  /** . */
046  private final LinkedList<EndElement> stack;
047
048  /** . */
049  private final List<String> prefixes;
050
051  /** . */
052  private final DefaultHandler attributesHandler = new DefaultHandler() {
053
054    @Override
055    public void startPrefixMapping(String prefix, String uri) throws SAXException {
056      if (stack.isEmpty()) {
057        log.log(Level.FINE, "Adding prefix mapping " + prefix + " for " + uri);
058        handler.startPrefixMapping(prefix, uri);
059        prefixes.add(prefix);
060      }
061    }
062
063    @Override
064    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
065      log.log(Level.FINE, "Creating element " + qName);
066      handler.startElement(uri, localName, qName, attributes);
067      stack.addLast(new EndElement(uri, localName, qName));
068    }
069  };
070
071  public Importer(ContentHandler handler) {
072    this.handler = handler;
073    this.stack = new LinkedList<EndElement>();
074    this.prefixes = new ArrayList<String>();
075  }
076
077  public void beginDirectory(String directoryName) throws IOException {
078  }
079
080  public void file(String fileName, int length, InputStream data) throws IOException {
081    try {
082      SAXParserFactory factory = SAXParserFactory.newInstance();
083      factory.setNamespaceAware(true);
084      factory.setValidating(true);
085      SAXParser parser = factory.newSAXParser();
086      parser.parse(data, attributesHandler);
087    }
088    catch (Exception e) {
089      Safe.rethrow(IOException.class, e);
090    }
091  }
092
093  public void endDirectory(String directoryName) throws IOException {
094    try {
095      EndElement end = stack.removeLast();
096      handler.endElement(end.uri, end.localName, end.qName);
097      if (stack.isEmpty()) {
098        for (String prefix : prefixes) {
099          log.log(Level.FINE, "Removing prefix mapping " + prefix);
100          handler.endPrefixMapping(prefix);
101        }
102        prefixes.clear();
103      }
104    }
105    catch (Exception e) {
106      Safe.rethrow(IOException.class, e);
107    }
108  }
109
110  private static class EndElement {
111
112    /** . */
113    private final String uri;
114
115    /** . */
116    private final String localName;
117
118    /** . */
119    private final String qName;
120
121    private EndElement(String uri, String localName, String qName) {
122      this.uri = uri;
123      this.localName = localName;
124      this.qName = qName;
125    }
126  }
127}
128