001/* 002 * Copyright (c) 2006-2012 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the Eclipse Public License v1.0 006 * which accompanies this distribution, and is available at 007 * http://www.eclipse.org/legal/epl-v10.html 008 * 009 * Contributors: 010 * Florent Guillaume, jcarsique 011 */ 012 013package org.nuxeo.ecm.core.blob.binary; 014 015import java.io.File; 016import java.io.IOException; 017import java.io.InputStream; 018 019import org.apache.commons.io.output.NullOutputStream; 020import org.nuxeo.ecm.core.api.Blob; 021import org.nuxeo.ecm.core.api.impl.blob.FileBlob; 022 023/** 024 * A simple filesystem-based binary manager. It stores the binaries according to their digest (hash), which means that 025 * no transactional behavior needs to be implemented. 026 * <p> 027 * A garbage collection is needed to purge unused binaries. 028 * <p> 029 * The format of the <em>binaries</em> directory is: 030 * <ul> 031 * <li><em>data/</em> hierarchy with the actual binaries in subdirectories,</li> 032 * <li><em>tmp/</em> temporary storage during creation,</li> 033 * <li><em>config.xml</em> a file containing the configuration used.</li> 034 * </ul> 035 * 036 * @author Florent Guillaume 037 */ 038public class DefaultBinaryManager extends LocalBinaryManager { 039 040 @Override 041 public Binary getBinary(Blob blob) throws IOException { 042 if (!(blob instanceof FileBlob) || !((FileBlob) blob).isTemporary()) { 043 return super.getBinary(blob); // just open the stream 044 } 045 String digest = storeAndDigest((FileBlob) blob); 046 File file = getFileForDigest(digest, false); 047 /* 048 * Now we can build the Binary. 049 */ 050 return new Binary(file, digest, blobProviderId); 051 } 052 053 /** 054 * Stores and digests a temporary FileBlob. 055 */ 056 protected String storeAndDigest(FileBlob blob) throws IOException { 057 String digest; 058 try (InputStream in = blob.getStream()) { 059 digest = storeAndDigest(in, NullOutputStream.NULL_OUTPUT_STREAM); 060 } 061 File digestFile = getFileForDigest(digest, true); 062 if (digestFile.exists()) { 063 // The file with the proper digest is already there so don't do anything. This is to avoid 064 // "Stale NFS File Handle" problems which would occur if we tried to overwrite it anyway. 065 // Note that this doesn't try to protect from the case where two identical files are uploaded 066 // at the same time. 067 // Update date for the GC. 068 digestFile.setLastModified(blob.getFile().lastModified()); 069 } else { 070 blob.moveTo(digestFile); 071 } 072 return digest; 073 } 074 075}