/*
 * $Id: EditAclAction.java,v 1.39 2006/03/23 11:45:57 marbobo Exp $
 * 
 * Copyright (c) Siemens AG 2008 
 *           (c) Universität Paderborn 2008 
 * Licensed under EUPL 1.1. 
 * 
 * $Log: EditAclAction.java,v $
 * Revision 1.39  2006/03/23 11:45:57  marbobo
 * + Mögliche NPE abgefangen
 *
 * Revision 1.38  2005/05/24 16:54:03  jonyp
 * *** empty log message ***
 *
 * Revision 1.37  2005/05/24 14:45:57  jonyp
 * added action for acl summary view
 *
 * Revision 1.36  2005/02/14 14:01:53  bigmac
 * Applikationsweites CSS konfigurierbar gemacht + Refactorings
 *
 * Revision 1.35  2005/01/18 16:16:24  jonyp
 * added methode to get infos of creator/created of each individual acl enty
 *
 * Revision 1.34  2004/12/08 14:16:43  jonyp
 * + Berücksichtigung der LDAP-Gruppen-Einträge beim selektieren
 *
 * Revision 1.33  2004/11/18 10:22:07  jonyp
 * set/getCreated: changed from date to Timestamp
 *
 * Revision 1.32  2004/11/15 12:35:39  vchris
 * + Cleanup-Job für obsolete LDAP-Group Einträge
 *
 * Revision 1.31  2004/11/15 09:52:29  jonyp
 * changed saveGroup ==> saveLdapGroup
 *
 * Revision 1.30  2004/11/10 15:02:45  koppy
 * Projektweite Überarbeitung von Error-Logs, Stacktraces,..
 *
 * Revision 1.29  2004/11/02 21:42:30  marbobo
 * + Einige Funktionen für Gast-Benutzer gesperrt
 * + WebShare.LOGIN_PAGE mit WebShare.getLoginPage() ersetzt
 *
 * Revision 1.28  2004/10/26 13:40:38  vchris
 * *** empty log message ***
 *
 * Revision 1.27  2004/10/25 14:20:44  vchris
 * *** empty log message ***
 *
 * Revision 1.26  2004/10/22 13:54:18  vchris
 * Erweiterungen LDAP
 *
 * Revision 1.25  2004/07/08 15:13:57  marbobo
 * + Mergen von Acls
 *
 * Revision 1.24  2004/06/24 23:35:16  marbobo
 * Quellcode maintenance
 *
 * Revision 1.23  2004/06/17 14:46:58  vchris
 * Bugfix bei der Anzeige
 *
 * Revision 1.22  2004/03/26 13:17:35  bigmac
 * NPE bei nicht vorhandenen ACL gefixt
 *
 * Revision 1.21  2004/03/24 13:07:32  bigmac
 * Handling für Rücksprung in Projektsicht eingefügt
 *
 * Revision 1.20  2004/03/15 13:40:01  bigmac
 * Anpassungen an PermissionManager und weitere Refactorings
 *
 * Revision 1.19  2004/03/15 10:33:59  bigmac
 * Anpassungen an VKCPermissionSerializer und VKCAclTypeSerializer
 *
 * Revision 1.18  2004/03/07 16:53:21  bigmac
 * Anpassungen an VKCAclSerializer
 *
 * Revision 1.17  2004/03/02 23:05:46  bigmac
 * Anpassungen an VKCDocumentSerializer und VKCCategorySerializer
 *
 * Revision 1.16  2004/02/23 16:18:55  vchris
 * DisplayACL Manager fertiggestellt
 *
 * Revision 1.15  2004/02/04 15:28:00  bigmac
 * u.U. inkorrekter Kategoriepfad im ACL-Dialog behoben
 *
 * Revision 1.14  2004/01/29 15:34:21  jonyp
 * load category/categoryId from request
 *
 * Revision 1.13  2004/01/07 13:45:51  jonyp
 * code cleaning
 *
 * Revision 1.12  2003/12/24 10:11:52  bigmac
 * Projektweite Import-Optimierung
 *
 * Revision 1.11  2003/11/19 11:34:09  vchris
 * Änderungen für geändertes Verhalten des DefaultACL Editors
 *
 * Revision 1.10  2003/11/19 09:23:48  vchris
 * *** empty log message ***
 *
 * Revision 1.9  2003/11/17 14:14:18  vchris
 * DefaultACL Editor aktiviert
 *
 * Revision 1.8  2003/11/12 11:15:15  vchris
 * (Änderugnen für) Default-ACL Editor
 *
 * Revision 1.7  2003/11/11 02:38:05  koppy
 * Anpassungen wegen dem TreeView Redesign
 *
 * Created on 16.10.2003
 */
