Package org.apache.marmotta.ldclient.provider.ldap

Source Code of org.apache.marmotta.ldclient.provider.ldap.LdapFoafProvider

/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.marmotta.ldclient.provider.ldap;

import java.io.IOException;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.directory.api.ldap.model.cursor.CursorException;
import org.apache.directory.api.ldap.model.cursor.EntryCursor;
import org.apache.directory.api.ldap.model.entry.Attribute;
import org.apache.directory.api.ldap.model.entry.Entry;
import org.apache.directory.api.ldap.model.exception.LdapException;
import org.apache.directory.api.ldap.model.message.SearchScope;
import org.apache.directory.api.ldap.model.name.Dn;
import org.apache.directory.ldap.client.api.LdapConnection;
import org.apache.directory.ldap.client.api.LdapConnectionConfig;
import org.apache.directory.ldap.client.api.LdapNetworkConnection;
import org.apache.marmotta.commons.constants.Namespace;
import org.apache.marmotta.ldclient.api.endpoint.Endpoint;
import org.apache.marmotta.ldclient.api.ldclient.LDClientService;
import org.apache.marmotta.ldclient.api.provider.DataProvider;
import org.apache.marmotta.ldclient.exception.DataRetrievalException;
import org.apache.marmotta.ldclient.model.ClientResponse;
import org.apache.marmotta.ldclient.provider.ldap.mapping.LiteralPredicateFactory;
import org.apache.marmotta.ldclient.provider.ldap.mapping.PredicateObjectFactory;
import org.apache.marmotta.ldclient.provider.ldap.mapping.UriPredicateFactory;
import org.openrdf.model.URI;
import org.openrdf.model.Value;
import org.openrdf.model.ValueFactory;
import org.openrdf.repository.Repository;
import org.openrdf.repository.RepositoryConnection;
import org.openrdf.repository.RepositoryException;
import org.openrdf.repository.sail.SailRepository;
import org.openrdf.sail.memory.MemoryStore;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* LdapFoafProvider maps LDAP accounts to foaf:Person instances
*
* @author Daniel Trabe <daniel.trabe@salzburgresearch.at>
* @author Jakob Frank <jakob.frank@salzburgresearch.at>
* @author Sergio  Fernández <wikier@apache.org>
*
*/
public class LdapFoafProvider implements DataProvider {
 
    public static final String PROVIDER_NAME = "LDAP";

    private static Logger log = LoggerFactory.getLogger(LdapFoafProvider.class);

    /**
     * Mapping for the Attributes in the LDAP-Directory
     */
    private static final Map<String, PredicateObjectFactory> MAPPING;
    static {
        Map<String, PredicateObjectFactory> m = new HashMap<String, PredicateObjectFactory>();
        m.put("distinguishedName", new LiteralPredicateFactory(Namespace.DCTERMS.identifier));
        m.put("name", new LiteralPredicateFactory(Namespace.FOAF.name));
        m.put("givenName", new LiteralPredicateFactory(Namespace.FOAF.firstName));
        m.put("sn", new LiteralPredicateFactory(Namespace.FOAF.surname));
        m.put("mail", new UriPredicateFactory(Namespace.FOAF.mbox) {
            @Override
            public Set<Value> createObjects(String value, ValueFactory valueFactory) {
                return super.createObjects("mailto:" + value, valueFactory);
            }
        });
        m.put("objectClass", new UriPredicateFactory(Namespace.RDF.type) {
            @Override
            public Set<Value> createObjects(String value, ValueFactory valueFactory) {
                if (value.equalsIgnoreCase("person"))
                    return super.createObjects(Namespace.FOAF.Person, valueFactory);
                else
                    return Collections.emptySet();
            }
        });

        MAPPING = Collections.unmodifiableMap(m);
    }

    @Override
    public String getName() {
        return "LdapFoafProvider";
    }

    @Override
    public String[] listMimeTypes() {
        return new String[] {};
    }

    /**
     * Opens a connection tho the LDAP-server. in most cases an Account + Password is needed to
     * connect
     * to the Server. This need to be configured at the endpoint
     *
     * @param endpoint
     * @return
     * @throws LDAPException if connecting failed.
     * @throws DataRetrievalException
     */
    private LdapConnection openLdapConnection(Endpoint endpoint) throws DataRetrievalException {
        java.net.URI u;
    try {
      u = new java.net.URI(endpoint.getEndpointUrl());
    } catch (URISyntaxException e) {
      throw new DataRetrievalException("Invalid enpooint URI", e);
    }
    LdapConnectionConfig config = new LdapConnectionConfig();
    config.setLdapHost(u.getHost());
    config.setLdapPort(u.getPort() > 0 ? u.getPort() : 389);
    if (endpoint.hasProperty("loginDN")) {
      config.setName(endpoint.getProperty("loginDN"));
    }
    if (endpoint.hasProperty("loginPW")) {
      config.setName(endpoint.getProperty("loginPW"));
    }
        LdapNetworkConnection connection = new LdapNetworkConnection(config);
        try {
      connection.bind();
    } catch (Exception e) {
      throw new DataRetrievalException("LDAP connnection could not be bind", e);
    }
        if (connection.isAuthenticated()) {
          return connection;
        } else {
          throw new DataRetrievalException("LDAP connnection could not be stablished");
        }

    }

