com.ibm.xsp.webdav.resource.DAVResourceDominoAttachments.java Source code

Java tutorial

Introduction

Here is the source code for com.ibm.xsp.webdav.resource.DAVResourceDominoAttachments.java

Source

/** ========================================================================= *
 * Copyright (C) 2011, 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.resource;

import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Date;
import java.util.Vector;

import lotus.domino.Base;
import lotus.domino.Database;
import lotus.domino.Document;
import lotus.domino.DocumentCollection;
import lotus.domino.EmbeddedObject;
import lotus.domino.NotesException;
import lotus.domino.Session;
import lotus.domino.View;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.xerces.impl.dv.util.Base64;

import biz.taoconsulting.dominodav.exceptions.DAVNotFoundException;
import biz.taoconsulting.dominodav.interfaces.IDAVAddressInformation;
import biz.taoconsulting.dominodav.interfaces.IDAVRepository;
import biz.taoconsulting.dominodav.interfaces.IDAVResource;

import com.ibm.xsp.webdav.domino.AttachmentInputStream;
import com.ibm.xsp.webdav.domino.AttachmentOutputStream;
import com.ibm.xsp.webdav.domino.DominoProxy;

/**
 * A WebDAV resource is an addressable Web object, such as a file or directory.
 * An ordinary resource can be viewed as a file. It can have a content body of
 * any MIME type [RFC2045], [RFC2046], including HTML-formatted text, other
 * text, an image, an executable, or an Office document. It can have locks and
 * properties. The specification for URI Syntax [RFC2396] defines a resource as
 * "anything that has identity." HTTP/1.1 [RFC2616] defines a resource both as
 * "a network data object or service" and "anything that has a URI." The WebDAV
 * specification does not redefine a resource but works from these definitions.
 * 
 * @author Stephan H. Wissel
 */
public class DAVResourceDominoAttachments extends DAVResourceDomino {

    /**
     * Directory composed out of temp directory, username, unid and File name
     */
    private String tempFileDir;

    /**
     * We need to ensure that a document is considered a collection
     */
    @Override
    public boolean isCollection() {
        if ("NotesDocument".equals(this.getResourceType())) {
            return true;
        }
        return super.isCollection();
    }

    /**
     * Logger for Errors
     */
    private static final Log LOGGER = LogFactory.getLog(DAVResourceDominoAttachments.class);

    /**
     * @param repository
     *            the repository the Resource is in
     * @param url
     *            the path relative to the repository -- as seen from the
     *            browser
     * @throws DAVNotFoundException
     *             --- if the file is not there
     */
    public DAVResourceDominoAttachments(IDAVRepository repository, String url) throws DAVNotFoundException {
        super(repository, url);
        this.populateAttachmentPropertiesFromNotesDoc();

    }

    /**
     * Light version
     * 
     * @param repository
     */
    public DAVResourceDominoAttachments(IDAVRepository repository) {
        this.setOwner(repository);
    }

    /**
     * @param rep
     *            The repository
     * @param url
     *            the requested path -- as seen from the browser
     * @param isMember
     *            - for directories: is it listed as part of the parent or by
     *            itself?
     * @throws DAVNotFoundException
     *             -- resource might not be there
     */
    public DAVResourceDominoAttachments(IDAVRepository rep, String url, boolean isMember)
            throws DAVNotFoundException {
        super(rep, url, isMember);
        this.populateAttachmentPropertiesFromNotesDoc();

    }

    /**
     * @see biz.taoconsulting.dominodav.resource.DAVAbstractResource#delete()
     */
    public boolean delete() {
        // TODO Auto-generated method stub
        return false;
    }

    /**
     * @see biz.taoconsulting.dominodav.resource.DAVAbstractResource#getOutputStream()
     */
    public OutputStream getOutputStream() {
        // This returns the OutputStream when writing back to the class

        if (this.out == null) {
            this.out = new AttachmentOutputStream(this);
        }

        return this.out;

    }

