/** ========================================================================= *
* 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.repository;
import java.io.File;
import java.util.HashMap;
import java.util.Vector;
import lotus.domino.Document;
import lotus.domino.NotesException;
import lotus.domino.View;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import biz.taoconsulting.dominodav.exceptions.DAVNotFoundException;
import biz.taoconsulting.dominodav.interfaces.IDAVAddressInformation;
import biz.taoconsulting.dominodav.interfaces.IDAVListener;
import biz.taoconsulting.dominodav.interfaces.IDAVRepository;
import biz.taoconsulting.dominodav.interfaces.IDAVResource;
import biz.taoconsulting.dominodav.repository.AbstractRepositoryImplementation;
import biz.taoconsulting.dominodav.repository.DAVRepositoryListing;
import biz.taoconsulting.dominodav.resource.DAVAbstractResource;
import biz.taoconsulting.dominodav.resource.DAVResourceMETA;
import com.ibm.domino.osgi.core.context.ContextInfo;
import com.ibm.xsp.webdav.WebDavManager;
import com.ibm.xsp.webdav.domino.DominoProxy;
/**
* DAVRepositorMETA holds all the information about the Repositories used in
* DominoWebDAV It is used to display the toplevel Entries in DominoWEebDAV
* Servlet There is only one Meta Repository used at a time, so it is
* implemented as Singleton
*
* @author Stephan H. Wissel
*
*/
public class DAVRepositoryMETA extends AbstractRepositoryImplementation
implements IDAVRepository, IDAVAddressInformation {
/**
* The internal Object to hold the singleTon
*/
private static DAVRepositoryMETA internalRepository;
/**
* The logger object for event logging
*/
private static final Log LOGGER = LogFactory
.getLog(DAVRepositoryMETA.class);
/**
* Where is the repository located
*/
public static final String DEFAULT_REPOSITORY_LOCATION = "notes:///webdavconfig.nsf/repositories";
/**
*
*/
public static final String INTERNAL_REPOSITORY_NAME = "DAVinternal";
/**
*
*/
public static final String FOLDER_INFOFILE = "desktop.ini";
/**
*
*/
public static final String DEFAULT_PROPFIND_STYLE = "/webdav/"
+ INTERNAL_REPOSITORY_NAME + "/propfind.xslt";
/**
*
*/
public static final String DEFAULT_ROOT_STYLE = "/webdav/"
+ INTERNAL_REPOSITORY_NAME + "/repositories.xslt";
/**
* What is the name of the view to read the repositories from
*/
private boolean autoReloadRepositoryList = true;
/**
* Where do the current repositories come from
*/
private String repositoryConfigLocation = null;
public String getRepositoryConfigLocation() {
if (this.repositoryConfigLocation == null) {
this.repositoryConfigLocation = DAVRepositoryMETA.DEFAULT_REPOSITORY_LOCATION;
}
return repositoryConfigLocation;
}
public void setRepositoryConfigNSFLocation(
String repositoryConfigNSFLocation) {
this.repositoryConfigLocation = repositoryConfigNSFLocation;
}
public boolean isAutoReloadRepositoryList() {
return autoReloadRepositoryList;
}
public void setAutoReloadRepositoryList(
boolean reloadRepositoryListwhenNotFound) {
autoReloadRepositoryList = reloadRepositoryListwhenNotFound;
}
/**
* @param configNSFLocation
* Path to the NSF containing the configuration
* @return DAVRepositoryMETA - the single instance
*/
public static DAVRepositoryMETA getRepository(String configNSFLocation) {
// Initialize the lock Manager Singleton
if (internalRepository == null) {
synchronized (DAVRepositoryMETA.class) {
internalRepository = new DAVRepositoryMETA();
internalRepository
.setRepositoryConfigNSFLocation(configNSFLocation);
internalRepository.loadListOfRepositories(configNSFLocation);
}
}
return internalRepository;
}
/**
* Where is the Domino html directory
*/
private String DominoHTMLDir = ContextInfo.getDataDirectory()
+ "/domino/html/";
String directoryField = null;
/**
* List of Repositories, not initialized, read from Notes view
*/
private HashMap<String, DAVRepositoryListing> repositoryList = null;
/**
* Default constructor is private to implement a singleton
*/
private DAVRepositoryMETA() {
// The methods for the meta directory
this.setAvailableMethods("GET,PROPFIND,HEAD,OPTIONS");
}
@Override
public String getPublicHref() {
return WebDavManager.getManager(null).getServletPath();
}
/**
* @see biz.taoconsulting.dominodav.interfaces.IDAVRepository#addListener(biz.taoconsulting.dominodav.interfaces.IDAVListener)
*/
public void addListener(IDAVListener listener) {
// Not implemented
}
/**
* Make sure our singleton can't be cloned
*
* @return actually nothing -- throws an exception
* @throws CloneNotSupportedException
* -- we don't Clown around
*/
@Override
public Object clone() throws CloneNotSupportedException {
throw new CloneNotSupportedException();
// that'll teach 'em
}
/**
* @see biz.taoconsulting.dominodav.interfaces.IDAVRepository#createNewCollection(java.lang.String)
*/
public DAVAbstractResource createNewCollection(String uri) {
// Not implemented
return null;
}
/**
* @see biz.taoconsulting.dominodav.interfaces.IDAVRepository#createNewResource(java.lang.String)
*/
public DAVAbstractResource createNewResource(String uri) {
// Not implemented
return null;
}
/**
* @return Returns the repositoryList.
*/
public HashMap<String, DAVRepositoryListing> getRepositoryList() {
return this.repositoryList;
}
/**
* @see biz.taoconsulting.dominodav.interfaces.IDAVRepository#getRepositoryListing()
*/
public DAVRepositoryListing getRepositoryListing() {
// Not implemented for Meta
return null;
}
/**
* (non-Javadoc)
*
* @see biz.taoconsulting.dominodav.interfaces.IDAVAddressInformation#getInternalAddress()
*/
public String getInternalAddress() {
// Default for META
return "/";
}
/**
* (non-Javadoc)
*
* @see biz.taoconsulting.dominodav.interfaces.IDAVAddressInformation#getName()
*/
public String getName() {
return "METArepository";
}
/**
* @see biz.taoconsulting.dominodav.interfaces.IDAVRepository#getResource(java.lang.String,
* java.lang.String)
*/
public DAVAbstractResource getResource(String requestURI)
throws DAVNotFoundException {
DAVAbstractResource resc = (DAVAbstractResource) (new DAVResourceMETA(
this, requestURI));
return resc;
}
/**
* @see biz.taoconsulting.dominodav.interfaces.IDAVRepository#getResource(java.lang.String,
* java.lang.String, boolean)
*/
public DAVAbstractResource getResource(String requestURI,
boolean isChildResource) throws DAVNotFoundException {
DAVAbstractResource resc = (DAVAbstractResource) (new DAVResourceMETA(
this, requestURI, isChildResource));
return resc;
}
/**
* Loads List of Repositories
*
* @author Stephan H. Wissel servletcontext ServletContext - The servletcontext to use for
* the parameters Loads the list of available repositories
* information: start directory, name and class into a global list.
* Available to all users. It does not initialize the repository
* instances
* @param repositorylistlocation
* String - the name of the configuration file witht all
* repositories Default is repositories.xml together with the
* ServletContext the absolute Path is determined and loaded. the
* fime MUST reside in the /WEB-INF/ directory
*
*/
private void loadListOfRepositories(String repositorylistlocation) {
LOGGER.debug("Start loading repository list");
int repCount = 0;
// Initialize the list of repositories
repositoryList = new HashMap<String, DAVRepositoryListing>();
// Read list of all repository locations from the repositories view
// from the database stated in the parameter repositorylist
LOGGER.debug("Load repository list from: " + repositorylistlocation);
this.repositoryConfigLocation = repositorylistlocation; // Memorize for
// autoload
Document doc = null;
View v = DominoProxy.getView(repositorylistlocation);
if (v == null) {
LOGGER.fatal("Repository List can't be loaded from:"
+ repositorylistlocation);
return;
}
try {
int repMax = v.getEntryCount();
LOGGER.debug("Number of repositories found:"
+ new Integer(repMax).toString());
doc = v.getFirstDocument();
while (doc != null) {
// TODO: Is that right to loop that way?
this.addOneRepositoryToList(doc);
repCount++;
doc = v.getNextDocument(doc);
}
} catch (NotesException e) {
LOGGER.error("Loading repositories didn't work:" + e.getMessage());
LOGGER.error(e);
} finally {
// Cleanup after the act
try {
if (doc != null) {
doc.recycle();
}
if (v != null) {
v.recycle();
}
} catch (NotesException e) {
LOGGER.error(e);
}
this.addInternalRepositoryToList();
}
LOGGER.info("Repository List loaded, Repositories found: "
+ new Integer(repCount).toString());
}
/**
* Adds the repository DAVinternal to the repository list This is where the
* XSLT and the img resources for the display come from
*/
private void addInternalRepositoryToList() {
String repositoryName = "DAVinternal";
Vector<String> supportedMethods = new Vector<String>();
supportedMethods.add("GET");
supportedMethods.add("OPTIONS");
supportedMethods.add("PROPFIND");
String repositoryClass = "com.ibm.xsp.webdav.repository.WebDAVInternalRepository";
String repositoryRoot = "properties::";
String tempDir = this.getTempDir();
Vector<String> additionalParameters = null;
DAVRepositoryListing curRepository = new DAVRepositoryListing(
repositoryName, repositoryClass, repositoryRoot,
supportedMethods, tempDir, additionalParameters);
curRepository.setURI(repositoryName);
repositoryList.put(repositoryName, curRepository);
LOGGER.debug("Repository listing initialized: " + repositoryName);
}
/**
* Extracts the repository from the view entry Col 0 : Name Col 1 : Methods
* Col 2 : class Col 3 : isRelative Col 4 : path Col 5 : temp file Col 6 :
* Parameters
*
* @param doc
* ViewEntry with the repository definition
* @throws NotesException
*/
private void addOneRepositoryToList(Document doc) {
String repositoryName = null;
Boolean isRelative = new Boolean(false);
@SuppressWarnings("rawtypes")
Vector supportedMethods = null;
String repositoryClass = null;
String repositoryRoot = null;
String tempDir = null;
@SuppressWarnings("rawtypes")
Vector additionalParameters = null;
try {
repositoryName = doc.getItemValueString("Subject");
supportedMethods = doc.getItemValue("supportedMethods");
repositoryClass = doc.getItemValueString("webdavclass");
if (doc.hasItem("Directoryname")) {
this.directoryField = doc.getItemValueString("Directoryname");
}
if (doc.hasItem("relativePath")) {
isRelative = new Boolean(doc.getItemValueString("relativePath"));
}
repositoryRoot = doc.getItemValueString("RepositoryRoot"); // Something
// that
// can
// be
// translated
// by
// the
// repository
// class
if (doc.hasItem("TempDir")) {
tempDir = doc.getItemValueString("TempDir");
}
if (doc.hasItem("AdditionalParameters")) {
additionalParameters = doc.getItemValue("AdditionalParameters");
}
} catch (NotesException e) {
LOGGER.error(e);
}
if (isRelative) {
// Ensure that on Windows we have backslashes instead of forward
// ones
repositoryRoot = (this.DominoHTMLDir + repositoryRoot).replace(
"/".toCharArray()[0], File.separatorChar);
}
DAVRepositoryListing curRepository = new DAVRepositoryListing(
repositoryName, repositoryClass, repositoryRoot,
supportedMethods, tempDir, additionalParameters);
curRepository.setURI(repositoryName);
repositoryList.put(repositoryName, curRepository);
// LOGGER.info("Repository listing initialized: " + repositoryName);
}
/**
* @param repositoryName
* The name of the repository to load
* @param reload
* if possible and needed
*
* @return the repository found
*/
private IDAVRepository loadRepository(String repositoryName,
boolean reloadIfPossibleAndNeeded) {
IDAVRepository repository = null;
// Ensure our list of repositories is loaded properly
if (this.repositoryList == null) {
this.loadListOfRepositories(this.getRepositoryConfigLocation());
}
if (this.repositoryList.containsKey(repositoryName)) {
// We know the repository, so we initialize it to have access
LOGGER.debug("Found " + repositoryName + " in repositoryList");
DAVRepositoryListing rl = this.repositoryList.get(repositoryName);
repository = rl.getRepository();
if (repository == null) {
// Repository could not be loaded from listing
LOGGER.error("Repository could not be loaded from listing: "
+ repositoryName);
}
} else if (repositoryName.equalsIgnoreCase(INTERNAL_REPOSITORY_NAME)
|| repositoryName.equalsIgnoreCase(FOLDER_INFOFILE)) {
// We need pseudo repository for the Desktop.ini request file
repository = new WebDAVInternalRepository();
} else {
// No repository could be loaded - it could be just added to the
// config
// so we try again after refreshing the config
if (reloadIfPossibleAndNeeded && this.autoReloadRepositoryList) {
// Load repository list
this.loadListOfRepositories(this.repositoryConfigLocation);
// recursive call ONCE (false means: no refresh of the
// repository list)
repository = this.loadRepository(repositoryName, false);
} else {
// ToDo: Should we throw an error here?
LOGGER.error("Repository not found: " + repositoryName);
}
}
return repository;
}
/**
* Public function to load a repository, calls internal method
*
* @param repositoryName
* The name of the repository to load
* @return the repository found
*/
public IDAVRepository loadRepository(String repositoryName) {
return this.loadRepository(repositoryName, true);
}
/**
* @see biz.taoconsulting.dominodav.interfaces.IDAVRepository#moveResource(java.lang.String,
* java.lang.String)
*/
public int moveResource(String from, String to) {
// Not implemented
return 0;
}
/**
* @see biz.taoconsulting.dominodav.interfaces.IDAVRepository#removeListener(biz.taoconsulting.dominodav.interfaces.IDAVListener)
*/
public void removeListener(IDAVListener listener) {
// not implemented
}
/*
* Extension to the DAVMetaRepository: List of Repositories
*/
/**
* @see biz.taoconsulting.dominodav.interfaces.IDAVRepository#setRepositoryListing(biz.taoconsulting.dominodav.repository.DAVRepositoryListing)
*/
public void setRepositoryListing(DAVRepositoryListing repositoryListing) {
// not implemented
}
/**
* @see biz.taoconsulting.dominodav.interfaces.IDAVRepository#writeResource(biz.taoconsulting.dominodav.resource.DAVAbstractResource)
*/
public void writeResource(IDAVResource resc) {
// Not implemented
}
public String getInternalAddressFromExternalUrl(String externalURL,
String callee) {
return "/"; // The meta address is always the same
}
}