/******************************************************************************* * Copyright (c) 2011 Arapiki Solutions Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * "Peter Smith <psmith@arapiki.com>" - initial API and * implementation and/or initial documentation *******************************************************************************/ package com.buildml.scanner.electricanno; import java.io.ByteArrayInputStream; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import org.xml.sax.ContentHandler; import org.xml.sax.EntityResolver; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.XMLReader; import org.xml.sax.helpers.XMLReaderFactory; import com.buildml.model.IBuildStore; import com.buildml.utils.files.ProgressFileInputStream; import com.buildml.utils.files.ProgressFileInputStreamListener; /** * Class for reading an Electric Accelerator annotation file, and populating a * BuildStore database from the build data it contains. * * @author "Peter Smith <psmith@arapiki.com>" */ public class ElectricAnnoScanner { /*=====================================================================================* * TYPES/FIELDS *=====================================================================================*/ /** The BuildStore object to which the annotation data will be added. */ private IBuildStore buildStore; /*=====================================================================================* * CONSTRUCTORS *=====================================================================================*/ /** * Create a new ElectricAnnoScanner object, which will add data to the specified BuildStore. * * @param buildStore The BuildStore to add the EC Annotation data into. */ public ElectricAnnoScanner(IBuildStore buildStore) { this.buildStore = buildStore; } /*=====================================================================================* * PUBLIC METHODS *=====================================================================================*/ /** * Parse and store the content of the specified Electric Accelerator annotation file. * * @param annoFileName The Electric Accelerator annotation file. * @param listener The callback to receive progress reports. * @throws IOException Something when wrong as the file was being read. * @throws FileNotFoundException The annotation file couldn't be found. * @throws SAXException The XML structure of this file is incorrect. */ public void parse(String annoFileName, ProgressFileInputStreamListener listener) throws FileNotFoundException, IOException, SAXException { /* Open the file for input, and report progress every two seconds */ FileInputStream in = new ProgressFileInputStream(annoFileName, listener, 2); /* * Create a new XMLReader to parse this file, then set the ContentHandler * to our own SAX handler class. */ XMLReader parser = XMLReaderFactory.createXMLReader(); ContentHandler contentHandler = new ElectricAnnoSAXHandler(buildStore); parser.setContentHandler(contentHandler); /* * We want to ignore the *.dtd file mentioned in this *.xml file by returning * the null String whenever a URL is resolved. The has the effect of allowing * us to parse the *.xml file without validating the XML structure. We override * the resolver's "resolveEntity" method with something that returns an empty file. */ parser.setEntityResolver(new EntityResolver() { @Override public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException { return new InputSource( new ByteArrayInputStream("<?xml version='1.0' encoding='UTF-8'?>".getBytes())); } }); /* * Read the *.xml file and process the content. This could take a long * time, so put the database in fast mode. */ boolean prevState = buildStore.setFastAccessMode(true); try { parser.parse(new InputSource(in)); } finally { buildStore.setFastAccessMode(prevState); } } /*-------------------------------------------------------------------------------------*/ }