    /**
     * @see biz.taoconsulting.dominodav.resource.DAVAbstractResource#getStream()
     *      Originally I tried EmbeddedObject.getInputStream(); but that didn't
     *      go down well with the servlet, so now I use a temp file approach
     *      where an attachment is stored into a temp file and then served to
     *      the servlet as fileinput stream
     */
    public InputStream getStream() {
        Session s = null;
        InputStream curStream = null;
        String notesURL = this.getInternalAddress();
        Document curDoc = null;

        s = DominoProxy.getUserSession();

        if (s != null) {
            try {
                // We need to find the $File to isolate the document
                int dollarFile = notesURL.lastIndexOf("/$File");

                if (dollarFile < 0) {
                    // This is not an attachment
                    return null;
                }

                String docURL = notesURL.substring(0, dollarFile);
                curDoc = (Document) s.resolve(docURL);
                String curAttName = this.getName();
                EmbeddedObject curAttachment = curDoc.getAttachment(curAttName);
                File tempFile = this.getTempfile();
                // Delete if it exists
                if (tempFile.exists()) {
                    tempFile.delete();
                }
                curAttachment.extractFile(tempFile.getAbsolutePath());
                curStream = new AttachmentInputStream(tempFile, this);
            } catch (Exception e) {
                LOGGER.error(e);
            }
        }
        return curStream;
    }

    /**
     * @param notesURL
     *            The attachment/document to be processed
     * @param notesViewMember
     *            Name of document/attachment in view
     * @return true/false if resource population worked or not
     */
    public void fetchChildren() {

        if (this.isMember()) {
            LOGGER.debug("No fetch children for isMember()= true");
            return;
        }

        // We fetch the right type of children
        String resType = this.getResourceType();

        if ("NotesDocument".equals(resType)) {
            this.fetchChildrenForNotesDocument();
        } else if ("NotesAttachment".equals(resType)) {
            // Notes Attachments don't have children
        } else if ("NotesDatabase".equals(resType)) {
            this.fetchChildrenForNotesDatabase();
        } else {
            // We presume a view for the resource type
            fetchChildrenForNotesView();
        }

    }

