com.adobe.communities.ugc.migration.legacyExport.GenericExportServlet.java Source code

Java tutorial

Introduction

Here is the source code for com.adobe.communities.ugc.migration.legacyExport.GenericExportServlet.java

Source

/*************************************************************************
 *
 * ADOBE SYSTEMS INCORPORATED
 * Copyright 2015 Adobe Systems Incorporated
 * All Rights Reserved.
 *
 * NOTICE:  Adobe permits you to use, modify, and distribute this file in accordance with the
 * terms of the Adobe license agreement accompanying it.  If you have received this file from a
 * source other than Adobe, then your use, modification, or distribution of it requires the prior
 * written permission of Adobe.
 **************************************************************************/
package com.adobe.communities.ugc.migration.legacyExport;

import com.adobe.cq.social.calendar.CalendarConstants;
import com.adobe.cq.social.calendar.CqCalendar;
import com.adobe.cq.social.calendar.Event;
import com.adobe.cq.social.commons.Comment;
import com.adobe.cq.social.commons.CommentSystem;
import com.adobe.cq.social.forum.api.Forum;
import com.adobe.cq.social.forum.api.Post;
import com.adobe.cq.social.journal.Journal;
import com.adobe.cq.social.journal.JournalEntry;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Properties;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Service;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ValueMap;
import org.apache.sling.api.servlets.SlingSafeMethodsServlet;
import org.apache.sling.commons.json.JSONException;
import org.apache.sling.commons.json.io.JSONWriter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.ServletException;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

@Component(label = "UGC Exporter for all UGC Data Types", description = "Moves any ugc data into a zip archive for storage or re-import", specVersion = "1.0")
@Service
@Properties({ @Property(name = "sling.servlet.paths", value = "/services/social/ugc/export") })
public class GenericExportServlet extends SlingSafeMethodsServlet {

    Logger logger = LoggerFactory.getLogger(this.getClass());
    Writer responseWriter;
    ZipOutputStream zip;
    Map<String, Boolean> entries;
    Map<String, Boolean> entriesToSkip;

    @Override
    protected void doGet(final SlingHttpServletRequest request, final SlingHttpServletResponse response)
            throws ServletException, IOException {

        if (!request.getRequestParameterMap().containsKey("path")) {
            throw new ServletException("No path specified for export. Exiting.");
        }
        final String path = StringUtils.stripEnd(request.getRequestParameter("path").getString(), "/");
        final Resource resource = request.getResourceResolver().getResource(path);
        if (resource == null) {
            throw new ServletException("Could not find a valid resource for export");
        }
        entries = new HashMap<String, Boolean>();
        entriesToSkip = new HashMap<String, Boolean>();
        File outFile = null;
        try {
            outFile = File.createTempFile(UUID.randomUUID().toString(), ".zip");
            if (!outFile.canWrite()) {
                throw new ServletException("Cannot write to specified output file");
            }
            response.setContentType("application/octet-stream");
            final String headerKey = "Content-Disposition";
            final String headerValue = "attachment; filename=\"export.zip\"";
            response.setHeader(headerKey, headerValue);

            FileOutputStream fos = new FileOutputStream(outFile);
            BufferedOutputStream bos = new BufferedOutputStream(fos);
            zip = new ZipOutputStream(bos);
            OutputStream outStream = null;
            InputStream inStream = null;
            try {
                exportContent(resource, path);
                if (entries.size() > 0) {
                    exportCommentSystems(entries, entriesToSkip, resource, path);
                }
                IOUtils.closeQuietly(zip);
                IOUtils.closeQuietly(bos);
                IOUtils.closeQuietly(fos);
                // obtains response's output stream
                outStream = response.getOutputStream();
                inStream = new FileInputStream(outFile);
                // copy from file to output
                IOUtils.copy(inStream, outStream);
            } catch (final IOException e) {
                throw new ServletException(e);
            } catch (final Exception e) {
                throw new ServletException(e);
            } finally {
                IOUtils.closeQuietly(zip);
                IOUtils.closeQuietly(bos);
                IOUtils.closeQuietly(fos);
                IOUtils.closeQuietly(inStream);
                IOUtils.closeQuietly(outStream);
            }
        } finally {
            if (outFile != null) {
                outFile.delete();
            }
        }
    }

