/** ========================================================================= * * Copyright (C) 2012 IBM Corporation * * based on work of * * Copyright (C) 2006, 2007 TAO Consulting Pte <http://www.taoconsulting.sg/> * * All rights reserved. * * ========================================================================== * * * * 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 com.ibm.xsp.webdav.domino; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.FileOutputStream; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import com.ibm.domino.osgi.core.context.ContextInfo; import com.ibm.xsp.webdav.resource.DAVResourceDominoCategorizedDocuments; import com.ibm.xsp.webdav.repository.DAVRepositoryDominoCategorizedDocuments; import lotus.domino.Document; import lotus.domino.EmbeddedObject; import lotus.domino.Item; import lotus.domino.NotesException; import lotus.domino.RichTextItem; import lotus.domino.Session; /** * The Domino output stream takes the stream, stores it into a temporary file * * @author Stephan H. Wissel * */ public class CategorizedDocumentOutputStream extends DominoOutputStream { /** * Logger for Errors */ private static final Log LOGGER = LogFactory .getLog(CategorizedDocumentOutputStream.class); /** * Creates a OutputStream that streams to a temporary file This file will * later be attached in Domino as attachment * * @param res * DAVResourceDomino */ public CategorizedDocumentOutputStream( DAVResourceDominoCategorizedDocuments res) { super(); this.setResource(res); } /** * setResource needs to be called when constructor was used without * parameter; * * @param res * DAVResourceDomino */ public void setResource(DAVResourceDominoCategorizedDocuments res) { super.setResource(res); File tempFile = res.getTempfile(); try { this.out = new FileOutputStream(tempFile); } catch (FileNotFoundException e) { LOGGER.error("File stream creation failed", e); } } /** * Closes the stream and copies the temp file into the Domino object * * @throws IOException * If something odes wrong */ public void close() throws IOException { // Write out the file object super.close(); LOGGER.info("Start close..."); boolean success = true; // We assume it will work Document curDoc = null; String docURL = null; RichTextItem body = null; // NotesSession Session s = ContextInfo.getUserSession(); if (s == null) { LOGGER.error("Could not establish Notes Session"); success = false; return; } LOGGER.info("Before resource"); DAVResourceDominoCategorizedDocuments res = (DAVResourceDominoCategorizedDocuments) this .getResource(); if (res.isCollection()) { LOGGER.info("Problem! resource is collection"); return; } DAVRepositoryDominoCategorizedDocuments repository = (DAVRepositoryDominoCategorizedDocuments) res .getRepository(); String notesURL = res.getInternalAddress(); LOGGER.info("Resource is not a collection; OK! Internal address=" + notesURL); // We need to find the $File to isolate the document int dollarFile = notesURL.lastIndexOf("/$File"); if (dollarFile < 0) { // This is not an attachment - we presume it is a file docURL = notesURL; } else { docURL = notesURL.substring(0, dollarFile) + "?OpenDocument"; } String trueFileName = null; Document oldVersion = null; // Now get to the document try { curDoc = (Document) s.resolve(docURL); String curAttName = res.getName(); // Now check if we can get the attachment and remove it EmbeddedObject att = curDoc.getAttachment(curAttName); if (att != null) { LOGGER.info("Attachment exists:" + curAttName); if (repository.versioning()) { oldVersion = curDoc.getParentDatabase().createDocument(); oldVersion.makeResponse(curDoc); curDoc.copyAllItems(oldVersion, false); String version = "2", oldversion = "1"; if (curDoc.hasItem("DAVVersion")) { version = curDoc.getItemValueString("DAVVersion"); // int minor=0; try { if (version.equals("")) { oldversion = "1"; version = "2"; } else { oldversion = version; version = new Integer( Integer.parseInt(version) + 1) .toString(); } } catch (Exception e) { version = "2"; oldversion = "1"; } } oldVersion.replaceItemValue("DAVVersion", oldversion); // curDoc.replaceItemValue("DAVVersion", version); oldVersion.save(true); } att.remove(); att.recycle(); att = null; LOGGER.info("Attachment removed"); } // Now attach it to the Body field - we can't attach to the document // directly if (curDoc.hasItem("Body")) { LOGGER.info("Has item Body"); Item bodyCandidate = curDoc.getFirstItem("Body"); if (bodyCandidate.getType() == Item.RICHTEXT) { LOGGER.info("Body is rtichtext"); body = (RichTextItem) bodyCandidate; } else { // TODO: is this OK or do we need to do something about it? LOGGER.info("Body is not a richtextitem; remove it"); curDoc.removeItem("Body"); body = curDoc.createRichTextItem("Body"); LOGGER.info("Created rich text item"); } } else { LOGGER.info("Doc has no Body field;"); body = curDoc.createRichTextItem("Body"); LOGGER.info("Created rich text item BODY"); } // Finally time to write out trueFileName = res.getTempfile().getAbsolutePath(); LOGGER.info("File name=" + trueFileName); body.embedObject(EmbeddedObject.EMBED_ATTACHMENT, null, trueFileName, curAttName); LOGGER.info("Embeded ...OK"); if (curDoc.hasItem("DAVCreated")) { curDoc.removeItem("DAVCreated"); } if (curDoc.hasItem("DAVModified")) { curDoc.removeItem("DAVModified"); } curDoc.save(); LOGGER.info("Saved ...OK"); } catch (NotesException e) { success = false; LOGGER.error(e); } catch (Exception e) { success = false; LOGGER.error(e); } finally { // Recyle the notes objects try { if (body != null) { body.recycle(); } if (curDoc != null) { curDoc.recycle(); } } catch (NotesException e) { // Not really critical, but we log it LOGGER.error("Notes objects recycle failed", e); } } // Remove the temporary file stuff but only if the write was sucessful // this way we might be able to recover if (success) { LOGGER.info("Removing the temp file(BUT NOT YET): " + trueFileName); // We don't want an error here bubbling up try { res.removeTempFiles(); // Close the parent object; super.close(); } catch (Exception e) { LOGGER.error("Temp Dir/File cleanup failed", e); } } else { LOGGER.error("Write to Domino unsuccesful, temp files not cleaned for recovery!"); // We need to throw an error throw new IOException(); } } /** * lazy init of an output stream */ protected void initOutputStream() throws IOException { if (this.res == null) { LOGGER.error("The DominoOutputStream has no ResourceObject"); throw new IOException(); } File destination = res.getTempfile(); this.out = new FileOutputStream(destination); } }