org.eclipse.smila.connectivity.framework.agent.jobfile.JobFileReader.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.smila.connectivity.framework.agent.jobfile.JobFileReader.java

Source

/*******************************************************************************
 * Copyright (c) 2008, 2011 Attensity Europe GmbH and brox IT Solutions GmbH. 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: Daniel Stucky (empolis GmbH) - initial API and implementation
 *******************************************************************************/

package org.eclipse.smila.connectivity.framework.agent.jobfile;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Iterator;

import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.smila.datamodel.Record;
import org.eclipse.smila.datamodel.xml.StaxRecordReader;

/**
 * StAX based JobFile reader. Should give better performance than the DOM based IdParser.
 */
public class JobFileReader {

    /**
     * XML tag JobFile.
     */
    public static final String TAG_JOB_FILE = "JobFile";

    /**
     * XML tag Add.
     */
    public static final String TAG_ADD = "Add";

    /**
     * XML tag Delete.
     */
    public static final String TAG_DELETE = "Delete";

    /**
     * my Record reader.
     */
    private final StaxRecordReader _recordReader;

    /**
     * Callback to the JobFileHandler.
     */
    private final JobFileHandler _jobFileHandler;

    /**
     * The separator of attachment name and url.
     */
    private final String _attachmentSeparator;

    /**
     * The length of the attachment separator.
     */
    private final int _attachmentSeparatorLength;

    /**
     * The LOG.
     */
    private final Log _log = LogFactory.getLog(JobFileReader.class);

    /**
     * create default instance.
     * 
     * @param jobFileHandler
     *          the JobFileHandler
     * @param attachmentSeparator
     *          the attachmentSeparator
     */
    public JobFileReader(final JobFileHandler jobFileHandler, final String attachmentSeparator) {
        this(jobFileHandler, attachmentSeparator, new StaxRecordReader());
    }

    /**
     * Conversion Constructor.
     * 
     * @param jobFileHandler
     *          the JobFileHandler
     * @param attachmentSeparator
     *          the attachmentSeparator
     * @param recordReader
     *          the RecordReader
     */
    public JobFileReader(final JobFileHandler jobFileHandler, final String attachmentSeparator,
            final StaxRecordReader recordReader) {
        // check parameters
        if (jobFileHandler == null) {
            throw new IllegalArgumentException("parameter jobFileHandler is null");
        }
        if (attachmentSeparator == null) {
            throw new IllegalArgumentException("parameter attachmentSeparator is null");
        }
        if (attachmentSeparator.trim().length() == 0) {
            throw new IllegalArgumentException("parameter attachmentSeparator is an empty String");
        }
        if (recordReader == null) {
            throw new IllegalArgumentException("parameter recordReader is null");
        }

        _jobFileHandler = jobFileHandler;
        _recordReader = recordReader;
        _attachmentSeparator = attachmentSeparator;
        _attachmentSeparatorLength = _attachmentSeparator.length();
    }

    /**
     * Reads in and processes a JobFile.
     * 
     * @param url
     *          the url of the job file
     * @throws XMLStreamException
     *           the StAX Exception
     */
    public void readJobFile(final URL url) throws XMLStreamException {
        // check parameters
        if (url == null) {
            throw new IllegalArgumentException("parameter url is null");
        }

        InputStream stream = null;
        try {
            stream = getInputStream(url);
            final XMLStreamReader staxReader = Activator.getXMLInputFactory().createXMLStreamReader(stream);
            parse(staxReader, url);
        } catch (XMLStreamException e) {
            throw e;
        } catch (Exception e) {
            final String msg = "Error while loading job file " + url;
            if (_log.isErrorEnabled()) {
                _log.error(msg, e);
            }
            throw new XMLStreamException(msg, e);
        } finally {
            IOUtils.closeQuietly(stream);
        }
    }