    protected void exportContent(Resource rootNode, final String rootPath) throws IOException, ServletException {

        final String relPath = rootNode.getPath()
                .substring(rootNode.getPath().indexOf(rootPath) + rootPath.length());
        String entryName = relPath.isEmpty() ? "root.json" : relPath + ".json";
        responseWriter = new OutputStreamWriter(zip);
        final JSONWriter writer = new JSONWriter(responseWriter);
        writer.setTidy(true);
        if (rootNode.isResourceType(Comment.RESOURCE_TYPE)) {
            // if we're traversing a tree and come to a comment, we need to be looking at the comment system's
            // resource instead of the resource for the comment itself as we continue our dive.
            Comment comment = rootNode.adaptTo(Comment.class);
            if (null != comment) {
                CommentSystem commentSystem = comment.getCommentSystem();
                entries.put(commentSystem.getResource().getPath(), true);
                return;
            }
        }
        try {
            if (rootNode.isResourceType("social/qna/components/qnaforum")) {
                final Forum forum = rootNode.adaptTo(Forum.class);
                if (forum == null) { // avoid throwing a null pointer exception
                    for (final Resource resource : rootNode.getChildren()) {
                        exportContent(resource, rootPath);
                    }
                    return;
                }
                final Iterator<Post> posts = forum.getTopics();
                if (posts.hasNext()) {
                    zip.putNextEntry(new ZipEntry(entryName));
                    final JSONWriter forumObject = writer.object();
                    forumObject.key(ContentTypeDefinitions.LABEL_CONTENT_TYPE);
                    forumObject.value(ContentTypeDefinitions.LABEL_QNA_FORUM);
                    forumObject.key(ContentTypeDefinitions.LABEL_CONTENT);
                    forumObject.object();
                    while (posts.hasNext()) {
                        final Post post = posts.next();
                        forumObject.key(post.getId());
                        final JSONWriter postObject = forumObject.object();
                        UGCExportHelper.extractTopic(postObject, post, rootNode.getResourceResolver(),
                                "social/qna/components/hbs/topic", "social/qna/components/hbs/post",
                                responseWriter);
                        forumObject.endObject();
                    }
                    forumObject.endObject();
                    writer.endObject();
                    responseWriter.flush();
                    zip.closeEntry();
                }
            } else if (rootNode.isResourceType(Forum.RESOURCE_TYPE)
                    || rootNode.isResourceType("social/forum/components/hbs/forum")) {
                final Forum forum = rootNode.adaptTo(Forum.class);
                if (forum == null) { // avoid throwing a null pointer exception
                    for (final Resource resource : rootNode.getChildren()) {
                        exportContent(resource, rootPath);
                    }
                    return;
                }
                final Iterator<Post> posts = forum.getTopics();
                if (posts.hasNext()) {
                    zip.putNextEntry(new ZipEntry(entryName));
                    final JSONWriter forumObject = writer.object();
                    forumObject.key(ContentTypeDefinitions.LABEL_CONTENT_TYPE);
                    forumObject.value(ContentTypeDefinitions.LABEL_FORUM);
                    forumObject.key(ContentTypeDefinitions.LABEL_CONTENT);
                    forumObject.object();
                    while (posts.hasNext()) {
                        final Post post = posts.next();
                        forumObject.key(post.getId());
                        final JSONWriter postObject = forumObject.object();
                        UGCExportHelper.extractTopic(postObject, post, rootNode.getResourceResolver(),
                                "social/forum/components/hbs/topic", "social/forum/components/hbs/post",
                                responseWriter);
                        forumObject.endObject();
                    }
                    forumObject.endObject();
                    writer.endObject();
                    responseWriter.flush();
                    zip.closeEntry();
                }
            } else if (rootNode.isResourceType(CommentSystem.RESOURCE_TYPE)) {
                if (rootNode.getName().equals("entrycomments")) {
                    return; // these are special cases of comments that will be handled by journal instead
                }
                final CommentSystem commentSystem = rootNode.adaptTo(CommentSystem.class);
                if (commentSystem == null) { // avoid throwing a null pointer exception
                    for (final Resource resource : rootNode.getChildren()) {
                        exportContent(resource, rootPath);
                    }
                    return;
                }
                // we only export after all other nodes have been searched and exported as needed
                entries.put(commentSystem.getResource().getPath(), true);
            } else if (rootNode.isResourceType(CalendarConstants.RT_CALENDAR_COMPONENT)
                    || rootNode.isResourceType(CalendarConstants.MIX_CALENDAR)
                    || rootNode.getResourceType().endsWith("calendar")) {
                CqCalendar calendar = rootNode.adaptTo(CqCalendar.class);
                if (calendar == null) { // avoid throwing a null pointer exception if this node isn't actually a
                                        // calendar
                    for (final Resource resource : rootNode.getChildren()) {
                        exportContent(resource, rootPath);
                    }
                    return;
                }
                final Iterator<Event> events = calendar.getEvents();
                if (!events.hasNext()) {
                    return;
                }
                zip.putNextEntry(new ZipEntry(entryName));
                final JSONWriter calendarNode = writer.object();
                calendarNode.key(ContentTypeDefinitions.LABEL_CONTENT_TYPE);
                calendarNode.value(ContentTypeDefinitions.LABEL_CALENDAR);
                calendarNode.key(ContentTypeDefinitions.LABEL_CONTENT);
                JSONWriter eventObjects = calendarNode.array();
                while (events.hasNext()) {
                    final Event event = events.next();
                    ValueMap eventProperties = event.getProperties();
                    // we renamed "start" and "end" going from version 5.6.1 to 6.1
                    Map<String, String> propertyNames = new HashMap<String, String>();
                    propertyNames.put("start", "calendar_event_start_dt");
                    propertyNames.put("end", "calendar_event_end_dt");
                    propertyNames.put("jcr:title", "subject");
                    propertyNames.put("jcr:created", "added");
                    propertyNames.put("jcr:primaryType", null);
                    UGCExportHelper.extractProperties(eventObjects.object(), eventProperties, propertyNames,
                            "social/calendar/components/hbs/event");
                    eventObjects.endObject();
                }
                calendarNode.endArray();
                writer.endObject();
                responseWriter.flush();
                zip.closeEntry();
            } else if (rootNode.isResourceType("social/tally/components/poll")) { // No constant defined in 5.6.1
                return; // we know what it is, but there's no antecedent to put it into for 6.1
            } else if (rootNode.isResourceType("social/tally/components/voting")) { // No constant defined in 5.6.1
                zip.putNextEntry(new ZipEntry(entryName));
                final JSONWriter tallyNode = writer.object();
                tallyNode.key(ContentTypeDefinitions.LABEL_CONTENT_TYPE);
                tallyNode.value(ContentTypeDefinitions.LABEL_TALLY);
                tallyNode.key(ContentTypeDefinitions.LABEL_CONTENT);
                final JSONWriter responseArray = tallyNode.array();
                UGCExportHelper.extractTally(responseArray, rootNode, "Voting");
                tallyNode.endArray();
                writer.endObject();
                responseWriter.flush();
                zip.closeEntry();
            } else if (rootNode.isResourceType("social/tally/components/rating")) { // No constant defined in 5.6.1
                zip.putNextEntry(new ZipEntry(entryName));
                final JSONWriter tallyNode = writer.object();
                tallyNode.key(ContentTypeDefinitions.LABEL_CONTENT_TYPE);
                tallyNode.value(ContentTypeDefinitions.LABEL_TALLY);
                tallyNode.key(ContentTypeDefinitions.LABEL_CONTENT);
                final JSONWriter responseArray = tallyNode.array();
                UGCExportHelper.extractTally(responseArray, rootNode, "Rating");
                tallyNode.endArray();
                writer.endObject();
                responseWriter.flush();
                zip.closeEntry();
            } else if (rootNode.isResourceType("social/journal/components/entrylist")) {
                final Journal journal = rootNode.adaptTo(Journal.class);
                if (journal == null) { // avoid throwing a null pointer exception
                    for (final Resource resource : rootNode.getChildren()) {
                        exportContent(resource, rootPath);
                    }
                    return;
                }
                zip.putNextEntry(new ZipEntry(entryName));
                final JSONWriter journalNode = writer.object();
                journalNode.key(ContentTypeDefinitions.LABEL_CONTENT_TYPE);
                journalNode.value(ContentTypeDefinitions.LABEL_JOURNAL);
                journalNode.key(ContentTypeDefinitions.LABEL_CONTENT);
                JSONWriter entryObjects = journalNode.object();
                final List<JournalEntry> entries = journal.getEntries();
                for (final JournalEntry entry : entries) {
                    entryObjects.key(entry.getId());
                    UGCExportHelper.extractJournalEntry(entryObjects.object(), entry, responseWriter);
                    entryObjects.endObject();
                    final Iterator<Comment> comments = entry.getComments();
                    if (comments.hasNext()) {
                        final Comment comment = comments.next();
                        final CommentSystem commentSystem = comment.getCommentSystem();
                        entriesToSkip.put(commentSystem.getResource().getPath(), true);
                    }
                }
                journalNode.endObject();
                writer.endObject();
                responseWriter.flush();
                zip.closeEntry();
            } else {
                for (final Resource resource : rootNode.getChildren()) {
                    exportContent(resource, rootPath);
                }
            }
        } catch (final JSONException e) {
            throw new ServletException(e);
        }
    }

