Package org.jboss.seam.wiki.core.upload.importers

Source Code of org.jboss.seam.wiki.core.upload.importers.ZipImporter

package org.jboss.seam.wiki.core.upload.importers;

import net.sf.jmimemagic.Magic;
import org.hibernate.validator.ClassValidator;
import org.hibernate.validator.InvalidValue;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Logger;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.AutoCreate;
import org.jboss.seam.core.Validators;
import static org.jboss.seam.international.StatusMessage.Severity.ERROR;
import static org.jboss.seam.international.StatusMessage.Severity.INFO;
import org.jboss.seam.international.StatusMessages;
import org.jboss.seam.log.Log;
import org.jboss.seam.wiki.core.dao.WikiNodeDAO;
import org.jboss.seam.wiki.core.model.WikiNode;
import org.jboss.seam.wiki.core.model.WikiUpload;
import org.jboss.seam.wiki.core.upload.UploadType;
import org.jboss.seam.wiki.core.upload.UploadTypes;
import org.jboss.seam.wiki.core.upload.Uploader;
import org.jboss.seam.wiki.core.upload.importers.annotations.UploadImporter;
import org.jboss.seam.wiki.core.upload.importers.metamodel.Importer;
import org.jboss.seam.wiki.util.WikiUtil;

import javax.persistence.EntityManager;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

/**
* TODO: Delegate code to util.Unarchiver
*
* @author Christian Bauer
*/
@Name("zipImporter")
@UploadImporter(
        handledMimeTypes = {"application/zip", "application/java-archive"},
        handledExtensions = {"zip", "jar"},
        description = "lacewiki.label.ZipImporter"
)
@AutoCreate
public class ZipImporter implements Importer {

    @Logger
    Log log;

    @In
    protected WikiNodeDAO wikiNodeDAO;

    @In
    protected Map<String, UploadType> uploadTypes;

    @In
    protected StatusMessages statusMessages;

    public boolean handleImport(EntityManager em, WikiUpload zipFile) {

        if (zipFile.getData().length == 0) return true;

        Map<String, Object> newObjects = new HashMap<String, Object>();

        ByteArrayInputStream byteStream = null;
        ZipInputStream zipInputStream = null;
        try {
            byteStream = new ByteArrayInputStream(zipFile.getData());
            zipInputStream = new ZipInputStream(new BufferedInputStream(byteStream));

            int                   bufferSize = 1024;
            ZipEntry              ze;
            ByteArrayOutputStream baos;
            byte[]                buffer = new byte[bufferSize];
            byte[]                uncompressedBytes;
            int                   bytesRead;

            while ((ze = zipInputStream.getNextEntry()) != null) {
                log.debug("extracting zip entry: " + ze.getName());

                if (!beforeUncompress(em, zipFile, ze)) continue;

                baos = new ByteArrayOutputStream();
                while ((bytesRead = zipInputStream.read(buffer, 0, bufferSize)) > 0) {
                    baos.write(buffer, 0, bytesRead);
                }
                baos.close();
                uncompressedBytes = baos.toByteArray();

                Object newObject = createNewObject(em, zipFile, ze, uncompressedBytes);
                if (newObject != null) {
                    newObjects.put(ze.getName(), newObject);
                }

                zipInputStream.closeEntry();
            }

        } catch (Exception ex) {
            throw new RuntimeException(ex);
        } finally {
            try {
                if (zipInputStream != null) zipInputStream.close();
                if (byteStream != null) byteStream.close();
            } catch (Exception e) {
                e.printStackTrace(System.err);
            }
        }

        handleNewObjects(em, zipFile, newObjects);

        return true;
    }

    protected boolean beforeUncompress(EntityManager em, WikiUpload zipFile, ZipEntry zipEntry) {

        if (zipEntry.getName().contains("/")) {
            log.debug("skipping directory: " + zipEntry.getName());
            statusMessages.addFromResourceBundleOrDefault(
                ERROR,
                "lacewiki.msg.ImportSkippingDirectory",
                "Skipping directory '{0}', importing not supported...",
                zipEntry.getName()
            );
            return false; // Not supported
        }

        // This assumes that the wiki name is the zip entry filename without extension - maybe we should
        // support with extension as option, that's unique inside a zip archive so we fail too often
        WikiUpload tmp = new WikiUpload();
        tmp.setFilename(zipEntry.getName());
        return validateNewWikiname(zipFile, WikiUtil.convertToWikiName(tmp.getFilenameWithoutExtension()));
    }