package vkc.view.action;

import java.util.ArrayList;
import java.sql.Timestamp;
import java.util.Iterator;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

import vkc.db.entities.VKCAclEntry;
import vkc.db.entities.VKCAclType;
import vkc.db.entities.VKCCategory;
import vkc.db.entities.VKCPermission;
import vkc.db.entities.VKCSubCategory;
import vkc.db.entities.VKCUser;
import vkc.db.serializer.VKCAclSerializer;
import vkc.db.serializer.VKCAclTypeSerializer;
import vkc.db.serializer.VKCCategorySerializer;
import vkc.db.serializer.VKCPermissionSerializer;
import vkc.exception.AclException;
import vkc.exception.DBException;
import vkc.ldap.db.entities.VKCLdapGroup;
import vkc.ldap.db.serializer.VKCLdapGroupSerializer;
import vkc.misc.VKCLogManager;
import vkc.security.AccessorInfo;
import vkc.security.PermissionManager;
import vkc.security.VKCAcl;
import vkc.util.treeview.TreeViewManager;
import vkc.view.WebShare;
import vkc.view.form.EditAclForm;

/**
 * DOCUMENT ME!!!
 * 
 * @author vchris
 */
public abstract class EditAclAction extends Action {

	private ActionForward INFO_FORWARD = 
		new ActionForward( "/templates/${template.name}/common/InfoPage.jsp" );

	/*
	 * Die folgenden Variablen müssen im Default-Konstruktor der Unterklassen angepasst werden
	 * Die abstrakten Methoden müssen in der Unterklasse implementiert werden.
	 */
	protected char requiredPermission = 'c';
	protected String permissionsContext = null;
	abstract protected VKCCategory retrieveCategory( HttpServletRequest request ) throws DBException;
	abstract protected VKCAcl retrieveAcl( HttpServletRequest request, VKCCategory category ) throws DBException;
	abstract protected VKCAcl retrieveParentAcl( HttpServletRequest request, VKCCategory category ) throws DBException;
	abstract protected ActionForward exitActionForward( EditAclForm aclForm );
	abstract protected void performSaveAcl( HttpServletRequest request, EditAclForm aclForm, VKCAcl acl ) throws DBException;		 	
	
