Package org.structr.websocket.command

Source Code of org.structr.websocket.command.UnarchiveCommand

/**
* Copyright (C) 2010-2014 Morgner UG (haftungsbeschränkt)
*
* This file is part of Structr <http://structr.org>.
*
* Structr is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* Structr 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 General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Structr.  If not, see <http://www.gnu.org/licenses/>.
*/
package org.structr.websocket.command;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.commons.compress.archivers.ArchiveEntry;
import org.apache.commons.compress.archivers.ArchiveException;
import org.apache.commons.compress.archivers.ArchiveInputStream;
import org.apache.commons.compress.archivers.ArchiveStreamFactory;
import org.apache.commons.lang3.StringUtils;
import org.structr.common.PathHelper;
import org.structr.common.SecurityContext;
import org.structr.common.error.FrameworkException;
import org.structr.core.app.App;
import org.structr.core.app.StructrApp;
import org.structr.core.graph.Tx;
import org.structr.dynamic.File;
import org.structr.web.common.FileHelper;
import org.structr.web.common.ImageHelper;
import org.structr.web.entity.AbstractFile;
import org.structr.web.entity.Folder;
import org.structr.web.entity.Image;
import org.structr.websocket.StructrWebSocket;
import org.structr.websocket.message.MessageBuilder;
import org.structr.websocket.message.WebSocketMessage;

//~--- classes ----------------------------------------------------------------
/**
* Websocket command for un-archiving archive files.
*
* @author Axel Morgner
*/
public class UnarchiveCommand extends AbstractCommand {

  private static final Logger logger = Logger.getLogger(UnarchiveCommand.class.getName());

  static {

    StructrWebSocket.addCommand(UnarchiveCommand.class);

  }

  //~--- methods --------------------------------------------------------
  @Override
  public void processMessage(WebSocketMessage webSocketData) {

    final Set<String> supportedByArchiveStreamFactory = new HashSet<>(Arrays.asList(new String[]{
      ArchiveStreamFactory.AR,
      ArchiveStreamFactory.ARJ,
      ArchiveStreamFactory.CPIO,
      ArchiveStreamFactory.DUMP,
      ArchiveStreamFactory.JAR,
      ArchiveStreamFactory.TAR,
      ArchiveStreamFactory.ZIP
    }));

    final SecurityContext securityContext = getWebSocket().getSecurityContext();
    final App app                         = StructrApp.getInstance(securityContext);

    try {

      final String id = (String) webSocketData.getId();
      final File file;

      try (final Tx tx = app.tx()) {

        file = app.get(File.class, id);

        if (file == null) {
          getWebSocket().send(MessageBuilder.status().code(400).message("File not found: ".concat(id)).build(), true);
          return;
        }

        final String fileExtension = StringUtils.substringAfterLast(file.getName(), ".");
        if (!supportedByArchiveStreamFactory.contains(fileExtension)) {

          getWebSocket().send(MessageBuilder.status().code(400).message("Unsupported archive format: ".concat(fileExtension)).build(), true);
          return;
        }

        tx.success();
      }

      // no transaction here since this is a bulk command
      unarchive(securityContext, file);


    } catch (Throwable t) {

      t.printStackTrace();

      String msg = t.toString();

      try (final Tx tx = app.tx()) {

        // return error message
        getWebSocket().send(MessageBuilder.status().code(400).message("Could not unarchive file: ".concat((msg != null) ? msg : "")).build(), true);

        tx.success();

      } catch (FrameworkException ignore) {}

    }
  }

  @Override
  public boolean requiresEnclosingTransaction() {
    return false;
  }

