Package org.pentaho.platform.plugin.services.importexport

Source Code of org.pentaho.platform.plugin.services.importexport.ZipExportProcessor

/*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU General Public License, version 2 as published by the Free Software
* Foundation.
*
* You should have received a copy of the GNU General Public License along with this
* program; if not, you can obtain a copy at http://www.gnu.org/licenses/gpl-2.0.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 General Public License for more details.
*
*
* Copyright 2006 - 2013 Pentaho Corporation.  All rights reserved.
*/

package org.pentaho.platform.plugin.services.importexport;

/*
* 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 2013 Pentaho Corporation.  All rights reserved.
*
* User: pminutillo
* Date: 1/16/13
* Time: 4:41 PM
*/

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Properties;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.pentaho.platform.api.engine.IPentahoSession;
import org.pentaho.platform.api.repository2.unified.IUnifiedRepository;
import org.pentaho.platform.api.repository2.unified.RepositoryFile;
import org.pentaho.platform.api.repository2.unified.RepositoryFileAcl;
import org.pentaho.platform.api.repository2.unified.RepositoryRequest;
import org.pentaho.platform.engine.core.system.PentahoSessionHolder;
import org.pentaho.platform.plugin.services.importexport.exportManifest.ExportManifest;
import org.pentaho.platform.plugin.services.importexport.exportManifest.ExportManifestFormatException;
import org.pentaho.platform.repository2.ClientRepositoryPaths;
import org.pentaho.platform.repository2.unified.webservices.LocaleMapDto;

/**
*
*/
public class ZipExportProcessor extends BaseExportProcessor {
  private static final Log log = LogFactory.getLog( ZipExportProcessor.class );

  private String path;

  private ExportManifest exportManifest;

  IUnifiedRepository unifiedRepository;

  private boolean withManifest = true;

  private List<String> localeExportList;

  /**
   * Encapsulates the logic of registering import handlers, generating the manifest, and performing the export
   */
  public ZipExportProcessor( String path, IUnifiedRepository repository, boolean withManifest ) {
    this.withManifest = withManifest;

    // set a default path at root if missing
    if ( StringUtils.isEmpty( path ) ) {
      this.path = "/";
    } else {
      this.path = path;
    }

    this.unifiedRepository = repository;

    this.exportHandlerList = new ArrayList<ExportHandler>();

    this.exportManifest = new ExportManifest();

    // set created by and create date in manifest information
    IPentahoSession session = PentahoSessionHolder.getSession();

    Date todaysDate = new Date();
    SimpleDateFormat dateFormat = new SimpleDateFormat( EXPORT_INFO_DATE_FORMAT );
    SimpleDateFormat timeFormat = new SimpleDateFormat( EXPORT_INFO_TIME_FORMAT );

    exportManifest.getManifestInformation().setExportBy( session.getName() );
    exportManifest.getManifestInformation().setExportDate(
        dateFormat.format( todaysDate ) + " " + timeFormat.format( todaysDate ) );
    exportManifest.getManifestInformation().setManifestVersion( "2" );
  }

  /**
   * Performs the export process, returns a zip File object
   *
   * @throws ExportException indicates an error in import processing
   */
  public File performExport( RepositoryFile exportRepositoryFile ) throws ExportException, IOException {
    File exportFile = null;

    // create temp file
    exportFile = File.createTempFile( EXPORT_TEMP_FILENAME_PREFIX, EXPORT_TEMP_FILENAME_EXT );
    exportFile.deleteOnExit();

    // get the file path
    String filePath = new File( this.path ).getParent();
    if ( filePath == null ) {
      filePath = "/";
    }

    // send a response right away if not found
    if ( exportRepositoryFile == null ) {
      // todo: add to messages.properties
      throw new FileNotFoundException( "JCR file not found: " + this.path );
    }

    ZipOutputStream zos = new ZipOutputStream( new FileOutputStream( exportFile ) );

    if ( exportRepositoryFile.isFolder() ) { // Handle recursive export
      exportManifest.getManifestInformation().setRootFolder( path.substring( 0, path.lastIndexOf( "/" ) + 1 ) );

      // don't zip root folder without name
      if ( !ClientRepositoryPaths.getRootFolderPath().equals( exportRepositoryFile.getPath() ) ) {
        zos.putNextEntry( new ZipEntry( ExportFileNameEncoder.encodeZipPathName( getZipEntryName( exportRepositoryFile, filePath ) ) ) );
      }
      exportDirectory( exportRepositoryFile, zos, filePath );

    } else {
      exportManifest.getManifestInformation().setRootFolder( path.substring( 0, path.lastIndexOf( "/" ) + 1 ) );
      exportFile( exportRepositoryFile, zos, filePath );
    }

    if ( this.withManifest ) {
      // write manifest to zip output stream
      ZipEntry entry = new ZipEntry( EXPORT_MANIFEST_FILENAME );
      zos.putNextEntry( entry );

      // pass output stream to manifest class for writing
      try {
        exportManifest.toXml( zos );
      } catch ( Exception e ) {
        // todo: add to messages.properties
        log.error( "Error generating export XML" );
      }

      zos.closeEntry();
    }

    zos.close();

    // clean up
    exportManifest = null;
    zos = null;

    return exportFile;
  }

