Java tutorial
/* * 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()); } }