    @Override
    public ClientResponse retrieveResource(String resource, LDClientService client, Endpoint endpoint) throws DataRetrievalException {
        String account = java.net.URI.create(resource.replaceAll(" ", "%20")).getPath().substring(1);
        String prefix = getEndpointSuffix(endpoint);
        try {
            final LdapConnection ldap = openLdapConnection(endpoint);

            Repository rep = new SailRepository(new MemoryStore());
            rep.initialize();

            RepositoryConnection conn = rep.getConnection();
            try {
                ValueFactory vf = conn.getValueFactory();
                String userDN = buildDN(prefix, account, ldap);

                Map<String, java.util.List<String>> accountData = getAccountData(userDN, ldap);

                final URI subject = vf.createURI(resource);
                for (String attr : MAPPING.keySet()) {
                    if (!accountData.containsKey(attr)) {
                        continue;
                    }

                    final PredicateObjectFactory factory = MAPPING.get(attr);
                    final URI predicate = factory.createPredicate(vf);

                    for (String val : accountData.get(attr)) {
                        for (Value object : factory.createObjects(val, vf)) {
                            conn.add(vf.createStatement(subject, predicate, object));
                        }
                    }

                }

                final ClientResponse resp = new ClientResponse(200, rep);
                resp.setExpires(new Date());
                return resp;

            } catch (Exception e) {
        throw new DataRetrievalException(e);
      } finally {
                conn.close();
            }
        } catch (RepositoryException e1) {
            log.warn("Could not create SailRep: {}", e1.getMessage());
            throw new DataRetrievalException(e1);
        }
    }

    /**
     * Returns the suffix (e.g. "dc=salzburgresearch,dc=at" of the Endpoint. This suffix is needed
     * to perform
     * miscellaneous LDAP-Operations
     *
     * @param endpoint
     * @return
     * @throws DataRetrievalException when Config of LDAP-Suffix for endpoint is invalid
     */
    private String getEndpointSuffix(Endpoint endpoint) throws DataRetrievalException {
        try {
            java.net.URI u;
            u = new java.net.URI(endpoint.getEndpointUrl());
            return u.getPath() != null ? u.getPath().substring(1) : "";
        } catch (URISyntaxException e) {
            throw new DataRetrievalException("Invalid LDAP-Suffix config for endpoint '" + endpoint.getName() + "'!");
        }
    }

    /**
     * Builds an distinguished name which is needed for many LDAP operations based
     * on the URL we get from the resource.
     * (e.g "/SRFG/USERS/Daniel%20Trabe" ==>
     * "cn=Daniel  Trabe,ou=USERS,ou=SRFG,dc=salzburgresearch,dc=at")
     *
     * @param suffix the LDAP-Suffix configured at the Endpoint
     * @param path part of the URL (e.g. /SRFG/USERS/DanielTrabe)
     * @param con an initialized LDAP-Context
     * @return the distinguished name of an Entry in the LDAP
     * @throws LDAPException if there is a problem with the LDAP connection
     * @throws DataRetrievalException when the Entry cannot be found
     */
    private String buildDN(String suffix, String path, LdapConnection con) throws DataRetrievalException {
        if (path.length() == 0) return suffix;

        String current = path.split("/")[0];

        List<String> data;
    try {
      data = getChildList(suffix, con);
    } catch (Exception e) {
      log.error("Error getting childs: {}", e.getMessage(), e);
      throw new DataRetrievalException(e);
    }
        String next = null;
        for (String dn : data) {
            if (dn.toLowerCase().endsWith((current + "," + suffix).toLowerCase())) {
                next = dn;
                break;
            }
        }

        if (next == null) throw new DataRetrievalException("The Object '" + current + "' cannot be found");

        return buildDN(next, path.replaceFirst("^[^/]*(/|$)", ""), con);
    }

    /**
     * Get child list
     *
     * @param entryDN The distinguished name of an Entry in the LDAP
     * @param con An initialized LDAP-Context
     * @return All child's of an Entry
     * @throws IOException
     * @throws CursorException
     * @throws LdapException
     * @throws LDAPSearchException
     */
    private List<String> getChildList(String entryDN, LdapConnection connection) throws CursorException, IOException, LdapException {
        List<String> childs = new ArrayList<String>();

        EntryCursor cursor = connection.search("ou=system", "(objectclass=*)", SearchScope.ONELEVEL);
        while (cursor.next()) {
            Entry entry = cursor.get();
            childs.add(entry.get("distinguishedName").getString());
        }

        //SearchResultDone done = cursor.getSearchResultDone();
        //ResultCodeEnum resultCode = done.getLdapResult().getResultCode();
        cursor.close();
        // ResultCodeEnum.SUCCESS == resultCode
        return childs;
    }

    /**
     * Get account data
     *
     * @param accountDN The distinguished Name of the Account (e.g
     *            "cn=Daniel  Trabe,ou=USERS,ou=SRFG,dc=salzburgresearch,dc=at")
     * @param connection An initialized LDAP-Context
     * @return a Map of Attributes and Values of an Account
     * @throws DataRetrievalException
     * @throws IOException
     * @throws CursorException
     * @throws LdapException
     * @throws LDAPException
     */
    private Map<String, List<String>> getAccountData(String accountDN, LdapConnection connection) throws DataRetrievalException, LdapException, CursorException, IOException {
        Map<String, List<String>> account = new HashMap<String, List<String>>();
        Dn dn = new Dn(accountDN);
        EntryCursor cursor = connection.search(dn, accountDN, SearchScope.ONELEVEL, (String[])null);
        if (cursor.next()) {
          //FIXME: only the first entry?
            Entry entry = cursor.get();
            for (Attribute attr : entry.getAttributes()) {
                String id = attr.getId();
              List<String> values;
                if (account.containsKey(id)) {
                  values = account.get(id)
                } else {
                  values = new ArrayList<String>();
                }
                values.add(attr.get().getValue().toString());
                account.put(id, values);
            }
        }
        return account;
    }

}
TOP

Related Classes of org.apache.marmotta.ldclient.provider.ldap.LdapFoafProvider

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.