org.jasig.portlet.announcements.Importer.java Source code

Java tutorial

Introduction

Here is the source code for org.jasig.portlet.announcements.Importer.java

Source

/**
 * Licensed to Apereo under one or more contributor license
 * agreements. See the NOTICE file distributed with this work
 * for additional information regarding copyright ownership.
 * Apereo licenses this file to you under the Apache License,
 * Version 2.0 (the "License"); you may not use this file
 * except in compliance with the License.  You may obtain a
 * copy of the License at the following location:
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.jasig.portlet.announcements;

import java.io.File;
import java.io.FileFilter;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.transform.stream.StreamSource;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.hibernate.HibernateException;
import org.jasig.portlet.announcements.model.Announcement;
import org.jasig.portlet.announcements.model.Topic;
import org.jasig.portlet.announcements.service.IAnnouncementService;
import org.jasig.portlet.announcements.spring.PortletApplicationContextLocator;
import org.springframework.context.ApplicationContext;

public class Importer {

    private static final String ANNOUNCEMENT_SVC_BEAN_NAME = "announcementService";

    private static final Logger log = Logger.getLogger(Importer.class);

    private File dataDirectory;
    private IAnnouncementService announcementService;
    private List<String> errors = new ArrayList<String>();

    public Importer(File dataDirectory,
            /*SessionFactory sessionFactory, */IAnnouncementService announcementService) {
        this.dataDirectory = dataDirectory;
        this.announcementService = announcementService;
    }

    /**
     * Imports topics and announcements into the database from XML data files.
     * <ul>
     *   <li>args[0] -- <b>file system directory</b> containing XML data files to import</li>
     *   <li>args[1] -- <b>classpath location</b> of the spring context XML config file, normally named importExportContext.xml</li>
     * </ul>
     *
     * @throws Exception Various exceptions like JAXBException
     */
    public static void main(String[] args) {

        if (args.length != 2) {
            log.error(
                    "Invalid number of arguments. Command:\n  $java org.jasig.portlet.announcements.Importer <dir> <classpathLocationOfSpringContextXmlFile>");
            System.exit(1);
        }

        // dataDirectory
        String dir = args[0];
        File dataDirectory = new File(dir);
        if (!dataDirectory.exists()) {
            log.error("The specified dataDirectory does not exist:  " + dir);
            System.exit(1);
        }

        // announcementService
        String contextClasspathLocation = args[1];
        // INPORTANT!  Must load from the context classpath, not the system 
        // classpath, since the Importer will commonly run in a ClassLoader-enhanced 
        // context, such as an Ant task.
        URL u = Thread.currentThread().getContextClassLoader().getResource(contextClasspathLocation);
        if (u == null) {
            log.error("Spring context file for Import/Export not found on classpath:  " + contextClasspathLocation);
            System.exit(1);
        }
        ApplicationContext context = PortletApplicationContextLocator.getApplicationContext(u.toString());
        IAnnouncementService announcementService = context.getBean(ANNOUNCEMENT_SVC_BEAN_NAME,
                IAnnouncementService.class);

        Importer importer = new Importer(dataDirectory, /*sessionFactory,*/ announcementService);
        importer.importData();

        if (importer.errors.size() > 0) {
            log.error("Import failed - see previous errors");
            System.exit(1);
        }

    }

    public void importData() {
        importTopics();
        importAnnouncements();
    }

    private void importTopics() {
        try {
            JAXBContext jc = JAXBContext.newInstance(Topic.class);
            Unmarshaller unmarshaller = jc.createUnmarshaller();

            File[] files = dataDirectory.listFiles(new TopicImportFileFilter());

            if (files == null) {
                errors.add("Directory " + dataDirectory + " is not a valid directory");
            } else {

                for (File f : files) {
                    log.info("Processing file " + f.toString());
                    StreamSource xmlFile = new StreamSource(f.getAbsoluteFile());
                    try {
                        JAXBElement<Topic> je1 = unmarshaller.unmarshal(xmlFile, Topic.class);
                        Topic topic = je1.getValue();

                        if (StringUtils.isBlank(topic.getTitle())) {
                            String msg = "Error parsing file " + f.toString() + "; did not get valid record:\n"
                                    + topic.toString();
                            log.error(msg);
                            errors.add(msg);
                        } else {
                            announcementService.addOrSaveTopic(topic);
                            log.info("Successfully imported topic '" + topic.getTitle() + "'");
                        }
                    } catch (JAXBException e) {
                        String msg = "JAXB exception " + e.getCause().getMessage() + " processing file "
                                + f.toString();
                        log.error(msg, e);
                        errors.add(msg + ". See stack trace");
                    } catch (HibernateException e) {
                        String msg = "Hibernate exception " + e.getCause().getMessage() + " processing file "
                                + f.toString();
                        log.error(msg, e);
                        errors.add(msg + ". See stack trace");
                    }
                }
            }
        } catch (JAXBException e) {
            String msg = "Fatal JAXBException in importTopics - no topics imported";
            log.fatal(msg, e);
            errors.add(msg + ".  See stack trace");
        }
    }

    private void importAnnouncements() {
        try {
            JAXBContext jc = JAXBContext.newInstance(Announcement.class);
            Unmarshaller unmarshaller = jc.createUnmarshaller();

            File[] files = dataDirectory.listFiles(new AnnouncementImportFileFilter());

            if (files == null) {
                errors.add("Directory " + dataDirectory + " is not a valid directory");
            } else {

                for (File f : files) {
                    log.info("Processing file " + f.toString());
                    StreamSource xml = new StreamSource(f.getAbsoluteFile());
                    try {
                        JAXBElement<Announcement> je1 = unmarshaller.unmarshal(xml, Announcement.class);
                        Announcement announcement = je1.getValue();
                        if (StringUtils.isBlank(announcement.getTitle())) {
                            String msg = "Error parsing " + f.toString() + "; did not get valid record:\n"
                                    + announcement.toString();
                            log.error(msg);
                            errors.add(msg);
                        } else if (announcement.getParent() == null
                                || StringUtils.isBlank(announcement.getParent().getTitle())) {
                            String msg = "Announcement in file " + f.toString()
                                    + " does not reference a topic with a title";
                            log.error(msg);
                            errors.add(msg);
                        } else {
                            Topic topic = findTopicForAnnouncement(announcement);
                            announcement.setParent(topic);
                            announcementService.addOrSaveAnnouncement(announcement);
                            log.info("Successfully imported announcement '" + announcement.getTitle() + "'");
                        }
                    } catch (ImportException e) {
                        log.error(e.getMessage());
                        errors.add(e.getMessage());
                    } catch (JAXBException e) {
                        String msg = "JAXB exception " + e.getCause().getMessage() + " processing file "
                                + f.toString();
                        log.error(msg, e);
                        errors.add(msg + ". See stack trace");
                    } catch (HibernateException e) {
                        String msg = "Hibernate exception " + e.getCause().getMessage() + " processing file "
                                + f.toString();
                        log.error(msg, e);
                        errors.add(msg + ". See stack trace");
                    }
                }
            }
        } catch (JAXBException e) {
            String msg = "Fatal JAXBException in importAnnouncements - no Announcements imported";
            log.fatal(msg, e);
            errors.add(msg + ".  See stack trace");
        }
    }

    private Topic findTopicForAnnouncement(Announcement announcement) {
        Topic topic = null;
        List<Topic> topics = announcementService.getAllTopics();
        for (Topic t : topics) {
            if (t.getTitle().equals(announcement.getParent().getTitle())) {
                if (topic != null) {
                    throw new ImportException("Unable to import Announcement '" + announcement.getTitle()
                            + "' - multiple topics exist with title '" + t.getTitle() + "'");
                } else {
                    topic = t;
                }
            }
        }
        return topic;
    }

    private static class TopicImportFileFilter implements FileFilter {
        public boolean accept(File pathname) {
            return (pathname.isFile() && pathname.getName().toLowerCase().endsWith("-topic.xml"));
        }
    }

    private static class AnnouncementImportFileFilter implements FileFilter {
        public boolean accept(File pathname) {
            return (pathname.isFile() && pathname.getName().toLowerCase().endsWith("-announcement.xml"));
        }
    }

    private class ImportException extends RuntimeException {

        private static final long serialVersionUID = 1L;

        public ImportException(String message) {
            super(message);
        }

    }

}