	/*
	 * Die nachfolgenden Methoden müssen nicht überschrieben werden
	 */
	public ActionForward execute( ActionMapping mapping, 
	        					  ActionForm form,
	        					  HttpServletRequest request,
	        					  HttpServletResponse response ) 
	throws ServletException {
        try {
    		boolean init = false;
    		String initParameter = request.getParameter( "init" );
    		Integer categoryId = new Integer( request.getParameter( "categoryId" ) ); 
    		
    		if ( initParameter != null && initParameter.toLowerCase().equals( "true" ) ) {
    			init = true;
    			VKCLogManager.infoLog( this, "Initializing ACL Manager" );
    		}
    
    		// ACLForm holen
    		EditAclForm aclForm = (EditAclForm)form;
    						
    		// Variable initialisieren
    		int ctrlAction = EditAclForm.ACTION_INIT;
    		String accessorSelect	= null; // --> vormals typeAndAccessorId
    		VKCAcl acl 				= null; // --> vormals categoryAcl
    		VKCCategory category 	= null;
    		AccessorInfo previousAi	= null;
    		
    		// categoryId setzen
    		aclForm.setCategoryId( categoryId );
    		
    		// Kategorie holen
    		category = retrieveCategory( request );
    		aclForm.setCategory( category );
    				
    		// Close Action
    		if ( request.getParameter( "close_action" ) != null && !init ) {
    			request.getSession().removeAttribute( "previousAccessor" );
    			request.getSession().removeAttribute( "modifiedAcl" );
    			request.getSession().removeAttribute( "EditCatAclForm" );
    			try {
    				VKCLdapGroupSerializer.deleteObsoleteEntries();
    			}
    			catch (Exception e) {}
    			
    			return exitActionForward( aclForm );
    		}
    		
            //  show summary action
    		if ( request.getParameter( "show_aclsummary" ) != null && !init ) {
    			request.getSession().removeAttribute( "previousAccessor" );
    			request.getSession().removeAttribute( "modifiedAcl" );
    			request.getSession().removeAttribute( "EditCatAclForm" );
    			try {
    				VKCLdapGroupSerializer.deleteObsoleteEntries();
    			}
    			catch (Exception e) {}
    			
    			return new ActionForward("/displayAclSummaryView.do" );    			
    		}
    		
    		// ACL Initialisieren: Beim ersten Mal aus DB holen, bei Reloads und Veränderungen aus Session
    		if ( init ) {
    			try {
    				VKCLogManager.infoLog( this,"Retrieving ACL (categoryId = " + category.getCategoryId() + ") from Database." );
    				aclForm.setActualAi( null );
    				aclForm.setActualTypeId( null );
    				aclForm.setAccessorSelect( null );
    				acl = retrieveAcl( request, category );
    				request.getSession().removeAttribute( "modifiedAcl" );
    				request.getSession().removeAttribute( "previousAccessor" );
    				request.getSession().setAttribute( "modifiedAcl", acl );
    			} catch ( DBException e ) {
    				VKCLogManager.errorLog( this,"1", "Error retrieving ACL from Database",e );
    			}
    		} else {
    			try {
    				acl = (VKCAcl)request.getSession().getAttribute( "modifiedAcl" );
    				previousAi = (AccessorInfo)request.getSession().getAttribute( "previousAccessor" );
    			} catch ( Exception e ) {
    				VKCLogManager.errorLog( this,"","Error retrieving modified ACL from session",e );
    			}
    		}
    		
    		// Prüfen, ob der User eingeloggt ist und ausreichende Berechtigung hat.
    		boolean userHasPermission = false;
    		VKCUser user = (VKCUser)request.getSession().getAttribute( WebShare.USER_KEY );
			userHasPermission = PermissionManager.hasPermission( category.getAcl(), user, requiredPermission );
			aclForm.setAdminUser(user.isAdmin());
    
    		if ( user.isGuestUser() || !userHasPermission ) {
    			request.setAttribute( WebShare.INFO_KEY, "vkc.info.access_denied" );
    			
    			return INFO_FORWARD;
    		}
    		
    		// Falls nötig, neue ACL erzeugen:
    		if ( acl == null ) {
    			acl = new VKCAcl();
    		} 

    		// AclId und CategoryAclId abgleichen
    		// -> Falls ACL noch keinen Eintrag enthält, also neu erzeugt wird, dafür sorgen, dass sie die richtige ID erhält
    		if ( category.getAcl().getAclId() != null && !category.getAcl().getAclId().equals( acl.getAclId() ) ) {
    			acl.setAclId( category.getAcl().getAclId() );
    		} 
    		
    		// Andere Parameter holen
    		if ( init ) {
    			ctrlAction = EditAclForm.ACTION_INIT;
    		} else {
				accessorSelect = request.getParameter( "accessorSelect" );
				ctrlAction = Integer.parseInt( request.getParameter( "ctrlAction" ) );
    		}
    
    		// ACL an aclForm übergeben
    		aclForm.setAcl( acl, request );
    		
    		// accessorSelect setzen
    		if ( accessorSelect == null ) {
    		    accessorSelect = getFirstAccessorInList( aclForm );
    		}
    
    		// AccessorType und AccessorId in aktuellem aclForm wiederfinden, Checkboxen nicht neu setzen
    		aclForm.locateEntry( accessorSelect,false );
    
    		// Aktionen ausführen
    		switch ( ctrlAction ) {
    			case EditAclForm.ACTION_SAVE : 
					executeChangeSelect( request, aclForm, acl, accessorSelect, previousAi ); 
                    executeSaveAcl( request, aclForm, category, acl, user );
                    break;

    			case EditAclForm.ACTION_DELETE : 
                    executeDeleteAcl( request, aclForm,acl, accessorSelect ); 
                    break;

    			case EditAclForm.ACTION_ADDACCESSOR : 
                    executeAddAccessor( request, aclForm, acl, accessorSelect ); 
                    break;

    			case EditAclForm.ACTION_CHANGE_SELECT : 
                    executeChangeSelect( request, aclForm, acl, accessorSelect, previousAi ); 
                    break;

    			case EditAclForm.ACTION_INIT : 
                    executeInit( request, aclForm, acl, accessorSelect ); 
                    break;

    			case EditAclForm.ACTION_INHERIT_FROM_PARENT : 
                    executeInheritFromParent( request, aclForm, category, acl, user, accessorSelect ); 
                    break;
                    
                case EditAclForm.ACTION_ADDLDAPACCESSOR :
                	executeAddLdapAccessor( request, aclForm, acl, accessorSelect );
                	break;

    			default : 
    			    VKCLogManager.errorLog( this,"","Requested action is unknown" );
    				break;
    		}
    
    		// aktuellen Accessor für neue Aktion in der Session als PreviousAccessor hinterlegen
    		request.getSession().setAttribute( "previousAccessor", aclForm.getActualAi() );
    		
    		// Seite erneut darstellen          
    		return mapping.getInputForward();        		        	
        } catch( Exception ex ) {
            throw new ServletException( ex );
        }
	}
	
