/** * Copyright 2010 The University of North Carolina at Chapel Hill * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package unc.lib.cdr.workbench.project; import edu.unc.lib.staging.StagingException; import gov.loc.mets.DivType; import gov.loc.mets.FileGrpType; import gov.loc.mets.FileType; import gov.loc.mets.FptrType; import gov.loc.mets.util.METSUtils; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.net.URI; import java.util.ArrayDeque; import java.util.Deque; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; import org.eclipse.core.filesystem.EFS; import org.eclipse.core.filesystem.IFileStore; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.emf.common.util.TreeIterator; import org.eclipse.emf.ecore.EObject; import staging.plugin.StagingPlugin; import unc.lib.cdr.workbench.originals.OriginalFileStore; import unc.lib.cdr.workbench.rcp.Activator; public class BagItZipExportJob extends Job { IProject project = null; String destination = null; public BagItZipExportJob(IProject project, String destination) { super("Export BagIt ZIP Package"); this.project = project; this.destination = destination; } @Override protected IStatus run(IProgressMonitor monitor) { MetsProjectNature nature = MetsProjectNature.get(project); if (nature == null) { return new Status(IStatus.ERROR, Activator.PLUGIN_ID, "Project is not a Curator's Workbench project."); } DivType bag = METSUtils.findBagDiv(nature.getMets()); FileGrpType fileGrp = METSUtils.getObjectsFileGroup(nature.getMets()); byte[] buffer = new byte[1024]; // create a ZIP file writer FileOutputStream fout = null; try { fout = new FileOutputStream(destination); } catch (IOException e) { return new Status(IStatus.ERROR, Activator.PLUGIN_ID, "Cannot create export ZIP file", e); } ZipOutputStream zout = new ZipOutputStream(fout); PrintWriter out = new PrintWriter(zout); zout.setComment("BagIt ZIP serialization by Curator's Workbench"); try { // add bagit.txt zout.putNextEntry(new ZipEntry(project.getName() + "/bagit.txt")); out.println("BagIt-version: 0.96"); out.println("Tag-File-Character-Encoding: UTF-8"); out.flush(); zout.closeEntry(); // build manifest-md5 and packaged files list zout.putNextEntry(new ZipEntry(project.getName() + "/manifest-md5.txt")); for (TreeIterator<EObject> iter = bag.eAllContents(); iter .hasNext();) { EObject eo = iter.next(); if (eo instanceof FptrType) { FptrType fptr = (FptrType) eo; String fid = fptr.getFILEID(); for (FileType ftype : fileGrp.getFile()) { if (fid.equals(ftype.getID())) { out.print(ftype.getCHECKSUM()); out.print(' '); out.println(getLocation( (DivType) fptr.eContainer(), bag)); } } } } out.flush(); zout.closeEntry(); // send files to ZIP for (TreeIterator<EObject> iter = bag.eAllContents(); iter .hasNext();) { EObject eo = iter.next(); if (eo instanceof FptrType) { FptrType fptr = (FptrType) eo; String fid = fptr.getFILEID(); for (FileType ftype : fileGrp.getFile()) { if (fid.equals(ftype.getID())) { // found file element, process this file.. zout.putNextEntry(new ZipEntry(this.project .getName() + "/" + getLocation((DivType) fptr.eContainer(), bag))); OriginalFileStore orig = MetsProjectNature .getOriginalFileStore((DivType) fptr.eContainer()); IFileStore source = orig; if (orig.getStagingLocatorType() != null) { URI manifestURI = URI.create(orig .getStagingLocatorType().getHref()); URI store; try { store = StagingPlugin.getDefault() .getStages() .getStorageURI(manifestURI); IFileStore test = EFS.getStore(store); if (test.fetchInfo().exists()) { source = test; } } catch (StagingException ignored) { } } stream(zout, source, buffer); zout.closeEntry(); } } } } } catch (IOException e) { return new Status(IStatus.ERROR, Activator.PLUGIN_ID, "Cannot create export ZIP file", e); } catch (CoreException e) { return e.getStatus(); } finally { if (zout != null) { try { zout.close(); } catch (IOException e) { } } if (out != null) out.close(); } try { nature.getProject().refreshLocal(IResource.DEPTH_ONE, new NullProgressMonitor()); } catch (CoreException ignored) { } // write all data files in main manifest // close the zip file return Status.OK_STATUS; } private void stream(ZipOutputStream zout, IFileStore store, byte[] buffer) throws IOException, CoreException { InputStream in = store.openInputStream(EFS.NONE, new NullProgressMonitor()); int length; while ((length = in.read(buffer)) > 0) { zout.write(buffer, 0, length); } in.close(); } /** * Generate a path to this file, based on labels in the div tree. * * @param div * the div for the File * @return BagIt path to the file */ private String getLocation(DivType div, DivType bagDiv) { Deque<String> pathSegments = new ArrayDeque<String>(); for (DivType d = div; !bagDiv.equals(d); d = (DivType) d.eContainer()) { pathSegments.push(d.getLABEL1()); } pathSegments.push("data"); StringBuilder sb = new StringBuilder(pathSegments.poll()); for (String seg = pathSegments.poll(); seg != null; seg = pathSegments .poll()) { sb.append("/"); sb.append(seg); } return sb.toString(); } }