Java tutorial
/* * This program is free software; you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software * Foundation. * * You should have received a copy of the GNU Lesser General Public License along with this * program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html * or from the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * 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. * * Copyright 2008 - 2009 Pentaho Corporation. All rights reserved. */ package org.pentaho.pac.server.biplatformproxy.xmlserializer; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.pentaho.pac.client.scheduler.model.Schedule; import org.pentaho.pac.common.SchedulerServiceException; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; public class SubscriptionXmlSerializer { private static final Log logger = LogFactory.getLog(SubscriptionXmlSerializer.class); private static final ThreadLocal<SAXParserFactory> SAX_FACTORY = new ThreadLocal<SAXParserFactory>(); public SubscriptionXmlSerializer() { } public Map<String, Schedule> getSubscriptionSchedulesFromXml(String strXml) throws XmlSerializerException, SchedulerServiceException { SubscriptionScheduleParserHandler subscriptionSchedHandler = null; try { detectSubscriptionExceptionInXml(strXml); subscriptionSchedHandler = parseSubscriptionScheduleJobsXml(strXml); } catch (SAXException e) { logger.error(e.getMessage()); throw new XmlSerializerException(e.getMessage()); } catch (IOException e) { logger.error(e.getMessage()); throw new XmlSerializerException(e.getMessage()); } catch (ParserConfigurationException e) { logger.error(e.getMessage()); throw new XmlSerializerException(e.getMessage()); } return subscriptionSchedHandler.schedules; } public void detectSubscriptionExceptionInXml(String strXml) throws SchedulerServiceException { SubscriptionExceptionParserHandler exceptionHandler; try { exceptionHandler = parseSubscriptionExceptionXml(strXml); } catch (SAXException e) { logger.error(e.getMessage()); throw new SchedulerServiceException(e.getMessage()); } catch (IOException e) { logger.error(e.getMessage()); throw new SchedulerServiceException(e.getMessage()); } catch (ParserConfigurationException e) { logger.error(e.getMessage()); throw new SchedulerServiceException(e.getMessage()); } if (null != exceptionHandler.exceptionMessage) { throw new SchedulerServiceException(exceptionHandler.exceptionMessage); } } public void detectSubscriptionErrorInXml(String strXml) throws SchedulerServiceException { SubscriptionErrorParserHandler errorHandler; try { errorHandler = parseSubscriptionErrorXml(strXml); } catch (SAXException e) { logger.error(e.getMessage()); throw new SchedulerServiceException(e.getMessage()); } catch (IOException e) { logger.error(e.getMessage()); throw new SchedulerServiceException(e.getMessage()); } catch (ParserConfigurationException e) { logger.error(e.getMessage()); throw new SchedulerServiceException(e.getMessage()); } if (null != errorHandler.errorMessage) { throw new SchedulerServiceException(errorHandler.errorMessage); } } /** * Get a SAX Parser Factory. This method implements a thread-relative * singleton. * * NOTE: Need sax parser factory per thread for thread safety. * See: http://java.sun.com/j2se/1.5.0/docs/api/javax/xml/parsers/SAXParserFactory.html * @return */ private static SAXParserFactory getSAXParserFactory() { SAXParserFactory threadLocalSAXParserFactory = SAX_FACTORY.get(); if (null == threadLocalSAXParserFactory) { threadLocalSAXParserFactory = SAXParserFactory.newInstance(); SAX_FACTORY.set(threadLocalSAXParserFactory); } return threadLocalSAXParserFactory; } private SubscriptionScheduleParserHandler parseSubscriptionScheduleJobsXml(String strXml) throws SAXException, IOException, ParserConfigurationException { SAXParser parser = getSAXParserFactory().newSAXParser(); SubscriptionScheduleParserHandler h = new SubscriptionScheduleParserHandler(); // TODO sbarkdull, need to set encoding // String encoding = CleanXmlHelper.getEncoding( strXml ); // InputStream is = new ByteArrayInputStream( strXml.getBytes( encoding ) ); InputStream is = new ByteArrayInputStream(strXml.getBytes("UTF-8")); //$NON-NLS-1$ parser.parse(is, h); return h; } /* <subscriptionAdmin> <listSchedules> <scheduledJobs> <job subscriberCount="0" triggerState="0"> <schedId>eb7ef4b4-4867-11dd-8266-ff19a6feec31</schedId> <schedRef>snb name 2</schedRef> <title>snb title 2</title> <desc>snb description 2</desc> <group>snb group 2</group> <cron>0 0 12 3 * ?</cron> <content> <action solution="samples" path="getting-started" action="HelloWorld.xaction" /> </content> <nextFireTime>Thu Jul 03 12:00:00 EDT 2008</nextFireTime> <prevFireTime>Never</prevFireTime> <jobId>snb name 2</jobId> </job> </scheduledJobs> <unScheduledJobs> <job subscriberCount="0" triggerState="-1"> <schedId>da95463f-4867-11dd-8266-ff19a6feec31</schedId> <schedRef>snb name</schedRef> <title>snb title</title> <desc>snb description</desc> <group>snb group</group> <cron>0 0 12 3 * *</cron> </job> </unScheduledJobs> <message result="WARNING">There are subscriptions that are not scheduled to run.</message> </listSchedules> <message result="INFO">There is no subscription content defined.</message> <schedulerStatus state="0" /> <returnURL>&schedulerAction=listSchedules&_TRUST_USER_=joe</returnURL> </subscriptionAdmin> */ private static class SubscriptionScheduleParserHandler extends DefaultHandler { public String currentText = null; public Map<String, Schedule> schedules = new HashMap<String, Schedule>(); private Schedule currentSchedule = null; private boolean isInSubscriptionAdmin = false; private boolean isInListSchedules = false; private boolean isInScheduledJobs = false; private boolean isInContent = false; private List<String> actionList = null; public SubscriptionScheduleParserHandler() { } public void characters(char[] ch, int startIdx, int length) { currentText = String.valueOf(ch, startIdx, length); } public void endElement(String uri, String localName, String qName) throws SAXException { if (qName.equals("subscriptionAdmin")) { //$NON-NLS-1$ isInSubscriptionAdmin = false; } else if (qName.equals("listSchedules")) { //$NON-NLS-1$ isInListSchedules = false; } else if (qName.equals("scheduledJobs")) { //$NON-NLS-1$ isInScheduledJobs = false; } else { if (isInSubscriptionAdmin && isInListSchedules && isInScheduledJobs) { if (qName.equals("job")) { //$NON-NLS-1$ assert currentSchedule.getJobName() != null : "Error, job name cannot be null."; //$NON-NLS-1$ schedules.put(currentSchedule.getJobName(), currentSchedule); currentSchedule = null; } else if (qName.equals("schedId")) { //$NON-NLS-1$ currentSchedule.setSchedId(currentText); } else if (qName.equals("schedRef")) { //$NON-NLS-1$ currentSchedule.setJobName(currentText); currentSchedule.setTriggerName(currentText); } else if (qName.equals("title")) { //$NON-NLS-1$ currentSchedule.setTitle(currentText); } else if (qName.equals("desc")) { //$NON-NLS-1$ currentSchedule.setDescription(currentText); } else if (qName.equals("group")) { //$NON-NLS-1$ currentSchedule.setJobGroup(currentText); } else if (qName.equals("cron")) { //$NON-NLS-1$ currentSchedule.setCronString(currentText); } else if (qName.equals("repeat-count")) { //$NON-NLS-1$ currentSchedule.setRepeatCount(currentText); } else if (qName.equals("repeat-time-millisecs")) { //$NON-NLS-1$ currentSchedule.setRepeatInterval(currentText); } else if (qName.equals("nextFireTime")) { //$NON-NLS-1$ currentSchedule.setNextFireTime(currentText); } else if (qName.equals("prevFireTime")) { //$NON-NLS-1$ currentSchedule.setPrevFireTime(currentText); } else if (qName.equals("jobId")) { //$NON-NLS-1$ currentSchedule.setJobName(currentText); } else if (qName.equals("start-date")) { //$NON-NLS-1$ try { currentSchedule.setStartDate(Long.parseLong(currentText)); } catch (NumberFormatException ex) { //Ignore this } } else if (qName.equals("end-date")) { //$NON-NLS-1$ try { currentSchedule.setEndDate(Long.parseLong(currentText)); } catch (NumberFormatException ex) { //Ignore this } } else if (qName.equals("content")) { //$NON-NLS-1$ isInContent = false; currentSchedule.setActionsList(actionList); actionList = null; } } } } public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { if (qName.equals("subscriptionAdmin")) { //$NON-NLS-1$ isInSubscriptionAdmin = true; } else if (qName.equals("listSchedules")) { //$NON-NLS-1$ isInListSchedules = true; } else if (qName.equals("scheduledJobs")) { //$NON-NLS-1$ isInScheduledJobs = true; } else { if (isInSubscriptionAdmin && isInListSchedules && isInScheduledJobs) { if (qName.equals("job")) { //$NON-NLS-1$ currentSchedule = new Schedule(); String val = attributes.getValue("subscriberCount"); //$NON-NLS-1$ currentSchedule.setSubscriberCount(val); val = attributes.getValue("triggerState"); //$NON-NLS-1$ currentSchedule.setTriggerState(XmlSerializerUtil.triggerInt2Name(val)); } else if (qName.equals("content")) { //$NON-NLS-1$ isInContent = true; actionList = new ArrayList<String>(); } else if (qName.equals("action")) { //$NON-NLS-1$ if (isInContent) { String solution = attributes.getValue("solution"); //$NON-NLS-1$ String path = attributes.getValue("path"); //$NON-NLS-1$ String action = attributes.getValue("action"); //$NON-NLS-1$ actionList.add(makePath(solution, path, action)); } } } } } private static String makePath(String solution, String path, String action) { return solution + "/" + path + "/" + action; //$NON-NLS-1$//$NON-NLS-2$ } } private SubscriptionExceptionParserHandler parseSubscriptionExceptionXml(String strXml) throws SAXException, IOException, ParserConfigurationException { SAXParser parser = getSAXParserFactory().newSAXParser(); SubscriptionExceptionParserHandler h = new SubscriptionExceptionParserHandler(); // TODO sbarkdull, need to set encoding // String encoding = CleanXmlHelper.getEncoding( strXml ); // InputStream is = new ByteArrayInputStream( strXml.getBytes( encoding ) ); InputStream is = new ByteArrayInputStream(strXml.getBytes("UTF-8")); //$NON-NLS-1$ parser.parse(is, h); return h; } /** * <exception> * <message result="ERROR"> * Error, these parameters are missing: actionRefs * </message> * </exception> * * @author Steven Barkdull * */ private static class SubscriptionExceptionParserHandler extends DefaultHandler { private String currentText = null; public String exceptionMessage = null; private boolean isException = false; private boolean isMessage = false; public SubscriptionExceptionParserHandler() { } public void characters(char[] ch, int startIdx, int length) { currentText = String.valueOf(ch, startIdx, length); } public void endElement(String uri, String localName, String qName) throws SAXException { if (qName.equals("exception")) { //$NON-NLS-1$ isException = false; } else if (qName.equals("message")) { //$NON-NLS-1$ if (isException && isMessage) { exceptionMessage = currentText; } isMessage = false; } } public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { if (qName.equals("exception")) { //$NON-NLS-1$ isException = true; } else if (qName.equals("message")) { //$NON-NLS-1$ isMessage = true; } } } private SubscriptionErrorParserHandler parseSubscriptionErrorXml(String strXml) throws SAXException, IOException, ParserConfigurationException { SAXParser parser = getSAXParserFactory().newSAXParser(); SubscriptionErrorParserHandler h = new SubscriptionErrorParserHandler(); // TODO sbarkdull, need to set encoding // String encoding = CleanXmlHelper.getEncoding( strXml ); // InputStream is = new ByteArrayInputStream( strXml.getBytes( encoding ) ); InputStream is = new ByteArrayInputStream(strXml.getBytes("UTF-8")); //$NON-NLS-1$ parser.parse(is, h); return h; } /** * <?xml version="1.0" encoding="UTF-8"?> * <commandResult result="ERROR"> * <message result="ERROR"> * Unable to complete request: * org.hibernate.exception.ConstraintViolationException: could not * delete: * [org.pentaho.platform.repository.subscription.SubscribeContent#34c6b532-5cd5-11dd-9b0d-53348ed62413] * </message> * </commandResult> * @author Steven Barkdull * */ private static class SubscriptionErrorParserHandler extends DefaultHandler { private String currentText = null; public String errorMessage = null; private boolean isCommandResult = false; private boolean isErrorMessage = false; private boolean isMessage = false; public SubscriptionErrorParserHandler() { } public void characters(char[] ch, int startIdx, int length) { currentText = String.valueOf(ch, startIdx, length); } public void endElement(String uri, String localName, String qName) throws SAXException { if (qName.equals("commandResult")) { //$NON-NLS-1$ isCommandResult = false; } else if (qName.equals("message")) { //$NON-NLS-1$ if (isCommandResult && isMessage && isErrorMessage) { errorMessage = currentText; isErrorMessage = false; } isMessage = false; } } public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { if (qName.equals("commandResult")) { //$NON-NLS-1$ isCommandResult = true; } else if (qName.equals("message")) { //$NON-NLS-1$ isMessage = true; // result="ERROR" isErrorMessage = attributes.getValue("result").equals("ERROR"); //$NON-NLS-1$ //$NON-NLS-2$ } } } }