View Javadoc

1   /*
2   jGuard is a security framework based on top of jaas (java authentication and authorization security).
3   it is written for web applications, to resolve simply, access control problems.
4   version $Name$
5   http://sourceforge.net/projects/jguard/
6   
7   Copyright (C) 2004  Charles GAY
8   
9   This library is free software; you can redistribute it and/or
10  modify it under the terms of the GNU Lesser General Public
11  License as published by the Free Software Foundation; either
12  version 2.1 of the License, or (at your option) any later version.
13  
14  This library is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  Lesser General Public License for more details.
18  
19  You should have received a copy of the GNU Lesser General Public
20  License along with this library; if not, write to the Free Software
21  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  
23  
24  jGuard project home page:
25  http://sourceforge.net/projects/jguard/
26  
27  */
28  package net.sf.jguard.ext.authentication.manager;
29  
30  import java.io.FileWriter;
31  import java.io.IOException;
32  import java.io.OutputStream;
33  import java.security.Principal;
34  import java.util.Collection;
35  import java.util.HashMap;
36  import java.util.HashSet;
37  import java.util.Iterator;
38  import java.util.List;
39  import java.util.Map;
40  import java.util.Set;
41  
42  import java.util.logging.Level;
43  import javax.security.auth.Subject;
44  
45  import net.sf.jguard.core.CoreConstants;
46  import net.sf.jguard.core.PolicyEnforcementPointOptions;
47  import net.sf.jguard.core.authentication.AuthenticationException;
48  import net.sf.jguard.core.authentication.credentials.JGuardCredential;
49  import net.sf.jguard.core.authentication.manager.AuthenticationManager;
50  import net.sf.jguard.core.organization.Organization;
51  import net.sf.jguard.core.organization.OrganizationUtils;
52  import net.sf.jguard.core.principals.RolePrincipal;
53  import net.sf.jguard.core.provisioning.OrganizationTemplate;
54  import net.sf.jguard.core.provisioning.SubjectTemplate;
55  import net.sf.jguard.ext.util.SubjectUtils;
56  import net.sf.jguard.core.util.XMLUtils;
57  
58  import org.dom4j.Document;
59  import org.dom4j.DocumentHelper;
60  import org.dom4j.Element;
61  
62  import org.dom4j.InvalidXPathException;
63  import org.dom4j.XPath;
64  import org.dom4j.io.HTMLWriter;
65  import org.dom4j.io.OutputFormat;
66  import org.dom4j.io.XMLWriter;
67  import org.slf4j.Logger;
68  import org.slf4j.LoggerFactory;
69  
70  /**
71   * AuthenticationManager implementation which persists in an XML repository file.
72   * @author <a href="mailto:diabolo512@users.sourceforge.net">Charles Gay</a>
73   * @author <a href="mailto:tandilero@users.sourceforge.net">Maximiliano Batelli</a>
74   *
75   */
76  public class XmlAuthenticationManager extends AbstractAuthenticationManager implements AuthenticationManager{
77  
78          public static final String AUTHENTICATION = "authentication";
79  	private static final String PUBLIC_OPTIONAL_CREDENTIALS = "publicOptionalCredentials";
80  	private static final String PRIVATE_OPTIONAL_CREDENTIALS = "privateOptionalCredentials";
81  	private static final String PUBLIC_REQUIRED_CREDENTIALS = "publicRequiredCredentials";
82  	private static final String CRED_TEMPLATE_ID = "credTemplateId";
83  	private static final String PRIVATE_REQUIRED_CREDENTIALS = "privateRequiredCredentials";
84  	private static final String USER_TEMPLATE = "userTemplate";
85  	private static final String VALUE = "value";
86  	private static final String ID = "id";
87  	private static final String CREDENTIAL = "credential";
88          private static final String CREDENTIALS = "credentials";
89  	private static final String PRINCIPAL_REF = "principalRef";
90  	private static final String PRINCIPALS_REF = "principalsRef";
91  	private static final String PUBLIC_CREDENTIALS = "publicCredentials";
92  	private static final String PRIVATE_CREDENTIALS = "privateCredentials";
93  	private static final String USER = "user";
94  	private static final String USERS = "users";
95  	private static final String APPLICATION_NAME = "applicationName";
96  	private static final String CLASS = "class";
97  	private static final String NAME = "name";
98  	private static final String ACTIVE = "active";
99  	private static final String DEFINITION = "definition";
100 	private static final String PRINCIPAL = "principal";
101 	private static final String PRINCIPALS = "principals";
102         private static final String ORGANIZATIONS = "organizations";
103         private static final String ORGANIZATION = "organization";
104         private static final String ORGANIZATION_TEMPLATE = "organizationTemplate";
105         private static final String ORGANIZATION_REF = "organizationRef";
106         
107 
108 	/** Logger for this class */
109 	private static final Logger logger = LoggerFactory.getLogger(XmlAuthenticationManager.class.getName());
110         private Document document = null;
111         private Element root = null;
112         private String fileLocation = null;
113 
114         //link principals applicationName#name(as keys) and principals objects from multiple applications
115         private  Map principals;
116         //principals from multiple applications
117         private  Set principalsSet;
118         private Set users;
119 
120     
121 
122      /**
123      * initialise the DAO by reading the XML file, and converting it in objects.
124      * @see net.sf.jguard.core.authentication.manager.AuthenticationManager#init(java.util.Map)
125      */
126     public  XmlAuthenticationManager(Map options) {
127         super(options);
128       
129             users = new HashSet();
130             principalsSet = new HashSet();
131             principals = new HashMap();
132             applicationName = (String) options.get(PolicyEnforcementPointOptions.APPLICATION_NAME.getLabel());
133 
134             debug = Boolean.valueOf((String) options.get("debug")).booleanValue();
135             fileLocation = (String) options.get(CoreConstants.AUTHENTICATION_XML_FILE_LOCATION);
136 
137             if (fileLocation == null) {
138                 logger.error(" parameter '" + CoreConstants.AUTHENTICATION_XML_FILE_LOCATION + "' which is null must be specified in the authentication configuration ");
139             }
140             if (debug && logger.isDebugEnabled()) {
141                     logger.debug("initAuthenticationDAO() - fileLocation=" + fileLocation);
142             }
143 
144             document = XMLUtils.read(fileLocation);
145             root = document.getRootElement();
146 
147             //initialize principals
148             Map principalsAndOrganizationRefs = initPrincipals(root);
149             super.organizationTemplate = getOrganizationTemplate(root);
150 
151             initOrganizations(root);
152 
153             resolvePrincipalsOrganizationRefs(principalsAndOrganizationRefs, organizations);
154             users = initUsers(root);
155 
156     }
157 	/**
158      * persist principal in the XML repository.
159      * @param principal to persist
160      * @see net.sf.jguard.core.authentication.manager.AuthenticationManager#createPrincipal(net.sf.jguard.core.principals.RolePrincipal)
161      */
162     protected void persistPrincipal(Principal principal) throws AuthenticationException {
163                 Element prpals = root.element(XmlAuthenticationManager.PRINCIPALS);
164 		Element newPrincipal = prpals.addElement(XmlAuthenticationManager.PRINCIPAL);
165 		Element principalName = newPrincipal.addElement(XmlAuthenticationManager.NAME);
166 		principalName.setText(principal.getName());
167 
168 		Element principalClass = newPrincipal.addElement(XmlAuthenticationManager.CLASS);
169 		principalClass.setText(principal.getClass().getName());
170 
171 		Element appName = newPrincipal.addElement(XmlAuthenticationManager.APPLICATION_NAME);
172 		if(principal instanceof RolePrincipal){
173 		  appName.setText(((RolePrincipal)principal).getApplicationName());
174 		}
175 		 try {
176 			XMLUtils.write(fileLocation,document);
177 		} catch (IOException e) {
178 			logger.error(e.getMessage());
179 			throw new AuthenticationException(e.getMessage(),e);
180                 }
181     }
182 
183 
184    
185 
186     /**
187      * update user's informations in the XML repository file.
188      * @see net.sf.jguard.core.authentication.manager.AuthenticationManager#updateUser(JGuardCredential, javax.security.auth.Subject)
189      */
190     protected void updateUserImpl(JGuardCredential identityCred, Subject user) throws AuthenticationException {
191     	logger.debug("update user - identityCred ="+identityCred);
192         Element userElement = findUser(identityCred);
193         if(userElement!=null){
194         	deleteUserFromMemory(identityCred);
195         	root.element(XmlAuthenticationManager.USERS).elements(XmlAuthenticationManager.USER).remove(userElement);
196         	try {
197 	       		   XMLUtils.write(fileLocation,document);
198 	        } catch (IOException e) {
199 	        	   logger.error( "removeUser(Subject)", e);
200 	        	   throw new AuthenticationException(e.getMessage());
201 	        }
202         	persistUser(user);
203         }
204     }
205 
206    
207 
208     /**
209      * remove user from users repository stored in memory.
210      * @param user to remove
211      * @throws AuthenticationException
212      */
213     private void deleteUserFromMemory(Subject user) throws AuthenticationException{
214     	deleteUserFromMemory(extractIdentityCredentialFromUser(user));
215     }
216 
217     /**
218      * remove user from users repository stored in memory.
219      * @param identityCred 'identity' credential from the user to remove.
220      * @throws AuthenticationException
221      */
222     private void deleteUserFromMemory(JGuardCredential identityCred) throws AuthenticationException{
223     	Iterator itUsers= users.iterator();
224     	while(itUsers.hasNext()){
225     		Subject user = (Subject)itUsers.next();
226     	    JGuardCredential credFromUser = extractIdentityCredentialFromUser(user);
227     	    if(identityCred.equals(credFromUser)){
228     	    	itUsers.remove();
229     	    	logger.debug("user with identityCred:"+identityCred.getName()+" ="+identityCred.getValue().toString()+" removed ");
230     	    	break;
231     	    }
232     	}
233     }
234     
235     /**
236      * remove the user from the XML repository.
237      * @param user to remove
238 	 * @throws AuthenticationException
239      * @see net.sf.jguard.core.authentication.manager.AuthenticationManager#deleteUser(javax.security.auth.Subject)
240      */
241     public void deleteUser(Subject user) throws AuthenticationException {
242         if(user!= null){
243         	deleteUserFromMemory(user);
244 
245         	Element userElement = findUser(user);
246         	if(userElement!= null){
247                root.element(XmlAuthenticationManager.USERS).elements(XmlAuthenticationManager.USER).remove(userElement);
248 	       	   try {
249 	       		   XMLUtils.write(fileLocation,document);
250 	           } catch (IOException e) {
251 	        	   logger.error( "removeUser(Subject)", e);
252 	        	   throw new AuthenticationException(e.getMessage());
253 	           }
254 
255     		}
256         }
257     }
258 
259     private Element getOrganization(String organizationId) throws InvalidXPathException {
260 
261         String xpath = getXpathSearchStringForOrganization(organizationId);
262         XPath xp2 = DocumentHelper.createXPath(xpath);
263         Map uris = new HashMap();
264         uris.put("j", "http://jguard.sourceforge.net/xsd/jGuardUsersPrincipals_1.1.0");
265         xp2.setNamespaceURIs(uris);
266 
267         Element organizationFound = (Element) xp2.selectSingleNode(root);
268 
269         return organizationFound;
270     }
271 
272     /**
273      * find the DOM4J Element corresponding to this Subject, null otherwise.
274      * @param user subject we are looking for in the XML repository file.
275      * @return Element corresponding to the found user, null if not found.
276      * @throws AuthenticationException
277      */
278     private Element findUser(Subject user)throws AuthenticationException{
279 
280         JGuardCredential identityCred = extractIdentityCredentialFromUser(user);
281 
282         return findUser(identityCred);
283     }
284 
285 
286     /**
287      * return the DOM4J element which match with the identityCredential provided.
288      * @param identityCred
289      * @return null if no user is found, an Element if user found
290      */
291 	private Element findUser(JGuardCredential identityCred) {
292 		logger.debug("try to find user with identityCredential="+identityCred);
293 		Element usersElement = root.element(XmlAuthenticationManager.USERS);
294     	List usersElementlist = usersElement.elements(XmlAuthenticationManager.USER);
295     	Iterator itUsersList = usersElementlist.iterator();
296     	while(itUsersList.hasNext()){
297 
298     		Element userElement = (Element)itUsersList.next();
299     		Element privateCredentialsElement = userElement.element(XmlAuthenticationManager.PRIVATE_CREDENTIALS);
300     		Element elt = (Element)privateCredentialsElement.selectSingleNode("./credential[id='"+identityCred.getName()+"' and value='"+identityCred.getValue().toString()+"']");
301     		if(elt!=null){
302     			logger.debug("user "+userElement+"has been found");
303     			return userElement;
304     		}
305 
306 
307     		Element publicCredentialsElement = userElement.element(XmlAuthenticationManager.PUBLIC_CREDENTIALS);
308     		Element elt2 = (Element)publicCredentialsElement.selectSingleNode("./credential[id='"+identityCred.getName()+"' and value='"+identityCred.getValue().toString()+"']");
309     		if(elt2!=null){
310     			logger.debug("user "+userElement+"has been found");
311     			return userElement;
312     		}
313     	}
314     	//no user has been found
315     	logger.debug("no user has been found");
316     	return null;
317 	}
318 
319     private Set getCredentialsSet(Element credentialsElement) {
320         List credentialsElements = credentialsElement.elements(XmlAuthenticationManager.CREDENTIAL);
321         Iterator itCred = credentialsElements.iterator();
322         Set credentials = new HashSet();
323         while (itCred.hasNext()) {
324             Element credentialElement = (Element) itCred.next();
325             JGuardCredential credential = new JGuardCredential();
326             String id = credentialElement.element(XmlAuthenticationManager.ID).getStringValue();
327             String value = credentialElement.element(XmlAuthenticationManager.VALUE).getStringValue();
328             credential.setName(id);
329             credential.setValue(value);
330             credentials.add(credential);
331         }
332         return credentials;
333     }
334 
335     private Organization getOrganization(Element organizationElement) {
336         if(organizationElement==null){
337             throw new IllegalArgumentException("organizationElement in argument is null");
338         }
339         Organization organization = new Organization();
340         
341         Set ppals = getPrincipalsReference(organizationElement);
342         organization.setPrincipals(ppals);
343         Element userTemplateElement = organizationElement.element(XmlAuthenticationManager.USER_TEMPLATE);
344         SubjectTemplate subjTemplate = buildSubjectTemplateFromElement(userTemplateElement);
345         organization.setSubjectTemplate(subjTemplate);
346 
347         Element credentialsElement = organizationElement.element(XmlAuthenticationManager.CREDENTIALS);
348         Set credentials = getCredentialsSet(credentialsElement);
349         organization.setCredentials(credentials);
350 
351         
352         return organization;
353     }
354 
355     private Organization getOrganizationPrincipal(Element userElement) {
356         String organizationName=  userElement.element(XmlAuthenticationManager.ORGANIZATION_REF).getStringValue();
357         Iterator itOrganizations = organizations.iterator();
358         while(itOrganizations.hasNext()){
359             Organization orga = (Organization)itOrganizations.next();
360             if(organizationName.equals(orga.getName())){
361                 return orga;
362             }
363         }
364         logger.error(" organization with name"+organizationName+" have not been found");
365         return null;
366     }
367 
368     /**
369      * @param DOM4J root Element
370      * @return OrganizationTemplate parsed by this method 
371      */
372     private OrganizationTemplate getOrganizationTemplate(Element root) {
373         Element organizationsElement = root.element(XmlAuthenticationManager.ORGANIZATIONS);
374         Element organizationTemplateElement = organizationsElement.element(XmlAuthenticationManager.ORGANIZATION_TEMPLATE);
375         OrganizationTemplate template = new OrganizationTemplate();
376         
377         Element requiredCredentialsElement = organizationTemplateElement.element(XmlAuthenticationManager.CREDENTIALS);
378         List reqCredsElement = requiredCredentialsElement.elements(XmlAuthenticationManager.CRED_TEMPLATE_ID);
379         Set reqCreds = getJGuardCredentialList(reqCredsElement);
380         template.setCredentials(reqCreds);
381         
382         Set orgaTemplatePrincipals = getPrincipalsReference(organizationTemplateElement);
383         template.setPrincipals(orgaTemplatePrincipals);
384         SubjectTemplate subjTemplate = getSubjectTemplate(organizationTemplateElement);
385         
386         template.setSubjectTemplate(subjTemplate);
387         return template;
388     }
389 
390     /**
391      * parse the DOM4J element and build the set of <i>RolePrincipal</i> referenced in
392      * the element.
393      * @param Element containing the <i>principalsRef</i> DOM4J Element.
394      * @return Set of RolePrincipal
395      */ 
396     private Set getPrincipalsReference(Element parentElement) {
397         
398         Set userPrincipals = new HashSet();
399 
400         Element principalsRefElement = parentElement.element(XmlAuthenticationManager.PRINCIPALS_REF);
401         List userPrincipalsRefElement = principalsRefElement.elements(XmlAuthenticationManager.PRINCIPAL_REF);
402         Iterator itUserPrincipals = userPrincipalsRefElement.iterator();
403         while (itUserPrincipals.hasNext()) {
404             Element principalElement = (Element) itUserPrincipals.next();
405             String principalName = principalElement.attributeValue(XmlAuthenticationManager.NAME);
406             String principalApplicationName = principalElement.attributeValue(XmlAuthenticationManager.APPLICATION_NAME);
407             //if the applicationName is not set, the current applicationName is implied
408             if (principalApplicationName == null) {
409                 principalApplicationName = super.applicationName;
410             }
411             String definition = principalElement.attributeValue(XmlAuthenticationManager.DEFINITION);
412             String active = principalElement.attributeValue(XmlAuthenticationManager.ACTIVE);
413 
414             RolePrincipal principal = new RolePrincipal();
415             principal.setLocalName(principalName);
416             principal.setApplicationName(principalApplicationName);
417             principal.setDefinition(definition);
418             if((XmlAuthenticationManager.PRINCIPALS).equals(parentElement.getName())){
419                 Element organizationRefElement = principalElement.element(XmlAuthenticationManager.ORGANIZATION_REF);
420                 String organizationRefId = organizationRefElement.getStringValue();
421                 Organization organization = OrganizationUtils.findOrganization(organizations, organizationRefId);
422                 principal.setOrganization(organization);
423             }
424             if ("true".equalsIgnoreCase(active)) {
425                 principal.setActive(true);
426             } else {
427                 principal.setActive(false);
428             }
429             userPrincipals.add(principal);
430         }
431         return userPrincipals;
432     }
433 
434     private String getXpathSearchStringForOrganization(String organizationId) {
435         String xpath ="/j:authentication/j:organizations/j:organization/j:credentials/j:credential[j:id='id' and j:value='"+organizationId+"']/../..";
436         return xpath;
437     }
438 
439     private void initOrganizations(Element root) {
440         Element organizationsElement = root.element(XmlAuthenticationManager.ORGANIZATIONS);
441         List organizationsList = organizationsElement.elements(XmlAuthenticationManager.ORGANIZATION);
442         Iterator itOrganizationsList = organizationsList.iterator();
443         while (itOrganizationsList.hasNext()) {
444             Element organizationElement = (Element) itOrganizationsList.next();
445             Organization organization = getOrganization(organizationElement);
446             organizations.add(organization);
447         }
448 
449     }
450 
451     /**
452      * initialize principals.
453      * @param root dom4j element
454      */
455     private Map initPrincipals(Element root){
456         Element principalsElement = root.element(XmlAuthenticationManager.PRINCIPALS);
457         List principalsList = principalsElement.elements(XmlAuthenticationManager.PRINCIPAL);
458         Iterator itPrincipalsList = principalsList.iterator();
459         Map principalsAndOrganizationRefs = new HashMap();
460         while(itPrincipalsList.hasNext()){
461             Element principalElement = (Element)itPrincipalsList.next();
462             String principalClass = principalElement.element(XmlAuthenticationManager.CLASS).getStringValue();
463             if(!RolePrincipal.class.getName().equals(principalClass)){
464                 throw new IllegalArgumentException("class=+"+principalClass +"is unsupported ; only class="+RolePrincipal.class.getName()+" is supported");
465             }
466             RolePrincipal principal = new RolePrincipal();
467             principal.setLocalName(principalElement.element(XmlAuthenticationManager.NAME).getStringValue());
468             Element applicationNameElement = principalElement.element(XmlAuthenticationManager.APPLICATION_NAME);
469             principal.setApplicationName(applicationNameElement.getStringValue());
470             Element organizationRefElement = principalElement.element(XmlAuthenticationManager.ORGANIZATION_REF);
471             String organizationRefId = organizationRefElement.getStringValue();
472             principalsAndOrganizationRefs.put(principal, organizationRefId);
473             principals.put(principal.getName(),principal);
474             principalsSet.add(principal);
475             if(principal.getApplicationName().equals(applicationName)){
476                 localPrincipalsSet.add(principal);
477                 localPrincipals.put(principal.getName(),principal);
478             }
479         }
480         
481         return principalsAndOrganizationRefs;
482 
483     }
484 
485     /**
486      * initialize users.
487      * @param root dom4j element
488      * @return users Set
489      */
490     private Set initUsers(Element root) {
491         Element usersElement = root.element(XmlAuthenticationManager.USERS);
492         List usersList = usersElement.elements(XmlAuthenticationManager.USER);
493         Iterator itUsersList = usersList.iterator();
494 
495         while(itUsersList.hasNext()){
496             Element userElement = (Element)itUsersList.next();
497 
498             Set privateCredentials;
499             
500             Element privateCredentialsElement = userElement.element(XmlAuthenticationManager.PRIVATE_CREDENTIALS);
501             privateCredentials = getCredentialsSet(privateCredentialsElement);
502 
503             Set publicCredentials;
504             Element publicCredentialsElement = userElement.element(XmlAuthenticationManager.PUBLIC_CREDENTIALS);
505             publicCredentials = getCredentialsSet(publicCredentialsElement);
506             Set userPrincipals = getPrincipalsReference(userElement);
507             Organization organization = getOrganizationPrincipal(userElement);
508             //set of RolePrincipal granted to the organization 
509             Set organizationPrincipals = organization.getPrincipals();
510             //we check that RolePrincipals granted to the user are a subset of 
511             //RolePrincipals granted to the organization: we remove Roleprincipals
512             //not granted to the organization
513             userPrincipals.retainAll(new HashSet(organizationPrincipals));
514             
515             //we add the organization Principal to the user to be reach in contextual permissions
516             userPrincipals.add(organization);
517                         
518             //subject is not in read-only mode
519             Subject  user = new Subject(false,userPrincipals,publicCredentials,privateCredentials);
520             if(userPrincipals.size()<=1){
521                 JGuardCredential cred = SubjectUtils.getIdentityCredential(user, this);
522                 logger.warn(" user "+cred.getName()+"="+cred.getValue()+" hasn't got any RolePrincipals granted (no roles owned by his organization is granted to him) ");
523             }
524             users.add(user);
525         }
526 
527         return users;
528     }
529 
530     /**
531      * construct from configuration file the subjectTemplate.
532      * @return Subject template built
533      * @throws AuthenticationException
534      */
535     public SubjectTemplate getSubjectTemplate(Element organizationNode){
536     
537         Element subjectTemplateElement = organizationNode.element(XmlAuthenticationManager.USER_TEMPLATE);
538         SubjectTemplate st = buildSubjectTemplateFromElement(subjectTemplateElement);
539     	return st;
540     }
541 
542 
543 	private SubjectTemplate buildSubjectTemplateFromElement(Element userTemplate) {
544 	Element privateRequiredCredentials = userTemplate.element(XmlAuthenticationManager.PRIVATE_REQUIRED_CREDENTIALS);
545         List privReqCreds = privateRequiredCredentials.elements(XmlAuthenticationManager.CRED_TEMPLATE_ID);
546         Set privReqCreds2 = getJGuardCredentialList(privReqCreds);
547         Element publicRequiredCredentials = userTemplate.element(XmlAuthenticationManager.PUBLIC_REQUIRED_CREDENTIALS);
548         List pubReqCreds = publicRequiredCredentials.elements(XmlAuthenticationManager.CRED_TEMPLATE_ID);
549         Set pubReqCreds2 = getJGuardCredentialList(pubReqCreds);
550         Element privateOptionalCredentials = userTemplate.element(XmlAuthenticationManager.PRIVATE_OPTIONAL_CREDENTIALS);
551         List privOptCreds = privateOptionalCredentials.elements(XmlAuthenticationManager.CRED_TEMPLATE_ID);
552         Set privOptCreds2 = getJGuardCredentialList(privOptCreds);
553         Element publicOptionalCredentials = userTemplate.element(XmlAuthenticationManager.PUBLIC_OPTIONAL_CREDENTIALS);
554         List pubOptCreds = publicOptionalCredentials.elements(XmlAuthenticationManager.CRED_TEMPLATE_ID);
555         Set pubOptCreds2 = getJGuardCredentialList(pubOptCreds);
556         SubjectTemplate st = new SubjectTemplate();
557         st.setPrivateRequiredCredentials(privReqCreds2);
558         st.setPublicRequiredCredentials(pubReqCreds2);
559         st.setPrivateOptionalCredentials(privOptCreds2);
560         st.setPublicOptionalCredentials(pubOptCreds2);
561 
562         List principalElements = userTemplate.element(XmlAuthenticationManager.PRINCIPALS_REF).elements(XmlAuthenticationManager.PRINCIPAL_REF);
563         Set genPpals = getPrincipals(principalElements);
564         st.setPrincipals(genPpals);
565         
566 		return st;
567 	}
568 
569 
570     /**
571      * return a Set of Principals referenced in a <i>principalsRef<i/> 
572      * element.
573      * @param genericPrincipalElements
574      * @return
575      */
576     private Set getPrincipals(List principalElements){
577         Set ppals = new HashSet();
578         Iterator principalsIterator = principalElements.iterator();
579         while(principalsIterator.hasNext()){
580         	Element ppalElement = (Element)principalsIterator.next();
581             Principal ppal = (Principal)principals.get(ppalElement.attribute(APPLICATION_NAME).getData()+"#"+ppalElement.attribute(NAME).getData());
582             if(ppal!=null){
583             	ppals.add(ppal);
584             }
585         }
586 
587     	return ppals;
588     }
589     /**
590      * transform a list of DOM4J elements into a Set of JGuardCredentials.
591      * @param credTemplateIdElements list of DOM4J elements
592      * @return Set of jGuardCredentials
593      */
594     private Set getJGuardCredentialList(List credTemplateIdElements){
595     	Iterator it = credTemplateIdElements.iterator();
596     	Set jguardCredlist = new HashSet();
597     	while(it.hasNext()){
598     		Element credElement = (Element)it.next();
599     		JGuardCredential jcred = new JGuardCredential();
600     		String id = credElement.getText();
601                 if(id.equals("id")){
602                     jcred.setValue("template");
603                 }
604     		jcred.setName(id);
605     		jguardCredlist.add(jcred);
606     	}
607     	return jguardCredlist;
608     }
609 
610     /**
611      * persist user into the XML repository file.
612      * @param user
613      * @throws AuthenticationException
614      */
615 	protected void persistUser(Subject user) throws AuthenticationException {
616 		Element xmlUsers = root.element(XmlAuthenticationManager.USERS);
617 		Element newUser = xmlUsers.addElement(XmlAuthenticationManager.USER);
618 		Element privateCredentials = newUser.addElement(XmlAuthenticationManager.PRIVATE_CREDENTIALS);
619 		Set privCredentialsSet  = user.getPrivateCredentials(JGuardCredential.class);
620 		persistCredentialsSet(privCredentialsSet,privateCredentials);
621 
622 		Element publicCredentials = newUser.addElement(XmlAuthenticationManager.PUBLIC_CREDENTIALS);
623 		Set pubCredentials  = user.getPublicCredentials(JGuardCredential.class);
624 		persistCredentialsSet(pubCredentials,publicCredentials);
625 
626 		Element ppals = newUser.addElement(XmlAuthenticationManager.PRINCIPALS_REF);
627 		Set prpals = user.getPrincipals();
628 		persistPrincipalRefs(prpals,ppals);
629                 
630                 Set organizations = user.getPrincipals(Organization.class);
631                 if(organizations.size()!=1){
632                     throw new IllegalArgumentException("user"+user+"hasn't got one Organization but "+organizations.size()+" organizations ");
633                 }
634                 Organization orga = (Organization)organizations.iterator().next();
635                 Element organizationRef = newUser.addElement(XmlAuthenticationManager.ORGANIZATION_REF);
636                 organizationRef.setText(orga.getName());
637                 
638 	    try {
639         	XMLUtils.write(fileLocation,document);
640             //add the user to the in-memory users repository
641             this.users.add(user);
642         } catch (IOException e) {
643 			logger.error( "persistUser(Subject)", e);
644 			throw new AuthenticationException(e.getMessage());
645         }
646 	}
647 
648     private void persistCredentialTemplates(Set credentials, Element subjectTemplateElement, String credentialConstant) {
649         Element credentialsElement = subjectTemplateElement.addElement(credentialConstant);
650         if(credentialsElement==null){
651             logger.debug("credentialTemplateID element in XML "+credentialConstant+" is null");
652             return;
653         }
654         if(credentials==null || credentials.size()==0){
655             logger.debug("credentials"+credentialConstant+" in Object is null or empty");
656             return;
657         }
658         Iterator credentialIterator = credentials.iterator();
659         while (credentialIterator.hasNext()) {
660             JGuardCredential cred = (JGuardCredential) credentialIterator.next();
661             Element cred1 = credentialsElement.addElement(XmlAuthenticationManager.CRED_TEMPLATE_ID);
662             cred1.setText(cred.getName());
663         }
664     }
665 
666     private void persistOrganization(Organization organization, Element organizationElement) throws AuthenticationException{
667         SubjectTemplate template = organization.getSubjectTemplate();
668         if(template==null){
669             throw new IllegalArgumentException("SubejctTemplate is null into Organization "+organization);
670         }
671         persistSubjectTemplate(organizationElement,template);
672 
673         Element newCredentialsElement = organizationElement.addElement(XmlAuthenticationManager.CREDENTIALS);
674 
675         Set credentials = organization.getCredentials();
676         Iterator itCreds = credentials.iterator();
677         while (itCreds.hasNext()) {
678             JGuardCredential cred = (JGuardCredential) itCreds.next();
679             Element credElement = newCredentialsElement.addElement(XmlAuthenticationManager.CREDENTIAL);
680             Element idElement = credElement.addElement(XmlAuthenticationManager.ID);
681             idElement.setText(cred.getName());
682             Element valueElement = credElement.addElement(XmlAuthenticationManager.VALUE);
683             valueElement.setText(cred.getValue().toString());
684         }
685 
686         Element principalsRefElement = organizationElement.addElement(XmlAuthenticationManager.PRINCIPALS_REF);
687         Set orgaPrincipals = organization.getPrincipals();
688         Iterator itOrgaPrincipals = orgaPrincipals.iterator();
689         while (itOrgaPrincipals.hasNext()) {
690             RolePrincipal ppal = (RolePrincipal) itOrgaPrincipals.next();
691             Element principalRefElement = principalsRefElement.addElement(XmlAuthenticationManager.PRINCIPAL_REF);
692             principalRefElement.addAttribute(XmlAuthenticationManager.NAME, ppal.getLocalName());
693             principalRefElement.addAttribute(XmlAuthenticationManager.APPLICATION_NAME, ppal.getApplicationName());
694             principalRefElement.addAttribute(XmlAuthenticationManager.DEFINITION, ppal.getDefinition());
695             principalRefElement.addAttribute(XmlAuthenticationManager.ACTIVE, ppal.isActive() == true ? "true" : "false");
696         }
697          try {
698             XMLUtils.write(fileLocation,document);
699 	 } catch (IOException e) {
700             logger.error(e.getMessage());
701             throw new AuthenticationException(e.getMessage());
702          }
703     }
704 
705 	/**
706          * persist principals into the XML repository file.
707 	 * @param principals
708 	 * @param <i>principalsRef</i> Element
709 	 */
710 	private void persistPrincipalRefs(Set principals, Element ppals) {
711 		
712 		Iterator itPrincipals = principals.iterator();
713 		while(itPrincipals.hasNext()){
714 			Principal ppal = (Principal)itPrincipals.next();
715 			if(ppal instanceof RolePrincipal) {
716 				RolePrincipal jppal = (RolePrincipal)ppal;
717 				Element principal = ppals.addElement(XmlAuthenticationManager.PRINCIPAL_REF);
718 				principal.addAttribute(XmlAuthenticationManager.NAME, jppal.getLocalName());
719 				principal.addAttribute(XmlAuthenticationManager.APPLICATION_NAME, jppal.getApplicationName());
720 				principal.addAttribute(XmlAuthenticationManager.DEFINITION, jppal.getDefinition());
721 				principal.addAttribute(XmlAuthenticationManager.ACTIVE, jppal.isActive()==true?"true":"false");
722 			}
723 		}
724 
725 	}
726 
727         
728         
729 	/**
730 	 * persist a jGuardCredential set into the XML subset corresponding to the
731 	 * credentialsSetElement.
732 	 * @param credentials
733 	 * @param credentialsSetElement
734 	 */
735 	private void persistCredentialsSet(Set credentials,Element credentialsSetElement){
736 		Iterator itPubCredentials = credentials.iterator();
737 		while(itPubCredentials.hasNext()){
738 			JGuardCredential jcred2 = (JGuardCredential)itPubCredentials.next();
739 			Element credential = credentialsSetElement.addElement(XmlAuthenticationManager.CREDENTIAL);
740 		    Element id = credential.addElement(XmlAuthenticationManager.ID);
741 		    id.setText(jcred2.getName());
742 		    Element value = credential.addElement(XmlAuthenticationManager.VALUE);
743 		    value.setText(jcred2.getValue().toString());
744 		}
745 
746 	}
747 
748 
749 	/**
750 	 * define and persist the SubjectTemplate for registration.
751 	 * @param template
752 	 */
753 	public void persistSubjectTemplate(Element organizationElement, SubjectTemplate template) {
754              Element subjectTemplateElement = organizationElement.addElement(XmlAuthenticationManager.USER_TEMPLATE);
755              if(subjectTemplateElement == null){
756                  throw new IllegalArgumentException(" subjectTemplate is not present into organizationElement "+organizationElement.getName());
757              }
758              
759              if(template == null){
760                  throw new IllegalArgumentException(" SubjectTemplate is null");
761              }
762              persistCredentialTemplates(template.getPrivateRequiredCredentials(), subjectTemplateElement, XmlAuthenticationManager.PRIVATE_REQUIRED_CREDENTIALS);
763              persistCredentialTemplates(template.getPublicRequiredCredentials(), subjectTemplateElement, XmlAuthenticationManager.PUBLIC_REQUIRED_CREDENTIALS);
764              persistCredentialTemplates(template.getPrivateOptionalCredentials(), subjectTemplateElement, XmlAuthenticationManager.PRIVATE_OPTIONAL_CREDENTIALS);
765              persistCredentialTemplates(template.getPublicOptionalCredentials(), subjectTemplateElement, XmlAuthenticationManager.PUBLIC_OPTIONAL_CREDENTIALS);
766              Element principalsRefElement = subjectTemplateElement.addElement(XmlAuthenticationManager.PRINCIPALS_REF);
767              persistPrincipalRefs(template.getPrincipals(),principalsRefElement);
768 	}
769 
770 	/**
771 	 * @return <i>true</i> if there is no principals and no permissions.
772 	 * <i>false</i> otherwise.
773 	 */
774 	public boolean isEmpty() {
775             Element principalsElement = root.element(XmlAuthenticationManager.PRINCIPALS);
776             List principalsList = principalsElement.elements(XmlAuthenticationManager.PRINCIPAL);
777             
778             
779             Element usersElement = root.element(XmlAuthenticationManager.USERS);
780             List usersList = usersElement.elements(XmlAuthenticationManager.USER);
781             
782             if(!principalsList.isEmpty()&&!usersList.isEmpty()){
783                 return false;
784             }
785 		return true;
786 
787 	}
788 
789 
790 
791 
792     public Set getAllPrincipalsSet(){
793     	return principalsSet;
794     }
795 
796 
797 
798 
799     /**
800      *  search the users which matches credentials criterions.
801      * @param credentials crierions used to grab the users
802      * @return users found
803      */
804     public Set findUsers(Collection privateCredentials,Collection publicCredentials){
805     	Set usersFound = new HashSet();
806         Iterator it = users.iterator();
807         while(it.hasNext()){
808         	Subject user = (Subject)it.next();
809             Iterator privItCred = privateCredentials.iterator();
810             boolean userFound = true;
811             while(privItCred.hasNext()){
812             	JGuardCredential jcred = (JGuardCredential)privItCred.next();
813                 if(user.getPrivateCredentials().contains(jcred)){
814                   continue;
815                 }else{
816                      userFound = false;
817                 }
818             }
819             if(userFound==false){
820                 //Subject in evaluation does not match private credentials constraints
821                 //we skip it and evaluate the next subject
822                 continue;
823             }
824             Iterator pubItCred = publicCredentials.iterator();
825             
826             while(pubItCred.hasNext()){
827             	JGuardCredential jcred = (JGuardCredential)pubItCred.next();
828                 if(user.getPublicCredentials().contains(jcred)){
829                   continue;
830                 }else{
831                      userFound = false;
832                 }
833             }
834 
835             if(userFound==true){
836                 //Subject in evaluation matches private and public credentials constraints
837             	usersFound.add(user);
838             }
839         }
840     	return usersFound;
841     }
842 
843 	public Set getUsers() {
844 		return users;
845 	}
846 
847 
848 	public void updatePrincipal(String oldPrincipalName, Principal principal) {
849             Principal oldPal = (Principal)principals.remove(oldPrincipalName);
850             if(oldPal==null){
851                     logger.warn(" principal "+oldPrincipalName+" cannot be updated because it does not exists ");
852                     return;
853             }
854             principalsSet.remove(oldPal);
855             principals.put(principal.getName(),principal);
856             principalsSet.add(principal);
857             
858             if(isRoleAndLocal(oldPal) && localPrincipalsSet.contains(oldPal)){
859                 localPrincipalsSet.remove(oldPal);
860                 localPrincipals.put(principal.getName(),principal);
861                 localPrincipalsSet.add(principal);
862             }
863             try {
864                     XMLUtils.write(fileLocation,document);
865             } catch (IOException e) {
866                             logger.error( "updateRole(String, RolePrincipal)", e);
867             }
868 
869 	}
870 
871 
872 	public boolean deletePrincipal(Principal principal) throws AuthenticationException {
873             Principal ppalReference = (Principal)principals.remove(principal.getName());
874             if(ppalReference==null){
875                     return false;
876             }
877             principalsSet.remove(ppalReference);
878             
879             if(isRoleAndLocal(principal)&& localPrincipalsSet.contains(principal)){
880                  localPrincipalsSet.remove(principal);
881                  localPrincipals.remove(principal);
882             }
883             Element principalsElement = root.element("principals");
884             Element principalElement = (Element)principalsElement.selectSingleNode("//principal[name='"+principal.getName()+"']");
885             principalsElement.remove(principalElement);
886             if(ppalReference.getClass().equals(RolePrincipal.class)){
887               //delete all the references of this principal
888               XMLUtils.deletePrincipalRefs(root,(RolePrincipal)ppalReference);
889             }
890             try {
891                     XMLUtils.write(fileLocation,document);
892             } catch (IOException e) {
893                             logger.error( "deletePrincipal(String)", e);
894                             throw new AuthenticationException(e.getMessage());
895             }
896             return true;
897 
898 	}
899 
900 	
901 	public String exportAsXMLString(){
902 		return document.asXML();
903 	}
904 	
905 	public void writeAsXML(OutputStream outputStream, String encodingScheme) throws IOException  {
906 	   OutputFormat outformat = OutputFormat.createPrettyPrint();
907 	   outformat.setEncoding(encodingScheme);
908 	   XMLWriter writer = new XMLWriter(outputStream, outformat);
909 	   writer.write(this.document);
910 	   writer.flush();
911 	}
912 
913 
914 	
915 	public void writeAsHTML(OutputStream outputStream) throws IOException{
916 		 HTMLWriter writer = new HTMLWriter(outputStream,OutputFormat.createPrettyPrint());
917 		 writer.write(this.document);
918 		 writer.flush();
919 	}
920 
921 
922 	public void exportAsXMLFile(String fileName) throws IOException {
923 		XMLWriter xmlWriter = new XMLWriter(new FileWriter(fileName), OutputFormat.createPrettyPrint());
924 		xmlWriter.write(document);
925 		xmlWriter.close();
926 	}
927 
928     public void persistUserLoginAttempt(String login, String hostAddress, String hostName, boolean succeeded, long timeStamp) throws AuthenticationException {
929         System.out.println(" persistUserLoginAttempt not yet implemented  in XmlAuthenticationManager ");
930     }
931 
932      public void persistUserLogoutAttempt(String login, String hostAddress, String hostName, long timeStamp) throws AuthenticationException {
933         System.out.println(" persistUserLogoutAttempt not yet implemented  in XmlAuthenticationManager ");
934     }
935    
936 
937     public void deleteOrganization(Organization organisation) {
938         String credId = organisation.getName();
939         Element organizationElement = getOrganization(credId);
940         root.remove(organizationElement);
941     }
942 
943     public void updateOrganization(String organizationId, Organization organization) throws AuthenticationException {
944         Element organizationElement = getOrganization(organizationId);
945         if(organizationElement==null){
946             throw new IllegalArgumentException("organization cannot be updated : it doesn't exist ");
947         }
948         
949         //remove userTemplate
950         Element userTemplate = organizationElement.element(XmlAuthenticationManager.USER_TEMPLATE);
951         if(userTemplate!=null){
952             organizationElement.remove(userTemplate);
953         }
954         
955         //remove credentilasElement
956         Element credentialsElement = organizationElement.element(XmlAuthenticationManager.CREDENTIALS);
957         organizationElement.remove(credentialsElement);
958         
959         Element oldPrincipalsRefElement = organizationElement.element(XmlAuthenticationManager.PRINCIPALS_REF);
960         organizationElement.remove(oldPrincipalsRefElement);
961         persistOrganization(organization, organizationElement);
962     }
963     
964     
965     public Organization findOrganization(String organizationId) {
966         
967         Element organizationFound  = getOrganization(organizationId);
968         
969         if(organizationFound==null){
970             return null;
971         }
972         Organization orgaFound = getOrganization(organizationFound);
973         return orgaFound;
974         
975     }
976     
977     protected void persistOrganization(Organization organization) throws AuthenticationException {
978         String id = organization.getName();
979         String xpath = getXpathSearchStringForOrganization(id);
980         logger.debug("id for organization ="+id);
981         logger.debug("xpath for organization ="+xpath);
982         Element organizationElement  = root.element(xpath);
983         if(organizationElement==null){
984             Element organizationsElement = root.element(ORGANIZATIONS);
985             organizationElement = organizationsElement.addElement(ORGANIZATION);
986         }
987         persistOrganization(organization, organizationElement);
988     }
989 
990     public Set getOrganizations() throws AuthenticationException{
991         return organizations;
992     }
993 
994     private void resolvePrincipalsOrganizationRefs(Map principalsAndOwners, Set organizations) {
995         Iterator it = principalsAndOwners.entrySet().iterator();
996         while(it.hasNext()){
997             Map.Entry entry = (Map.Entry)it.next();
998             RolePrincipal principal = (RolePrincipal)entry.getKey();
999             String organizationId = (String)entry.getValue();
1000             Organization orgaFound = OrganizationUtils.findOrganization(organizations, organizationId);
1001             principal.setOrganization(orgaFound);
1002         }
1003     }
1004 
1005     public Collection findOrganizations(Collection credentials)throws AuthenticationException {
1006      	Set organizationsFound = new HashSet();
1007         Iterator it = organizations.iterator();
1008         while(it.hasNext()){
1009         	Organization organization = (Organization)it.next();
1010             Iterator itCred = credentials.iterator();
1011             boolean organizationFound = true;
1012             while(itCred.hasNext()){
1013             	JGuardCredential jcred = (JGuardCredential)itCred.next();
1014                 if(organization.getCredentials().contains(jcred)){
1015                   continue;
1016                 }else{
1017                      organizationFound = false;
1018                 }
1019             }
1020 
1021             if(organizationFound==true){
1022             	organizationsFound.add(organization);
1023             }
1024         }
1025     	return organizationsFound;
1026     }
1027 
1028     public void setOrganizationTemplate(OrganizationTemplate organizationTemplate) throws AuthenticationException {
1029         Element organizationsElement = root.element(XmlAuthenticationManager.ORGANIZATIONS);
1030         Element organizationTemplateElement = organizationsElement.element(XmlAuthenticationManager.ORGANIZATION_TEMPLATE);
1031                 
1032         Element requiredCredentialsElement = organizationTemplateElement.element(XmlAuthenticationManager.CREDENTIALS);
1033         
1034         List reqCredsElement = requiredCredentialsElement.elements(XmlAuthenticationManager.CRED_TEMPLATE_ID);
1035         Iterator it = reqCredsElement.iterator();
1036         while(it.hasNext()){
1037             Element elt = (Element)it.next();
1038             requiredCredentialsElement.remove(elt);
1039         }
1040         
1041         Set creds = organizationTemplate.getCredentials();
1042         Iterator itCreds = creds.iterator();
1043         while(itCreds.hasNext()){
1044             JGuardCredential cred = (JGuardCredential)itCreds.next();
1045             String name = cred.getName();
1046             Element credTemplateId = requiredCredentialsElement.addElement(XmlAuthenticationManager.CRED_TEMPLATE_ID);
1047             credTemplateId.setText(name);
1048         }
1049         
1050         persistPrincipalRefs(organizationTemplate.getPrincipals(), organizationTemplateElement);
1051         persistSubjectTemplate(organizationTemplateElement, organizationTemplate.getSubjectTemplate());
1052         
1053         
1054     }
1055 
1056    
1057 }