	protected void executeSaveAcl( HttpServletRequest request, EditAclForm aclForm, VKCCategory category, VKCAcl acl, VKCUser user ) throws AclException, Exception {
		if ( this instanceof EditDefaultCatAclAction ) {
			acl.setAclId( category.getCategoryId() );
		} 

		performSaveAcl( request, aclForm, acl );

		switch ( aclForm.getSelectionMode().intValue() ) {
			case EditAclForm.SELECT_NONE: 
			    break;
			case EditAclForm.SELECT_MERGE_TO_SUBCATS: 
				try {
					mergeAclToSubcategories( category, acl, user );
				} catch ( DBException e ) {
					VKCLogManager.errorLog( this, "1", "Error inheriting ACL to all subcategories",e );
				}
	
				break;
			case EditAclForm.SELECT_OVERWRITE_TO_SUBCATS:
				try {
					saveAclToSubcategories( category, acl, user );
				} catch ( DBException e ) {
					VKCLogManager.errorLog( this, "1", "Error inheriting ACL to all subcategories",e );
				}
				
				break;
		}
		
		TreeViewManager.getInstance().getGlobalTreeView().setLastModified(System.currentTimeMillis());
	}

	protected void executeDeleteAcl( HttpServletRequest request, EditAclForm aclForm, VKCAcl acl, String accessorSelect ) {
		// Eintrag löschen
		aclForm.setAllCheckboxesToValue( false );
		performUpdateAcl( request, aclForm, acl );
		// Standardmäßig ersten Eintrag selektieren
		accessorSelect = getFirstAccessorInList( aclForm );	
		aclForm.setAccessorSelect( accessorSelect );										        				
		aclForm.locateEntry( accessorSelect, true );				
	}
	
	protected void executeAddAccessor( HttpServletRequest request, EditAclForm aclForm, VKCAcl acl, String accessorSelect ) throws DBException {
		performAddAccessor( request, aclForm, acl );
		accessorSelect = aclForm.getAccessorSelect();        	
		aclForm.locateEntry( accessorSelect, true );
	}
	
	protected void executeAddLdapAccessor( HttpServletRequest request, EditAclForm aclForm, VKCAcl acl, String accessorSelect )	throws DBException {
		if ( createNewLdapServerEntry( request, aclForm, acl ) ) {
			// Neuer LDAP Accessor konnte erfolgreich angelegt werden
			accessorSelect = aclForm.getAccessorSelect();        	
			aclForm.locateEntry( accessorSelect, true );
			// aclForm.setAccessorId( aclForm.getLdapServerId() );		
		} 
	}
	
