/*
Copyright 2008-2010 Gephi
Authors : Mathieu Bastian <mathieu.bastian@gephi.org>
Website : http://www.gephi.org
This file is part of Gephi.
Gephi is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
Gephi is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with Gephi. If not, see <http://www.gnu.org/licenses/>.
*/
package org.gephi.io.importer.api;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.LineNumberReader;
import java.io.Reader;
import java.nio.ByteBuffer;
import java.util.zip.GZIPInputStream;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.stream.Location;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLReporter;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream;
import org.gephi.utils.CharsetToolkit;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.util.Exceptions;
import org.openide.util.NbBundle;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
/**
*
* @author Mathieu Bastian
*/
public final class ImportUtils {
/**
* Returns a <code>LineNumberReader</code> for <code>fileObject</code>. The file must
* be a text file. The charset is detected automatically.
* @param fileObject the file object that is to be read
* @return a reader for the text file
* @throws IOException if the file can't be found or read
*/
public static LineNumberReader getTextReader(FileObject fileObject) throws IOException {
try {
return getTextReader(fileObject.getInputStream());
} catch (IOException ex) {
throw new IOException(NbBundle.getMessage(ImportUtils.class, "ImportUtils.error_file_not_found"));
}
}
/**
* Returns a <code>LineNumberReader</code> for <code>inputStream</code>. The stream must
* be a character stream. The charset is detected automatically.
* @param stream the stream that is to be read
* @return a reader for the character stream
* @throws IOException if the stream can't be read
*/
public static LineNumberReader getTextReader(InputStream stream) throws IOException {
LineNumberReader reader;
CharsetToolkit charsetToolkit = new CharsetToolkit(stream);
reader = (LineNumberReader) charsetToolkit.getReader();
return reader;
}
public static LineNumberReader getTextReader(Reader reader) {
LineNumberReader lineNumberReader = new LineNumberReader(reader);
return lineNumberReader;
}
public static Document getXMLDocument(InputStream stream) throws RuntimeException {
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(stream);
return document;
} catch (ParserConfigurationException ex) {
throw new RuntimeException(NbBundle.getMessage(ImportUtils.class, "ImportUtils.error_missing_document_instance_factory"));
} catch (FileNotFoundException ex) {
throw new RuntimeException(NbBundle.getMessage(ImportUtils.class, "ImportUtils.error_file_not_found"));
} catch (SAXException ex) {
throw new RuntimeException(NbBundle.getMessage(ImportUtils.class, "ImportUtils.error_sax"));
} catch (IOException ex) {
throw new RuntimeException(NbBundle.getMessage(ImportUtils.class, "ImportUtils.error_io"));
}
}
public static Document getXMLDocument(Reader reader) throws RuntimeException {
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(new InputSource(reader));
return document;
} catch (ParserConfigurationException ex) {
throw new RuntimeException(NbBundle.getMessage(ImportUtils.class, "ImportUtils.error_missing_document_instance_factory"));
} catch (FileNotFoundException ex) {
throw new RuntimeException(NbBundle.getMessage(ImportUtils.class, "ImportUtils.error_file_not_found"));
} catch (SAXException ex) {
throw new RuntimeException(NbBundle.getMessage(ImportUtils.class, "ImportUtils.error_sax"));
} catch (IOException ex) {
throw new RuntimeException(NbBundle.getMessage(ImportUtils.class, "ImportUtils.error_io"));
}
}
public static Document getXMLDocument(FileObject fileObject) throws RuntimeException {
try {
InputStream stream = fileObject.getInputStream();
return getXMLDocument(stream);
} catch (FileNotFoundException ex) {
throw new RuntimeException(NbBundle.getMessage(ImportUtils.class, "ImportUtils.error_file_not_found"));
}
}
public static XMLStreamReader getXMLReader(Reader reader) {
try {
XMLInputFactory inputFactory = XMLInputFactory.newInstance();
if (inputFactory.isPropertySupported("javax.xml.stream.isValidating")) {
inputFactory.setProperty("javax.xml.stream.isValidating", Boolean.FALSE);
}
inputFactory.setXMLReporter(new XMLReporter() {
@Override
public void report(String message, String errorType, Object relatedInformation, Location location) throws XMLStreamException {
throw new RuntimeException("Error:" + errorType + ", message : " + message);
//System.out.println("Error:" + errorType + ", message : " + message);
}
});
return inputFactory.createXMLStreamReader(reader);
} catch (XMLStreamException ex) {
throw new RuntimeException(NbBundle.getMessage(ImportUtils.class, "ImportUtils.error_io"));
}
}
public static FileObject getArchivedFile(FileObject fileObject) {
if (FileUtil.isArchiveFile(fileObject)) {
fileObject = FileUtil.getArchiveRoot(fileObject).getChildren()[0];
}
return fileObject;
}
/**
* Uncompress a Bzip2 file.
*/
public static File getBzipFile(FileObject in, File out, boolean isTar) throws IOException {
// Stream buffer
final int BUFF_SIZE = 8192;
final byte[] buffer = new byte[BUFF_SIZE];
BZip2CompressorInputStream inputStream = null;
FileOutputStream outStream = null;
try {
FileInputStream is = new FileInputStream(in.getPath());
inputStream = new BZip2CompressorInputStream(is);
outStream = new FileOutputStream(out.getAbsolutePath());
if (isTar) {
// Read Tar header
int remainingBytes = readTarHeader(inputStream);
// Read content
ByteBuffer bb = ByteBuffer.allocateDirect(4 * BUFF_SIZE);
byte[] tmpCache = new byte[BUFF_SIZE];
int nRead, nGet;
while ((nRead = inputStream.read(tmpCache)) != -1) {
if (nRead == 0) {
continue;
}
bb.put(tmpCache);
bb.position(0);
bb.limit(nRead);
while (bb.hasRemaining() && remainingBytes > 0) {
nGet = Math.min(bb.remaining(), BUFF_SIZE);
nGet = Math.min(nGet, remainingBytes);
bb.get(buffer, 0, nGet);
outStream.write(buffer, 0, nGet);
remainingBytes -= nGet;
}
bb.clear();
}
} else {
int len;
while ((len = inputStream.read(buffer)) > 0) {
outStream.write(buffer, 0, len);
}
}
} catch (IOException ex) {
Exceptions.printStackTrace(ex);
} finally {
if (inputStream != null) {
inputStream.close();
}
if (outStream != null) {
outStream.close();
}
}
return out;
}
/**
* Uncompress a GZIP file.
*/
public static File getGzFile(FileObject in, File out, boolean isTar) throws IOException {
// Stream buffer
final int BUFF_SIZE = 8192;
final byte[] buffer = new byte[BUFF_SIZE];
GZIPInputStream inputStream = null;
FileOutputStream outStream = null;
try {
inputStream = new GZIPInputStream(new FileInputStream(in.getPath()));
outStream = new FileOutputStream(out);
if (isTar) {
// Read Tar header
int remainingBytes = readTarHeader(inputStream);
// Read content
ByteBuffer bb = ByteBuffer.allocateDirect(4 * BUFF_SIZE);
byte[] tmpCache = new byte[BUFF_SIZE];
int nRead, nGet;
while ((nRead = inputStream.read(tmpCache)) != -1) {
if (nRead == 0) {
continue;
}
bb.put(tmpCache);
bb.position(0);
bb.limit(nRead);
while (bb.hasRemaining() && remainingBytes > 0) {
nGet = Math.min(bb.remaining(), BUFF_SIZE);
nGet = Math.min(nGet, remainingBytes);
bb.get(buffer, 0, nGet);
outStream.write(buffer, 0, nGet);
remainingBytes -= nGet;
}
bb.clear();
}
} else {
int len;
while ((len = inputStream.read(buffer)) > 0) {
outStream.write(buffer, 0, len);
}
}
} catch (IOException ex) {
Exceptions.printStackTrace(ex);
} finally {
if (inputStream != null) {
inputStream.close();
}
if (outStream != null) {
outStream.close();
}
}
return out;
}
private static int readTarHeader(InputStream inputStream) throws IOException {
// Tar bytes
final int FILE_SIZE_OFFSET = 124;
final int FILE_SIZE_LENGTH = 12;
final int HEADER_LENGTH = 512;
ignoreBytes(inputStream, FILE_SIZE_OFFSET);
String fileSizeLengthOctalString = readString(inputStream, FILE_SIZE_LENGTH).trim();
final int fileSize = Integer.parseInt(fileSizeLengthOctalString, 8);
ignoreBytes(inputStream, HEADER_LENGTH - (FILE_SIZE_OFFSET + FILE_SIZE_LENGTH));
return fileSize;
}
private static void ignoreBytes(InputStream inputStream, int numberOfBytes) throws IOException {
for (int counter = 0; counter < numberOfBytes; counter++) {
inputStream.read();
}
}
private static String readString(InputStream inputStream, int numberOfBytes) throws IOException {
return new String(readBytes(inputStream, numberOfBytes));
}
private static byte[] readBytes(InputStream inputStream, int numberOfBytes) throws IOException {
byte[] readBytes = new byte[numberOfBytes];
inputStream.read(readBytes);
return readBytes;
}
}