    private void fetchChildrenForNotesDocument() {
        LOGGER.debug("Fetching children for " + this.getName());

        Document curDoc = null;
        String docID = null;
        Vector<IDAVResource> resMembers = new Vector<IDAVResource>();
        String notesURL = this.getInternalAddress();

        curDoc = DominoProxy.getDocument(notesURL);

        if (curDoc == null) {
            LOGGER.error("Could not retrieve the document");
            return;
        }

        // Read the repository list to get the view
        try {
            docID = curDoc.getUniversalID();

            LOGGER.debug("Openend document " + docID);

            // No children if there are no attachments
            if (!curDoc.hasEmbedded()) {
                // E.C. It is a directory, so fetch the children documents as
                // resources
                LOGGER.error("Current doc with unid=" + curDoc.getUniversalID()
                        + " has no embedded files. Try to find children");
                DocumentCollection responses = curDoc.getResponses();
                int numOfResponses = responses.getCount();
                if (numOfResponses > 0) {
                    LOGGER.error("Current doc has " + numOfResponses + " responses");
                    Document docResp = responses.getFirstDocument();
                    while (docResp != null) {
                        LOGGER.error("Doc response has unid=" + docResp.getUniversalID());
                        @SuppressWarnings("rawtypes")
                        Vector allEmbedded = DominoProxy.evaluate("@AttachmentNames", docResp);
                        int numOfAttchments = allEmbedded.size();
                        if (numOfAttchments == 0) { // No attachments in here!
                            LOGGER.error("Doc response has no attachment; is a directory");
                            LOGGER.debug(docID + " has no attachments (@AttachmentNames)"); // embed
                            // as
                            // doc
                            DAVResourceDominoAttachments resAtt = getDocumentResource(docResp);
                            if (resAtt != null) {
                                LOGGER.error("Created DavResourceDomino Attachments from getDocumentResource-OK");
                                resMembers.add(resAtt);
                                LOGGER.error("Resource successfull added");
                            } else {
                                LOGGER.error(
                                        "Problem, DavResourceDomino Attachments from getDocumentResource- FAILED");
                            }
                        } else {
                            LOGGER.error("Doc response has attachments;");
                            String curAttName = allEmbedded.get(0).toString();
                            DAVResourceDominoAttachments curAttachment = getAttachmentResource(this.isReadOnly(),
                                    docResp, curAttName);
                            if (curAttachment != null) {
                                // Now add it to the Vector
                                LOGGER.error("Created DavResourceDominoAttachments with getAttachmentResource-OK");
                                resMembers.add(curAttachment);
                                LOGGER.error("Resource successfull added");
                                Date viewDate = this.getLastModified();
                                Date docDate = curAttachment.getLastModified();
                                if (viewDate == null || (docDate != null && viewDate.before(docDate))) {
                                    this.setLastModified(docDate);
                                }
                                LOGGER.error("Resource successfull updated last modified");

                                LOGGER.debug("Processing complete attachment " + curAttName);
                            } else {
                                LOGGER.error("Could not load attachment " + curAttName);
                            }
                        }
                        Document docTmp = docResp;
                        docResp = responses.getNextDocument(docResp);
                        docTmp.recycle();
                    } // end while

                } // end if numresp>0

                try {

                    if (curDoc != null) {
                        curDoc.recycle();
                    }

                } catch (Exception e) {
                    LOGGER.error(e);
                }
                // Now save back the members to the main object
                this.setMembers(resMembers);
                return;
            }

            // Get all attachments
            @SuppressWarnings("rawtypes")
            Vector allEmbedded = DominoProxy.evaluate("@AttachmentNames", curDoc);
            int numOfAttchments = allEmbedded.size();
            if (numOfAttchments == 0) { // No attachments in here!
                LOGGER.debug(docID + " has no attachments (@AttachmentNames)");
                return;
            }
            LOGGER.debug(docID + " has " + new Integer(numOfAttchments).toString() + " attachment(s)");
            // Initialize an empty vector at the right size
            // We might need to enlarge it if we have more attachments
            resMembers = new Vector<IDAVResource>(numOfAttchments);

            for (int i = 0; i < numOfAttchments; i++) {

                String curAttName = allEmbedded.get(i).toString();
                DAVResourceDominoAttachments curAttachment = getAttachmentResource(this.isReadOnly(), curDoc,
                        curAttName);

                if (curAttachment != null) {
                    // Now add it to the Vector
                    resMembers.add(curAttachment);
                    LOGGER.debug("Processing complete attachment " + curAttName);
                } else {
                    LOGGER.error("Could not load attachment " + curAttName);
                }
            }

        } catch (NotesException ne) {
            LOGGER.error(ne);

        } catch (Exception e) {
            LOGGER.error(e);

        } finally {

            try {

                if (curDoc != null) {
                    curDoc.recycle();
                }

            } catch (Exception e) {
                LOGGER.error(e);
            }
            // Now save back the members to the main object
            this.setMembers(resMembers);
            LOGGER.debug("Completed reading attachments resources from Notes document");
        }

    }

    private void fetchChildrenForNotesView() {
        LOGGER.debug("Fetching children for " + this.getName());

        Document curDoc = null;
        Document nextDoc = null;

        View curView = null;
        Database curDb = null;
        Vector<IDAVResource> resMembers = null;
        String notesURL = this.getInternalAddress();

        curView = DominoProxy.getView(notesURL);

        if (curView == null) {
            LOGGER.error("Could not retrieve view: " + notesURL);
            return;
        }

        // Read the repository list to get the view
        try {
            LOGGER.debug("Openend view " + curView.getName());

            // Initialize an empty vector at the right size
            // We might need to enlarge it if we have more attachments
            resMembers = new Vector<IDAVResource>(curView.getEntryCount());

            curDoc = curView.getFirstDocument();

            if (curDoc == null) {
                LOGGER.info(this.getName() + " does not (yet) contain resources");
                return;
            }

            while (curDoc != null) {
                nextDoc = curView.getNextDocument(curDoc);
                // TODO: Fix this!
                DAVResourceDominoAttachments docRes = this.addAttachmentsFromDocument(curDoc);

                if (docRes != null) {
                    resMembers.add(docRes);

                    // Capture last modified based on the latest date of the
                    // documents in view
                    Date viewDate = this.getLastModified();
                    Date docDate = docRes.getLastModified();
                    if (viewDate == null || (docDate != null && viewDate.before(docDate))) {
                        this.setLastModified(docDate);
                    }

                }

                curDoc.recycle();
                curDoc = nextDoc;
            }

        } catch (NotesException ne) {
            LOGGER.error(ne);

        } catch (Exception e) {
            LOGGER.error(e);

        } finally {

            try {

                if (curDoc != null) {
                    curDoc.recycle();
                }

                if (nextDoc != null) {
                    nextDoc.recycle();
                }

                if (curView != null) {
                    curView.recycle();
                }

                if (curDb != null) {
                    curDb.recycle();
                }

            } catch (Exception e) {
                LOGGER.error(e);
            }

            LOGGER.debug("Completed reading file resources from Domino view");
        }
        // Now save back the members to the main object
        this.setMembers(resMembers);
    }