	protected void executeChangeSelect( HttpServletRequest request, EditAclForm aclForm, VKCAcl acl, String accessorSelect, AccessorInfo previousAi ) throws DBException {
		// Die Änderungen an den Checkboxen für den vorherigen Eintrag zunächst speichern
		if ( previousAi != null  && !( aclForm.getAccessorSelect() == null || aclForm.getAccessorSelect() == "" ) ) {
			AccessorInfo actualAi = aclForm.getActualAi();
			aclForm.setActualAi( previousAi );
			performUpdateAcl( request,aclForm,acl );
			aclForm.setActualAi( actualAi );
		}
		
		// Anzeige aktualisieren
		if( accessorSelect == null ) { 
		    accessorSelect = getFirstAccessorInList( aclForm ); // Defaultwert für html:select
		}
		
		aclForm.setAcl( acl, request );
		aclForm.locateEntry( accessorSelect, true );
	}
	
	protected void executeInit( HttpServletRequest request, EditAclForm aclForm, VKCAcl acl, String accessorSelect ) throws DBException {
		if( accessorSelect == null ) { 
		    accessorSelect = getFirstAccessorInList( aclForm ); // Defaultwert für html:select
		}
		
		aclForm.setAcl( acl, request );
		aclForm.locateEntry( accessorSelect, true );
	}
	
	protected void executeInheritFromParent( HttpServletRequest request, EditAclForm aclForm, VKCCategory category, VKCAcl acl, VKCUser user, String accessorSelect ) {
		try {
			aclForm.setActualAi( null );
			aclForm.setActualTypeId( null );
			aclForm.setAccessorSelect( null );
			acl = retrieveParentAcl( request, category );
			aclForm.setAcl( acl, request );
			accessorSelect = getFirstAccessorInList( aclForm );
			aclForm.locateEntry( accessorSelect, true );
			request.getSession().removeAttribute( "modifiedAcl" );
			request.getSession().removeAttribute( "previousAccessor" );
			request.getSession().setAttribute( "modifiedAcl", acl );
		} catch ( DBException e ) {
			VKCLogManager.errorLog( this,"1", "Error retrieving ACL from Database",e );
		}
	}
	
	private String getFirstAccessorInList( EditAclForm aclForm ) {
		String accessorSelect = null;
		AccessorInfo ai = null;
		
		if ( aclForm.getAnyothers().size() != 0 ) {
			// anyother selektieren
			ai = (AccessorInfo)aclForm.getAnyothers().get( 0 );
		} else if ( aclForm.getUsers().size() != 0 ) {
			// ersten user selektieren
			ai = (AccessorInfo)aclForm.getUsers().get( 0 );
		} else if ( aclForm.getGroups().size() != 0 ) {
			// ersten Group-Eintrag selektieren
			ai = (AccessorInfo)aclForm.getGroups().get( 0 );
		} else if ( aclForm.getLdapGroups().size() != 0 ) {
			// ersten LDAP-Group-Eintrag selektieren
			ai = (AccessorInfo)aclForm.getLdapGroups().get( 0 );
		}
		
		if ( ai != null ) {
		    accessorSelect = ai.getSelectIdString();
		}
		
		return accessorSelect;				
	}

	/**
	 * Aktualisiert das VKCAcl Objekt gemäß der Änderungen im Dialog, jedoch ohne es ein der Datenbank zu speichern
	 * 
	 * @param request
	 * @param aclForm
	 * @param categoryAcl
	 */
	private void performUpdateAcl( HttpServletRequest request, EditAclForm aclForm, VKCAcl acl ) {		 
		try {
			aclForm.updateAcl( request, acl );
			aclForm.setAcl( acl, request );
			request.getSession().setAttribute( "modifiedAcl", acl );
		} catch ( Exception ex ) {
			VKCLogManager.errorLog( this,"1","Error while updating ACL!", ex );
		}
	}

	private boolean containsAccessor( Integer accessorTypeId, ArrayList list ) {
		Iterator it = list.iterator();
		
		while ( it.hasNext() ) {
			AccessorInfo a = (AccessorInfo)it.next();
		    
		    if ( a.getAccessorTypeId().equals( accessorTypeId ) ) {
		        return true; 
		    }
		}
		
		return false;
	}

