ch.entwine.weblounge.common.impl.content.AbstractResourceReaderImpl.java Source code

Java tutorial

Introduction

Here is the source code for ch.entwine.weblounge.common.impl.content.AbstractResourceReaderImpl.java

Source

/*
 *  Weblounge: Web Content Management System
 *  Copyright (c) 2003 - 2011 The Weblounge Team
 *  http://entwinemedia.com/weblounge
 *
 *  This program is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public License
 *  as published by the Free Software Foundation; either version 2
 *  of the License, or (at your option) any later version.
 *
 *  This program 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 Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public License
 *  along with this program; if not, write to the Free Software Foundation
 *  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

package ch.entwine.weblounge.common.impl.content;

import ch.entwine.weblounge.common.content.Resource;
import ch.entwine.weblounge.common.content.ResourceContent;
import ch.entwine.weblounge.common.content.ResourceReader;
import ch.entwine.weblounge.common.content.ResourceUtils;
import ch.entwine.weblounge.common.impl.language.LanguageUtils;
import ch.entwine.weblounge.common.language.Language;
import ch.entwine.weblounge.common.security.Authority;
import ch.entwine.weblounge.common.security.Permission;
import ch.entwine.weblounge.common.security.User;
import ch.entwine.weblounge.common.site.Site;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;

import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.WeakReference;
import java.util.Date;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

/**
 * Utility class used to parse page data.
 */