    private void fetchChildrenForNotesDatabase() {
        LOGGER.debug("Fetching children for " + this.getName());

        Document curDoc = null;
        Document nextDoc = null;

        DocumentCollection curEntries = null;
        Vector<IDAVResource> resMembers = null;
        String notesURL = this.getInternalAddress();
        Database curDb = DominoProxy.getDatabase(notesURL);

        if (curDb == null) {
            LOGGER.error("Could not get the database " + notesURL);
            return;
        }

        // Read the repository list to get the view
        try {
            LOGGER.debug("Openend databasew " + curDb.getFileName());

            // Initialize an empty vector at the right size
            // We might need to enlarge it if we have more attachments
            curEntries = curDb.getAllDocuments();
            resMembers = new Vector<IDAVResource>(curEntries.getCount());

            curDoc = curEntries.getFirstDocument();

            if (curDoc == null) {
                LOGGER.info(this.getName() + " does not (yet) contain resources");
                return;
            }

            while (curDoc != null) {
                nextDoc = curEntries.getNextDocument(curDoc);

                DAVResourceDominoAttachments docRes = this.addAttachmentsFromDocument(curDoc);

                if (docRes != null) {
                    resMembers.add(docRes);
                }

                curDoc.recycle();
                curDoc = nextDoc;
            }

        } catch (NotesException ne) {
            LOGGER.error(ne);

        } catch (Exception e) {
            LOGGER.error(e);

        } finally {

            try {

                if (curDoc != null) {
                    curDoc.recycle();
                }

                if (nextDoc != null) {
                    nextDoc.recycle();
                }

                if (curEntries != null) {
                    curEntries.recycle();
                }

                if (curDb != null) {
                    curDb.recycle();
                }

            } catch (Exception e) {
                LOGGER.error(e);
            }

            LOGGER.debug("Completed reading file resources from Domino view");
        }
        // Now save back the members to the main object
        this.setMembers(resMembers);
    }

    /**
     * Reads all attachments in a document and adds them to the resourcelist.
     * Since a document can contain more than one attachment we treat documents
     * as directories since webDAV from Windows/Linux ignores the URL and uses
     * the name to build the request URL
     * 
     * @param s
     * @param curDoc
     * @param resMembers
     */
    private DAVResourceDominoAttachments addAttachmentsFromDocument(Document curDoc) {

        String docID = null;
        DAVResourceDominoAttachments docRes = null;

        try {
            docID = curDoc.getUniversalID();
            if (!curDoc.hasEmbedded()) {
                LOGGER.debug(docID + " has no attachments (hasEmbedded)");
            } else {
                docRes = this.getDocumentResource(curDoc);
            }
        } catch (NotesException e) {
            LOGGER.error(e);
            docRes = null;
        }

        return docRes;

    }

