/* * Copyright (C) 2005 Alfresco, Inc. * * Licensed under the Mozilla Public License version 1.1 * with a permitted attribution clause. You may obtain a * copy of the License at * * http://www.alfresco.org/legal/license.txt * * 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 org.alfresco.repo.content; import java.io.BufferedOutputStream; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.nio.channels.Channels; import java.nio.channels.WritableByteChannel; import java.util.ArrayList; import java.util.List; import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.service.cmr.repository.ContentAccessor; import org.alfresco.service.cmr.repository.ContentIOException; import org.alfresco.service.cmr.repository.ContentReader; import org.alfresco.service.cmr.repository.ContentStreamListener; import org.alfresco.service.cmr.repository.ContentWriter; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.aop.framework.ProxyFactory; import org.springframework.util.FileCopyUtils; /** * Implements all the convenience methods of the interface. The only methods * that need to be implemented, i.e. provide low-level content access are: *
* Only the instance need be constructed. The required mimetype, encoding, etc * will be copied across by this class. *
* * @return Returns a reader onto the location referenced by this instance. * The instance must always be a new instance and never null. * @throws ContentIOException */ protected abstract ContentReader createReader() throws ContentIOException; /** * Performs checks and copies required reader attributes */ public final ContentReader getReader() throws ContentIOException { if (!isClosed()) { return null; } ContentReader reader = createReader(); if (reader == null) { throw new AlfrescoRuntimeException("ContentReader failed to create new reader: \n" + " writer: " + this); } else if (reader.getContentUrl() == null || !reader.getContentUrl().equals(getContentUrl())) { throw new AlfrescoRuntimeException("ContentReader has different URL: \n" + " writer: " + this + "\n" + " new reader: " + reader); } // copy across common attributes reader.setMimetype(this.getMimetype()); reader.setEncoding(this.getEncoding()); // done if (logger.isDebugEnabled()) { logger.debug("Writer spawned new reader: \n" + " writer: " + this + "\n" + " new reader: " + reader); } return reader; } /** * An automatically created listener sets the flag */ public synchronized final boolean isClosed() { if (channel != null) { return !channel.isOpen(); } else { return false; } } /** * Provides low-level access to write content to the repository. *
* This is the only of the content writing methods that needs to be implemented
* by derived classes. All other content access methods make use of this in their
* underlying implementations.
*
* @return Returns a channel with which to write content
* @throws ContentIOException if the channel could not be opened
*/
protected abstract WritableByteChannel getDirectWritableChannel() throws ContentIOException;
/**
* Optionally override to supply an alternate callback channel.
*
* @param directChannel the result of {@link #getDirectWritableChannel()}
* @param listeners the listeners to call
* @return Returns a callback channel
* @throws ContentIOException
*/
protected WritableByteChannel getCallbackWritableChannel(
WritableByteChannel directChannel,
List