    protected boolean validateNewWikiname(WikiUpload zipFile, String newWikiname) {
        log.debug("validating wiki name of new file: " + newWikiname);

        if (wikiNodeDAO.isUniqueWikiname(zipFile.getAreaNumber(), newWikiname) ) {
            log.debug("new name is unique and valid");
            return true;
        } else {
            log.debug("new name is not unique and invalid");
            statusMessages.addFromResourceBundleOrDefault(
                ERROR,
                "lacewiki.msg.ImportDuplicateName",
                "Skipping file '{0}', name is already used in this area...",
                newWikiname
            );
            return false;
        }
    }

    protected Object createNewObject(EntityManager em, WikiUpload zipFile, ZipEntry zipEntry, byte[] uncompressedBytes) {
        log.debug("creating new file from zip entry: " + zipEntry.getName());

        // First figure out what it is
        String mimeType = null;
        try {
            mimeType = Magic.getMagicMatch(uncompressedBytes).getMimeType();
        } catch (Exception ex) {}
        String contentType = mimeType != null ? mimeType : UploadTypes.DEFAULT_UPLOAD_TYPE;

        // Just a temporary value holder this time
        Uploader uploader = new Uploader();
        uploader.setData(uncompressedBytes);
        uploader.setFilename(zipEntry.getName());
        uploader.setContentType(contentType);

        // Get the right handler for that type and produce a WikiUpload instance
        UploadType uploadType = uploadTypes.get(contentType);
        if (uploadType == null) uploadType = uploadTypes.get(UploadTypes.GENERIC_UPLOAD_TYPE);
        WikiUpload wikiUpload = uploadType.getUploadHandler().handleUpload(uploader);

        // Now set the other properties so we can persist it directly
        wikiUpload.setName(wikiUpload.getFilenameWithoutExtension());
        wikiUpload.setWikiname(WikiUtil.convertToWikiName(wikiUpload.getName()));
        wikiUpload.setAreaNumber(zipFile.getAreaNumber());
        wikiUpload.setCreatedBy(zipFile.getCreatedBy());
        wikiUpload.setLastModifiedBy(wikiUpload.getCreatedBy());
        wikiUpload.setCreatedOn(new Date(zipEntry.getTime()));
        wikiUpload.setLastModifiedOn(wikiUpload.getCreatedOn());
        wikiUpload.setReadAccessLevel(zipFile.getReadAccessLevel());
        wikiUpload.setWriteAccessLevel(zipFile.getWriteAccessLevel());

        log.debug("created new file from zip entry: " + wikiUpload);

        return wikiUpload;
    }

    public void handleNewObjects(EntityManager em, WikiUpload zipFile, Map<String, Object> newObjects) {
        persistWikiUploadsSorted(
            em,
            zipFile,
            newObjects,
            new Comparator() {
                public int compare(Object o, Object o1) {
                    if ( !(o instanceof WikiNode) &&  !(o1 instanceof WikiNode) ) return 0;
                    return ((WikiNode)o).getWikiname().compareTo( ((WikiNode)o1).getWikiname() );
                }
            }
        );
    }

    private void persistWikiUploadsSorted(EntityManager em, WikiUpload zipFile, Map<String, Object> newObjects, Comparator comparator) {

        List<WikiNode> newNodes = new ArrayList<WikiNode>();
        for (Object newObject : newObjects.values()) {
            if (newObject instanceof WikiNode) {
                newNodes.add((WikiNode)newObject);
            }
        }
        Collections.sort(newNodes, comparator);

        for (WikiNode newNode : newNodes) {
            log.debug("validating new node");

            ClassValidator validator = Validators.instance().getValidator(newNode.getClass());
            InvalidValue[] invalidValues = validator.getInvalidValues(newNode);
            if (invalidValues != null && invalidValues.length > 0) {
                log.debug("new node is invalid: " + newNode);
                for (InvalidValue invalidValue : invalidValues) {
                    statusMessages.addFromResourceBundleOrDefault(
                        ERROR,
                        "lacewiki.msg.ImportInvalidNode",
                        "Skipping entry '{0}', invalid: {1}",
                        newNode.getName(),
                        invalidValue.getMessage()

                    );
                }
                continue;
            }

            log.debug("persisting newly imported node: " + newNode);
            newNode.setParent(zipFile.getParent());
            em.persist(newNode);
            statusMessages.addFromResourceBundleOrDefault(
                INFO,
                "lacewiki.msg.ImportOk",
                "Created file '{0}' in current directory.",
                newNode.getName()
            );
        }
    }


}
TOP

Related Classes of org.jboss.seam.wiki.core.upload.importers.ZipImporter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.