    /**
     * Create a Attachment resource for an attachment inside of a document
     * 
     * @param s
     * @param curDoc
     * @param curAttName
     * @return
     */
    private DAVResourceDominoAttachments getAttachmentResource(boolean readOnly, Document curDoc,
            String curAttName) {

        LOGGER.debug("Retrieving attachment [" + curAttName + "]");
        EmbeddedObject curAttachment = null;
        DAVResourceDominoAttachments curRes = null;

        try {
            curAttachment = curDoc.getAttachment(curAttName);
            if (curAttachment == null) {
                return null;
            }
            String docID = curDoc.getUniversalID();
            Date curCreationDate = curDoc.getCreated().toJavaDate();
            Date curChangeDate = curDoc.getLastModified().toJavaDate();
            Long curSize = new Long(curAttachment.getFileSize());
            String curName = curAttachment.getName();
            String curInternalPath = docID + "/$File/" + curAttachment.getName();
            // We hide the $File from external resources
            String curExternalPath = docID + "/" + curAttachment.getName();

            LOGGER.debug("Processing Attachment " + curName + " (" + curInternalPath + ")");

            // Now the repository
            String pubHRef = ((IDAVAddressInformation) this.getRepository()).getPublicHref() + "/"
                    + curExternalPath;
            curRes = new DAVResourceDominoAttachments(this.getRepository());
            curRes.setPublicHref(pubHRef);
            curRes.setMember(true);
            curRes.setName(curName);
            curRes.setInternalAddress(
                    ((IDAVAddressInformation) this.getRepository()).getInternalAddress() + "/" + curInternalPath);
            curRes.setOwner(this.getRepository());
            curRes.setResourceType("NotesAttachment");
            curRes.setCreationDate(curCreationDate);
            curRes.setLastModified(curChangeDate);
            curRes.setContentLength(curSize);
            curRes.setReadOnly(readOnly);
        } catch (NotesException e) {
            LOGGER.error(e);
        }

        return curRes;
    }

    private DAVResourceDominoAttachments getDocumentResource(Document curDoc) {

        // The result we are giving back
        DAVResourceDominoAttachments curRes = null;

        try {
            String docID = curDoc.getUniversalID();
            LOGGER.debug("Creating resource for document [" + docID + "]");

            boolean readOnly = this.checkReadOnlyAccess(curDoc);
            Date curCreationDate = curDoc.getCreated().toJavaDate();
            Date curChangeDate = curDoc.getLastModified().toJavaDate();
            String curPath = docID; // ?OpenDocument doesn't work with DAV +
            // "?OpenDocument";
            String curName = docID; // ToDo -- better naming scheme for
            // documents e.g. when view is sorted
            // Now the repository
            String pubHRef = this.getPublicHref() + "/" + curPath;
            curRes = new DAVResourceDominoAttachments(this.getRepository(), pubHRef, true);
            curRes.setResourceType("NotesDocument");
            curRes.setMember(true);
            curRes.setCollection(true); // We treat it as a directory
            curRes.setName(curName);
            curRes.setInternalAddress(
                    ((IDAVAddressInformation) this.getRepository()).getInternalAddress() + "/" + curPath);
            curRes.setOwner(this.getRepository());
            curRes.setCreationDate(curCreationDate);
            curRes.setLastModified(curChangeDate);
            curRes.setContentLength(0L);
            curRes.setReadOnly(readOnly);
        } catch (NotesException e) {
            LOGGER.error(e);
        } catch (DAVNotFoundException e) {
            LOGGER.error(e);
        }
        return curRes;
    }

    // This function overwrites the main function in DAVResourceDomino
    protected String getNameFromInternalAddress(String internalName) throws Exception {
        int lastSlash = internalName.lastIndexOf("/");
        if (lastSlash < 0) {
            return internalName;
        }

        String candidate = internalName.substring(lastSlash + 1);
        int questionMarkPos = candidate.indexOf("?");

        if (questionMarkPos < 0) {
            return candidate;
        }

        return candidate.substring(0, questionMarkPos);
    }

    /**
     * @return The file to read/write the data to since stream in attachments
     *         doesn't seem to be reliable
     */
    public File getTempfile() {
        // We check for a directory with the UNID of the resource
        // and write the file there
        String unid = this.getDocumentUniqueID();
        File returnFile = null;

        // Check for the root temp Dir
        String rootTempDir = this.getRepository().getTempDir();

        // Get the username in base64 encoded, so we can use it as temp file
        // name

        String userDir = null;
        try {
            String userName = DominoProxy.getUserName();
            userDir = Base64.encode(userName.getBytes());
        } catch (Exception e) {
            LOGGER.error(e);
            userDir = "Anonymous";
        }

        // Save the values for reuse
        this.tempFileDir = rootTempDir + File.separator + userDir + File.separator + unid;

        // Create the directory if needed
        File curTempDir = new File(this.tempFileDir);
        if (!curTempDir.exists()) {
            // Create the directory structure - we keep the user dir
            curTempDir.mkdirs();
        } else if (!curTempDir.isDirectory()) {
            // Very bad
            LOGGER.error("Tempdir exists and is not a directory: " + this.tempFileDir);
            return null;
        }
        // Update the full value
        this.tempFileDir = curTempDir.getAbsolutePath();

        // Now create the file object
        String trueFileName = this.tempFileDir + File.separator + this.getName();
        returnFile = new File(trueFileName);

        return returnFile;
    }

