package org.simantics.export.core.impl; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; import org.eclipse.core.runtime.IProgressMonitor; import org.osgi.service.prefs.Preferences; import org.simantics.databoard.Accessors; import org.simantics.databoard.Bindings; import org.simantics.databoard.Datatypes; import org.simantics.databoard.accessor.RecordAccessor; import org.simantics.databoard.accessor.error.AccessorConstructionException; import org.simantics.databoard.accessor.error.AccessorException; import org.simantics.databoard.accessor.reference.LabelReference; import org.simantics.databoard.binding.mutable.Variant; import org.simantics.databoard.forms.DataboardForm; import org.simantics.databoard.type.RecordType; import org.simantics.databoard.util.StreamUtil; import org.simantics.export.core.ExportContext; import org.simantics.export.core.error.ExportException; import org.simantics.export.core.intf.PublisherClass; import org.simantics.export.core.manager.Content; import org.simantics.export.core.util.ExporterUtils; /** * There are two fields in this publisher: * [ ] Overwrite file(s) * [ ] Export to Zip * * TODO Zip pref saving should be based on content selection * * @author toni.kalajainen@semantum.fi */ public class ZipPublisher implements PublisherClass { private static final String ZIP_EXTENSION = ".zip"; public static RecordType RT_ZIP; public static LabelReference P_ALLOW_OVERWRITE = new LabelReference("Overwrite file(s)"); public static LabelReference P_ZIP = new LabelReference("Export to .zip"); static { RT_ZIP = new RecordType(); RT_ZIP.addComponent(P_ZIP.label, DataboardForm.fileSaveDialog(ZIP_EXTENSION, "*.zip")); RT_ZIP.addComponent(P_ALLOW_OVERWRITE.label, Datatypes.BOOLEAN); } @Override public void publish(ExportContext ctx, List contents, Variant options, Variant locationOptions, IProgressMonitor monitor) throws ExportException { Boolean canOverwrite = ExporterUtils.getBoolean(locationOptions, P_ALLOW_OVERWRITE); String zipPath = ExporterUtils.getString( locationOptions, P_ZIP ); if ( zipPath == null ) throw new ExportException("Zip option missing"); if ( canOverwrite == null ) throw new ExportException("CanOverwrite option missing"); zipPath = PublisherUtil.ensureEndsWith(true, ZIP_EXTENSION, zipPath); File file = new File( zipPath ); if ( file.exists() ) { if ( canOverwrite ) { file.delete(); } else { throw new ExportException("Would not overwrite " + file.getAbsolutePath()); } } // Assert the data is OK. Expected to be. for ( Content content : contents ) { if ( content.tmpFile == null ) throw new ExportException("Internal error, tmpFile was null"); } FileOutputStream fos = null; try { fos = new FileOutputStream( file ); ZipOutputStream zos = new ZipOutputStream(fos); for ( Content content : contents ) { FileInputStream fis = new FileInputStream( content.tmpFile ); try { zos.putNextEntry(new ZipEntry( content.filename )); StreamUtil.copyStream(fis, zos); zos.closeEntry(); } finally { fis.close(); } } zos.close(); } catch (IOException e) { throw new ExportException( e ); } finally { if ( fos != null ) try { fos.close(); } catch (IOException e) {} } } @Override public List validate(ExportContext ctx, List contents, Variant options, Variant locationOptions) throws ExportException { List result = new ArrayList(); Boolean canOverwrite = ExporterUtils.getBoolean(locationOptions, P_ALLOW_OVERWRITE); String pathName = ExporterUtils.getString( locationOptions, P_ZIP ); if ( pathName == null ) { result.add("Zip option missing?"); return result; } if ( canOverwrite == null ) { result.add("CanOverwrite option missing?"); return result; } if ( pathName.isEmpty() ) { result.add("Zip must be entered."); return result; } pathName = PublisherUtil.ensureEndsWith(true, ZIP_EXTENSION, pathName); File file = new File( pathName ); if ( !canOverwrite && file.exists() ) result.add( file.getAbsolutePath()+ " already exists." ); return result; } @Override public RecordType locationOptions(ExportContext ctx, List contents) throws ExportException { return RT_ZIP; } @Override public Variant createLocation(ExportContext ctx, Variant locationOptions) throws ExportException { // Make Dirs to the path. String zipName = ExporterUtils.getString( locationOptions, P_ZIP ); if ( zipName == null ) throw new ExportException("Zip option not found?"); File file = new File( zipName ); File path = file.getParentFile(); if ( path == null ) return locationOptions; if ( path.exists() && !path.isDirectory()) throw new ExportException(path+" exists but is not a directory."); if ( !path.mkdirs() ) throw new ExportException( "Failed to create "+path); return locationOptions; } @Override public boolean locationExists(ExportContext ctx, Variant locationOptions) throws ExportException { try { RecordAccessor ra = Accessors.getAccessor(locationOptions); String zipName = (String) ra.getValue(P_ZIP, Bindings.STRING); if ( zipName == null ) return false; File file = new File( zipName ); File path = file.getParentFile(); if ( path == null ) return false; return path.exists() && path.isDirectory(); } catch (AccessorConstructionException e) { throw new ExportException( e ); } catch (AccessorException e) { throw new ExportException( e ); } } @Override public void fillDefaultPrefs(ExportContext ctx, List contents, Variant options, Variant locationOptions) throws ExportException { try { RecordAccessor ra = Accessors.getAccessor(locationOptions); ra.setValue(P_ALLOW_OVERWRITE, Bindings.BOOLEAN, true); ra.setValue(P_ZIP, Bindings.STRING, ""); } catch (AccessorConstructionException e) { throw new ExportException(e); } catch (AccessorException e) { throw new ExportException(e); } } @Override public void savePref(Variant locationOptions, Preferences contentScopeNode, Preferences workspaceScopeNode) throws ExportException { try { RecordAccessor ra = Accessors.getAccessor( locationOptions ); Boolean b = (Boolean) ra.getValue(P_ALLOW_OVERWRITE, Bindings.BOOLEAN); if ( b!=null ) { contentScopeNode.putBoolean(P_ALLOW_OVERWRITE.tail().toString(), b); workspaceScopeNode.putBoolean(P_ALLOW_OVERWRITE.tail().toString(), b); } String s = (String) ra.getValue(P_ZIP, Bindings.STRING); if ( s!=null ) { contentScopeNode.put(P_ZIP.tail().toString(), s); //workspaceScopeNode.put(P_ZIP.tail().toString(), s); } } catch (AccessorException e) { throw new ExportException( e ); } catch (AccessorConstructionException e) { throw new ExportException( e ); } } @Override public void loadPref(Variant locationOptions, Preferences contentScopePrefs, Preferences workspaceScopePrefs) throws ExportException { try { RecordAccessor ra = Accessors.getAccessor(locationOptions); Boolean b = ExporterUtils.getPrefBoolean( contentScopePrefs, workspaceScopePrefs, P_ALLOW_OVERWRITE.tail().toString() ); if ( b!=null ) ra.setValue(P_ALLOW_OVERWRITE, Bindings.BOOLEAN, b); String s = ExporterUtils.getPrefString( contentScopePrefs, null, P_ZIP.tail().toString() ); if ( s!=null ) ra.setValue(P_ZIP, Bindings.STRING, s); } catch (AccessorConstructionException e) { throw new ExportException( e ); } catch (AccessorException e) { throw new ExportException( e ); } } }