public abstract class AbstractResourceReaderImpl<S extends ResourceContent, T extends Resource<S>>
        extends WebloungeContentReader implements ResourceReader<S, T> {

    /** Logging facility */
    private static final Logger logger = LoggerFactory.getLogger(AbstractResourceReaderImpl.class);

    /** Parser factory */
    private static final SAXParserFactory parserFactory = SAXParserFactory.newInstance();

    /** The SAX parser */
    protected WeakReference<SAXParser> parserRef = null;

    /** The resource object */
    protected T resource = null;

    /** The root tag */
    protected String rootTag = null;

    /** Flag to indicate whether the page header should be read */
    protected boolean readHeader = true;

    /** Flag to indicate whether the page body should be read */
    protected boolean readBody = true;

    protected enum ParserContext {
        Document, Resource, Head, Body, Content
    };

    /** The parser context */
    protected ParserContext parserContext = ParserContext.Document;

    /**
     * Creates a new resource reader reader that will parse the XML data and store
     * it in the <code>Resource</code> object that is returned by the
     * {@link #read} method.
     * 
     * @param rootTag
     *          name of the root tag
     * @throws ParserConfigurationException
     *           if the SAX parser setup failed
     * @throws SAXException
     *           if an error occurs while parsing
     */
    public AbstractResourceReaderImpl(String rootTag) throws ParserConfigurationException, SAXException {
        if (rootTag == null)
            throw new IllegalArgumentException("Root tag name must not be null");
        this.rootTag = rootTag.toLowerCase();
        parserRef = new WeakReference<SAXParser>(parserFactory.newSAXParser());
    }

    /**
     * This method is called when a <code>Page</code> object is instantiated.
     * 
     * @param is
     *          the xml input stream
     * @param uri
     *          the page uri
     * 
     * @throws IOException
     *           if reading the input stream fails
     */
    public T read(InputStream is, Site site) throws SAXException, IOException, ParserConfigurationException {
        reset();
        resource = createResource(site);
        readHeader = true;
        readBody = true;
        SAXParser parser = parserRef.get();
        if (parser == null) {
            parser = parserFactory.newSAXParser();
            parserRef = new WeakReference<SAXParser>(parser);
        }
        parser.parse(is, this);
        return resource;
    }

    /**
     * Creates an empty instance of the resource to read.
     * 
     * @param site
     *          the site
     * @return the empty resource
     */
    protected abstract T createResource(Site site);

    /**
     * This method is called to read the head section of a resource.
     * 
     * @param is
     *          the xml input stream
     * @param site
     *          the site
     * @throws ParserConfigurationException
     *           if the SAX parser setup failed
     * @throws IOException
     *           if reading the input stream fails
     * @throws SAXException
     *           if an error occurs while parsing
     */
    public T readHeader(InputStream is, Site site) throws SAXException, IOException, ParserConfigurationException {
        if (resource == null) {
            resource = createResource(site);
        }
        readHeader = true;
        readBody = false;
        SAXParser parser = parserRef.get();
        if (parser == null) {
            parser = parserFactory.newSAXParser();
            parserRef = new WeakReference<SAXParser>(parser);
        }
        parser.parse(is, this);
        return resource;
    }

    /**
     * This method is called to read the body of a resource.
     * 
     * @param is
     *          the xml input stream
     * @param site
     *          the site
     * @throws ParserConfigurationException
     *           if the SAX parser setup failed
     * @throws IOException
     *           if reading the input stream fails
     * @throws SAXException
     *           if an error occurs while parsing
     */
    public T readBody(InputStream is, Site site) throws SAXException, IOException, ParserConfigurationException {
        if (resource == null) {
            resource = createResource(site);
        }
        readHeader = false;
        readBody = true;
        SAXParser parser = parserRef.get();
        if (parser == null) {
            parser = parserFactory.newSAXParser();
            parserRef = new WeakReference<SAXParser>(parser);
        }
        parser.parse(is, this);
        return resource;
    }

    /**
     * Sets the resource that needs to be further enriched with content from an
     * xml document.
     * 
     * @param resource
     *          the page
     */
    public void init(T resource) {
        this.resource = resource;
    }

    /**
     * Resets this parser instance.
     */
    @Override
    public void reset() {
        this.resource = null;
        this.parserContext = ParserContext.Document;
        SAXParser parser = parserRef.get();
        if (parser != null)
            parser.reset();
    }

    /**
     * {@inheritDoc}
     * 
     * @see ch.entwine.weblounge.common.impl.content.WebloungeContentReader#setOwner(ch.entwine.weblounge.common.security.User)
     */
    @Override
    protected void setOwner(User owner) {
        resource.setOwner(owner);
    }

    /**
     * {@inheritDoc}
     * 
     * @see ch.entwine.weblounge.common.impl.content.WebloungeContentReader#allow(ch.entwine.weblounge.common.security.Permission,
     *      ch.entwine.weblounge.common.security.Authority)
     */
    @Override
    protected void allow(Permission permission, Authority authority) {
        resource.allow(permission, authority);
    }

    /**
     * {@inheritDoc}
     * 
     * @see ch.entwine.weblounge.common.impl.content.WebloungeContentReader#setCreated(ch.entwine.weblounge.common.security.User,
     *      java.util.Date)
     */
    @Override
    protected void setCreated(User user, Date date) {
        resource.setCreated(user, date);
    }

    /**
     * {@inheritDoc}
     * 
     * @see ch.entwine.weblounge.common.impl.content.WebloungeContentReader#setModified(ch.entwine.weblounge.common.security.User,
     *      java.util.Date)
     */
    @Override
    protected void setModified(User modifier, Date date) {
        resource.setModified(modifier, date);
    }

    /**
     * {@inheritDoc}
     * 
     * @see ch.entwine.weblounge.common.impl.content.WebloungeContentReader#setPublished(ch.entwine.weblounge.common.security.User,
     *      java.util.Date, java.util.Date)
     */
    @Override
    protected void setPublished(User publisher, Date startDate, Date endDate) {
        resource.setPublished(publisher, startDate, endDate);
    }

    /**
     * The parser found the start of an element. Information about this element as
     * well as the attached attributes are passed to this method.
     * 
     * @param uri
     *          information about the namespace
     * @param local
     *          the local name of the element
     * @param raw
     *          the raw name of the element
     * @param attrs
     *          the element's attributes
     */
    @Override
    public void startElement(String uri, String local, String raw, Attributes attrs) throws SAXException {

        // read the page url
        if (rootTag.equals(raw)) {
            parserContext = ParserContext.Resource;
            resource.getURI().setType(rootTag);
            resource.getURI().setIdentifier(attrs.getValue("id"));
            if (StringUtils.isNotBlank(attrs.getValue("path")))
                resource.getURI().setPath(attrs.getValue("path"));
            if (StringUtils.isNotBlank(attrs.getValue("version"))) {
                long version = ResourceUtils.getVersion(attrs.getValue("version"));
                resource.getURI().setVersion(version);
            }
        }

        // in the header
        else if ("head".equals(raw)) {
            parserContext = ParserContext.Head;
        }

        // in the body
        else if ("body".equals(raw)) {
            parserContext = ParserContext.Body;
        }

        if (readHeader) {

            // title, subject and the like
            if ("title".equals(raw) || "subject".equals(raw) || "description".equals(raw) || "coverage".equals(raw)
                    || "rights".equals(raw)) {
                String language = attrs.getValue("language");
                if (language != null) {
                    Language l = LanguageUtils.getLanguage(language);
                    clipboard.put("language", l);
                } else {
                    clipboard.remove("language");
                }
            }

        }

        super.startElement(uri, local, raw, attrs);

    }

    /**
     * @see org.xml.sax.ContentHandler#endElement(java.lang.String,
     *      java.lang.String, java.lang.String)
     */
    @Override
    public void endElement(String uri, String local, String raw) throws SAXException {

        if (readHeader && parserContext.equals(ParserContext.Head)) {

            // Promote
            if ("promote".equals(raw)) {
                resource.setPromoted("true".equals(characters.toString()));
            }

            // Type
            else if ("type".equals(raw)) {
                resource.setType(characters.toString());
            }

            // Title
            else if ("title".equals(raw)) {
                Language l = (Language) clipboard.remove("language");
                resource.setTitle(characters.toString(), l);
            }

            // Description
            else if ("description".equals(raw)) {
                Language l = (Language) clipboard.remove("language");
                resource.setDescription(characters.toString(), l);
            }

            // Coverage
            else if ("coverage".equals(raw)) {
                Language l = (Language) clipboard.remove("language");
                resource.setCoverage(characters.toString(), l);
            }

            // Rights
            else if ("rights".equals(raw)) {
                Language l = (Language) clipboard.remove("language");
                resource.setRights(characters.toString(), l);
            }

            // Subject
            else if ("subject".equals(raw)) {
                resource.addSubject(characters.toString());
            }

            // Series
            else if ("series".equals(raw)) {
                resource.addSeries(characters.toString());
            }

            // Pagelock
            else if ("locked".equals(raw)) {
                User user = (User) clipboard.remove("user");
                if (user != null)
                    resource.lock(user);
            }

        }

        // Head
        if ("head".equals(raw)) {
            parserContext = ParserContext.Resource;
        }

        // Body
        else if ("body".equals(raw)) {
            parserContext = ParserContext.Resource;
        }

        // Have the super implementation handle the unkown
        else {
            super.endElement(uri, local, raw);
        }

    }

    /**
     * The parser encountered problems while parsing. The warning is printed out
     * but the parsing process continues.
     * 
     * @param e
     *          information about the warning
     */
    @Override
    public void warning(SAXParseException e) {
        logger.warn("Warning while reading {}: {}", resource, e.getMessage());
    }

    /**
     * The parser encountered problems while parsing. The error is printed out and
     * the parsing process is stopped.
     * 
     * @param e
     *          information about the error
     */
    @Override
    public void error(SAXParseException e) {
        logger.warn("Error while reading {}: {}", resource, e.getMessage());
    }

    /**
     * The parser encountered problems while parsing. The fatal error is printed
     * out and the parsing process is stopped.
     * 
     * @param e
     *          information about the error
     */
    @Override
    public void fatalError(SAXParseException e) {
        logger.warn("Fatal error while reading {}: {}", resource, e.getMessage());
    }

}