/**
 * @author : Thomas Bellembois
 * @version : 1.3
 * creation date : 2005 jan. 07
 * last modification date : 2005 apr. 06
 * modifications:
 * 09.02.2005 Thomas Bellembois (Rennes1) : acl modifications
 * 04.03.2005 Thomas Bellembois (Rennes1) : upgrading library esup-acl-manager > 1.0.3
 * 06.04.2005 Thomas Bellembois (Rennes1) : correcting a bug when the context is "/"
 **/

package org.esupportail.portal.utils.injac.injacV2SpacesCreation;

import java.io.IOException;
import java.net.URLEncoder;
import java.util.Enumeration;
import java.util.StringTokenizer;
import java.util.Vector;

import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpURL;
import org.apache.commons.httpclient.URIException;
import org.apache.log4j.Logger;
import org.apache.webdav.lib.Property;
import org.apache.webdav.lib.PropertyName;
import org.apache.webdav.lib.WebdavResource;
import org.apache.webdav.lib.methods.DepthSupport;
import org.apache.webdav.lib.methods.PropFindMethod;
import org.esupportail.portal.utils.injac.injacV2SpacesCreation.config.Config;
import org.esupportail.portal.utils.injac.injacV2SpacesCreation.exception.ConfigException;
import org.esupportail.portal.utils.injac.injacV2SpacesCreation.exception.WrongPathException;
import org.esupportail.portal.utils.webdav.acl.ACLManager;
import org.esupportail.portal.utils.webdav.acl.EsupPermissions;
import org.esupportail.portal.utils.webdav.acl.exception.ReadAclException;
import org.esupportail.portal.utils.webdav.acl.exception.WriteAclException;

public class InjacV2SpacesCreation {
	
	private HttpURL httpUrl;
	private WebdavResource webDavResource;
	private String context;
	
	private ACLManager aclManager;
	
	private String injacPath;
	
	private String webdavServerUrl;
	private String webdavServerLogin;
	private String webdavServerPassword;
	
	private String userDirectoryRootDirectory;
	
	private String roleDirectoryRootDirectory;
	private String localRolesDirectory;
	private String uPortalRolesDirectory;
	