  /**
   * @param repositoryFile
   * @param outputStream
   * @throws ExportManifestFormatException
   */
  public void exportFile( RepositoryFile repositoryFile, OutputStream outputStream, String filePath ) throws
      ExportException, IOException {

    // we need a zip
    ZipOutputStream zos = (ZipOutputStream) outputStream;

    // iterate through handlers to perform export
    for ( ExportHandler exportHandler : exportHandlerList ) {

      InputStream is = exportHandler.doExport( repositoryFile, filePath );

      // if we don't get a valid input stream back, skip it
      if ( is != null ) {
        addToManifest( repositoryFile );
        ZipEntry entry =
            new ZipEntry( ExportFileNameEncoder.encodeZipPathName( getZipEntryName( repositoryFile, filePath ) ) );
        zos.putNextEntry( entry );
        IOUtils.copy( is, outputStream );
        zos.closeEntry();
        is.close();
        createLocales( repositoryFile, filePath, repositoryFile.isFolder(), outputStream );
      }
    }
  }

  /**
   * create an entry in the export manifest for this file or folder
   *
   * @param repositoryFile
   * @throws ExportException
   */
  private void addToManifest( RepositoryFile repositoryFile ) throws ExportException {
    if ( this.withManifest ) {
      // add this entity to the manifest
      RepositoryFileAcl fileAcl = unifiedRepository.getAcl( repositoryFile.getId() );
      try {
        exportManifest.add( repositoryFile, fileAcl );
      } catch ( ExportManifestFormatException e ) {
        throw new ExportException( e.getMessage() );
      }
    }
  }

  /**
   * @param repositoryDir
   * @param outputStream
   */
  @Override
  public void exportDirectory( RepositoryFile repositoryDir, OutputStream outputStream, String filePath ) throws
      ExportException, IOException {
    addToManifest( repositoryDir );
    List<RepositoryFile> children = this.unifiedRepository.getChildren( new RepositoryRequest(
        String.valueOf( repositoryDir.getId() ), true, 1, null ) );
    for ( RepositoryFile repositoryFile : children ) {
      // exclude 'etc' folder - datasources and etc.
      if ( !ClientRepositoryPaths.getEtcFolderPath().equals( repositoryFile.getPath() ) ) {
        if ( repositoryFile.isFolder() ) {
          if ( outputStream.getClass().isAssignableFrom( ZipOutputStream.class ) ) {
            ZipOutputStream zos = (ZipOutputStream) outputStream;
            ZipEntry entry =
                new ZipEntry( ExportFileNameEncoder.encodeZipPathName( getZipEntryName( repositoryFile, filePath ) ) );
            zos.putNextEntry( entry );
          }
          exportDirectory( repositoryFile, outputStream, filePath );
        } else {
          exportFile( repositoryFile, outputStream, filePath );
        }
      }
    }
    createLocales( repositoryDir, filePath, repositoryDir.isFolder(), outputStream );
  }

  /**
   * Take repository file path and local file path and return computed zip entry path
   *
   * @param repositoryFile
   * @param filePath
   * @return
   */
  private String getZipEntryName( RepositoryFile repositoryFile, String filePath ) {
    String result = "";

    // if we are at the root, get substring differently
    int filePathLength = 0;

    if ( filePath.equals( "/" ) || filePath.equals( "\\" ) ) {
      filePathLength = filePath.length();
    } else {
      filePathLength = filePath.length() + 1;
    }

    result = repositoryFile.getPath().substring( filePathLength );

    // add trailing slash for folders
    if ( repositoryFile.isFolder() ) {
      result += "/";
    }

    return result;
  }