  /**
   * Return the folder node which corresponds with the parent path.
   *
   * @param path
   */
  private Folder createOrGetParentFolder(final SecurityContext securityContext, final String path) throws FrameworkException {

    final String[] parts = PathHelper.getParts(path);

    // string is empty or a single file in root dir
    if (parts == null || parts.length == 1) {
      return null;
    }

    // Find root folder
    final App app = StructrApp.getInstance(securityContext);
    Folder folder = null;
    for (final Folder possibleRootFolder : app.nodeQuery(Folder.class).andName(parts[0])) {

      if (possibleRootFolder.getProperty(Folder.parent) == null) {
        folder = possibleRootFolder;
        break;
      }

    }

    if (folder == null) {

      // Root folder doesn't exist, so create it and all child folders
      folder = app.create(Folder.class, parts[0]);
      logger.log(Level.INFO, "Created root folder {0}", new Object[]{parts[0]});

      for (int i = 1; i < parts.length - 1; i++) {
        Folder childFolder = app.create(Folder.class, parts[i]);
        childFolder.setProperty(Folder.parent, folder);
        logger.log(Level.INFO, "Created {0} {1} with path {2}", new Object[]{childFolder.getType(), childFolder, FileHelper.getFolderPath(childFolder)});
        folder = childFolder;
      }

      return folder;

    }

    // Root folder exists, so walk over children and search for next path part
    for (int i = 1; i < parts.length - 1; i++) {

      Folder subFolder = null;

      for (AbstractFile child : folder.getProperty(Folder.children)) {

        if (child instanceof Folder && child.getName().equals(parts[i])) {
          subFolder = (Folder) child;
          break;
        }

      }

      if (subFolder == null) {

        // sub folder doesn't exist, so create it and all child folders
        subFolder = app.create(Folder.class, parts[i]);
        subFolder.setProperty(Folder.parent, folder);
        logger.log(Level.INFO, "Created {0} {1} with path {2}", new Object[]{subFolder.getType(), subFolder, FileHelper.getFolderPath(subFolder)});

      }

      folder = subFolder;
    }

    return folder;

  }

  private void unarchive(final SecurityContext securityContext, final File file) throws ArchiveException, IOException, FrameworkException {

    final App app = StructrApp.getInstance(securityContext);
    final InputStream is;

    try (final Tx tx = app.tx()) {

      final String fileName = file.getName();

      logger.log(Level.INFO, "Unarchiving file {0}", fileName);

      is = file.getInputStream();
      tx.success();


      if (is == null) {

        getWebSocket().send(MessageBuilder.status().code(400).message("Could not get input stream from file ".concat(fileName)).build(), true);
        return;
      }
    }

    final ArchiveInputStream in = new ArchiveStreamFactory().createArchiveInputStream(new BufferedInputStream(is));
    ArchiveEntry entry          = in.getNextEntry();
    int overallCount            = 0;

    while (entry != null) {

      try (final Tx tx = app.tx()) {

        int count = 0;

        while (entry != null && count++ < 50) {

          final String entryPath = "/" + PathHelper.clean(entry.getName());
          logger.log(Level.INFO, "Entry path: {0}", entryPath);

          final AbstractFile f = FileHelper.getFileByAbsolutePath(securityContext, entryPath);
          if (f == null) {

            final Folder parentFolder = createOrGetParentFolder(securityContext, entryPath);
            final String name         = PathHelper.getName(entry.getName());

            if (StringUtils.isNotEmpty(name) && (parentFolder == null || !(FileHelper.getFolderPath(parentFolder).equals(entryPath)))) {

              AbstractFile fileOrFolder = null;

              if (entry.isDirectory()) {

                fileOrFolder = app.create(Folder.class, name);

              } else {

                fileOrFolder = ImageHelper.isImageType(name)
                  ? ImageHelper.createImage(securityContext, in, null, Image.class, name, false)
                  : FileHelper.createFile(securityContext, in, null, File.class, name);
              }

              if (parentFolder != null) {
                fileOrFolder.setProperty(AbstractFile.parent, parentFolder);
              }

              logger.log(Level.INFO, "Created {0} {1} with path {2}", new Object[]{fileOrFolder.getType(), fileOrFolder, FileHelper.getFolderPath(fileOrFolder)});

              // create thumbnails while importing data
              if (fileOrFolder instanceof Image) {
                fileOrFolder.getProperty(Image.tnMid);
                fileOrFolder.getProperty(Image.tnSmall);
              }

            }
          }

          entry = in.getNextEntry();

          overallCount++;
        }

        logger.log(Level.INFO, "Committing transaction after {0} files..", overallCount);

        tx.success();
      }

    }

    in.close();

  }

  //~--- get methods ----------------------------------------------------
  @Override
  public String getCommand() {
    return "UNARCHIVE";
  }
}
TOP

Related Classes of org.structr.websocket.command.UnarchiveCommand

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.