    protected void exportCommentSystems(final Map<String, Boolean> entries,
            final Map<String, Boolean> entriesToSkip, final Resource resource, final String path)
            throws IOException, JSONException {
        for (final String commentSystemPath : entries.keySet()) {
            if (!entriesToSkip.containsKey(commentSystemPath)) {
                final String relPath = commentSystemPath.substring(commentSystemPath.indexOf(path) + path.length());
                String entryName = relPath.isEmpty() ? ".root.json" : relPath + ".json";
                responseWriter = new OutputStreamWriter(zip);
                final JSONWriter writer = new JSONWriter(responseWriter);
                writer.setTidy(true);
                final Resource commentSystemResource = resource.getResourceResolver()
                        .getResource(commentSystemPath);
                if (commentSystemResource == null) {
                    logger.error("Could not find comment parent resource: " + commentSystemPath
                            + "; will not export its comments");
                    continue;
                }
                final CommentSystem commentSystem = commentSystemResource.adaptTo(CommentSystem.class);
                final Iterator<Comment> comments = commentSystem.getComments();
                if (comments.hasNext()) {
                    try {
                        zip.putNextEntry(new ZipEntry(entryName));
                        final JSONWriter commentsNode = writer.object();
                        commentsNode.key(ContentTypeDefinitions.LABEL_CONTENT_TYPE);
                        commentsNode.value(ContentTypeDefinitions.LABEL_COMMENTS);
                        commentsNode.key(ContentTypeDefinitions.LABEL_CONTENT);
                        commentsNode.object();
                        while (comments.hasNext()) {
                            final Comment comment = comments.next();
                            if (null == comment) {
                                continue;
                            }
                            commentsNode.key(comment.getId());
                            final JSONWriter commentObject = commentsNode.object();
                            UGCExportHelper.extractComment(commentObject, comment, resource.getResourceResolver(),
                                    responseWriter);
                            commentsNode.endObject();
                        }
                        commentsNode.endObject();
                        writer.endObject();
                        responseWriter.flush();
                        zip.closeEntry();
                    } catch (Exception e) {
                        logger.error("Cannot add zip entry: " + e);
                    }
                }
            }
        }
    }
}