    /**
     * Removes the temporary file
     */
    public void removeTempFiles() {
        try {
            // First the file, then the temp dir
            File fullFile = new File(this.tempFileDir + File.separator + this.getName());
            if (fullFile.exists()) {
                fullFile.delete();
            }
            fullFile = null;

            // Temp dir
            File docTempDir = new File(this.tempFileDir);

            // We only can remove the directory if it isn't empty
            // Other files might be opened in other tabs or windows
            if (docTempDir.exists()) {

                File[] content = docTempDir.listFiles();

                if (content == null || content.length == 0) {
                    String userTempDirName = docTempDir.getParent();
                    docTempDir.delete();
                    docTempDir = null;

                    File userTempDir = new File(userTempDirName);

                    if (userTempDir.exists()) {
                        File[] otherTemp = userTempDir.listFiles();
                        if (otherTemp == null || otherTemp.length == 0) {
                            userTempDir.delete();
                        }
                    }
                }
            }
        } catch (Exception e) {
            LOGGER.error(e);
        }

    }

    /**
     * Gets to the Notes document and populates all the attachment properties
     * that need the NotesSession
     */
    private void populateAttachmentPropertiesFromNotesDoc() {
        String thisResType = this.getResourceType();
        if (!"NotesAttachment".equals(thisResType) && !"NotesDocument".equals(thisResType)) {
            return; // This is for attachments and documents only
        }

        String adr = this.getInternalAddress();
        String notesURL = "NotesAttachment".equals(thisResType) ? this.getDocURLFromAttachmentURL(adr) : adr;
        Document curDoc = DominoProxy.getDocument(notesURL);

        try {

            if (curDoc == null) {
                LOGGER.error("Could not retrieve Notes doc " + notesURL);
            } else {

                boolean readOnly = this.checkReadOnlyAccess(curDoc);
                Date curCreationDate = curDoc.getCreated().toJavaDate();
                Date curChangeDate = curDoc.getLastModified().toJavaDate();
                this.setCreationDate(curCreationDate);
                this.setLastModified(curChangeDate);
                this.setReadOnly(readOnly);

                EmbeddedObject curAtt = curDoc.getAttachment(this.getName());
                // Content length
                if (curAtt != null) {
                    this.setContentLength(new Long(curAtt.getFileSize()).longValue());
                }
            }
        } catch (NotesException e) {
            LOGGER.error(e);
        } finally {
            try {
                if (curDoc != null) {
                    curDoc.recycle();
                }
            } catch (NotesException e) {
                LOGGER.error(e);
            }
        }

    }

    /**
     * We return the NotesURL including ?OpenDocument
     * 
     * @param internalAddress
     * @return
     */
    private String getDocURLFromAttachmentURL(String internalAddress) {

        int maxLen = internalAddress.indexOf("/$File");
        if (maxLen < 0) {
            maxLen = internalAddress.lastIndexOf("/");
        }
        if (maxLen < 0) {
            LOGGER.error("No proper NotesURL found for " + internalAddress);
            return internalAddress;
        }

        return internalAddress.substring(0, maxLen) + "?OpenDocument";

    }

    public void patchLastModified(Date dt) {
    }

    public void patchCreationDate(Date dt) {
    }

    public Document getDocument() {
        String intAddress = this.getInternalAddress();
        Base notesObj = DominoProxy.resolve(intAddress);
        if (notesObj == null) {
            return null;
        }
        if (notesObj instanceof Document) {
            return (Document) notesObj;
        }
        return null;
    }
}