  /**
   * for each locale stored in in Jcr create a .locale file with the stored node properties
   *
   * @param zos
   * @param repositoryFile
   * @param filePath
   * @throws IOException
   */
  private void createLocales( RepositoryFile repositoryFile, String filePath, boolean isFolder,
                              OutputStream outputStrean ) throws IOException {
    ZipEntry entry;
    String zipName;
    String name;
    String localeName;
    Properties properties;
    ZipOutputStream zos = (ZipOutputStream) outputStrean;
    // only process files and folders that we know will have locale settings
    if ( supportedLocaleFileExt( repositoryFile ) ) {
      List<LocaleMapDto> locales = getAvailableLocales( repositoryFile.getId() );
      zipName = ExportFileNameEncoder.encodeZipPathName( getZipEntryName( repositoryFile, filePath ) );
      name = repositoryFile.getName();
      for ( LocaleMapDto locale : locales ) {
        localeName = locale.getLocale().equalsIgnoreCase( "default" ) ? "" : "_" + locale.getLocale();
        if ( isFolder ) {
          zipName = ExportFileNameEncoder.encodeZipPathName( getZipEntryName( repositoryFile, filePath ) + "index" );
          name = "index";
        }

        properties = unifiedRepository.getLocalePropertiesForFileById( repositoryFile.getId(), locale.getLocale() );
        if ( properties != null ) {
          properties.remove( "jcr:primaryType" ); // Pentaho Type
          InputStream is = createLocaleFile( name + localeName, properties, locale.getLocale() );
          if ( is != null ) {
            entry = new ZipEntry( zipName + localeName + LOCALE_EXT );
            zos.putNextEntry( entry );
            IOUtils.copy( is, outputStrean );
            zos.closeEntry();
            is.close();
          }
        }
      }
    }
  }

  /**
   * there are certain extensions that get imported with locale maps (incorrectly?) like .png only export locale maps
   * for the list from importexport.xml
   *
   * @param repositoryFile
   * @return true if supported
   */
  private boolean supportedLocaleFileExt( RepositoryFile repositoryFile ) {
    boolean ans = true;
    String ext = repositoryFile.getName();
    if ( !repositoryFile.isFolder() ) {
      int idx = ext.lastIndexOf( "." );
      if ( idx > 0 ) {
        ext = ext.substring( idx, ext.length() );
      }
      List<String> exportList = getLocaleExportList();
      if ( exportList != null ) {
        ans = exportList.contains( ext );
      }

    }
    return ans;
  }

  /**
   * lookup the list of available locale values
   *
   * @param fileId
   * @return
   */
  private List<LocaleMapDto> getAvailableLocales( Serializable fileId ) {
    List<LocaleMapDto> availableLocales = new ArrayList<LocaleMapDto>();
    List<Locale> locales = unifiedRepository.getAvailableLocalesForFileById( fileId );
    if ( locales != null && !locales.isEmpty() ) {
      for ( Locale locale : locales ) {
        availableLocales.add( new LocaleMapDto( locale.toString(), null ) );
      }
    }
    return availableLocales;
  }

  /**
   * need to create the locale file
   *
   * @param name
   * @param properties
   * @param locale
   * @throws IOException
   * @returns inputStream pointer to created file or null
   */
  private InputStream createLocaleFile( String name, Properties properties, String locale ) throws IOException {
    InputStream is = null;
    if ( properties != null ) {
      File localeFile = File.createTempFile( ExportFileNameEncoder.encodeZipFileName( name ), LOCALE_EXT );
      localeFile.deleteOnExit();
      FileOutputStream fileOut = new FileOutputStream( localeFile );
      properties.store( fileOut, "Locale = " + locale );
      fileOut.close();
      is = new FileInputStream( localeFile );

    }
    return is;
  }

  /**
   * get the list of files we are interested in supporting locale from Spring
   *
   * @return
   */
  public List<String> getLocaleExportList() {
    if ( this.localeExportList == null || this.localeExportList.isEmpty() ) {
      for ( ExportHandler exportHandler : exportHandlerList ) {
        this.localeExportList = ( (DefaultExportHandler) exportHandler ).getLocaleExportList();
        break;
      }
    }
    return localeExportList;
  }

  public void setLocaleExportList( List<String> localeExportList ) {
    this.localeExportList = localeExportList;
  }
}
TOP

Related Classes of org.pentaho.platform.plugin.services.importexport.ZipExportProcessor

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.