mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-24 17:32:48 +00:00
Merged enterprise features
git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@2746 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright (C) 2005 Alfresco, Inc.
|
||||
*
|
||||
* Licensed under the Alfresco Network License. You may obtain a
|
||||
* copy of the License at
|
||||
*
|
||||
* http://www.alfrescosoftware.com/legal/
|
||||
*
|
||||
* Please view the license relevant to your network subscription.
|
||||
*
|
||||
* BY CLICKING THE "I UNDERSTAND AND ACCEPT" BOX, OR INSTALLING,
|
||||
* READING OR USING ALFRESCO'S Network SOFTWARE (THE "SOFTWARE"),
|
||||
* YOU ARE AGREEING ON BEHALF OF THE ENTITY LICENSING THE SOFTWARE
|
||||
* ("COMPANY") THAT COMPANY WILL BE BOUND BY AND IS BECOMING A PARTY TO
|
||||
* THIS ALFRESCO NETWORK AGREEMENT ("AGREEMENT") AND THAT YOU HAVE THE
|
||||
* AUTHORITY TO BIND COMPANY. IF COMPANY DOES NOT AGREE TO ALL OF THE
|
||||
* TERMS OF THIS AGREEMENT, DO NOT SELECT THE "I UNDERSTAND AND AGREE"
|
||||
* BOX AND DO NOT INSTALL THE SOFTWARE OR VIEW THE SOURCE CODE. COMPANY
|
||||
* HAS NOT BECOME A LICENSEE OF, AND IS NOT AUTHORIZED TO USE THE
|
||||
* SOFTWARE UNLESS AND UNTIL IT HAS AGREED TO BE BOUND BY THESE LICENSE
|
||||
* TERMS. THE "EFFECTIVE DATE" FOR THIS AGREEMENT SHALL BE THE DAY YOU
|
||||
* CHECK THE "I UNDERSTAND AND ACCEPT" BOX.
|
||||
*/
|
||||
package org.alfresco.repo.security.authentication.ldap;
|
||||
|
||||
import javax.naming.NamingException;
|
||||
import javax.naming.directory.InitialDirContext;
|
||||
|
||||
import org.alfresco.repo.security.authentication.AbstractAuthenticationComponent;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationException;
|
||||
|
||||
/**
|
||||
* Currently expects the cn name of the user which is in a fixed location.
|
||||
*
|
||||
* @author Andy Hind
|
||||
*/
|
||||
public class LDAPAuthenticationComponentImpl extends AbstractAuthenticationComponent
|
||||
{
|
||||
|
||||
private String userNameFormat;
|
||||
|
||||
private LDAPInitialDirContextFactory ldapInitialContextFactory;
|
||||
|
||||
public LDAPAuthenticationComponentImpl()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
|
||||
public void setLDAPInitialDirContextFactory(LDAPInitialDirContextFactory ldapInitialDirContextFactory)
|
||||
{
|
||||
this.ldapInitialContextFactory = ldapInitialDirContextFactory;
|
||||
}
|
||||
|
||||
|
||||
public void setUserNameFormat(String userNameFormat)
|
||||
{
|
||||
this.userNameFormat = userNameFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implement the authentication method
|
||||
*/
|
||||
public void authenticate(String userName, char[] password) throws AuthenticationException
|
||||
{
|
||||
InitialDirContext ctx = null;
|
||||
try
|
||||
{
|
||||
ctx = ldapInitialContextFactory.getInitialDirContext(String.format(userNameFormat, new Object[]{userName}), new String(password));
|
||||
|
||||
// Authentication has been successful.
|
||||
// Set the current user, they are now authenticated.
|
||||
setCurrentUser(userName);
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
if(ctx != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
ctx.close();
|
||||
}
|
||||
catch (NamingException e)
|
||||
{
|
||||
clearCurrentSecurityContext();
|
||||
throw new AuthenticationException("Failed to close connection", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected boolean implementationAllowsGuestLogin()
|
||||
{
|
||||
InitialDirContext ctx = null;
|
||||
try
|
||||
{
|
||||
ctx = ldapInitialContextFactory.getDefaultIntialDirContext();
|
||||
return true;
|
||||
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if(ctx != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
ctx.close();
|
||||
}
|
||||
catch (NamingException e)
|
||||
{
|
||||
throw new AuthenticationException("Failed to close connection", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
@@ -0,0 +1,695 @@
|
||||
/*
|
||||
* Copyright (C) 2005 Alfresco, Inc.
|
||||
*
|
||||
* Licensed under the Alfresco Network License. You may obtain a
|
||||
* copy of the License at
|
||||
*
|
||||
* http://www.alfrescosoftware.com/legal/
|
||||
*
|
||||
* Please view the license relevant to your network subscription.
|
||||
*
|
||||
* BY CLICKING THE "I UNDERSTAND AND ACCEPT" BOX, OR INSTALLING,
|
||||
* READING OR USING ALFRESCO'S Network SOFTWARE (THE "SOFTWARE"),
|
||||
* YOU ARE AGREEING ON BEHALF OF THE ENTITY LICENSING THE SOFTWARE
|
||||
* ("COMPANY") THAT COMPANY WILL BE BOUND BY AND IS BECOMING A PARTY TO
|
||||
* THIS ALFRESCO NETWORK AGREEMENT ("AGREEMENT") AND THAT YOU HAVE THE
|
||||
* AUTHORITY TO BIND COMPANY. IF COMPANY DOES NOT AGREE TO ALL OF THE
|
||||
* TERMS OF THIS AGREEMENT, DO NOT SELECT THE "I UNDERSTAND AND AGREE"
|
||||
* BOX AND DO NOT INSTALL THE SOFTWARE OR VIEW THE SOURCE CODE. COMPANY
|
||||
* HAS NOT BECOME A LICENSEE OF, AND IS NOT AUTHORIZED TO USE THE
|
||||
* SOFTWARE UNLESS AND UNTIL IT HAS AGREED TO BE BOUND BY THESE LICENSE
|
||||
* TERMS. THE "EFFECTIVE DATE" FOR THIS AGREEMENT SHALL BE THE DAY YOU
|
||||
* CHECK THE "I UNDERSTAND AND ACCEPT" BOX.
|
||||
*/
|
||||
package org.alfresco.repo.security.authentication.ldap;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
|
||||
import javax.naming.NamingEnumeration;
|
||||
import javax.naming.NamingException;
|
||||
import javax.naming.directory.Attribute;
|
||||
import javax.naming.directory.Attributes;
|
||||
import javax.naming.directory.InitialDirContext;
|
||||
import javax.naming.directory.SearchControls;
|
||||
import javax.naming.directory.SearchResult;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.importer.ExportSource;
|
||||
import org.alfresco.repo.importer.ExportSourceImporterException;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.util.ApplicationContextHelper;
|
||||
import org.alfresco.util.EqualsHelper;
|
||||
import org.alfresco.util.GUID;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.dom4j.io.OutputFormat;
|
||||
import org.dom4j.io.XMLWriter;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.helpers.AttributesImpl;
|
||||
|
||||
public class LDAPGroupExportSource implements ExportSource, InitializingBean
|
||||
{
|
||||
private static Log s_logger = LogFactory.getLog(LDAPGroupExportSource.class);
|
||||
|
||||
private String groupQuery = "(objectclass=groupOfNames)";
|
||||
|
||||
private String searchBase;
|
||||
|
||||
private String groupIdAttributeName = "cn";
|
||||
|
||||
private String userIdAttributeName = "uid";
|
||||
|
||||
private String groupType = "groupOfNames";
|
||||
|
||||
private String personType = "inetOrgPerson";
|
||||
|
||||
private LDAPInitialDirContextFactory ldapInitialContextFactory;
|
||||
|
||||
private NamespaceService namespaceService;
|
||||
|
||||
private String memberAttribute = "member";
|
||||
|
||||
private boolean errorOnMissingMembers = false;
|
||||
|
||||
private QName viewRef;
|
||||
|
||||
private QName viewId;
|
||||
|
||||
private QName viewAssociations;
|
||||
|
||||
private QName childQName;
|
||||
|
||||
private QName viewValueQName;
|
||||
|
||||
private QName viewIdRef;
|
||||
|
||||
public LDAPGroupExportSource()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
public void setGroupIdAttributeName(String groupIdAttributeName)
|
||||
{
|
||||
this.groupIdAttributeName = groupIdAttributeName;
|
||||
}
|
||||
|
||||
public void setGroupQuery(String groupQuery)
|
||||
{
|
||||
this.groupQuery = groupQuery;
|
||||
}
|
||||
|
||||
public void setGroupType(String groupType)
|
||||
{
|
||||
this.groupType = groupType;
|
||||
}
|
||||
|
||||
public void setLDAPInitialDirContextFactory(LDAPInitialDirContextFactory ldapInitialDirContextFactory)
|
||||
{
|
||||
this.ldapInitialContextFactory = ldapInitialDirContextFactory;
|
||||
}
|
||||
|
||||
public void setMemberAttribute(String memberAttribute)
|
||||
{
|
||||
this.memberAttribute = memberAttribute;
|
||||
}
|
||||
|
||||
public void setNamespaceService(NamespaceService namespaceService)
|
||||
{
|
||||
this.namespaceService = namespaceService;
|
||||
}
|
||||
|
||||
public void setPersonType(String personType)
|
||||
{
|
||||
this.personType = personType;
|
||||
}
|
||||
|
||||
public void setSearchBase(String searchBase)
|
||||
{
|
||||
this.searchBase = searchBase;
|
||||
}
|
||||
|
||||
public void setUserIdAttributeName(String userIdAttributeName)
|
||||
{
|
||||
this.userIdAttributeName = userIdAttributeName;
|
||||
}
|
||||
|
||||
public void setErrorOnMissingMembers(boolean errorOnMissingMembers)
|
||||
{
|
||||
this.errorOnMissingMembers = errorOnMissingMembers;
|
||||
}
|
||||
|
||||
public void generateExport(XMLWriter writer)
|
||||
{
|
||||
HashSet<Group> rootGroups = new HashSet<Group>();
|
||||
HashMap<String, Group> lookup = new HashMap<String, Group>();
|
||||
HashSet<SecondaryLink> secondaryLinks = new HashSet<SecondaryLink>();
|
||||
|
||||
buildGroupsAndRoots(rootGroups, lookup, secondaryLinks);
|
||||
|
||||
buildXML(rootGroups, lookup, secondaryLinks, writer);
|
||||
|
||||
}
|
||||
|
||||
private void buildXML(HashSet<Group> rootGroups, HashMap<String, Group> lookup,
|
||||
HashSet<SecondaryLink> secondaryLinks, XMLWriter writer)
|
||||
{
|
||||
|
||||
Collection<String> prefixes = namespaceService.getPrefixes();
|
||||
QName childQName = QName.createQName(NamespaceService.REPOSITORY_VIEW_PREFIX, "childName", namespaceService);
|
||||
|
||||
try
|
||||
{
|
||||
AttributesImpl attrs = new AttributesImpl();
|
||||
attrs.addAttribute(NamespaceService.REPOSITORY_VIEW_1_0_URI, childQName.getLocalName(), childQName
|
||||
.toPrefixString(), null, ContentModel.TYPE_PERSON.toPrefixString(namespaceService));
|
||||
|
||||
writer.startDocument();
|
||||
|
||||
for (String prefix : prefixes)
|
||||
{
|
||||
if (!prefix.equals("xml"))
|
||||
{
|
||||
String uri = namespaceService.getNamespaceURI(prefix);
|
||||
writer.startPrefixMapping(prefix, uri);
|
||||
}
|
||||
}
|
||||
|
||||
writer.startElement(NamespaceService.REPOSITORY_VIEW_PREFIX, "view",
|
||||
NamespaceService.REPOSITORY_VIEW_PREFIX + ":" + "view", new AttributesImpl());
|
||||
|
||||
// Create group structure
|
||||
|
||||
for (Group group : rootGroups)
|
||||
{
|
||||
addRootGroup(lookup, group, writer);
|
||||
}
|
||||
|
||||
// Create secondary links.
|
||||
|
||||
for (SecondaryLink sl : secondaryLinks)
|
||||
{
|
||||
addSecondarylink(lookup, sl, writer);
|
||||
}
|
||||
|
||||
for (String prefix : prefixes)
|
||||
{
|
||||
if (!prefix.equals("xml"))
|
||||
{
|
||||
writer.endPrefixMapping(prefix);
|
||||
}
|
||||
}
|
||||
|
||||
writer.endElement(NamespaceService.REPOSITORY_VIEW_PREFIX, "view", NamespaceService.REPOSITORY_VIEW_PREFIX
|
||||
+ ":" + "view");
|
||||
|
||||
writer.endDocument();
|
||||
}
|
||||
catch (SAXException e)
|
||||
{
|
||||
throw new ExportSourceImporterException("Failed to create file for import.", e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void addSecondarylink(HashMap<String, Group> lookup, SecondaryLink sl, XMLWriter writer)
|
||||
throws SAXException
|
||||
{
|
||||
|
||||
String fromId = lookup.get(sl.from).guid;
|
||||
String toId = lookup.get(sl.to).guid;
|
||||
|
||||
AttributesImpl attrs = new AttributesImpl();
|
||||
attrs.addAttribute(viewIdRef.getNamespaceURI(), viewIdRef.getLocalName(), viewIdRef.toPrefixString(), null, fromId);
|
||||
|
||||
writer.startElement(viewRef.getNamespaceURI(), viewRef.getLocalName(),
|
||||
viewRef.toPrefixString(namespaceService), attrs);
|
||||
|
||||
writer.startElement(viewAssociations.getNamespaceURI(), viewAssociations.getLocalName(), viewAssociations
|
||||
.toPrefixString(namespaceService), new AttributesImpl());
|
||||
|
||||
writer.startElement(ContentModel.ASSOC_MEMBER.getNamespaceURI(), ContentModel.ASSOC_MEMBER.getLocalName(),
|
||||
ContentModel.ASSOC_MEMBER.toPrefixString(namespaceService), new AttributesImpl());
|
||||
|
||||
AttributesImpl attrsRef = new AttributesImpl();
|
||||
attrsRef.addAttribute(viewIdRef.getNamespaceURI(), viewIdRef.getLocalName(), viewIdRef.toPrefixString(), null, toId);
|
||||
attrsRef.addAttribute(childQName.getNamespaceURI(), childQName.getLocalName(), childQName.toPrefixString(),
|
||||
null, QName.createQName(ContentModel.USER_MODEL_URI, sl.to).toPrefixString(namespaceService));
|
||||
|
||||
writer.startElement(viewRef.getNamespaceURI(), viewRef.getLocalName(),
|
||||
viewRef.toPrefixString(namespaceService), attrsRef);
|
||||
|
||||
writer.endElement(viewRef.getNamespaceURI(), viewRef.getLocalName(), viewRef.toPrefixString(namespaceService));
|
||||
|
||||
writer.endElement(ContentModel.ASSOC_MEMBER.getNamespaceURI(), ContentModel.ASSOC_MEMBER.getLocalName(),
|
||||
ContentModel.ASSOC_MEMBER.toPrefixString(namespaceService));
|
||||
|
||||
writer.endElement(viewAssociations.getNamespaceURI(), viewAssociations.getLocalName(), viewAssociations
|
||||
.toPrefixString(namespaceService));
|
||||
|
||||
writer.endElement(viewRef.getNamespaceURI(), viewRef.getLocalName(), viewRef.toPrefixString(namespaceService));
|
||||
|
||||
}
|
||||
|
||||
private void addRootGroup(HashMap<String, Group> lookup, Group group, XMLWriter writer) throws SAXException
|
||||
{
|
||||
|
||||
AttributesImpl attrs = new AttributesImpl();
|
||||
attrs.addAttribute(NamespaceService.REPOSITORY_VIEW_1_0_URI, childQName.getLocalName(), childQName
|
||||
.toPrefixString(), null, QName.createQName(ContentModel.USER_MODEL_URI, group.gid).toPrefixString(
|
||||
namespaceService));
|
||||
attrs.addAttribute(viewId.getNamespaceURI(), viewId.getLocalName(), viewId
|
||||
.toPrefixString(), null, group.guid);
|
||||
|
||||
writer.startElement(ContentModel.TYPE_AUTHORITY_CONTAINER.getNamespaceURI(),
|
||||
ContentModel.TYPE_AUTHORITY_CONTAINER.getLocalName(), ContentModel.TYPE_AUTHORITY_CONTAINER
|
||||
.toPrefixString(namespaceService), attrs);
|
||||
|
||||
writer.startElement(ContentModel.PROP_AUTHORITY_NAME.getNamespaceURI(), ContentModel.PROP_AUTHORITY_NAME
|
||||
.getLocalName(), ContentModel.PROP_AUTHORITY_NAME.toPrefixString(namespaceService),
|
||||
new AttributesImpl());
|
||||
|
||||
writer.characters(group.gid.toCharArray(), 0, group.gid.length());
|
||||
|
||||
writer.endElement(ContentModel.PROP_AUTHORITY_NAME.getNamespaceURI(), ContentModel.PROP_AUTHORITY_NAME
|
||||
.getLocalName(), ContentModel.PROP_AUTHORITY_NAME.toPrefixString(namespaceService));
|
||||
|
||||
if (group.members.size() > 0)
|
||||
{
|
||||
writer.startElement(ContentModel.PROP_MEMBERS.getNamespaceURI(), ContentModel.PROP_MEMBERS.getLocalName(),
|
||||
ContentModel.PROP_MEMBERS.toPrefixString(namespaceService), new AttributesImpl());
|
||||
|
||||
for (String member : group.members)
|
||||
{
|
||||
writer.startElement(viewValueQName.getNamespaceURI(), viewValueQName.getLocalName(), viewValueQName
|
||||
.toPrefixString(namespaceService), new AttributesImpl());
|
||||
|
||||
writer.characters(member.toCharArray(), 0, member.length());
|
||||
|
||||
writer.endElement(viewValueQName.getNamespaceURI(), viewValueQName.getLocalName(), viewValueQName
|
||||
.toPrefixString(namespaceService));
|
||||
}
|
||||
|
||||
writer.endElement(ContentModel.PROP_MEMBERS.getNamespaceURI(), ContentModel.PROP_MEMBERS.getLocalName(),
|
||||
ContentModel.PROP_MEMBERS.toPrefixString(namespaceService));
|
||||
}
|
||||
|
||||
for (Group child : group.children)
|
||||
{
|
||||
addgroup(lookup, child, writer);
|
||||
}
|
||||
|
||||
writer.endElement(ContentModel.TYPE_AUTHORITY_CONTAINER.getNamespaceURI(),
|
||||
ContentModel.TYPE_AUTHORITY_CONTAINER.getLocalName(), ContentModel.TYPE_AUTHORITY_CONTAINER
|
||||
.toPrefixString(namespaceService));
|
||||
|
||||
}
|
||||
|
||||
private void addgroup(HashMap<String, Group> lookup, Group group, XMLWriter writer) throws SAXException
|
||||
{
|
||||
AttributesImpl attrs = new AttributesImpl();
|
||||
|
||||
writer.startElement(ContentModel.ASSOC_MEMBER.getNamespaceURI(), ContentModel.ASSOC_MEMBER.getLocalName(),
|
||||
ContentModel.ASSOC_MEMBER.toPrefixString(namespaceService), attrs);
|
||||
|
||||
addRootGroup(lookup, group, writer);
|
||||
|
||||
writer.endElement(ContentModel.ASSOC_MEMBER.getNamespaceURI(), ContentModel.ASSOC_MEMBER.getLocalName(),
|
||||
ContentModel.ASSOC_MEMBER.toPrefixString(namespaceService));
|
||||
}
|
||||
|
||||
private void buildGroupsAndRoots(HashSet<Group> rootGroups, HashMap<String, Group> lookup,
|
||||
HashSet<SecondaryLink> secondaryLinks)
|
||||
{
|
||||
InitialDirContext ctx = null;
|
||||
try
|
||||
{
|
||||
ctx = ldapInitialContextFactory.getDefaultIntialDirContext();
|
||||
|
||||
SearchControls userSearchCtls = new SearchControls();
|
||||
userSearchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
|
||||
|
||||
NamingEnumeration searchResults = ctx.search(searchBase, groupQuery, userSearchCtls);
|
||||
while (searchResults.hasMoreElements())
|
||||
{
|
||||
SearchResult result = (SearchResult) searchResults.next();
|
||||
Attributes attributes = result.getAttributes();
|
||||
Attribute gidAttribute = attributes.get(groupIdAttributeName);
|
||||
if(gidAttribute == null)
|
||||
{
|
||||
throw new ExportSourceImporterException("Group returned by group search does not have mandatory group id attribute "+attributes);
|
||||
}
|
||||
String gid = (String) gidAttribute.get(0);
|
||||
|
||||
Group group = lookup.get(gid);
|
||||
if (group == null)
|
||||
{
|
||||
group = new Group(gid);
|
||||
lookup.put(group.gid, group);
|
||||
rootGroups.add(group);
|
||||
}
|
||||
Attribute memAttribute = attributes.get(memberAttribute);
|
||||
// check for null
|
||||
if (memAttribute != null)
|
||||
{
|
||||
for (int i = 0; i < memAttribute.size(); i++)
|
||||
{
|
||||
String attribute = (String) memAttribute.get(i);
|
||||
if (attribute != null)
|
||||
{
|
||||
group.distinguishedNames.add(attribute);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (s_logger.isDebugEnabled())
|
||||
{
|
||||
s_logger.debug("Found " + lookup.size());
|
||||
}
|
||||
|
||||
for (Group group : lookup.values())
|
||||
{
|
||||
if (s_logger.isDebugEnabled())
|
||||
{
|
||||
s_logger.debug("Linking " + group.gid);
|
||||
}
|
||||
for (String dn : group.distinguishedNames)
|
||||
{
|
||||
if (s_logger.isDebugEnabled())
|
||||
{
|
||||
s_logger.debug("... " + dn);
|
||||
}
|
||||
String id;
|
||||
Boolean isGroup = null;
|
||||
|
||||
SearchControls memberSearchCtls = new SearchControls();
|
||||
memberSearchCtls.setSearchScope(SearchControls.OBJECT_SCOPE);
|
||||
NamingEnumeration memberSearchResults;
|
||||
try
|
||||
{
|
||||
memberSearchResults = ctx.search(dn, "(objectClass=*)", memberSearchCtls);
|
||||
}
|
||||
catch (NamingException e)
|
||||
{
|
||||
if (errorOnMissingMembers)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
s_logger.warn("Failed to resolve distinguished name: " + dn);
|
||||
continue;
|
||||
}
|
||||
while (memberSearchResults.hasMoreElements())
|
||||
{
|
||||
id = null;
|
||||
|
||||
SearchResult result;
|
||||
try
|
||||
{
|
||||
result = (SearchResult) memberSearchResults.next();
|
||||
}
|
||||
catch (NamingException e)
|
||||
{
|
||||
if (errorOnMissingMembers)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
s_logger.warn("Failed to resolve distinguished name: " + dn);
|
||||
continue;
|
||||
}
|
||||
Attributes attributes = result.getAttributes();
|
||||
Attribute objectclass = attributes.get("objectclass");
|
||||
if(objectclass == null)
|
||||
{
|
||||
throw new ExportSourceImporterException("Failed to find attribute objectclass for DN "+dn);
|
||||
}
|
||||
for (int i = 0; i < objectclass.size(); i++)
|
||||
{
|
||||
String testType;
|
||||
try
|
||||
{
|
||||
testType = (String) objectclass.get(i);
|
||||
}
|
||||
catch (NamingException e)
|
||||
{
|
||||
if (errorOnMissingMembers)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
s_logger.warn("Failed to resolve object class attribute for distinguished name: " + dn);
|
||||
continue;
|
||||
}
|
||||
if (testType.equals(groupType))
|
||||
{
|
||||
isGroup = true;
|
||||
try
|
||||
{
|
||||
Attribute groupIdAttribute = attributes.get(groupIdAttributeName);
|
||||
if(groupIdAttribute == null)
|
||||
{
|
||||
throw new ExportSourceImporterException("Group missing group id attribute DN ="+dn + " att = "+groupIdAttributeName);
|
||||
}
|
||||
id = (String) groupIdAttribute.get(0);
|
||||
}
|
||||
catch (NamingException e)
|
||||
{
|
||||
if (errorOnMissingMembers)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
s_logger.warn("Failed to resolve group identifier "
|
||||
+ groupIdAttributeName + " for distinguished name: " + dn);
|
||||
id = "Unknown sub group";
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if (testType.equals(personType))
|
||||
{
|
||||
isGroup = false;
|
||||
try
|
||||
{
|
||||
Attribute userIdAttribute = attributes.get(userIdAttributeName);
|
||||
if(userIdAttribute == null)
|
||||
{
|
||||
throw new ExportSourceImporterException("User missing user id attribute DN ="+dn + " att = "+userIdAttributeName);
|
||||
}
|
||||
id = (String) userIdAttribute.get(0);
|
||||
}
|
||||
catch (NamingException e)
|
||||
{
|
||||
if (errorOnMissingMembers)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
s_logger.warn("Failed to resolve group identifier "
|
||||
+ userIdAttributeName + " for distinguished name: " + dn);
|
||||
id = "Unknown member";
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (id != null)
|
||||
{
|
||||
if (isGroup == null)
|
||||
{
|
||||
throw new ExportSourceImporterException("Type not recognised for DN"+dn);
|
||||
}
|
||||
else if (isGroup)
|
||||
{
|
||||
if (s_logger.isDebugEnabled())
|
||||
{
|
||||
s_logger.debug("... is sub group");
|
||||
}
|
||||
Group child = lookup.get("GROUP_" + id);
|
||||
if (child == null)
|
||||
{
|
||||
throw new ExportSourceImporterException("Failed to find child group " + id);
|
||||
}
|
||||
if (rootGroups.contains(child))
|
||||
{
|
||||
if (s_logger.isDebugEnabled())
|
||||
{
|
||||
s_logger.debug("... Primary created from "
|
||||
+ group.gid + " to " + child.gid);
|
||||
}
|
||||
group.children.add(child);
|
||||
rootGroups.remove(child);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (s_logger.isDebugEnabled())
|
||||
{
|
||||
s_logger.debug("... Secondary created from "
|
||||
+ group.gid + " to " + child.gid);
|
||||
}
|
||||
secondaryLinks.add(new SecondaryLink(group.gid, child.gid));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (s_logger.isDebugEnabled())
|
||||
{
|
||||
s_logger.debug("... is member");
|
||||
}
|
||||
group.members.add(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (s_logger.isDebugEnabled())
|
||||
{
|
||||
s_logger.debug("Top " + rootGroups.size());
|
||||
s_logger.debug("Secondary " + secondaryLinks.size());
|
||||
}
|
||||
}
|
||||
catch (NamingException e)
|
||||
{
|
||||
throw new ExportSourceImporterException("Failed to import people.", e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (ctx != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
ctx.close();
|
||||
}
|
||||
catch (NamingException e)
|
||||
{
|
||||
throw new ExportSourceImporterException("Failed to import people.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class Group
|
||||
{
|
||||
String gid;
|
||||
|
||||
String guid = GUID.generate();
|
||||
|
||||
HashSet<Group> children = new HashSet<Group>();
|
||||
|
||||
HashSet<String> members = new HashSet<String>();
|
||||
|
||||
HashSet<String> distinguishedNames = new HashSet<String>();
|
||||
|
||||
private Group(String gid)
|
||||
{
|
||||
this.gid = "GROUP_" + gid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
if (this == o)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (!(o instanceof Group))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
Group g = (Group) o;
|
||||
return this.gid.equals(g.gid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return gid.hashCode();
|
||||
}
|
||||
}
|
||||
|
||||
private static class SecondaryLink
|
||||
{
|
||||
String from;
|
||||
|
||||
String to;
|
||||
|
||||
private SecondaryLink(String from, String to)
|
||||
{
|
||||
this.from = from;
|
||||
this.to = to;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
if (this == o)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (!(o instanceof Group))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
SecondaryLink l = (SecondaryLink) o;
|
||||
return EqualsHelper.nullSafeEquals(this.from, l.from) && EqualsHelper.nullSafeEquals(this.to, l.to);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
int hashCode = 0;
|
||||
if (from != null)
|
||||
{
|
||||
hashCode = hashCode * 37 + from.hashCode();
|
||||
}
|
||||
if (to != null)
|
||||
{
|
||||
hashCode = hashCode * 37 + to.hashCode();
|
||||
}
|
||||
return hashCode;
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws IOException
|
||||
{
|
||||
ApplicationContext ctx = ApplicationContextHelper.getApplicationContext();
|
||||
ExportSource source = (ExportSource) ctx.getBean("ldapGroupExportSource");
|
||||
|
||||
File file = new File(args[0]);
|
||||
Writer writer = new BufferedWriter(new FileWriter(file));
|
||||
XMLWriter xmlWriter = createXMLExporter(writer);
|
||||
source.generateExport(xmlWriter);
|
||||
xmlWriter.close();
|
||||
|
||||
}
|
||||
|
||||
private static XMLWriter createXMLExporter(Writer writer)
|
||||
{
|
||||
// Define output format
|
||||
OutputFormat format = OutputFormat.createPrettyPrint();
|
||||
format.setNewLineAfterDeclaration(false);
|
||||
format.setIndentSize(3);
|
||||
format.setEncoding("UTF-8");
|
||||
|
||||
// Construct an XML Exporter
|
||||
|
||||
XMLWriter xmlWriter = new XMLWriter(writer, format);
|
||||
return xmlWriter;
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() throws Exception
|
||||
{
|
||||
viewRef = QName.createQName(NamespaceService.REPOSITORY_VIEW_PREFIX, "reference", namespaceService);
|
||||
viewId = QName.createQName(NamespaceService.REPOSITORY_VIEW_PREFIX, "id", namespaceService);
|
||||
viewIdRef = QName.createQName(NamespaceService.REPOSITORY_VIEW_PREFIX, "idref", namespaceService);
|
||||
viewAssociations = QName.createQName(NamespaceService.REPOSITORY_VIEW_PREFIX, "associations", namespaceService);
|
||||
childQName = QName.createQName(NamespaceService.REPOSITORY_VIEW_PREFIX, "childName", namespaceService);
|
||||
viewValueQName = QName.createQName(NamespaceService.REPOSITORY_VIEW_PREFIX, "value", namespaceService);
|
||||
|
||||
}
|
||||
}
|
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (C) 2005 Alfresco, Inc.
|
||||
*
|
||||
* Licensed under the Alfresco Network License. You may obtain a
|
||||
* copy of the License at
|
||||
*
|
||||
* http://www.alfrescosoftware.com/legal/
|
||||
*
|
||||
* Please view the license relevant to your network subscription.
|
||||
*
|
||||
* BY CLICKING THE "I UNDERSTAND AND ACCEPT" BOX, OR INSTALLING,
|
||||
* READING OR USING ALFRESCO'S Network SOFTWARE (THE "SOFTWARE"),
|
||||
* YOU ARE AGREEING ON BEHALF OF THE ENTITY LICENSING THE SOFTWARE
|
||||
* ("COMPANY") THAT COMPANY WILL BE BOUND BY AND IS BECOMING A PARTY TO
|
||||
* THIS ALFRESCO NETWORK AGREEMENT ("AGREEMENT") AND THAT YOU HAVE THE
|
||||
* AUTHORITY TO BIND COMPANY. IF COMPANY DOES NOT AGREE TO ALL OF THE
|
||||
* TERMS OF THIS AGREEMENT, DO NOT SELECT THE "I UNDERSTAND AND AGREE"
|
||||
* BOX AND DO NOT INSTALL THE SOFTWARE OR VIEW THE SOURCE CODE. COMPANY
|
||||
* HAS NOT BECOME A LICENSEE OF, AND IS NOT AUTHORIZED TO USE THE
|
||||
* SOFTWARE UNLESS AND UNTIL IT HAS AGREED TO BE BOUND BY THESE LICENSE
|
||||
* TERMS. THE "EFFECTIVE DATE" FOR THIS AGREEMENT SHALL BE THE DAY YOU
|
||||
* CHECK THE "I UNDERSTAND AND ACCEPT" BOX.
|
||||
*/
|
||||
package org.alfresco.repo.security.authentication.ldap;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.naming.directory.InitialDirContext;
|
||||
|
||||
import org.alfresco.repo.security.authentication.AuthenticationException;
|
||||
|
||||
/**
|
||||
* Interface that defines a factory for obtaining ldap directory contexts.
|
||||
*
|
||||
* @author Andy Hind
|
||||
*/
|
||||
public interface LDAPInitialDirContextFactory
|
||||
{
|
||||
/**
|
||||
* Set the LDAP environment Hashtable properties used ot initialise the LDAP connection.
|
||||
*
|
||||
* @param environment
|
||||
*/
|
||||
public void setInitialDirContextEnvironment(Map<String, String> environment);
|
||||
|
||||
/**
|
||||
* Use the environment properties and connect to the LDAP server.
|
||||
* Used to obtain read only access to the LDAP server.
|
||||
*
|
||||
* @return
|
||||
* @throws AuthenticationException
|
||||
*/
|
||||
public InitialDirContext getDefaultIntialDirContext() throws AuthenticationException;
|
||||
|
||||
/**
|
||||
* Augment the connection environment with the identity and credentials and bind to the ldap server.
|
||||
* Mainly used to validate a user's credentials during authentication.
|
||||
*
|
||||
* @param principal
|
||||
* @param credentials
|
||||
* @return
|
||||
* @throws AuthenticationException
|
||||
*/
|
||||
public InitialDirContext getInitialDirContext(String principal, String credentials) throws AuthenticationException;
|
||||
}
|
@@ -0,0 +1,197 @@
|
||||
/*
|
||||
* Copyright (C) 2005 Alfresco, Inc.
|
||||
*
|
||||
* Licensed under the Alfresco Network License. You may obtain a
|
||||
* copy of the License at
|
||||
*
|
||||
* http://www.alfrescosoftware.com/legal/
|
||||
*
|
||||
* Please view the license relevant to your network subscription.
|
||||
*
|
||||
* BY CLICKING THE "I UNDERSTAND AND ACCEPT" BOX, OR INSTALLING,
|
||||
* READING OR USING ALFRESCO'S Network SOFTWARE (THE "SOFTWARE"),
|
||||
* YOU ARE AGREEING ON BEHALF OF THE ENTITY LICENSING THE SOFTWARE
|
||||
* ("COMPANY") THAT COMPANY WILL BE BOUND BY AND IS BECOMING A PARTY TO
|
||||
* THIS ALFRESCO NETWORK AGREEMENT ("AGREEMENT") AND THAT YOU HAVE THE
|
||||
* AUTHORITY TO BIND COMPANY. IF COMPANY DOES NOT AGREE TO ALL OF THE
|
||||
* TERMS OF THIS AGREEMENT, DO NOT SELECT THE "I UNDERSTAND AND AGREE"
|
||||
* BOX AND DO NOT INSTALL THE SOFTWARE OR VIEW THE SOURCE CODE. COMPANY
|
||||
* HAS NOT BECOME A LICENSEE OF, AND IS NOT AUTHORIZED TO USE THE
|
||||
* SOFTWARE UNLESS AND UNTIL IT HAS AGREED TO BE BOUND BY THESE LICENSE
|
||||
* TERMS. THE "EFFECTIVE DATE" FOR THIS AGREEMENT SHALL BE THE DAY YOU
|
||||
* CHECK THE "I UNDERSTAND AND ACCEPT" BOX.
|
||||
*/
|
||||
package org.alfresco.repo.security.authentication.ldap;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.naming.Context;
|
||||
import javax.naming.NamingException;
|
||||
import javax.naming.directory.Attribute;
|
||||
import javax.naming.directory.Attributes;
|
||||
import javax.naming.directory.BasicAttribute;
|
||||
import javax.naming.directory.BasicAttributes;
|
||||
import javax.naming.directory.InitialDirContext;
|
||||
|
||||
import org.alfresco.repo.security.authentication.AuthenticationException;
|
||||
import org.alfresco.util.ApplicationContextHelper;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
|
||||
public class LDAPInitialDirContextFactoryImpl implements LDAPInitialDirContextFactory
|
||||
{
|
||||
private Map<String, String> initialDirContextEnvironment = Collections.<String, String> emptyMap();
|
||||
|
||||
static
|
||||
{
|
||||
System.setProperty("javax.security.auth.useSubjectCredentialsOnly", "false");
|
||||
}
|
||||
|
||||
public LDAPInitialDirContextFactoryImpl()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
public void setInitialDirContextEnvironment(Map<String, String> initialDirContextEnvironment)
|
||||
|
||||
{
|
||||
this.initialDirContextEnvironment = initialDirContextEnvironment;
|
||||
}
|
||||
|
||||
public Map<String, String> getInitialDirContextEnvironment()
|
||||
{
|
||||
return initialDirContextEnvironment;
|
||||
}
|
||||
|
||||
public InitialDirContext getDefaultIntialDirContext() throws AuthenticationException
|
||||
{
|
||||
Hashtable<String, String> env = new Hashtable<String, String>(initialDirContextEnvironment.size());
|
||||
env.putAll(initialDirContextEnvironment);
|
||||
env.put("javax.security.auth.useSubjectCredsOnly", "false");
|
||||
return buildInitialDirContext(env);
|
||||
}
|
||||
|
||||
private InitialDirContext buildInitialDirContext(Hashtable<String, String> env) throws AuthenticationException
|
||||
{
|
||||
try
|
||||
{
|
||||
return new InitialDirContext(env);
|
||||
}
|
||||
catch (javax.naming.AuthenticationException ax)
|
||||
{
|
||||
throw new AuthenticationException("LDAP authentication failed.", ax);
|
||||
}
|
||||
catch (NamingException nx)
|
||||
{
|
||||
throw new AuthenticationException("Unable to connect to LDAP Server; check LDAP configuration", nx);
|
||||
}
|
||||
}
|
||||
|
||||
public InitialDirContext getInitialDirContext(String principal, String credentials) throws AuthenticationException
|
||||
{
|
||||
if (principal == null)
|
||||
{
|
||||
throw new AuthenticationException("Null user name provided.");
|
||||
}
|
||||
|
||||
if (credentials == null)
|
||||
{
|
||||
throw new AuthenticationException("No credentials provided.");
|
||||
}
|
||||
Hashtable<String, String> env = new Hashtable<String, String>(initialDirContextEnvironment.size());
|
||||
env.putAll(initialDirContextEnvironment);
|
||||
env.put(Context.SECURITY_PRINCIPAL, principal);
|
||||
env.put(Context.SECURITY_CREDENTIALS, credentials);
|
||||
|
||||
return buildInitialDirContext(env);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
// ....build a pyramid selling scheme .....
|
||||
|
||||
// A group has three user members and 2 group members .... and off we go ....
|
||||
// We make the people and groups to represent this and stick them into LDAP ...used to populate a test data base for user and groups
|
||||
|
||||
int userMembers = Integer.parseInt(args[3]);
|
||||
|
||||
ApplicationContext applicationContext = ApplicationContextHelper.getApplicationContext();
|
||||
LDAPInitialDirContextFactory factory = (LDAPInitialDirContextFactory) applicationContext
|
||||
.getBean("ldapInitialDirContextFactory");
|
||||
|
||||
InitialDirContext ctx = null;
|
||||
try
|
||||
{
|
||||
ctx = factory.getInitialDirContext("cn=" + args[0] + "," + args[2], args[1]);
|
||||
|
||||
/* Values we'll use in creating the entry */
|
||||
Attribute objClasses = new BasicAttribute("objectclass");
|
||||
objClasses.add("top");
|
||||
objClasses.add("person");
|
||||
objClasses.add("organizationalPerson");
|
||||
objClasses.add("inetOrgPerson");
|
||||
|
||||
for (int i = 0; i < userMembers; i++)
|
||||
{
|
||||
|
||||
Attribute cn = new BasicAttribute("cn", "User" + i + " TestUser");
|
||||
Attribute sn = new BasicAttribute("sn", "TestUser");
|
||||
Attribute givenNames = new BasicAttribute("givenName", "User" + i);
|
||||
Attribute telephoneNumber = new BasicAttribute("telephoneNumber", "123");
|
||||
Attribute uid = new BasicAttribute("uid", "User" + i);
|
||||
Attribute mail = new BasicAttribute("mail", "woof@woof");
|
||||
Attribute o = new BasicAttribute("o", "Alfresco");
|
||||
Attribute userPassword = new BasicAttribute("userPassword", "bobbins");
|
||||
/* Specify the DN we're adding */
|
||||
String dn = "cn=User" + i + " TestUser," + args[2];
|
||||
|
||||
Attributes orig = new BasicAttributes();
|
||||
orig.put(objClasses);
|
||||
orig.put(cn);
|
||||
orig.put(sn);
|
||||
orig.put(givenNames);
|
||||
orig.put(telephoneNumber);
|
||||
orig.put(uid);
|
||||
orig.put(mail);
|
||||
orig.put(o);
|
||||
orig.put(userPassword);
|
||||
|
||||
try
|
||||
{
|
||||
ctx.destroySubcontext(dn);
|
||||
}
|
||||
catch (NamingException e)
|
||||
{
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
ctx.createSubcontext(dn, orig);
|
||||
}
|
||||
|
||||
}
|
||||
catch (NamingException e)
|
||||
{
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (ctx != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
ctx.close();
|
||||
}
|
||||
catch (NamingException e)
|
||||
{
|
||||
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,328 @@
|
||||
/*
|
||||
* Copyright (C) 2005 Alfresco, Inc.
|
||||
*
|
||||
* Licensed under the Alfresco Network License. You may obtain a
|
||||
* copy of the License at
|
||||
*
|
||||
* http://www.alfrescosoftware.com/legal/
|
||||
*
|
||||
* Please view the license relevant to your network subscription.
|
||||
*
|
||||
* BY CLICKING THE "I UNDERSTAND AND ACCEPT" BOX, OR INSTALLING,
|
||||
* READING OR USING ALFRESCO'S Network SOFTWARE (THE "SOFTWARE"),
|
||||
* YOU ARE AGREEING ON BEHALF OF THE ENTITY LICENSING THE SOFTWARE
|
||||
* ("COMPANY") THAT COMPANY WILL BE BOUND BY AND IS BECOMING A PARTY TO
|
||||
* THIS ALFRESCO NETWORK AGREEMENT ("AGREEMENT") AND THAT YOU HAVE THE
|
||||
* AUTHORITY TO BIND COMPANY. IF COMPANY DOES NOT AGREE TO ALL OF THE
|
||||
* TERMS OF THIS AGREEMENT, DO NOT SELECT THE "I UNDERSTAND AND AGREE"
|
||||
* BOX AND DO NOT INSTALL THE SOFTWARE OR VIEW THE SOURCE CODE. COMPANY
|
||||
* HAS NOT BECOME A LICENSEE OF, AND IS NOT AUTHORIZED TO USE THE
|
||||
* SOFTWARE UNLESS AND UNTIL IT HAS AGREED TO BE BOUND BY THESE LICENSE
|
||||
* TERMS. THE "EFFECTIVE DATE" FOR THIS AGREEMENT SHALL BE THE DAY YOU
|
||||
* CHECK THE "I UNDERSTAND AND ACCEPT" BOX.
|
||||
*/
|
||||
package org.alfresco.repo.security.authentication.ldap;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.naming.NamingEnumeration;
|
||||
import javax.naming.NamingException;
|
||||
import javax.naming.directory.Attribute;
|
||||
import javax.naming.directory.Attributes;
|
||||
import javax.naming.directory.InitialDirContext;
|
||||
import javax.naming.directory.SearchControls;
|
||||
import javax.naming.directory.SearchResult;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.importer.ExportSource;
|
||||
import org.alfresco.repo.importer.ExportSourceImporterException;
|
||||
import org.alfresco.service.cmr.security.PersonService;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.util.ApplicationContextHelper;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.dom4j.io.OutputFormat;
|
||||
import org.dom4j.io.XMLWriter;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.helpers.AttributesImpl;
|
||||
|
||||
public class LDAPPersonExportSource implements ExportSource
|
||||
{
|
||||
private static Log s_logger = LogFactory.getLog(LDAPPersonExportSource.class);
|
||||
|
||||
private String personQuery = "(objectclass=inetOrgPerson)";
|
||||
|
||||
private String searchBase;
|
||||
|
||||
private String userIdAttributeName;
|
||||
|
||||
private LDAPInitialDirContextFactory ldapInitialContextFactory;
|
||||
|
||||
private PersonService personService;
|
||||
|
||||
private Map<String, String> attributeMapping;
|
||||
|
||||
private NamespaceService namespaceService;
|
||||
|
||||
private String defaultHomeFolder;
|
||||
|
||||
public LDAPPersonExportSource()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
public void setPersonQuery(String personQuery)
|
||||
{
|
||||
this.personQuery = personQuery;
|
||||
}
|
||||
|
||||
public void setSearchBase(String searchBase)
|
||||
{
|
||||
this.searchBase = searchBase;
|
||||
}
|
||||
|
||||
public void setUserIdAttributeName(String userIdAttributeName)
|
||||
{
|
||||
this.userIdAttributeName = userIdAttributeName;
|
||||
}
|
||||
|
||||
public void setLDAPInitialDirContextFactory(LDAPInitialDirContextFactory ldapInitialDirContextFactory)
|
||||
{
|
||||
this.ldapInitialContextFactory = ldapInitialDirContextFactory;
|
||||
}
|
||||
|
||||
public void setPersonService(PersonService personService)
|
||||
{
|
||||
this.personService = personService;
|
||||
}
|
||||
|
||||
public void setDefaultHomeFolder(String defaultHomeFolder)
|
||||
{
|
||||
this.defaultHomeFolder = defaultHomeFolder;
|
||||
}
|
||||
|
||||
public void setNamespaceService(NamespaceService namespaceService)
|
||||
{
|
||||
this.namespaceService = namespaceService;
|
||||
}
|
||||
|
||||
public void setAttributeMapping(Map<String, String> attributeMapping)
|
||||
{
|
||||
this.attributeMapping = attributeMapping;
|
||||
}
|
||||
|
||||
public void generateExport(XMLWriter writer)
|
||||
{
|
||||
QName nodeUUID = QName.createQName("sys:node-uuid", namespaceService);
|
||||
|
||||
Collection<String> prefixes = namespaceService.getPrefixes();
|
||||
QName childQName = QName.createQName(NamespaceService.REPOSITORY_VIEW_PREFIX, "childName", namespaceService);
|
||||
|
||||
try
|
||||
{
|
||||
AttributesImpl attrs = new AttributesImpl();
|
||||
attrs.addAttribute(NamespaceService.REPOSITORY_VIEW_1_0_URI, childQName.getLocalName(), childQName
|
||||
.toPrefixString(), null, ContentModel.TYPE_PERSON.toPrefixString(namespaceService));
|
||||
|
||||
writer.startDocument();
|
||||
|
||||
for (String prefix : prefixes)
|
||||
{
|
||||
if (!prefix.equals("xml"))
|
||||
{
|
||||
String uri = namespaceService.getNamespaceURI(prefix);
|
||||
writer.startPrefixMapping(prefix, uri);
|
||||
}
|
||||
}
|
||||
|
||||
writer.startElement(NamespaceService.REPOSITORY_VIEW_PREFIX, "view",
|
||||
NamespaceService.REPOSITORY_VIEW_PREFIX + ":" + "view", new AttributesImpl());
|
||||
|
||||
InitialDirContext ctx = null;
|
||||
try
|
||||
{
|
||||
ctx = ldapInitialContextFactory.getDefaultIntialDirContext();
|
||||
|
||||
// Authentication has been successful.
|
||||
// Set the current user, they are now authenticated.
|
||||
|
||||
SearchControls userSearchCtls = new SearchControls();
|
||||
userSearchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
|
||||
System.out.println("COUNT "+userSearchCtls.getCountLimit());
|
||||
System.out.println("TIME "+userSearchCtls.getTimeLimit());
|
||||
userSearchCtls.setCountLimit(Integer.MAX_VALUE);
|
||||
|
||||
NamingEnumeration searchResults = ctx.search(searchBase, personQuery, userSearchCtls);
|
||||
while (searchResults.hasMoreElements())
|
||||
{
|
||||
SearchResult result = (SearchResult) searchResults.next();
|
||||
Attributes attributes = result.getAttributes();
|
||||
Attribute uidAttribute = attributes.get(userIdAttributeName);
|
||||
String uid = (String) uidAttribute.get(0);
|
||||
|
||||
if(s_logger.isDebugEnabled())
|
||||
{
|
||||
s_logger.debug("Adding user for "+uid);
|
||||
}
|
||||
System.out.println("User "+uid);
|
||||
|
||||
writer.startElement(ContentModel.TYPE_PERSON.getNamespaceURI(), ContentModel.TYPE_PERSON
|
||||
.getLocalName(), ContentModel.TYPE_PERSON.toPrefixString(namespaceService), attrs);
|
||||
|
||||
// permissions
|
||||
|
||||
// owner
|
||||
|
||||
writer.startElement(ContentModel.ASPECT_OWNABLE.getNamespaceURI(), ContentModel.ASPECT_OWNABLE
|
||||
.getLocalName(), ContentModel.ASPECT_OWNABLE.toPrefixString(namespaceService),
|
||||
new AttributesImpl());
|
||||
|
||||
writer.endElement(ContentModel.ASPECT_OWNABLE.getNamespaceURI(), ContentModel.ASPECT_OWNABLE
|
||||
.getLocalName(), ContentModel.ASPECT_OWNABLE.toPrefixString(namespaceService));
|
||||
|
||||
writer.startElement(ContentModel.PROP_OWNER.getNamespaceURI(), ContentModel.PROP_OWNER
|
||||
.getLocalName(), ContentModel.PROP_OWNER.toPrefixString(namespaceService),
|
||||
new AttributesImpl());
|
||||
|
||||
writer.characters(uid.toCharArray(), 0, uid.length());
|
||||
|
||||
writer.endElement(ContentModel.PROP_OWNER.getNamespaceURI(),
|
||||
ContentModel.PROP_OWNER.getLocalName(), ContentModel.PROP_OWNER
|
||||
.toPrefixString(namespaceService));
|
||||
|
||||
for (String key : attributeMapping.keySet())
|
||||
{
|
||||
QName keyQName = QName.createQName(key, namespaceService);
|
||||
|
||||
writer.startElement(keyQName.getNamespaceURI(), keyQName.getLocalName(), keyQName
|
||||
.toPrefixString(namespaceService), new AttributesImpl());
|
||||
|
||||
// cater for null
|
||||
String attribute = attributeMapping.get(key);
|
||||
if (attribute != null)
|
||||
{
|
||||
String value = (String) attributes.get(attribute).get(0);
|
||||
if (value != null)
|
||||
{
|
||||
writer.characters(value.toCharArray(), 0, value.length());
|
||||
}
|
||||
}
|
||||
|
||||
writer.endElement(keyQName.getNamespaceURI(), keyQName.getLocalName(), keyQName
|
||||
.toPrefixString(namespaceService));
|
||||
}
|
||||
|
||||
// Default home folder
|
||||
|
||||
if (!(attributeMapping.keySet().contains(ContentModel.PROP_HOMEFOLDER.toString()) || attributeMapping
|
||||
.keySet().contains(ContentModel.PROP_HOMEFOLDER.toPrefixString(namespaceService))))
|
||||
{
|
||||
// Only if we are creating the person for the first time
|
||||
if (!personService.personExists(uid))
|
||||
{
|
||||
writer.startElement(ContentModel.PROP_HOMEFOLDER.getNamespaceURI(),
|
||||
ContentModel.PROP_HOMEFOLDER.getLocalName(), ContentModel.PROP_HOMEFOLDER
|
||||
.toPrefixString(namespaceService), new AttributesImpl());
|
||||
|
||||
if (defaultHomeFolder != null)
|
||||
{
|
||||
writer.characters(defaultHomeFolder.toCharArray(), 0, defaultHomeFolder.length());
|
||||
}
|
||||
|
||||
writer.endElement(ContentModel.PROP_HOMEFOLDER.getNamespaceURI(),
|
||||
ContentModel.PROP_HOMEFOLDER.getLocalName(), ContentModel.PROP_HOMEFOLDER
|
||||
.toPrefixString(namespaceService));
|
||||
}
|
||||
}
|
||||
|
||||
if (personService.personExists(uid))
|
||||
{
|
||||
String uguid = personService.getPerson(uid).getId();
|
||||
|
||||
writer.startElement(nodeUUID.getNamespaceURI(), nodeUUID.getLocalName(), nodeUUID
|
||||
.toPrefixString(namespaceService), new AttributesImpl());
|
||||
|
||||
writer.characters(uguid.toCharArray(), 0, uguid.length());
|
||||
|
||||
writer.endElement(nodeUUID.getNamespaceURI(), nodeUUID.getLocalName(), nodeUUID
|
||||
.toPrefixString(namespaceService));
|
||||
}
|
||||
writer.endElement(ContentModel.TYPE_PERSON.getNamespaceURI(), ContentModel.TYPE_PERSON
|
||||
.getLocalName(), ContentModel.TYPE_PERSON.toPrefixString(namespaceService));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
catch (NamingException e)
|
||||
{
|
||||
throw new ExportSourceImporterException("Failed to import people.", e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (ctx != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
ctx.close();
|
||||
}
|
||||
catch (NamingException e)
|
||||
{
|
||||
throw new ExportSourceImporterException("Failed to import people.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (String prefix : prefixes)
|
||||
{
|
||||
if (!prefix.equals("xml"))
|
||||
{
|
||||
writer.endPrefixMapping(prefix);
|
||||
}
|
||||
}
|
||||
|
||||
writer.endElement(NamespaceService.REPOSITORY_VIEW_PREFIX, "view", NamespaceService.REPOSITORY_VIEW_PREFIX
|
||||
+ ":" + "view");
|
||||
|
||||
writer.endDocument();
|
||||
}
|
||||
catch (SAXException e)
|
||||
{
|
||||
throw new ExportSourceImporterException("Failed to create file for import.", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws IOException
|
||||
{
|
||||
ApplicationContext ctx = ApplicationContextHelper.getApplicationContext();
|
||||
ExportSource source = (ExportSource) ctx.getBean("ldapPeopleExportSource");
|
||||
|
||||
File file = new File(args[0]);
|
||||
Writer writer = new BufferedWriter(new FileWriter(file));
|
||||
XMLWriter xmlWriter = createXMLExporter(writer);
|
||||
source.generateExport(xmlWriter);
|
||||
xmlWriter.close();
|
||||
|
||||
}
|
||||
|
||||
private static XMLWriter createXMLExporter(Writer writer)
|
||||
{
|
||||
// Define output format
|
||||
OutputFormat format = OutputFormat.createPrettyPrint();
|
||||
format.setNewLineAfterDeclaration(false);
|
||||
format.setIndentSize(3);
|
||||
format.setEncoding("UTF-8");
|
||||
|
||||
// Construct an XML Exporter
|
||||
|
||||
XMLWriter xmlWriter = new XMLWriter(writer, format);
|
||||
return xmlWriter;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user