	/**
	 * Füg einen Accessor der ACL neu hinzu.
	 * AccessorType und AccessorId werden über die aclForm ermittelt mittels getAccessorType() bzw. getAccessorId()
	 * 
	 * @param request Der aus der Execute Methode übergebene Request
	 * @param aclForm Die ACLForm, auf dessen Eigenschaften zugegriffen wird 
	 * @param categoryAcl Die zu ändernde ACL
	 */
	private void performAddAccessor( HttpServletRequest request, EditAclForm aclForm, VKCAcl acl ) throws DBException {
		// anyother? owner?
		boolean addAnyother = false;
		boolean addOwner = false;
		
		if ( aclForm.getAddAccessorType() == VKCAclType.ANYOTHER_TYPE ) {
		    addAnyother = true;
		} else if ( aclForm.getAddAccessorType() == VKCAclType.OWNER_TYPE ) {
		    addOwner = true;
		}
		
		if ( addAnyother && containsAccessor( new Integer( VKCAclType.ANYOTHER_TYPE ), aclForm.getAnyothers() ) ) {
			// falls anyother-Eintrag hinzugefügt werden soll, überprüfen ob nicht schon vorhanden
			request.setAttribute( "vkc.acl.failed", "vkc.acl.contains_already_anyother" );
			
			return;
		} else if ( addOwner && containsAccessor( new Integer( VKCAclType.OWNER_TYPE ), aclForm.getAnyothers() ) ) {
			// gleicher Test für Owner
			request.setAttribute( "vkc.acl.failed", "vkc.acl.contains_already_owner" );
			
			return;
		}

		// neuen Accessor erzeugen
		// neues VKCAclEntry Objekt erzeugen
		VKCAclEntry newCatAcl = new VKCAclEntry();
		// Neues VKCPermission Objekt erzeugen
		Map permissions = VKCPermissionSerializer.getPermissions( permissionsContext );
		Map aclTypes = VKCAclTypeSerializer.retrieveAclTypes();
		VKCPermission newPermission = (VKCPermission) permissions.get( "r" );

		// Creator holen
		VKCUser aclCreator = (VKCUser) request.getSession().getAttribute( WebShare.USER_KEY );
			
		newCatAcl.setAccessorId( new Integer( aclForm.getAddAccessorId() ) );
		newCatAcl.setAclId( acl.getAclId() );
		newCatAcl.setPermission( newPermission );
		newCatAcl.setCreated( new Timestamp( System.currentTimeMillis() ) );
		newCatAcl.setCreatorId( aclCreator.getUserId() );		
			
		// VKCAclType
		// ACLType wiederfinden
		Iterator iter = aclTypes.values().iterator();
		VKCAclType aclt = null;
		boolean gefunden = false; 
		
		while ( iter.hasNext() ) {
			aclt = (VKCAclType)iter.next();
			
			if ( aclt.getAclTypeId().equals( new Integer( aclForm.getAddAccessorType() ) ) ) {
			    gefunden = true;
			    break;
			}
		}
		
		if ( !gefunden ) {
		    VKCLogManager.errorLog( this,"1","Error resolving ACL Type!" );
		} else {
			newCatAcl.setAclType( aclt );
		}
		
		try {
			acl.addAclEntry( newCatAcl );
			// VKCLogManager.infoLog(this,"Neuer ACL Eintrag: " + newCatAcl.toString());
		} catch ( Exception ex ) {
			VKCLogManager.errorLog( this,"1","Error adding new ACL Entry!",ex );
		}
		
		aclForm.setAcl( acl, request );
		// neuen Eintrag fokussieren
		String type = "";
		
		if ( aclForm.getAddAccessorType() == VKCAclType.ANYOTHER_TYPE ) {
		    type = VKCAclType.ANYOTHER;
		}
		
		switch ( aclForm.getAddAccessorType() )	{
			case VKCAclType.ANYOTHER_TYPE: 
			    type = VKCAclType.ANYOTHER; 
				break;
			case VKCAclType.GROUP_TYPE: 
			    type = VKCAclType.GROUP; 
				break;
			case VKCAclType.LDAP_GROUP_TYPE:
			    type = VKCAclType.LDAP_GROUP;
				break;
			case VKCAclType.USER_TYPE:
			    type = VKCAclType.USER;
				break;
			case VKCAclType.MASK_TYPE:
			    type = VKCAclType.MASK;
				break;
		}
		
		type = type + "_" + aclForm.getAddAccessorId();
		// typeAndAccessorId = type;	
		aclForm.setAccessorSelect( type );
		performUpdateAcl( request, aclForm, acl );					
	}