	private Logger logger = Logger.getLogger(getClass().getName());

	
	/**
	 * Initializes all the variables and connect to the WebDAV server
	 */
	private void init(){ // context == /slide for example
		try{
			webdavServerUrl = Config.getInstance().getWebdavServerUrl();		     // WebDav server URL
			webdavServerLogin = Config.getInstance().getWebdavServerLogin();	     // WebDav server login
			webdavServerPassword = Config.getInstance().getWebdavServerPassword();   // WebDav server password
			
			userDirectoryRootDirectory = Config.getInstance().getUserDirectoryRootDirectory(); // Root directory to create homedirs on the WebDav server
			roleDirectoryRootDirectory = Config.getInstance().getRoleDirectoryRootDirectory(); // Root directory to create roles on the WebDav server

			// Connecting to the Webdav server
			httpUrl = new HttpURL(webdavServerUrl+"/");
			httpUrl.setUserinfo(webdavServerLogin, webdavServerPassword);
			context = httpUrl.getCurrentHierPath();
			if (context.equalsIgnoreCase("/")) context = "";
			webDavResource = new WebdavResource(httpUrl);
			logger.info("Connected to "+webDavResource.getPath());
			
			injacPath = context+"/"+Config.getInstance().getInjacPath();
			userDirectoryRootDirectory = context+"/"+Config.getInstance().getUserDirectoryRootDirectory(); // Root directory to create homedirs on the WebDav server
			roleDirectoryRootDirectory = context+"/"+Config.getInstance().getRoleDirectoryRootDirectory(); // Root directory to create roles on the WebDav server
			localRolesDirectory = context+"/"+Config.getInstance().getRoleDirectoryLocalRolesDirectory();  // Root directory to create local roles on the WebDav server
			uPortalRolesDirectory = context+"/"+Config.getInstance().getRoleDirectoryUPortalRolesDirectory(); // Root directory to create uPortal roles on the WebDav server
			
			aclManager = new ACLManager(webDavResource, ACLManager.DEFAULT_SLIDE_NAMESPACE, userDirectoryRootDirectory, roleDirectoryRootDirectory);
			
			logger.debug(getClass().getName()+":init:..context="+context);
			logger.debug(getClass().getName()+":init:..injacPath="+injacPath);
			logger.debug(getClass().getName()+":init:..userDirectoryRootDirectory="+userDirectoryRootDirectory);
			logger.debug(getClass().getName()+":init:..roleDirectoryRootDirectory="+roleDirectoryRootDirectory);
			logger.debug(getClass().getName()+":init:..localRolesDirectory="+localRolesDirectory);
			logger.debug(getClass().getName()+":init:..uPortalRolesDirectory="+uPortalRolesDirectory);
		}
		catch (ConfigException configException){logger.info("InjacSpacesCreation::init::"+configException);}
		catch (HttpException httpException){logger.info("InjacSpacesCreation::init::"+httpException);}
		catch (IOException ioException){logger.info("InjacSpacesCreation::init::"+ioException);}
	}// init
	
	
	/**
	 * Set a resource property
	 * @return true if no problem occured
	 */
	private boolean setProperty(WebdavResource webdavResource, String path, String propertyName, String propertyValue) throws URIException, IOException {
		
		String encodedPropertyValue = URLEncoder.encode(propertyValue, "utf-8");
		
		logger.debug("InjacV2SpacesCreation::setProperty::propertyName="+propertyName+" propertyValue="+propertyValue+" path="+path);
		boolean result = webdavResource.proppatchMethod(path, new PropertyName("INJAC:", propertyName), encodedPropertyValue, true);
		
		return result;
	 }// setProperty
	
	
	/**
	 * Check that a WebDAV ressource exists
	 * @param webDavResource name of the resource to process
	 * @param path path of the resource to process
	 * @return true if the path exists, else false
	 */
	private boolean pathExist(WebdavResource webDavResource, String path){
		boolean result = false;
		try {
			webDavResource.setPath(path);
			result = webDavResource.exists();
			return result;
		} catch (IOException ioException) {
			logger.error("InjacSpacesCreation::pathExist::"+ioException);
		}
		return result;
	}// isExist
	
	
	/**
	 * Create an Injac space.
	 * @param webDavResource webDavResource where to create the space
	 * @param spaceName name of the space to create
	 * @throws WrongPathException
	 */
	private void createInjacSpace(WebdavResource webDavResource, String spaceName) throws WrongPathException{
		try{
			String spacePath = null;
			
				if (!pathExist(webDavResource,injacPath)){
					logger.error("Directory "+injacPath+" does not exist !");
					throw new WrongPathException("InjacSpacesCreation", "createInjacSpace", injacPath);
				}// if
				spacePath = new String(injacPath+"/"+spaceName);
				
				if (pathExist(webDavResource, spacePath)){
					logger.error("Space "+spacePath+" already exists !");
					throw new WrongPathException("InjacSpacesCreation", "createInjacSpace", spacePath);
				}// if
			
			logger.info("Creation of "+spacePath);
			webDavResource.mkcolMethod(spacePath);
		}
		catch(HttpException httpException){logger.info("InjacSpacesCreation::createInjacSpace::"+httpException);}
		catch(IOException ioException){logger.info("InjacSpacesCreation::createInjacSpace::"+ioException);}
	}// createInjacSpace
	
	
	/**
	 * Parse a user list given in parameter of the application
	 * @param userList syntax: user1:user2:user3:...
	 * @return an Enumeration of String with Element1=user1 Element2=user2...
	 */
	private Enumeration parseUserList(String userList){
		Vector userVector = new Vector();
		
		StringTokenizer st = new StringTokenizer(userList, ":", false);
		while (st.hasMoreTokens()) {
			userVector.addElement(st.nextToken());
		}// while
		
		return userVector.elements();
	}// parseUserList
	
	
	public static void main(String[] args) {
		
		InjacV2SpacesCreation injacV2SpacesCreation = new InjacV2SpacesCreation();
		
		///////////////////////////
		//
		// Verifying the parameters
		//
		if(!(args.length==3)){
			injacV2SpacesCreation.logger.info("Wrong number of parameters");
			System.exit(0);
		}
		if(args[0].equals("-help")){
			injacV2SpacesCreation.logger.info("InjacV2SpacesCreation [spaceName] [admin] [commonWebDAVChannelAccount]\n");
			System.exit(0);
		}
		
		/////////////////////////
		// Getting the parameters
		//
		String spaceName = args[0];
		String admin = args[1];
		String commonWebDAVChannelAccount = args[2];
		
		injacV2SpacesCreation.logger.info("spaceName > "+spaceName);
		injacV2SpacesCreation.logger.info("admin > "+admin);
		injacV2SpacesCreation.logger.info("commonWebDAVChannelAccount > "+commonWebDAVChannelAccount);
		
		// Initializing variables - connecting to the WebDAV server
		injacV2SpacesCreation.logger.info("initializing the process");
		injacV2SpacesCreation.init();
		
		try {
			
		// Creating the InJac root space
		injacV2SpacesCreation.logger.info("creating the InJac root space "+spaceName);
		injacV2SpacesCreation.createInjacSpace(injacV2SpacesCreation.webDavResource, spaceName);
		
		spaceName = new String(injacV2SpacesCreation.injacPath+"/"+spaceName);
		
		
		// Giving the right "all" on the root space for the user "commonWebDAVChannelAccount"
		//                  "all" on the root space for the role "root"
		// Removing the right "read" for everybody
		// Removing the right "write" for everybody
		EsupPermissions esupPermissions = null;
		injacV2SpacesCreation.logger.info("granting all for "+commonWebDAVChannelAccount+" on the InJac root space "+spaceName);
		esupPermissions = injacV2SpacesCreation.aclManager.grant(spaceName, injacV2SpacesCreation.userDirectoryRootDirectory+"/"+commonWebDAVChannelAccount, "all");
		injacV2SpacesCreation.logger.info("granting all for "+injacV2SpacesCreation.localRolesDirectory+"/"+"root"+" on the InJac root space "+spaceName);
		esupPermissions = injacV2SpacesCreation.aclManager.grant(spaceName, injacV2SpacesCreation.localRolesDirectory+"/"+"root", "all");
		injacV2SpacesCreation.logger.info("denying read for "+"all"+" on the InJac root space "+spaceName);
		esupPermissions = injacV2SpacesCreation.aclManager.deny(spaceName, "all", "read");
		injacV2SpacesCreation.logger.info("denying write for "+"all"+" on the InJac root space "+spaceName);
		esupPermissions = injacV2SpacesCreation.aclManager.deny(spaceName, "all", "write");
		
		injacV2SpacesCreation.logger.debug("listing permissions of the resource "+spaceName);
		esupPermissions.toString();
		
		/////////////////////////////
		// Initializing some metadata
		//
		// --> injac-type
		injacV2SpacesCreation.logger.info("initializing metadata \"injac-type\" to \"space\"");
		boolean result;
		result = injacV2SpacesCreation.setProperty(injacV2SpacesCreation.webDavResource, spaceName, "injac-type", "space");
		if (result) injacV2SpacesCreation.logger.info("metadata \"injac-type\" successfully initialized");
		else injacV2SpacesCreation.logger.error("metadata \"injac-type\" initialization failed !");
		
		// --> manager
		// getting the displayname
		injacV2SpacesCreation.logger.info("initializing metadata \"manager\" to "+admin);
		String displayName = null;
		String adminPath = injacV2SpacesCreation.userDirectoryRootDirectory+"/"+admin;
		Vector properties = new Vector();
		String propName = "displayName";
		PropertyName property = new PropertyName("LDAP:", propName);
		properties.add(property);
		injacV2SpacesCreation.webDavResource.setPath(adminPath);
		PropFindMethod method = new PropFindMethod(adminPath, DepthSupport.DEPTH_INFINITY, properties.elements());
		injacV2SpacesCreation.webDavResource.retrieveSessionInstance().executeMethod(method);
		Enumeration enumeration = method.getResponseProperties(adminPath);
		
		int counter = 0;
		while (enumeration.hasMoreElements()) {
			if (counter == 1) {
				injacV2SpacesCreation.logger.error("WARNING ! More than one LDAP:displayname property exist for "+adminPath+" - only the first one is retrieved");
				break;
			}// if (counter == 1)
			Property element = (Property) enumeration.nextElement();
			displayName = element.getPropertyAsString();
			counter++;
		}// while (enumeration.hasMoreElements())
		
		String managers = "<managers><manager type=\"user\" key=\""+admin+"\" displayName=\""+displayName+"\" /></managers>";
		injacV2SpacesCreation.logger.debug("managers="+managers);
		result = injacV2SpacesCreation.setProperty(injacV2SpacesCreation.webDavResource, spaceName, "managers", managers);
		if (result) injacV2SpacesCreation.logger.info("metadata \"manager\" successfully initialized");
		else injacV2SpacesCreation.logger.error("metadata \"manager\" initialization failed !");
		
		}
		catch (WrongPathException e) {injacV2SpacesCreation.logger.error(e.getMessage());}
		catch (URIException e) {injacV2SpacesCreation.logger.error(e.getMessage());}
		catch (IOException e) {injacV2SpacesCreation.logger.error(e.getMessage());}
		catch (ReadAclException e) {injacV2SpacesCreation.logger.error(e.getMessage());}
		catch (WriteAclException e) {injacV2SpacesCreation.logger.error(e.getMessage());}
		
		injacV2SpacesCreation.logger.info("Process finished");
	}// main
}// injacSpacesCreation
