/** ========================================================================= *
* 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.DateTime;
import lotus.domino.Document;
import lotus.domino.DocumentCollection;
import lotus.domino.EmbeddedObject;
import lotus.domino.Item;
import lotus.domino.NotesException;
import lotus.domino.Session;
import lotus.domino.View;
import lotus.domino.ViewEntryCollection;
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.CategorizedDocumentInputStream;
import com.ibm.xsp.webdav.domino.CategorizedDocumentOutputStream;
import com.ibm.xsp.webdav.domino.DominoProxy;
import com.ibm.xsp.webdav.repository.DAVRepositoryDominoCategorizedDocuments;
/**
* 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 DAVResourceDominoCategorizedDocuments 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() {
return super.isCollection();
// if (!("NotesAttachment".equals(this.getResourceType()))) {
// return true;
// }
// return false;
}
/**
* Logger for Errors
*/
private static final Log LOGGER = LogFactory
.getLog(DAVResourceDominoDocuments.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 DAVResourceDominoCategorizedDocuments(IDAVRepository repository,
String url) throws DAVNotFoundException {
setup(repository, url, false);
// this.setOwner(repository);
// this.setPublicHref(url);
// this.populateAttachmentPropertiesFromNotesDoc();
}
/**
* Light version
*
* @param repository
*/
public DAVResourceDominoCategorizedDocuments(IDAVRepository repository) {
this.setOwner(repository);
this.setPublicHref("");
}
/**
* @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 DAVResourceDominoCategorizedDocuments(IDAVRepository rep,
String url, boolean isMember) throws DAVNotFoundException {
setup(rep, url, isMember);
// this.setOwner(rep);
// this.setPublicHref(url);
// this.setMember(isMember);
// this.populateAttachmentPropertiesFromNotesDoc();
}
public DAVResourceDominoCategorizedDocuments(IDAVRepository rep,
String url, boolean isMember, boolean forceCreate)
throws DAVNotFoundException {
setup(rep, url, isMember, forceCreate);
// this.setOwner(rep);
// this.setPublicHref(url);
// this.setMember(isMember);
// this.populateAttachmentPropertiesFromNotesDoc();
}
/**
* @see biz.taoconsulting.dominodav.resource.DAVAbstractResource#delete()
*/
public boolean delete() {
Document curDoc = null;
String notesURL = this.getInternalAddress();
curDoc = DominoProxy.getDocument(notesURL);
if (curDoc != null) {
try {
curDoc.remove(true);
return true;
} catch (NotesException ne) {
return false;
}
}
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 CategorizedDocumentOutputStream(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();
// LOGGER.info("NotesUrl="+notesURL);
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);
LOGGER.info("docURL=" + docURL);
curDoc = (Document) s.resolve(docURL);
String curAttName = this.getName();
curAttName = java.net.URLDecoder.decode(curAttName, "utf-8");
LOGGER.info("curAttName=" + curAttName);
EmbeddedObject curAttachment = curDoc.getAttachment(curAttName);
if (curAttachment == null) {
LOGGER.info("�ttachment is null");
}
File tempFile = this.getTempfile();
// Delete if it exists
if (tempFile.exists()) {
tempFile.delete();
}
curAttachment.extractFile(tempFile.getAbsolutePath());
LOGGER.info("Current attachment path extracted is ="
+ tempFile.getAbsolutePath());
curStream = new CategorizedDocumentInputStream(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() {
// LOGGER.info(getCallingMethod()+":"+"Start fetchChildren..");
if (this.isMember()) {
// LOGGER.info(getCallingMethod()+":"+"No fetch children for isMember()= true");
return;
}
// We fetch the right type of children
String resType = this.getResourceType();
// LOGGER.info(getCallingMethod()+":"+"This resource is not a member; so start fetching..");
try {
if ("NotesDocument".equals(resType)) {
// LOGGER.info(getCallingMethod()+":"+"Resource is a NotesDocument; Start fetchingChildren for it...!");
this.fetchChildrenForNotesDocument();
// LOGGER.info(getCallingMethod()+":"+"End fetching children for NotesDocument OK!");
} else if ("NotesAttachment".equals(resType)) {
// Notes Attachments don't have children
// LOGGER.info(getCallingMethod()+":"+"Resource is a NotesAttachment.. NO IMPLEMENTATION!");
} else if ("NotesDatabase".equals(resType)) {
// LOGGER.info(getCallingMethod()+":"+"Resource is NotesDatabase; Start fetchingChildren for it..!");
this.fetchChildrenForNotesDatabase();
// LOGGER.info(getCallingMethod()+":"+"End fetching children for NotesDatabase OK!");
} else {
// We presume a view for the resource type
// LOGGER.info(getCallingMethod()+":"+"Resource is a View; Start fetching Children for it....!");
fetchChildrenForNotesView();
// LOGGER.info(getCallingMethod()+":"+"End fetching children for NotesView OK!");
}
} catch (NotesException e) {
}
// LOGGER.info(getCallingMethod()+":"+"End function fetchChildren OK!");
}
@SuppressWarnings("unchecked")
private void fetchChildrenForNotesDocument() throws NotesException {
// LOGGER.info(getCallingMethod()+":"+"Start fetchChildrenForNotesDocument; Fetching children for doc with UNID="
// + this.getDocumentUniqueID());
Document curDoc = null;
String docID = null;
Vector<IDAVResource> resMembers = null;
this.setMembers(new Vector<IDAVResource>());
String notesURL = this.getInternalAddress();
DAVRepositoryDominoCategorizedDocuments repository = (DAVRepositoryDominoCategorizedDocuments) this
.getRepository();
// LOGGER.info("Internal Address is "+notesURL);
// LOGGER.info("PublicHref is "+this.getPublicHref());
curDoc = DominoProxy.getDocument(notesURL);
// LOGGER.info(getCallingMethod()+":"+"Currdoc not null ; OK");
if (curDoc == null) {
LOGGER.error("Could not retrieve the document");
return;
}
boolean readOnly = this.checkReadOnlyAccess(curDoc);
Date curCreationDate = curDoc.getCreated().toJavaDate();
if (curDoc.hasItem("DAVCreated")) {
@SuppressWarnings("rawtypes")
Vector times = curDoc.getItemValueDateTimeArray("DAVCreated");
Object time = times.elementAt(0);
if (time.getClass().getName().endsWith("DateTime")) {
curCreationDate = ((DateTime) time).toJavaDate();
}
}
Date curChangeDate = curDoc.getLastModified().toJavaDate();
if (curDoc.hasItem("DAVModified")) {
@SuppressWarnings("rawtypes")
Vector times = curDoc.getItemValueDateTimeArray("DAVModified");
Object time = times.elementAt(0);
if (time.getClass().getName().endsWith("DateTime")) {
curChangeDate = ((DateTime) time).toJavaDate();
}
}
this.setCreationDate(curCreationDate);
this.setLastModified(curChangeDate);
this.setReadOnly(readOnly);
// Read the repository list to get the view
try {
LOGGER.info(getCallingMethod() + ":"
+ "Currdoc not null ; OK; Has UNID="
+ curDoc.getUniversalID());
docID = curDoc.getUniversalID();
LOGGER.info(getCallingMethod() + ":" + "Openend document " + docID);
// No children if there are no attachments
if (!curDoc.hasEmbedded()) { // folder
ViewEntryCollection responses = repository
.getAllEntriesByKey(curDoc
.getItemValueString(repository
.getPubHrefField()));
LOGGER.info(getCallingMethod() + ":" + "Get Responses...");
int numOfResponses = responses.getCount();
LOGGER.info(getCallingMethod() + ":" + "Current doc has "
+ String.valueOf(numOfResponses) + " responses");
if (numOfResponses > 1) {
resMembers = new Vector<IDAVResource>(numOfResponses - 1);
LOGGER.info(getCallingMethod() + ":"
+ "Start Process responses");
lotus.domino.ViewEntry ve = responses.getFirstEntry();
ve = responses.getNextEntry();
Document docResp = null;
while (ve != null) {
docResp = ve.getDocument();
// if(docResp.getUniversalID()!=docID){
LOGGER.info(getCallingMethod() + ":"
+ "Doc response has unid="
+ docResp.getUniversalID()
+ "; Try find attachment(s)");
Vector<String> allEmbedded = DominoProxy.evaluate(
"@AttachmentNames", docResp);
int numOfAttachments = allEmbedded.isEmpty() ? 0
: (allEmbedded.get(0).toString().equals("") ? 0
: allEmbedded.size());
LOGGER.info(getCallingMethod() + ":" + "Doc has "
+ String.valueOf(numOfAttachments)
+ " attachment(s)");
if (numOfAttachments == 0) { // No attachments in here!
LOGGER.info(getCallingMethod()
+ ":"
+ "Doc "
+ docResp.getUniversalID()
+ " response has no attachment; is a directory; Create resource for it");
DAVResourceDominoCategorizedDocuments resAtt = new DAVResourceDominoCategorizedDocuments(
this.getRepository(),
this.getPublicHref()
+ "/"
+ docResp
.getItemValueString(((DAVRepositoryDominoCategorizedDocuments) (this
.getRepository()))
.getDirectoryField()),
true);
resAtt.setup(docResp);
if (resAtt != null) {
LOGGER.info(getCallingMethod()
+ ":"
+ "Created DavResourceDomino Attachments from getDocumentResource-OK");
if (resAtt.filter()) {
this.getMembers().add(resAtt);
}
resMembers.add(resAtt);
LOGGER.info(getCallingMethod() + ":"
+ "Resource successfull added");
}
} else {
LOGGER.info(getCallingMethod() + ":"
+ "Doc response "
+ docResp.getUniversalID()
+ " has attachments >0; ");
String curAttName = allEmbedded.get(0).toString();
if ((curAttName != null)
&& (!curAttName.equals(""))) {
LOGGER.info(getCallingMethod()
+ ":"
+ "Doc response fitrst attachment has name "
+ curAttName);
DAVResourceDominoCategorizedDocuments resAtt = new DAVResourceDominoCategorizedDocuments(
this.getRepository(),
this.getPublicHref() + "/" + curAttName,
true);
resAtt.setup(docResp);
if (resAtt != null) {
// Now add it to the Vector
LOGGER.info(getCallingMethod()
+ ":"
+ "Created DAVResourceDominoDocuments with getAttachmentResource-OK!\n Start load resource");
// resMembers.add(curAttachment);
if (resAtt.filter()) {
this.getMembers().add(resAtt);
}
LOGGER.info(getCallingMethod() + ":"
+ "Resource successfull added");
Date viewDate = this.getLastModified();
Date docDate = resAtt.getLastModified();
if (viewDate == null
|| (docDate != null && viewDate
.before(docDate))) {
this.setLastModified(docDate);
}
LOGGER.info(getCallingMethod()
+ ":"
+ "Resource successfull updated last modified");
LOGGER.info(getCallingMethod() + ":"
+ "Processing complete attachment:"
+ curAttName);
}
}
}
LOGGER.info(getCallingMethod() + ":"
+ "Start recycling..");
// Document docTmp=docResp;
// } //end
// if(docResp.getUniversalID()!=curDoc.getUniversalID()){
ve = responses.getNextEntry();
// docTmp.recycle();
LOGGER.info(getCallingMethod() + ":" + "Recycling OK!");
} // end while
} // end if numresp>0
try {
LOGGER.info(getCallingMethod() + ":" + "Final recycling..");
if (curDoc != null) {
curDoc.recycle();
}
LOGGER.info(getCallingMethod() + ":"
+ "End FINAL recycling OK!");
} catch (Exception e) {
LOGGER.error(e);
}
// Now save back the members to the main object
LOGGER.info(getCallingMethod()
+ ":"
+ "Finish processing current doc as a directory; No more attachment(s) in it; Return!");
return;
}
// Get all attachments
LOGGER.info(getCallingMethod() + ":"
+ "Current doc has attachments!");
@SuppressWarnings("rawtypes")
Vector allEmbedded = DominoProxy.evaluate("@AttachmentNames",
curDoc);
int numOfAttchments = allEmbedded.size();
if (numOfAttchments == 0) { // No attachments in here!
LOGGER.info(getCallingMethod() + ":"
+ "Something wrong: Doc + " + docID
+ " has no attachments (@AttachmentNames)");
return;
}
LOGGER.info(getCallingMethod() + ":" + 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);
LOGGER.info(getCallingMethod() + ":"
+ "Start processing attachment(s)..");
for (int i = 0; i < numOfAttchments; i++) {
String curAttName = allEmbedded.get(i).toString();
DAVResourceDominoCategorizedDocuments curAttachment = getDocumentResource(curDoc);
if (curAttachment != null) {
// Now add it to the Vector
LOGGER.info(getCallingMethod() + ":"
+ "Resource attachment successfully created!");
// resMembers.add(curAttachment);
if (curAttachment.filter()) {
this.getMembers().add(curAttachment);
}
LOGGER.info("Resource attachment successfully added: "
+ curAttName + "; OK!");
} else {
LOGGER.error("Could not load attachment#" + curAttName
+ "#");
}
}
} catch (NotesException ne) {
LOGGER.error(ne);
} catch (Exception e) {
LOGGER.error(e);
} finally {
try {
LOGGER.info(getCallingMethod() + ":"
+ "Final block; Start Recycling!");
if (curDoc != null) {
curDoc.recycle();
}
} catch (Exception e) {
LOGGER.error(e);
}
// Now save back the members to the main object
// this.setMembers(resMembers);
LOGGER.info("Completed reading attachments resources from Notes document; OK!");
}
}
private void fetchChildrenForNotesView() {
// LOGGER.info(getCallingMethod()+":"+"Start fetchChildrenForNotesView; Fetching children for "
// +
// this.getName()+" with internal address= "+this.getInternalAddress()+" and public href= "+this.getPublicHref());
Document curDoc = null;
View curView = null;
Database curDb = null;
Vector<IDAVResource> resMembers = new Vector<IDAVResource>();
this.setMembers(resMembers);
String notesURL = this.getInternalAddress();
curView = DominoProxy.getView(notesURL);
if (curView == null) {
LOGGER.error("Could not retrieve view: " + notesURL);
return;
}
DAVRepositoryDominoCategorizedDocuments repository = (DAVRepositoryDominoCategorizedDocuments) this
.getRepository();
// Read the repository list to get the view
try {
// LOGGER.info(getCallingMethod()+":"+"Openend view " +
// curView.getName());
// Initialize an empty vector at the right size
// We might need to enlarge it if we have more attachments
// LOGGER.info( "View num doc is "+new
// Integer(curView.getEntryCount()).toString());
DocumentCollection docColl = repository.getAllDocumentsByKey("/");
curDoc = docColl.getFirstDocument();
while (curDoc != null) {
// LOGGER.info( "Start processing doc no "+ new
// Integer(i).toString());
// LOGGER.info(getCallingMethod()+":"+"Start process view ");
DAVResourceDominoCategorizedDocuments docRes = null;
if (curDoc.hasEmbedded()) {
// LOGGER.info(getCallingMethod()+":"+"Document "+curDoc.getUniversalID()+
// " has embedded; Start Add Attachments");
// docRes = this.addAttachmentsFromDocument(curDoc);
docRes = new DAVResourceDominoCategorizedDocuments(
this.getRepository());
docRes.setup(curDoc);
// docRes.setCollection(false);
// docRes.setMember(true);
// LOGGER.info(getCallingMethod()+":"+"Successfully create attachments for "+curDoc.getUniversalID());
} else {
// LOGGER.info(getCallingMethod()+":"+"Document "+
// curDoc.getUniversalID()+
// " has no attachment; try to get a resource");
docRes = new DAVResourceDominoCategorizedDocuments(
this.getRepository());
docRes.setup(curDoc);
docRes.setCollection(true);
docRes.setMember(false);
// LOGGER.info(getCallingMethod()+":"+"Successfully create resource from doc "+docRes.getName());
}
// TODO: Fix this!
if (docRes != null) {
// LOGGER.info(getCallingMethod()+":"+"Resource "+docRes.getName()+"created OK; Try to add to resMembers");
if (docRes.filter()) {
this.getMembers().add(docRes);
}
// LOGGER.info(getCallingMethod()+":"+"Resources added OK;");
// 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);
}
// LOGGER.info(getCallingMethod()+":"+"Resource processes OK");
}
// //
// LOGGER.info(getCallingMethod()+":"+"Try recycle and find the next for "+curDoc.getUniversalID()+"....");
// Document oldDoc=curDoc;
// curDoc = curView.getNextDocument(curDoc);
// oldDoc.recycle();
// // LOGGER.info(getCallingMethod()+":"+"Recycle OK!");
// //
// LOGGER.info("Next doc is "+((curDoc!=null)?"Not null":"null"));
curDoc = docColl.getNextDocument();
} // end for
} catch (NotesException ne) {
LOGGER.error(ne);
} catch (Exception e) {
LOGGER.error(e);
} finally {
try {
// LOGGER.info(getCallingMethod()+":"+"Final recycle....");
if (curDoc != null) {
// curDoc.recycle();
}
if (curView != null) {
curView.recycle();
}
if (curDb != null) {
curDb.recycle();
}
// LOGGER.info(getCallingMethod()+":"+"Final recycle OK!");
} catch (Exception e) {
LOGGER.error(e);
}
// LOGGER.info(getCallingMethod()+":"+"Completed reading file resources from Domino view");
// LOGGER.info(getCallingMethod()+":"+"Start to setMembers...");
// this.setMembers(resMembers);
// LOGGER.info(getCallingMethod()+":"+"SetMembers OK! Exit fetchChildrenforNotesView");
}
// Now save back the members to the main object
}
private void fetchChildrenForNotesDatabase() {
// LOGGER.info(getCallingMethod()+":"+"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.info(getCallingMethod()+":"+"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(getCallingMethod()+":"+this.getName() +
// " does not (yet) contain resources");
return;
}
while (curDoc != null) {
nextDoc = curEntries.getNextDocument(curDoc);
DAVResourceDominoCategorizedDocuments 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.info(getCallingMethod()+":"+"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 DAVResourceDominoCategorizedDocuments addAttachmentsFromDocument(
Document curDoc) {
String docID = null;
DAVResourceDominoCategorizedDocuments docRes = null;
try {
// LOGGER.info(getCallingMethod()+":"+"Start addAttachmentsFromDocument "+curDoc.getUniversalID());
docID = curDoc.getUniversalID();
if (!curDoc.hasEmbedded()) {
LOGGER.info(getCallingMethod() + ":" + docID
+ " has no attachments (hasEmbedded)");
} else {
LOGGER.info(getCallingMethod()
+ ":"
+ docID
+ " has attachments; start creating resource of type attachment(file)");
docRes = this.getDocumentResource(curDoc);
// LOGGER.info(getCallingMethod()+":"+"End creating resource of type attachment!");
}
} catch (NotesException e) {
LOGGER.error(e);
docRes = null;
}
// LOGGER.info(getCallingMethod()+":"+"Return docRes OK! ");
return docRes;
}
/**
* Create a Attachment resource for an attachment inside of a document
*
* @param s
* @param curDoc
* @param curAttName
* @return
*/
// 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
*/
/**
* We return the NotesURL including ?OpenDocument
*
* @param internalAddress
* @return
*/
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;
}
public void updateHierarchy() {
Document doc = getDocument();
DAVRepositoryDominoCategorizedDocuments rep = ((DAVRepositoryDominoCategorizedDocuments) this
.getRepository());
try {
if (doc.isResponse()) {
doc.removeItem("$Ref");
}
String pubHref = doc.getItemValueString(rep.getPubHrefField());
if (!pubHref.equals("")) {
if (pubHref.lastIndexOf("/") > 0) {
String parentPubHref = pubHref.substring(0,
pubHref.lastIndexOf("/"));
Document docP = rep.getDocumentByKey(parentPubHref);
if (docP != null) {
doc.makeResponse(docP);
}
}
}
doc.save(true);
} catch (NotesException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public String getCallingMethod() {
return trace(Thread.currentThread().getStackTrace(), 2);
}
public String getCallingMethod(int level) {
return trace(Thread.currentThread().getStackTrace(), 2 + level);
}
private String trace(StackTraceElement e[], int level) {
if (e != null && e.length >= level) {
StackTraceElement s = e[level];
if (s != null) {
return s.getMethodName();
}
}
return null;
}
private void setup(Document curDoc) {
try {
DAVRepositoryDominoCategorizedDocuments rep = (DAVRepositoryDominoCategorizedDocuments) this
.getRepository();
LOGGER.info("Start setup with doc ..."
+ curDoc.getItemValueString(rep.getPubHrefField()));
@SuppressWarnings("rawtypes")
Vector allEmbedded = DominoProxy.evaluate("@AttachmentNames",
curDoc);
// LOGGER.info(getCallingMethod()+":"+"All Embedded computed");
int numOfAttachments = allEmbedded.isEmpty() ? 0 : (allEmbedded
.get(0).equals("") ? 0 : allEmbedded.size());
String docID = curDoc.getUniversalID();
this.setDocumentUniqueID(docID);
LOGGER.info("Num of attachments="
+ new Integer(numOfAttachments).toString());
boolean readOnly = this.checkReadOnlyAccess(curDoc);
this.setReadOnly(readOnly);
// LOGGER.info("Creation date for "+curDoc.getUniversalID()+" ="+curDoc.getCreated().toString()+"; Time zone="+curDoc.getCreated().getZoneTime()+"; Local time="+curDoc.getCreated().getLocalTime());
Date curCreationDate = curDoc.getCreated().toJavaDate();
// LOGGER.info("Current date in Java is "+curCreationDate.toString()+"Time zone="+new
// Integer(curCreationDate.getTimezoneOffset()).toString()+"; Locale time is:"+curCreationDate.toLocaleString());
if (curDoc.hasItem("DAVCreated")) {
// Item davCreated=curDoc.getFirstItem("DAVCreated");
@SuppressWarnings("rawtypes")
Vector times = curDoc.getItemValueDateTimeArray("DAVCreated");
if (times != null) {
if (times.size() > 0) {
Object time = times.elementAt(0);
if (time != null) {
if (time.getClass().getName().endsWith("DateTime")) {
curCreationDate = ((DateTime) time)
.toJavaDate();
if (curCreationDate == null) {
curCreationDate = curDoc.getCreated()
.toJavaDate();
}
}
}
}
}
}
Date curChangeDate = curDoc.getLastModified().toJavaDate();
if (curDoc.hasItem("DAVModified")) {
@SuppressWarnings("rawtypes")
Vector times = curDoc.getItemValueDateTimeArray("DAVModified");
if (times != null) {
if (times.size() > 0) {
Object time = times.elementAt(0);
if (time != null) {
if (time.getClass().getName().endsWith("DateTime")) {
curChangeDate = ((DateTime) time).toJavaDate();
if (curChangeDate == null) {
curChangeDate = curDoc.getLastModified()
.toJavaDate();
}
}
}
}
}
}
this.setCreationDate(curCreationDate);
this.setLastModified(curChangeDate);
// LOGGER.info("Creation date is set to "+this.getCreationDate().toString());
// LOGGER.info("Last modified date is set to "+this.getLastModified().toString());
String pubHRef = ((IDAVAddressInformation) this.getRepository())
.getPublicHref();
// LOGGER.info("THIS getpublichref="+this.getPublicHref());
String curAttName = null;
if (numOfAttachments == 0) {
// LOGGER.info(getCallingMethod()+":"+"Start setting resource");
String name = curDoc
.getItemValueString(((DAVRepositoryDominoCategorizedDocuments) (this
.getRepository())).getDirectoryField());
this.setName(name);
if (this.getPublicHref().equals("")) {
this.setPublicHref(pubHRef
+ curDoc.getItemValueString(((DAVRepositoryDominoCategorizedDocuments) (this
.getRepository())).getPubHrefField()));
}
this.setCollection(true);
this.setInternalAddress(((IDAVAddressInformation) this
.getRepository()).getInternalAddress() + "/" + docID);
this.setResourceType("NotesDocument");
this.setMember(false);
this.setContentLength(0L);
// this.fetchChildren();
} else {
curAttName = allEmbedded.get(0).toString();
// LOGGER.info("Attachment name is "+curAttName);
this.setMember(true);
this.setResourceType("NotesAttachment");
if (this.getPublicHref().equals("")) {
try {
this.setPublicHref(pubHRef
+ curDoc.getItemValueString(((DAVRepositoryDominoCategorizedDocuments) (this
.getRepository())).getPubHrefField()));
} catch (Exception e) {
LOGGER.error(e);
}
// this.setPublicHref( pubHRef+"/"+curAttName);
}
this.setInternalAddress(((IDAVAddressInformation) this
.getRepository()).getInternalAddress()
+ "/"
+ docID
+ "/$File/" + curAttName);
this.setCollection(false);
this.setName(curAttName);
EmbeddedObject curAtt = curDoc.getAttachment(curAttName);
if (curAtt == null) {
return;
}
Long curSize = new Long(curAtt.getFileSize());
this.setContentLength(curSize);
}
// LOGGER.info("Current res realized! pubHREF="+this.getPublicHref()+"; Internal Address="+this.getInternalAddress()+"; ");
} catch (NotesException ne) {
LOGGER.error("ERROR! Can not set; " + ne.getMessage());
}
}
private void setup(IDAVRepository rep, String url, boolean isMember,
boolean forceCreate) throws DAVNotFoundException {
LOGGER.info("Start setup with force create; url=" + url);
this.setOwner(rep);
String folderUrl = null;
String fileName = null;
DAVRepositoryDominoCategorizedDocuments repository = (DAVRepositoryDominoCategorizedDocuments) rep;
try {
url = java.net.URLDecoder.decode(url, "UTF-8");
} catch (Exception e) {
}
LOGGER.info("setup with url=" + url);
if (url.lastIndexOf("/") > 0) {
folderUrl = url.substring(0, url.lastIndexOf("/"));
fileName = url.substring(url.lastIndexOf("/") + 1);
}
LOGGER.info("Folder=" + folderUrl + "; FileName=" + fileName);
if ((fileName != null) && (folderUrl != null)) {
LOGGER.info("in if");
DAVResourceDominoCategorizedDocuments folder = new DAVResourceDominoCategorizedDocuments(
rep, folderUrl, false);
if (folder != null) {
LOGGER.info("Folder not null");
Base notesObj = DominoProxy.resolve(repository
.getInternalAddressFromExternalUrl(folderUrl, ""));
Database db = null;
Document docParent = null;
if (notesObj instanceof View) {
LOGGER.info("isView");
View notesView = (View) notesObj;
try {
db = notesView.getParent();
} catch (NotesException e) {
}
} else {
if (notesObj instanceof Document) {
docParent = (Document) notesObj;
LOGGER.info("is doc");
try {
db = docParent.getParentDatabase();
} catch (NotesException e) {
}
}
}
if (db != null) {
try {
LOGGER.info("db not null");
String pubhref = folderUrl;
if (pubhref.startsWith(repository.getPublicHref())) {
pubhref = pubhref.substring(repository
.getPublicHref().length());
}
Document doc = db.createDocument();
doc.replaceItemValue("Form",
repository.getFileFormName());
doc.computeWithForm(true, false);
Session s = DominoProxy.getUserSession(); // NotesSession
Item webdavAuthor = doc.replaceItemValue("AuthorDAV",
s.getEffectiveUserName());
webdavAuthor.setSummary(true);
webdavAuthor.setAuthors(true);
LOGGER.info("Set OK!FolderUrl=" + folderUrl
+ "; fileName=" + fileName);
doc.replaceItemValue(repository.getPubHrefField(),
pubhref + "/" + fileName);
if (docParent != null) {
doc.makeResponse(docParent);
}
if (!isMember) { // is collection
doc.replaceItemValue(
"Form",
((DAVRepositoryDominoCategorizedDocuments) rep)
.getDirectoryFormName());
doc.replaceItemValue(
((DAVRepositoryDominoCategorizedDocuments) rep)
.getDirectoryField(), fileName);
}
doc.save(true);
LOGGER.info("Saved ok");
this.setDocumentUniqueID(doc.getUniversalID());
this.setPublicHref(url);
this.setName(fileName);
this.setMember(isMember);
LOGGER.info("Set member ok");
if (isMember) {
this.setInternalAddress(((IDAVAddressInformation) this
.getRepository()).getInternalAddress()
+ "/"
+ doc.getUniversalID()
+ "/$File/"
+ this.getName());
this.setCollection(false);
} else {
this.setInternalAddress(((IDAVAddressInformation) this
.getRepository()).getInternalAddress()
+ "/" + doc.getUniversalID());
this.setCollection(true);
}
LOGGER.info("Internal address ="
+ this.getInternalAddress());
} catch (NotesException ne) {
}
}
}
}
// this.setDominoResourceType();
}
private void setup(IDAVRepository rep, String url, boolean isMember)
throws DAVNotFoundException {
// Store a link to the repository
this.setOwner(rep);
try {
url = java.net.URLDecoder.decode(url, "UTF-8");
} catch (Exception e) {
}
DAVRepositoryDominoCategorizedDocuments repository = (DAVRepositoryDominoCategorizedDocuments) this
.getRepository();
LOGGER.info("DAVResouceDomino for " + url + "; Directory field="
+ repository.getDirectoryField());
if (url.endsWith("/")) {
url = url.substring(0, url.length() - 1);
}
// The path can't be null and can't be empty. if it is empty we use "/"
if (url == null || url.equals("")) {
url = new String("/");
}
IDAVAddressInformation repAdr = (IDAVAddressInformation) this
.getRepository();
String repUrl = repAdr.getPublicHref();
LOGGER.info("Repository url=" + repUrl);
if (url.indexOf(repUrl) == 0) {
url = url.substring(repUrl.length());
}
LOGGER.info("New url=" + url);
String fpath = rep.getInternalAddressFromExternalUrl(url,
"DAVREsourceDomino-setup");
// Keep the address
// IDAVAddressInformation repAdr = (IDAVAddressInformation)
// this.getRepository();
// LOGGER.info("-----repositoryInternalAddr="+repAdr.getInternalAddress());
LOGGER.info("FPATH=" + fpath);
// LOGGER.info("-----repositorypubhref="+repAdr.getPublicHref());
// LOGGER.info("url="+url);
// if(repAdr.getInternalAddress().equals(fpath) &&
// (!url.startsWith(repAdr.getPublicHref()))){
// throw new DAVNotFoundException();
// }
this.setInternalAddress(fpath);
if (fpath.equals("")) {
return;
// throw new DAVNotFoundException();
}
LOGGER.info("Output url=" + fpath);
// FIXME XXX TODO Borked code!
// Next check -- if Repository and Resource have the same path then the
// resource it top level
if (fpath.equals(((IDAVAddressInformation) rep).getInternalAddress())) {
LOGGER.info("Repository and Resource address match:" + fpath);
this.setName(((IDAVAddressInformation) rep).getName());
LOGGER.info(this.getName() + " is the repository-resource at "
+ this.getInternalAddress());
this.setCollection(true);
this.setResourceType("DominoRepository");
// this.setMember(false);
// this.fetchChildren();
this.setPublicHref(repository.getPublicHref());
this.setMember(isMember);
if (!this.isMember()) {
// search for members (children)
this.fetchChildren();
}
return;
}
LOGGER.info("Url after extracting repository=" + url);
if (url.equals("")) {
return;
}
Document doc = repository.getDocumentByKey(url);
if (doc == null) {
LOGGER.info("ERROR doc is null");
return;
} else {
LOGGER.info("OK found doc with key =" + url);
this.setup(doc);
}
this.setMember(isMember);
if (!this.isMember()) {
// search for members (children)
this.fetchChildren();
}
}
public String getTempfileName() {
// 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);
if (returnFile.exists()) {
return trueFileName;
}
return "";
}
public void patchCreationDate(Date date) {
Document curDoc = null;
String notesURL = this.getInternalAddress();
curDoc = DominoProxy.getDocument(notesURL);
if (curDoc == null) {
return;
}
if (curDoc instanceof Document) {
try {
Session ses = DominoProxy.getUserSession();
DateTime dt = ses.createDateTime(date);
curDoc.replaceItemValue("DAVCreated", dt);
curDoc.save(true);
this.setCreationDate(date);
} catch (Exception ne) {
LOGGER.info("Error. Can not change DAVCreated");
}
}
}
public void patchLastModified(Date date) {
Document curDoc = null;
String notesURL = this.getInternalAddress();
curDoc = DominoProxy.getDocument(notesURL);
if (curDoc == null) {
return;
}
if (curDoc instanceof Document) {
try {
Session ses = DominoProxy.getUserSession();
DateTime dt = ses.createDateTime(date);
curDoc.replaceItemValue("DAVModified", dt);
curDoc.save(true);
this.setLastModified(date);
} catch (Exception ne) {
LOGGER.info("Error. Can not change DAVCModified");
}
}
}
private DAVResourceDominoCategorizedDocuments getDocumentResource(
Document curDoc) {
// The result we are giving back
DAVResourceDominoCategorizedDocuments curRes = null;
curRes = new DAVResourceDominoCategorizedDocuments(this.getRepository());
curRes.setup(curDoc);
// LOGGER.info(getCallingMethod()+":"+"End getDocumentResource OK!");
return curRes;
}
}