	private boolean createNewLdapServerEntry( HttpServletRequest request, EditAclForm aclForm, VKCAcl acl ) throws DBException {
		if ( ! ( aclForm.getGroupRdn().equals( "" ) || aclForm.getGroupRdn() == null ) ) {
			int ldapServerId = aclForm.getLdapServerId();
		
			// zunächst neuen Eintrag in der DB erzeugen.
			// später werden nicht benötigte Einträge in saveAcl() gelöscht.
			VKCLdapGroup ldapGroup = new VKCLdapGroup();
			ldapGroup.setLdapServerId( new Integer( ldapServerId ) );
			ldapGroup.setLdapGroupRDN( aclForm.getGroupRdn() );	
			VKCLdapGroupSerializer.saveLdapGroup( ldapGroup );
			aclForm.setAddAccessorId( ldapGroup.getLdapGroupId().intValue() );
			aclForm.setAddAccessorType( VKCAclType.LDAP_GROUP_TYPE );			
			performAddAccessor( request, aclForm, acl );
		} else {
			// Fehlermeldung, GroupRDN darf nicht leer sein.
			request.setAttribute( "vkc.acl.failed","vkc.acl.groupRdnEmpty" );
			
			return false;			
		}
		
		return true;
	}

	/**
	 * Speichert die ACL bei entsprechender Berechtigung für alle Unterkategorien
	 * Dabei werden in den Unterkategorien vorhandene ACLs mit der angegebenen ACL 
	 * vermischt
	 * @param category Startkategorie
	 * @param acl Zu mergende ACL
	 * @param user Userobjekt zum Feststellen der Berechtigung
	 * @throws AclException
	 * @throws Exception
	 */
	private void mergeAclToSubcategories( VKCCategory category, VKCAcl acl, VKCUser user ) throws AclException, Exception {
		for ( int i = 0; i < category.getSubCategories().size(); i++ ) {
		    VKCSubCategory sc = (VKCSubCategory)category.getSubCategories().get( i );
		    VKCCategory c = VKCCategorySerializer.retrieveCategory( sc.getSubCategoryId() );
		    
			if ( PermissionManager.hasPermission( c.getAcl(), user, requiredPermission ) ) {
				PermissionManager.mergeAcls( acl, c.getAcl() );
                VKCAclSerializer.saveAcl( c.getAcl() );
				VKCLogManager.infoLog( this, "Saving ACL also for Category ID = " + c.getCategoryId() + " (" + c.getName() + ")" );	
			} else {
			    VKCLogManager.infoLog( this, "No permission to edit ACL for Category ID = " + c.getCategoryId() + " (" + c.getName() + ")" );
			}
			
			mergeAclToSubcategories( c, acl, user );
		}
	}

	/**
	 * Speichert die ACL bei entsprechender Berechtigung für alle Unterkategorien
	 * Dabei werden in den Unterkategorien vorhandene ACLs überschrieben
	 * @param category Startkategorie
	 * @param acl Zu speichernde ACL
	 * @param user Userobjekt zum Feststellen der Berechtigung
	 * @throws DBException
	 */
	private void saveAclToSubcategories( VKCCategory category, VKCAcl acl, VKCUser user ) throws DBException {
		for ( int i = 0; i < category.getSubCategories().size(); i++ ) {
		    VKCSubCategory sc = (VKCSubCategory)category.getSubCategories().get( i );
		    VKCCategory c = VKCCategorySerializer.retrieveCategory( sc.getSubCategoryId() );
		    
			if ( PermissionManager.hasPermission( c.getAcl(), user, requiredPermission ) ) {
				Integer aclId = acl.getAclId();
				acl.setAclId( c.getAcl().getAclId() );
                VKCAclSerializer.saveAcl( acl );
        		acl.setAclId( aclId );
				VKCLogManager.infoLog( this, "Saving ACL also for Category ID = " + c.getCategoryId() + " (" + c.getName() + ")" );	
			} else {
			    VKCLogManager.infoLog( this, "No permission to edit ACL for Category ID = " + c.getCategoryId() + " (" + c.getName() + ")" );
			}
			
			saveAclToSubcategories( c, acl, user);
		}				
	}
}
