| /* |
| * Copyright 2005 The Apache Software Foundation. |
| * |
| * 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 org.apache.jackrabbit.server.io; |
| |
| import org.apache.log4j.Logger; |
| import org.apache.jackrabbit.webdav.io.OutputContext; |
| import org.apache.jackrabbit.webdav.DavConstants; |
| import org.apache.jackrabbit.webdav.DavResource; |
| |
| import javax.jcr.Item; |
| import java.util.Map; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.Date; |
| import java.io.File; |
| import java.io.OutputStream; |
| import java.io.FileInputStream; |
| import java.io.IOException; |
| import java.io.FileOutputStream; |
| |
| /** |
| * <code>ExportContextImpl</code> implements an <code>ExportContext</code> that |
| * wraps around the specified OutputContext as it was passed to |
| * {@link DavResource#spool(OutputContext)}. If a stream is provided a temporary |
| * file is created, which is deleted as soon as {@link #informCompleted(boolean)} |
| * is called on this context. Note however, that the properties and the stream |
| * are written to the <code>OutputContext</code> but upon successful completion. |
| * |
| * @see #informCompleted(boolean) |
| */ |
| public class ExportContextImpl extends AbstractExportContext { |
| |
| private static Logger log = Logger.getLogger(ExportContextImpl.class); |
| |
| private final Map properties = new HashMap(); |
| private final OutputContext outputCtx; |
| |
| private File outFile; |
| private OutputStream outStream; |
| |
| public ExportContextImpl(Item exportRoot, OutputContext outputCtx) throws IOException { |
| super(exportRoot, (outputCtx != null) ? outputCtx.hasStream() : false, null); |
| this.outputCtx = outputCtx; |
| if (hasStream()) { |
| // we need a tmp file, since the export could fail |
| outFile = File.createTempFile("__exportcontext", "tmp"); |
| } |
| } |
| |
| /** |
| * Returns a new <code>OutputStream</code> to the temporary file or |
| * <code>null</code> if this context provides no stream. |
| * |
| * @see ExportContext#getOutputStream() |
| * @see #informCompleted(boolean) |
| */ |
| public OutputStream getOutputStream() { |
| checkCompleted(); |
| if (hasStream()) { |
| try { |
| // clean up the stream retrieved by the preceeding handler, that |
| // did not behave properly and failed to export although initially |
| // willing to handle the export. |
| if (outStream != null) { |
| outStream.close(); |
| } |
| outStream = new FileOutputStream(outFile); |
| return outStream; |
| } catch (IOException e) { |
| // unexpected error... ignore and return null |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * @see ExportContext#setContentLanguage(String) |
| */ |
| public void setContentLanguage(String contentLanguage) { |
| properties.put(DavConstants.HEADER_CONTENT_LANGUAGE, contentLanguage); |
| } |
| |
| /** |
| * @see ExportContext#setContentLength(long) |
| */ |
| public void setContentLength(long contentLength) { |
| properties.put(DavConstants.HEADER_CONTENT_LENGTH, contentLength + ""); |
| } |
| |
| /** |
| * @see ExportContext#setContentType(String,String) |
| */ |
| public void setContentType(String mimeType, String encoding) { |
| properties.put(DavConstants.HEADER_CONTENT_TYPE, IOUtil.buildContentType(mimeType, encoding)); |
| } |
| |
| /** |
| * Does nothing since the wrapped output context does not understand |
| * creation time |
| * |
| * @param creationTime |
| * @see ExportContext#setCreationTime(long) |
| */ |
| public void setCreationTime(long creationTime) { |
| // ignore since output-ctx does not understand creation time |
| } |
| |
| /** |
| * @see ExportContext#setModificationTime(long) |
| */ |
| public void setModificationTime(long modificationTime) { |
| if (modificationTime <= IOUtil.UNDEFINED_TIME) { |
| modificationTime = new Date().getTime(); |
| } |
| String lastMod = IOUtil.getLastModified(modificationTime); |
| properties.put(DavConstants.HEADER_LAST_MODIFIED, lastMod); |
| } |
| |
| /** |
| * @see ExportContext#setETag(String) |
| */ |
| public void setETag(String etag) { |
| properties.put(DavConstants.HEADER_ETAG, etag); |
| } |
| |
| /** |
| * @see ExportContext#setProperty(Object, Object) |
| */ |
| public void setProperty(Object propertyName, Object propertyValue) { |
| properties.put(propertyName, propertyValue); |
| } |
| |
| /** |
| * If success is true, the properties set before an the output stream are |
| * written to the wrapped <code>OutputContext</code>. |
| * |
| * @param success |
| * @see ExportContext#informCompleted(boolean) |
| */ |
| public void informCompleted(boolean success) { |
| checkCompleted(); |
| completed = true; |
| // make sure the outputStream gets closed (and don't assume the handlers |
| // took care of this. |
| if (outStream != null) { |
| try { |
| outStream.close(); |
| } catch (IOException e) { |
| // ignore |
| } |
| } |
| if (success) { |
| // write properties and data to the output-context |
| if (outputCtx != null) { |
| boolean hasContentLength = false; |
| Iterator it = properties.keySet().iterator(); |
| while (it.hasNext()) { |
| String name = it.next().toString(); |
| String value = properties.get(name).toString(); |
| outputCtx.setProperty(name, value); |
| // check for content-length |
| hasContentLength = DavConstants.HEADER_CONTENT_LENGTH.equals(name); |
| } |
| |
| if (outputCtx.hasStream() && outFile != null) { |
| OutputStream out = outputCtx.getOutputStream(); |
| try { |
| // make sure the content-length is set |
| if (!hasContentLength) { |
| outputCtx.setContentLength(outFile.length()); |
| } |
| FileInputStream in = new FileInputStream(outFile); |
| IOUtil.spool(in, out); |
| } catch (IOException e) { |
| log.error(e); |
| } |
| } |
| } |
| } |
| if (outFile != null) { |
| outFile.delete(); |
| } |
| } |
| } |