    /**
     * Parse JobFile, read Records from the XML stream. The stream must be currently at the RecordList start tag.
     * 
     * @param staxReader
     *          source XML stream
     * @param url
     *          the url of the job file
     * @throws XMLStreamException
     *           StAX error.
     */
    private void parse(final XMLStreamReader staxReader, final URL url) throws XMLStreamException {
        staxReader.nextTag();
        if (isStartTag(staxReader, TAG_JOB_FILE)) {
            while (staxReader.hasNext()) {
                staxReader.nextTag();
                if (isStartTag(staxReader, TAG_ADD)) {
                    staxReader.nextTag();
                    do {
                        final Record record = _recordReader.readRecord(staxReader);
                        if (record != null) {
                            try {
                                loadAttachments(record);
                                _jobFileHandler.add(record);
                            } catch (IOException e) {
                                final String msg = "Error loading attachments for record " + record.getId()
                                        + ". Record is skipped.";
                                if (_log.isErrorEnabled()) {
                                    _log.error(msg, e);
                                }
                            }
                        } // if
                        staxReader.nextTag();
                    } while (staxReader.hasNext() && !isEndTag(staxReader, TAG_ADD));
                } else if (isStartTag(staxReader, TAG_DELETE)) {
                    staxReader.nextTag();
                    do {
                        final Record record = _recordReader.readRecord(staxReader);
                        _jobFileHandler.delete(record);
                        staxReader.nextTag();
                    } while (staxReader.hasNext() && !isEndTag(staxReader, TAG_DELETE));
                } else if (isEndTag(staxReader, TAG_JOB_FILE)) {
                    break;
                }
            } // while
        } else {
            throw new XMLStreamException(
                    "Invalid document " + url + ". Must begin with tag <" + TAG_JOB_FILE + ">");
        }
    }

    /**
     * 
     * @param staxReader
     *          source XML stream
     * @param tagName
     *          tag name
     * @return true if we are currently at a start tag with the specified name
     */
    private boolean isStartTag(final XMLStreamReader staxReader, final String tagName) {
        return staxReader.isStartElement() && tagName.equals(staxReader.getLocalName());
    }

    /**
     * 
     * @param staxReader
     *          source XML stream
     * @param tagName
     *          tag name
     * @return true if we are currently at a end tag with the specified name
     */
    private boolean isEndTag(final XMLStreamReader staxReader, final String tagName) {
        return staxReader.isEndElement() && tagName.equals(staxReader.getLocalName());
    }

    /**
     * Loads all attachments for the given record.
     * 
     * @param record
     *          the record
     * @throws IOException
     *           if any error occurs
     */
    private void loadAttachments(final Record record) throws IOException {
        final Iterator<String> attachmentNames = record.getAttachmentNames();
        while (attachmentNames.hasNext()) {
            loadAttachment(record, attachmentNames.next());
        }
    }

    /**
     * Loads the attachment specified by nameUrl into the given record.
     * 
     * @param record
     *          the record
     * @param nameUrl
     *          the nameUrl, a String containing the attachment name separated from the url to the attachment
     * @throws IOException
     *           if any error occurs
     */
    private void loadAttachment(final Record record, final String nameUrl) throws IOException {
        if (nameUrl != null) {
            final int index = nameUrl.indexOf(_attachmentSeparator);
            if (index > 0) {
                final String attachmentName = nameUrl.substring(0, index);
                String urlString = nameUrl.substring(index + _attachmentSeparatorLength);
                if (!urlString.startsWith("http") && !urlString.startsWith("file")) {
                    urlString = "file://" + urlString.replaceAll("\\\\", "/");
                }
                record.setAttachment(attachmentName, readBytes(new URL(urlString.trim())));
            } else {
                if (_log.isWarnEnabled()) {
                    _log.warn("Invalid name pattern for attachment name " + nameUrl + " for record id "
                            + record.getId() + ". Attachment is skipped.");
                }
            }
            // remove the name-url attachment
            record.removeAttachment(nameUrl);
        } // if
    }

    /**
     * Get the InputStream to the given url.
     * 
     * @param url
     *          the url
     * @return a InputStream or null
     * @throws IOException
     *           if any error occurs
     */
    private InputStream getInputStream(final URL url) throws IOException {
        InputStream stream = null;
        if (url != null) {
            if (url.getProtocol().startsWith("file")) {
                stream = new FileInputStream(url.getAuthority() + url.getPath());
            } else {
                final HttpClient httpClient = new HttpClient();
                final GetMethod getMethod = new GetMethod(url.toString());
                httpClient.executeMethod(getMethod);
                stream = getMethod.getResponseBodyAsStream();
            }
        } // if
        return stream;
    }

    /**
     * Returns the bytes for the given url.
     * 
     * @param url
     *          the url
     * @return a byte[]
     * @throws IOException
     *           if any error occurs
     */
    private byte[] readBytes(final URL url) throws IOException {
        InputStream stream = null;
        try {
            stream = getInputStream(url);
            return IOUtils.toByteArray(stream);
        } finally {
            IOUtils.closeQuietly(stream);
        }
    }
}