| | |
| | | <?xml version="1.0"?> |
| | | <!-- |
| | | ! CDDL HEADER START |
| | | ! |
| | | ! The contents of this file are subject to the terms of the |
| | | ! Common Development and Distribution License, Version 1.0 only |
| | | ! (the "License"). You may not use this file except in compliance |
| | | ! with the License. |
| | | ! |
| | | ! You can obtain a copy of the license at legal-notices/CDDLv1_0.txt |
| | | ! or http://forgerock.org/license/CDDLv1.0.html. |
| | | ! See the License for the specific language governing permissions |
| | | ! and limitations under the License. |
| | | ! |
| | | ! When distributing Covered Code, include this CDDL HEADER in each |
| | | ! file and include the License file at legal-notices/CDDLv1_0.txt. |
| | | ! If applicable, add the following below this CDDL HEADER, with the |
| | | ! fields enclosed by brackets "[]" replaced with your own identifying |
| | | ! information: |
| | | ! Portions Copyright [yyyy] [name of copyright owner] |
| | | ! |
| | | ! CDDL HEADER END |
| | | ! |
| | | ! Copyright 2012 ForgeRock AS |
| | | ! |
| | | The contents of this file are subject to the terms of the Common Development and |
| | | Distribution License (the License). You may not use this file except in compliance with the |
| | | License. |
| | | |
| | | You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | specific language governing permission and limitations under the License. |
| | | |
| | | When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | information: "Portions Copyright [year] [name of copyright owner]". |
| | | |
| | | Copyright 2012 ForgeRock AS. |
| | | --> |
| | | <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
| | | xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
| | |
| | | <packaging>jar</packaging> |
| | | <properties> |
| | | <forgerockRestVersion>2.0.0-SNAPSHOT</forgerockRestVersion> |
| | | <checkstyleHeaderLocation>org/forgerock/checkstyle/default-java-header</checkstyleHeaderLocation> |
| | | </properties> |
| | | <dependencies> |
| | | <dependency> |
| | |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyrighted [year] [name of copyright owner]". |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2012 ForgeRock AS. All rights reserved. |
| | | * Copyright 2012 ForgeRock AS. |
| | | */ |
| | | |
| | | package org.forgerock.opendj.rest2ldap; |
| | | |
| | | import java.util.List; |
| | |
| | | * @param h |
| | | * The result handler. |
| | | */ |
| | | void toJson(ServerContext c, Entry e, ResultHandler<Map<String, Object>> h); |
| | | void toJSON(ServerContext c, Entry e, ResultHandler<Map<String, Object>> h); |
| | | |
| | | /** |
| | | * Transforms JSON content in the provided JSON value to LDAP attributes, |
| | |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyrighted [year] [name of copyright owner]". |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2012 ForgeRock AS. All rights reserved. |
| | | * Copyright 2012 ForgeRock AS. |
| | | */ |
| | | |
| | | package org.forgerock.opendj.rest2ldap; |
| | | |
| | | import static org.forgerock.opendj.rest2ldap.Utils.toLowerCase; |
| | |
| | | |
| | | import org.forgerock.json.fluent.JsonPointer; |
| | | import org.forgerock.json.fluent.JsonValue; |
| | | import org.forgerock.json.resource.ResourceException; |
| | | import org.forgerock.json.resource.ResultHandler; |
| | | import org.forgerock.json.resource.ServerContext; |
| | | import org.forgerock.json.resource.ResourceException; |
| | | import org.forgerock.opendj.ldap.Attribute; |
| | | import org.forgerock.opendj.ldap.Entry; |
| | | |
| | | /** |
| | | * An attribute mapper which will wrap the results of the provided mapper as a |
| | | * complex JSON object. |
| | | * An attribute mapper which maps a single JSON attribute to the result of |
| | | * another attribute mapper. |
| | | */ |
| | | public class ComplexAttributeMapper implements AttributeMapper { |
| | | |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public void getLDAPAttributes(final JsonPointer jsonAttribute, final Set<String> ldapAttributes) { |
| | | if (attributeMatchesPointer(jsonAttribute)) { |
| | | final JsonPointer relativePointer = jsonAttribute.relativePointer(); |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public void toJson(final ServerContext c, final Entry e, |
| | | @Override |
| | | public void toJSON(final ServerContext c, final Entry e, |
| | | final ResultHandler<Map<String, Object>> h) { |
| | | final ResultHandler<Map<String, Object>> wrapper = new ResultHandler<Map<String, Object>>() { |
| | | |
| | | @Override |
| | | public void handleError(final ResourceException e) { |
| | | h.handleError(e); |
| | | } |
| | | |
| | | @Override |
| | | public void handleResult(final Map<String, Object> result) { |
| | | final Map<String, Object> complexResult = Collections.singletonMap( |
| | | jsonAttributeName, (Object) result); |
| | | h.handleResult(complexResult); |
| | | } |
| | | }; |
| | | mapper.toJson(c, e, wrapper); |
| | | mapper.toJSON(c, e, wrapper); |
| | | } |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public void toLDAP(final ServerContext c, final JsonValue v, |
| | | final ResultHandler<List<Attribute>> h) { |
| | | // TODO Auto-generated method stub |
| | |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyrighted [year] [name of copyright owner]". |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2012 ForgeRock AS. All rights reserved. |
| | | * Copyright 2012 ForgeRock AS. |
| | | */ |
| | | |
| | | package org.forgerock.opendj.rest2ldap; |
| | | |
| | | import java.util.ArrayList; |
| | |
| | | |
| | | import org.forgerock.json.fluent.JsonPointer; |
| | | import org.forgerock.json.fluent.JsonValue; |
| | | import org.forgerock.json.resource.ResourceException; |
| | | import org.forgerock.json.resource.ResultHandler; |
| | | import org.forgerock.json.resource.ServerContext; |
| | | import org.forgerock.json.resource.ResourceException; |
| | | import org.forgerock.opendj.ldap.Attribute; |
| | | import org.forgerock.opendj.ldap.Entry; |
| | | |
| | | /** |
| | | * A collection of one or more attribute mappers whose content will be combined |
| | | * into a single JSON array. |
| | | * An attribute mapper which combines the results of a set of subordinate |
| | | * attribute mappers into a single JSON object. |
| | | */ |
| | | public final class CompositeAttributeMapper implements AttributeMapper { |
| | | private final List<AttributeMapper> attributeMappers = new LinkedList<AttributeMapper>(); |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public void getLDAPAttributes(final JsonPointer jsonAttribute, final Set<String> ldapAttributes) { |
| | | for (final AttributeMapper attribute : attributeMappers) { |
| | | attribute.getLDAPAttributes(jsonAttribute, ldapAttributes); |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public void toJson(final ServerContext c, final Entry e, |
| | | @Override |
| | | public void toJSON(final ServerContext c, final Entry e, |
| | | final ResultHandler<Map<String, Object>> h) { |
| | | final ResultHandler<Map<String, Object>> resultAccumulater = new ResultHandler<Map<String, Object>>() { |
| | | private final AtomicInteger latch = new AtomicInteger(attributeMappers.size()); |
| | | private final List<Map<String, Object>> results = new ArrayList<Map<String, Object>>( |
| | | latch.get()); |
| | | |
| | | @Override |
| | | public void handleError(final ResourceException e) { |
| | | // Ensure that handler is only invoked once. |
| | | if (latch.getAndSet(0) > 0) { |
| | |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public void handleResult(final Map<String, Object> result) { |
| | | if (result != null && !result.isEmpty()) { |
| | | synchronized (this) { |
| | |
| | | }; |
| | | |
| | | for (final AttributeMapper mapper : attributeMappers) { |
| | | mapper.toJson(c, e, resultAccumulater); |
| | | mapper.toJSON(c, e, resultAccumulater); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public void toLDAP(final ServerContext c, final JsonValue v, |
| | | final ResultHandler<List<Attribute>> h) { |
| | | // TODO Auto-generated method stub |
| | |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyrighted [year] [name of copyright owner]". |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2012 ForgeRock AS. All rights reserved. |
| | | * Copyright 2012 ForgeRock AS. |
| | | */ |
| | | |
| | | package org.forgerock.opendj.rest2ldap; |
| | | |
| | | import java.util.Collections; |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public void getLDAPAttributes(final JsonPointer jsonAttribute, final Set<String> ldapAttributes) { |
| | | // Nothing to do. |
| | | } |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public void toJson(final ServerContext c, final Entry e, |
| | | @Override |
| | | public void toJSON(final ServerContext c, final Entry e, |
| | | final ResultHandler<Map<String, Object>> h) { |
| | | // FIXME: how do we know if the user requested it??? |
| | | h.handleResult(Collections.singletonMap(jsonAttributeName, jsonAttributeValue)); |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public void toLDAP(final ServerContext c, final JsonValue v, |
| | | final ResultHandler<List<Attribute>> h) { |
| | | // TODO Auto-generated method stub |
| | |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyrighted [year] [name of copyright owner]". |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2012 ForgeRock AS. All rights reserved. |
| | | * Copyright 2012 ForgeRock AS. |
| | | */ |
| | | |
| | | package org.forgerock.opendj.rest2ldap; |
| | | |
| | | import static org.forgerock.opendj.rest2ldap.Utils.attributeToJson; |
| | |
| | | import org.forgerock.opendj.ldap.Entry; |
| | | |
| | | /** |
| | | * |
| | | * An attribute mapper that directly maps a configurable selection of attributes |
| | | * to and from LDAP without any transformation. |
| | | */ |
| | | public final class DefaultAttributeMapper implements AttributeMapper { |
| | | |
| | |
| | | // All user attributes by default. |
| | | private final Map<String, String> includedAttributes = new LinkedHashMap<String, String>(); |
| | | |
| | | /** |
| | | * Creates a new default attribute mapper which will map all user attributes |
| | | * to JSON by default. |
| | | */ |
| | | public DefaultAttributeMapper() { |
| | | // No implementation required. |
| | | } |
| | | |
| | | /** |
| | | * Excludes one or more LDAP attributes from this mapping. |
| | | * |
| | | * @param attributes |
| | | * The attributes to be excluded. |
| | | * @return This attribute mapper. |
| | | */ |
| | | public DefaultAttributeMapper excludeAttribute(final String... attributes) { |
| | | for (final String attribute : attributes) { |
| | | excludedAttributes.put(toLowerCase(attribute), attribute); |
| | |
| | | return this; |
| | | } |
| | | |
| | | @Override |
| | | public void getLDAPAttributes(final JsonPointer jsonAttribute, final Set<String> ldapAttributes) { |
| | | switch (jsonAttribute.size()) { |
| | | case 0: |
| | |
| | | } |
| | | } |
| | | |
| | | public void getLDAPAttributes(final Set<String> ldapAttributes) { |
| | | if (!includedAttributes.isEmpty()) { |
| | | ldapAttributes.addAll(includedAttributes.values()); |
| | | } else { |
| | | // All user attributes. |
| | | ldapAttributes.add("*"); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Includes one or more LDAP attributes in this mapping. |
| | | * |
| | | * @param attributes |
| | | * The attributes to be included. |
| | | * @return This attribute mapper. |
| | | */ |
| | | public DefaultAttributeMapper includeAttribute(final String... attributes) { |
| | | for (final String attribute : attributes) { |
| | | includedAttributes.put(toLowerCase(attribute), attribute); |
| | |
| | | return this; |
| | | } |
| | | |
| | | public void toJson(final ServerContext c, final Entry e, |
| | | @Override |
| | | public void toJSON(final ServerContext c, final Entry e, |
| | | final ResultHandler<Map<String, Object>> h) { |
| | | final Map<String, Object> result = new LinkedHashMap<String, Object>(e.getAttributeCount()); |
| | | for (final Attribute a : e.getAllAttributes()) { |
| | |
| | | h.handleResult(result); |
| | | } |
| | | |
| | | @Override |
| | | public void toLDAP(final ServerContext c, final JsonValue v, |
| | | final ResultHandler<List<Attribute>> h) { |
| | | // TODO: |
| | |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyrighted [year] [name of copyright owner]". |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2012 ForgeRock AS. All rights reserved. |
| | | * Copyright 2012 ForgeRock AS. |
| | | */ |
| | | |
| | | package org.forgerock.opendj.rest2ldap; |
| | | |
| | | import java.util.Collection; |
| | |
| | | import org.forgerock.opendj.ldap.responses.SearchResultReference; |
| | | |
| | | /** |
| | | * |
| | | * An entry container. |
| | | */ |
| | | public final class EntryContainer { |
| | | private abstract class AbstractRequestCompletionHandler<R, H extends ResultHandler<? super R>> |
| | |
| | | |
| | | private final ConnectionFactory factory; |
| | | |
| | | /** |
| | | * Creates a new entry container for the provided base DN and LDAP |
| | | * connection factory. |
| | | * |
| | | * @param baseDN |
| | | * The base DN. |
| | | * @param factory |
| | | * The LDAP connection factory. |
| | | */ |
| | | public EntryContainer(final DN baseDN, final ConnectionFactory factory) { |
| | | this.baseDN = baseDN; |
| | | this.factory = factory; |
| | | } |
| | | |
| | | /** |
| | | * Returns the ETag for the provided entry. |
| | | * |
| | | * @param entry |
| | | * The entry. |
| | | * @return The ETag. |
| | | */ |
| | | public String getEtagFromEntry(final Entry entry) { |
| | | return entry.parseAttribute(ETAG_ATTRIBUTE).asString(); |
| | | } |
| | | |
| | | /** |
| | | * Returns the resource ID for the provided entry. |
| | | * |
| | | * @param entry |
| | | * The entry. |
| | | * @return The resource ID. |
| | | */ |
| | | public String getIDFromEntry(final Entry entry) { |
| | | return entry.parseAttribute(UUID_ATTRIBUTE).asString(); |
| | | } |
| | | |
| | | /** |
| | | * Lists the entries contained in this container. |
| | | * |
| | | * @param context |
| | | * The request context. |
| | | * @param attributes |
| | | * The list of LDAP attributes to be returned. |
| | | * @param handler |
| | | * The search result handler. |
| | | */ |
| | | public void listEntries(final Context context, final Collection<String> attributes, |
| | | final SearchResultHandler handler) { |
| | | final String[] tmp = getSearchAttributes(attributes); |
| | | final ConnectionCompletionHandler<Result> outerHandler = |
| | | new ConnectionCompletionHandler<Result>(handler) { |
| | | final ConnectionCompletionHandler<Result> outerHandler = new ConnectionCompletionHandler<Result>( |
| | | handler) { |
| | | |
| | | @Override |
| | | public void handleResult(final Connection connection) { |
| | | final SearchRequestCompletionHandler innerHandler = |
| | | new SearchRequestCompletionHandler(connection, handler); |
| | | final SearchRequest request = |
| | | Requests.newSearchRequest(baseDN, SearchScope.SINGLE_LEVEL, Filter |
| | | .objectClassPresent(), tmp); |
| | | final SearchRequestCompletionHandler innerHandler = new SearchRequestCompletionHandler( |
| | | connection, handler); |
| | | final SearchRequest request = Requests.newSearchRequest(baseDN, |
| | | SearchScope.SINGLE_LEVEL, Filter.objectClassPresent(), tmp); |
| | | connection.searchAsync(request, null, innerHandler); |
| | | } |
| | | |
| | |
| | | factory.getConnectionAsync(outerHandler); |
| | | } |
| | | |
| | | /** |
| | | * Reads the entry having the specified resource ID. |
| | | * |
| | | * @param c |
| | | * The request context. |
| | | * @param id |
| | | * The resource ID. |
| | | * @param attributes |
| | | * The list of LDAP attributes to be returned. |
| | | * @param handler |
| | | * The search result handler. |
| | | */ |
| | | public void readEntry(final Context c, final String id, final Collection<String> attributes, |
| | | final ResultHandler<SearchResultEntry> handler) { |
| | | final String[] tmp = getSearchAttributes(attributes); |
| | | // @Checkstyle:off |
| | | final ConnectionCompletionHandler<SearchResultEntry> outerHandler = |
| | | new ConnectionCompletionHandler<SearchResultEntry>(handler) { |
| | | |
| | |
| | | public void handleResult(final Connection connection) { |
| | | final RequestCompletionHandler<SearchResultEntry> innerHandler = |
| | | new RequestCompletionHandler<SearchResultEntry>(connection, handler); |
| | | final SearchRequest request = |
| | | Requests.newSearchRequest(baseDN, SearchScope.SINGLE_LEVEL, Filter |
| | | .equality(UUID_ATTRIBUTE, id), tmp); |
| | | final SearchRequest request = Requests.newSearchRequest(baseDN, |
| | | SearchScope.SINGLE_LEVEL, Filter.equality(UUID_ATTRIBUTE, id), tmp); |
| | | connection.searchSingleEntryAsync(request, innerHandler); |
| | | } |
| | | |
| | | }; |
| | | |
| | | // @Checkstyle:on |
| | | factory.getConnectionAsync(outerHandler); |
| | | } |
| | | |
| | |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyrighted [year] [name of copyright owner]". |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2012 ForgeRock AS. All rights reserved. |
| | | * Copyright 2012 ForgeRock AS. |
| | | */ |
| | | |
| | | package org.forgerock.opendj.rest2ldap; |
| | | |
| | | import java.util.Collection; |
| | |
| | | |
| | | import org.forgerock.json.fluent.JsonPointer; |
| | | import org.forgerock.json.fluent.JsonValue; |
| | | import org.forgerock.json.resource.*; |
| | | import org.forgerock.json.resource.ActionRequest; |
| | | import org.forgerock.json.resource.CollectionResourceProvider; |
| | | import org.forgerock.json.resource.CreateRequest; |
| | | import org.forgerock.json.resource.DeleteRequest; |
| | | import org.forgerock.json.resource.NotSupportedException; |
| | | import org.forgerock.json.resource.PatchRequest; |
| | | import org.forgerock.json.resource.QueryRequest; |
| | | import org.forgerock.json.resource.QueryResult; |
| | | import org.forgerock.json.resource.QueryResultHandler; |
| | | import org.forgerock.json.resource.ReadRequest; |
| | | import org.forgerock.json.resource.Resource; |
| | | import org.forgerock.json.resource.ResourceException; |
| | | import org.forgerock.json.resource.ResultHandler; |
| | | import org.forgerock.json.resource.ServerContext; |
| | | import org.forgerock.json.resource.UncategorizedException; |
| | | import org.forgerock.json.resource.UpdateRequest; |
| | | import org.forgerock.opendj.ldap.AssertionFailureException; |
| | | import org.forgerock.opendj.ldap.AuthenticationException; |
| | | import org.forgerock.opendj.ldap.AuthorizationException; |
| | |
| | | import org.forgerock.opendj.ldap.responses.SearchResultReference; |
| | | |
| | | /** |
| | | * |
| | | * A {@code CollectionResourceProvider} implementation which maps a JSON |
| | | * resource collection to LDAP entries beneath a base DN. |
| | | */ |
| | | public class LDAPCollectionResourceProvider implements CollectionResourceProvider { |
| | | private final AttributeMapper attributeMapper; |
| | | private final EntryContainer entryContainer; |
| | | |
| | | // Dummy exception used for signalling search success. |
| | | private static final ResourceException SUCCESS = new UncategorizedException(0, null, null); |
| | | private final AttributeMapper attributeMapper; |
| | | |
| | | private final EntryContainer entryContainer; |
| | | |
| | | /** |
| | | * Creates a new LDAP resource. |
| | | * |
| | | * @param container |
| | | * The LDAP entry container. |
| | | * @param mapper |
| | | * The attribute mapper which will be used for mapping LDAP |
| | | * attributes to JSON attributes. |
| | | */ |
| | | public LDAPCollectionResourceProvider(final EntryContainer container, final AttributeMapper mapper) { |
| | | public LDAPCollectionResourceProvider(final EntryContainer container, |
| | | final AttributeMapper mapper) { |
| | | this.entryContainer = container; |
| | | this.attributeMapper = mapper; |
| | | } |
| | |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public void actionCollection(ServerContext context, ActionRequest request, |
| | | ResultHandler<JsonValue> handler) { |
| | | public void actionCollection(final ServerContext context, final ActionRequest request, |
| | | final ResultHandler<JsonValue> handler) { |
| | | handler.handleError(new NotSupportedException("Not yet implemented")); |
| | | } |
| | | |
| | |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public void actionInstance(ServerContext context, String resourceId, ActionRequest request, |
| | | ResultHandler<JsonValue> handler) { |
| | | public void actionInstance(final ServerContext context, final String resourceId, |
| | | final ActionRequest request, final ResultHandler<JsonValue> handler) { |
| | | handler.handleError(new NotSupportedException("Not yet implemented")); |
| | | } |
| | | |
| | |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public void createInstance(ServerContext context, CreateRequest request, |
| | | ResultHandler<Resource> handler) { |
| | | public void createInstance(final ServerContext context, final CreateRequest request, |
| | | final ResultHandler<Resource> handler) { |
| | | handler.handleError(new NotSupportedException("Not yet implemented")); |
| | | } |
| | | |
| | |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public void deleteInstance(ServerContext context, String resourceId, DeleteRequest request, |
| | | ResultHandler<Resource> handler) { |
| | | public void deleteInstance(final ServerContext context, final String resourceId, |
| | | final DeleteRequest request, final ResultHandler<Resource> handler) { |
| | | handler.handleError(new NotSupportedException("Not yet implemented")); |
| | | } |
| | | |
| | |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public void patchInstance(ServerContext context, String resourceId, PatchRequest request, |
| | | ResultHandler<Resource> handler) { |
| | | public void patchInstance(final ServerContext context, final String resourceId, |
| | | final PatchRequest request, final ResultHandler<Resource> handler) { |
| | | handler.handleError(new NotSupportedException("Not yet implemented")); |
| | | } |
| | | |
| | |
| | | private final AtomicReference<ResourceException> pendingResult = new AtomicReference<ResourceException>(); |
| | | private final AtomicBoolean resultSent = new AtomicBoolean(); |
| | | |
| | | @Override |
| | | public boolean handleEntry(final SearchResultEntry entry) { |
| | | /* |
| | | * Search result entries will be returned before the search |
| | | * result/error so the only reason pendingResult will be |
| | | * non-null is if a mapping error has occurred. |
| | | */ |
| | | if (pendingResult.get() != null) { |
| | | return false; |
| | | } |
| | | |
| | | // TODO: should the resource or the container define the ID |
| | | // mapping? |
| | | final String id = entryContainer.getIDFromEntry(entry); |
| | | final String revision = entryContainer.getEtagFromEntry(entry); |
| | | final ResultHandler<Map<String, Object>> mapHandler = new ResultHandler<Map<String, Object>>() { |
| | | @Override |
| | | public void handleError(final ResourceException e) { |
| | | pendingResult.compareAndSet(null, e); |
| | | pendingResourceCount.decrementAndGet(); |
| | | completeIfNecessary(); |
| | | } |
| | | |
| | | @Override |
| | | public void handleResult(final Map<String, Object> result) { |
| | | final Resource resource = new Resource(id, revision, new JsonValue(result)); |
| | | handler.handleResource(resource); |
| | | pendingResourceCount.decrementAndGet(); |
| | | completeIfNecessary(); |
| | | } |
| | | }; |
| | | |
| | | pendingResourceCount.incrementAndGet(); |
| | | attributeMapper.toJSON(context, entry, mapHandler); |
| | | return true; |
| | | } |
| | | |
| | | @Override |
| | | public void handleErrorResult(final ErrorResultException error) { |
| | | pendingResult.compareAndSet(null, adaptErrorResult(error)); |
| | | completeIfNecessary(); |
| | | } |
| | | |
| | | @Override |
| | | public boolean handleReference(final SearchResultReference reference) { |
| | | // TODO: should this be classed as an error since rest2ldap |
| | | // assumes entries are all colocated? |
| | | return true; |
| | | } |
| | | |
| | | @Override |
| | | public void handleResult(final Result result) { |
| | | pendingResult.compareAndSet(null, SUCCESS); |
| | | completeIfNecessary(); |
| | | } |
| | | |
| | | /* |
| | | * Close out the query result set if there are no more pending |
| | | * resources and the LDAP result has been received. |
| | |
| | | } |
| | | } |
| | | } |
| | | |
| | | public boolean handleEntry(final SearchResultEntry entry) { |
| | | /* |
| | | * Search result entries will be returned before the search |
| | | * result/error so the only reason pendingResult will be |
| | | * non-null is if a mapping error has occurred. |
| | | */ |
| | | if (pendingResult.get() != null) { |
| | | return false; |
| | | } |
| | | |
| | | // TODO: should the resource or the container define the ID |
| | | // mapping? |
| | | final String id = entryContainer.getIDFromEntry(entry); |
| | | final String revision = entryContainer.getEtagFromEntry(entry); |
| | | final ResultHandler<Map<String, Object>> mapHandler = new ResultHandler<Map<String, Object>>() { |
| | | public void handleError(final ResourceException e) { |
| | | pendingResult.compareAndSet(null, e); |
| | | pendingResourceCount.decrementAndGet(); |
| | | completeIfNecessary(); |
| | | } |
| | | |
| | | public void handleResult(final Map<String, Object> result) { |
| | | Resource resource = new Resource(id, revision, new JsonValue(result)); |
| | | handler.handleResource(resource); |
| | | pendingResourceCount.decrementAndGet(); |
| | | completeIfNecessary(); |
| | | } |
| | | }; |
| | | |
| | | pendingResourceCount.incrementAndGet(); |
| | | attributeMapper.toJson(context, entry, mapHandler); |
| | | return true; |
| | | } |
| | | |
| | | public void handleErrorResult(final ErrorResultException error) { |
| | | pendingResult.compareAndSet(null, adaptErrorResult(error)); |
| | | completeIfNecessary(); |
| | | } |
| | | |
| | | public boolean handleReference(final SearchResultReference reference) { |
| | | // TODO: should this be classed as an error since rest2ldap |
| | | // assumes entries are all colocated? |
| | | return true; |
| | | } |
| | | |
| | | public void handleResult(final Result result) { |
| | | pendingResult.compareAndSet(null, SUCCESS); |
| | | completeIfNecessary(); |
| | | } |
| | | }; |
| | | entryContainer.listEntries(context, requestedLDAPAttributes, searchHandler); |
| | | } |
| | |
| | | */ |
| | | @Override |
| | | public void readInstance(final ServerContext context, final String resourceId, |
| | | ReadRequest request, final ResultHandler<Resource> handler) { |
| | | final ReadRequest request, final ResultHandler<Resource> handler) { |
| | | // TODO: Determine the set of LDAP attributes that need to be read. |
| | | final Set<JsonPointer> requestedAttributes = new LinkedHashSet<JsonPointer>(); |
| | | final Collection<String> requestedLDAPAttributes = getRequestedLDAPAttributes(requestedAttributes); |
| | | |
| | | final org.forgerock.opendj.ldap.ResultHandler<SearchResultEntry> searchHandler = new org.forgerock.opendj.ldap.ResultHandler<SearchResultEntry>() { |
| | | // @Checkstyle:off |
| | | final org.forgerock.opendj.ldap.ResultHandler<SearchResultEntry> searchHandler = |
| | | new org.forgerock.opendj.ldap.ResultHandler<SearchResultEntry>() { |
| | | @Override |
| | | public void handleErrorResult(final ErrorResultException error) { |
| | | handler.handleError(adaptErrorResult(error)); |
| | | } |
| | | |
| | | @Override |
| | | public void handleResult(final SearchResultEntry entry) { |
| | | final String revision = entryContainer.getEtagFromEntry(entry); |
| | | final ResultHandler<Map<String, Object>> mapHandler = new ResultHandler<Map<String, Object>>() { |
| | | @Override |
| | | public void handleError(final ResourceException e) { |
| | | handler.handleError(e); |
| | | } |
| | | |
| | | @Override |
| | | public void handleResult(final Map<String, Object> result) { |
| | | Resource resource = new Resource(resourceId, revision, |
| | | new JsonValue(result)); |
| | | final Resource resource = new Resource(resourceId, revision, new JsonValue( |
| | | result)); |
| | | handler.handleResult(resource); |
| | | } |
| | | }; |
| | | attributeMapper.toJson(context, entry, mapHandler); |
| | | attributeMapper.toJSON(context, entry, mapHandler); |
| | | } |
| | | }; |
| | | // @Checkstyle:on |
| | | entryContainer.readEntry(context, resourceId, requestedLDAPAttributes, searchHandler); |
| | | } |
| | | |
| | |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public void updateInstance(ServerContext context, String resourceId, UpdateRequest request, |
| | | ResultHandler<Resource> handler) { |
| | | public void updateInstance(final ServerContext context, final String resourceId, |
| | | final UpdateRequest request, final ResultHandler<Resource> handler) { |
| | | handler.handleError(new NotSupportedException("Not yet implemented")); |
| | | } |
| | | |
| | |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyrighted [year] [name of copyright owner]". |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2012 ForgeRock AS. All rights reserved. |
| | | * Copyright 2012 ForgeRock AS. |
| | | */ |
| | | |
| | | package org.forgerock.opendj.rest2ldap; |
| | | |
| | | import java.util.List; |
| | |
| | | import org.forgerock.opendj.ldap.Entry; |
| | | |
| | | /** |
| | | * |
| | | * An attribute mapper which maps DN valued LDAP attributes to resource IDs. |
| | | */ |
| | | public class ReferenceAttributeMapper implements AttributeMapper { |
| | | |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public void getLDAPAttributes(final JsonPointer jsonAttribute, final Set<String> ldapAttributes) { |
| | | // TODO Auto-generated method stub |
| | | |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public void toJson(final ServerContext c, final Entry e, final ResultHandler<Map<String, Object>> h) { |
| | | @Override |
| | | public void toJSON(final ServerContext c, final Entry e, |
| | | final ResultHandler<Map<String, Object>> h) { |
| | | // TODO Auto-generated method stub |
| | | |
| | | } |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public void toLDAP(final ServerContext c, final JsonValue v, final ResultHandler<List<Attribute>> h) { |
| | | @Override |
| | | public void toLDAP(final ServerContext c, final JsonValue v, |
| | | final ResultHandler<List<Attribute>> h) { |
| | | // TODO Auto-generated method stub |
| | | |
| | | } |
| | |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyrighted [year] [name of copyright owner]". |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2012 ForgeRock AS. All rights reserved. |
| | | * Copyright 2012 ForgeRock AS. |
| | | */ |
| | | |
| | | package org.forgerock.opendj.rest2ldap; |
| | | |
| | | import static org.forgerock.opendj.rest2ldap.Utils.byteStringToJson; |
| | |
| | | import org.forgerock.opendj.ldap.Functions; |
| | | |
| | | /** |
| | | * |
| | | * An attribute mapper which maps a single JSON attribute to a single LDAP |
| | | * attribute. |
| | | */ |
| | | public class SimpleAttributeMapper implements AttributeMapper { |
| | | |
| | |
| | | private Object defaultValue = null; |
| | | private boolean forceSingleValued = false; |
| | | |
| | | private boolean isReadOnly = false; |
| | | // private boolean isReadOnly = false; |
| | | private final String jsonAttributeName; |
| | | private final String ldapAttributeName; |
| | | private final String normalizedJsonAttributeName; |
| | |
| | | this.normalizedJsonAttributeName = toLowerCase(jsonAttributeName); |
| | | } |
| | | |
| | | public SimpleAttributeMapper forceSingleValued(final boolean singleValued) { |
| | | /** |
| | | * Sets the decoder which will be used for converting LDAP attribute values |
| | | * to JSON values. |
| | | * |
| | | * @param f |
| | | * The function to use for decoding LDAP attribute values. |
| | | * @return This attribute mapper. |
| | | */ |
| | | public SimpleAttributeMapper decoder(final Function<ByteString, ?, Void> f) { |
| | | this.decoder = f; |
| | | return this; |
| | | } |
| | | |
| | | /** |
| | | * Sets the default JSON value which should be substituted when the LDAP |
| | | * attribute is not found in the LDAP entry. |
| | | * |
| | | * @param defaultValue |
| | | * The default JSON value. |
| | | * @return This attribute mapper. |
| | | */ |
| | | public SimpleAttributeMapper defaultJSONValue(final Object defaultValue) { |
| | | this.defaultValue = defaultValue; |
| | | return this; |
| | | } |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public void getLDAPAttributes(final JsonPointer jsonAttribute, final Set<String> ldapAttributes) { |
| | | if (attributeMatchesPointer(jsonAttribute)) { |
| | | ldapAttributes.add(ldapAttributeName); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Prevents the LDAP attribute from being updated. |
| | | * |
| | | * @param readOnly |
| | | * {@code true} if the LDAP attribute is read-only. |
| | | * @return This attribute mapper. |
| | | */ |
| | | public SimpleAttributeMapper readOnly(final boolean readOnly) { |
| | | // TODO: enforcement policy: ignore, warn, or reject. |
| | | // this.isReadOnly = readOnly; |
| | | return this; |
| | | } |
| | | |
| | | /** |
| | | * Forces a multi-valued LDAP attribute to be represented as a single-valued |
| | | * JSON value, rather than an array of values. |
| | | * |
| | | * @param singleValued |
| | | * {@code true} if the LDAP attribute should be treated as a |
| | | * single-valued attribute. |
| | | * @return This attribute mapper. |
| | | */ |
| | | public SimpleAttributeMapper singleValued(final boolean singleValued) { |
| | | this.forceSingleValued = singleValued; |
| | | return this; |
| | | } |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public void getLDAPAttributes(final JsonPointer jsonAttribute, final Set<String> ldapAttributes) { |
| | | if (attributeMatchesPointer(jsonAttribute)) { |
| | | ldapAttributes.add(ldapAttributeName); |
| | | } |
| | | } |
| | | |
| | | public SimpleAttributeMapper isReadOnly(final boolean readOnly) { |
| | | this.isReadOnly = readOnly; |
| | | return this; |
| | | } |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public void toJson(final ServerContext c, final Entry e, final ResultHandler<Map<String, Object>> h) { |
| | | @Override |
| | | public void toJSON(final ServerContext c, final Entry e, |
| | | final ResultHandler<Map<String, Object>> h) { |
| | | final Attribute a = e.getAttribute(ldapAttributeName); |
| | | if (a != null) { |
| | | final Function<ByteString, ?, Void> f = |
| | | decoder == null ? Functions.fixedFunction(byteStringToJson(), a) : decoder; |
| | | final Function<ByteString, ?, Void> f = decoder == null ? Functions.fixedFunction( |
| | | byteStringToJson(), a) : decoder; |
| | | final Object value; |
| | | if (forceSingleValued || a.getAttributeDescription().getAttributeType().isSingleValue()) { |
| | | value = a.parse().as(f, defaultValue); |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public void toLDAP(final ServerContext c, final JsonValue v, final ResultHandler<List<Attribute>> h) { |
| | | @Override |
| | | public void toLDAP(final ServerContext c, final JsonValue v, |
| | | final ResultHandler<List<Attribute>> h) { |
| | | // TODO Auto-generated method stub |
| | | |
| | | } |
| | | |
| | | public SimpleAttributeMapper withDecoder(final Function<ByteString, ?, Void> f) { |
| | | this.decoder = f; |
| | | return this; |
| | | } |
| | | |
| | | public SimpleAttributeMapper withDefaultValue(final Object defaultValue) { |
| | | this.defaultValue = defaultValue; |
| | | return this; |
| | | } |
| | | |
| | | private boolean attributeMatchesPointer(final JsonPointer resourceAttribute) { |
| | | return resourceAttribute.isEmpty() |
| | | || toLowerCase(resourceAttribute.get(0)).equals(normalizedJsonAttributeName); |
| | |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyrighted [year] [name of copyright owner]". |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2012 ForgeRock AS. All rights reserved. |
| | | * Copyright 2012 ForgeRock AS. |
| | | */ |
| | | |
| | | package org.forgerock.opendj.rest2ldap; |
| | | |
| | | import java.util.List; |
| | |
| | | import org.forgerock.opendj.ldap.Entry; |
| | | |
| | | /** |
| | | * |
| | | * An attribute mapper which inlines LDAP attributes from subordinate LDAP |
| | | * entries. |
| | | */ |
| | | public class SubContainerAttributeMapper implements AttributeMapper { |
| | | |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public void getLDAPAttributes(final JsonPointer jsonAttribute, final Set<String> ldapAttributes) { |
| | | // TODO Auto-generated method stub |
| | | |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public void toJson(final ServerContext c, final Entry e, final ResultHandler<Map<String, Object>> h) { |
| | | @Override |
| | | public void toJSON(final ServerContext c, final Entry e, |
| | | final ResultHandler<Map<String, Object>> h) { |
| | | // TODO Auto-generated method stub |
| | | |
| | | } |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public void toLDAP(final ServerContext c, final JsonValue v, final ResultHandler<List<Attribute>> h) { |
| | | @Override |
| | | public void toLDAP(final ServerContext c, final JsonValue v, |
| | | final ResultHandler<List<Attribute>> h) { |
| | | // TODO Auto-generated method stub |
| | | |
| | | } |
| | |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyrighted [year] [name of copyright owner]". |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2012 ForgeRock AS. All rights reserved. |
| | | * Copyright 2012 ForgeRock AS. |
| | | */ |
| | | |
| | | package org.forgerock.opendj.rest2ldap; |
| | | |
| | | import static org.forgerock.opendj.ldap.schema.CoreSchema.getBooleanSyntax; |
| | |
| | | import org.forgerock.opendj.ldap.schema.Syntax; |
| | | |
| | | /** |
| | | * |
| | | * Internal utility methods. |
| | | */ |
| | | final class Utils { |
| | | |
| | | // @Checkstyle:off |
| | | private static final Function<ByteString, Object, Attribute> BYTESTRING_TO_JSON = |
| | | new Function<ByteString, Object, Attribute>() { |
| | | @Override |
| | | public Object apply(final ByteString value, final Attribute a) { |
| | | final Syntax syntax = |
| | | a.getAttributeDescription().getAttributeType().getSyntax(); |
| | | final Syntax syntax = a.getAttributeDescription().getAttributeType().getSyntax(); |
| | | if (syntax.equals(getBooleanSyntax())) { |
| | | return Functions.byteStringToBoolean().apply(value, null); |
| | | } else if (syntax.equals(getIntegerSyntax())) { |
| | | return Functions.byteStringToLong().apply(value, null); |
| | | } else if (syntax.equals(getGeneralizedTimeSyntax())) { |
| | | return DatatypeConverter.printDateTime(Functions |
| | | .byteStringToGeneralizedTime().apply(value, null).toCalendar()); |
| | | return DatatypeConverter.printDateTime(Functions.byteStringToGeneralizedTime() |
| | | .apply(value, null).toCalendar()); |
| | | } else if (syntax.isHumanReadable()) { |
| | | return Functions.byteStringToString().apply(value, null); |
| | | } else { |
| | |
| | | } |
| | | } |
| | | }; |
| | | // @Checkstyle:on |
| | | |
| | | static Object attributeToJson(final Attribute a) { |
| | | final Function<ByteString, Object, Void> f = Functions.fixedFunction(BYTESTRING_TO_JSON, a); |
| | | final boolean isSingleValued = |
| | | a.getAttributeDescription().getAttributeType().isSingleValue(); |
| | | final boolean isSingleValued = a.getAttributeDescription().getAttributeType() |
| | | .isSingleValue(); |
| | | return isSingleValued ? a.parse().as(f) : asList(a.parse().asSetOf(f)); |
| | | } |
| | | |
| | |
| | | /* |
| | | * CDDL HEADER START |
| | | * The contents of this file are subject to the terms of the Common Development and |
| | | * Distribution License (the License). You may not use this file except in compliance with the |
| | | * License. |
| | | * |
| | | * The contents of this file are subject to the terms of the |
| | | * Common Development and Distribution License, Version 1.0 only |
| | | * (the "License"). You may not use this file except in compliance |
| | | * with the License. |
| | | * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | * specific language governing permission and limitations under the License. |
| | | * |
| | | * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt |
| | | * or http://forgerock.org/license/CDDLv1.0.html. |
| | | * See the License for the specific language governing permissions |
| | | * and limitations under the License. |
| | | * |
| | | * When distributing Covered Code, include this CDDL HEADER in each |
| | | * file and include the License file at legal-notices/CDDLv1_0.txt. |
| | | * If applicable, add the following below this CDDL HEADER, with the |
| | | * fields enclosed by brackets "[]" replaced with your own identifying |
| | | * information: |
| | | * Portions Copyright [yyyy] [name of copyright owner] |
| | | * |
| | | * CDDL HEADER END |
| | | * |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2012 ForgeRock AS. |
| | | */ |
| | |
| | | import org.glassfish.grizzly.servlet.WebappContext; |
| | | |
| | | /** |
| | | * Example |
| | | * Example. |
| | | */ |
| | | public class Example { |
| | | |
| | | private static final Logger LOGGER = Logger.getLogger(Example.class.getName()); |
| | | private static final int PORT = 18890; |
| | | |
| | | /** |
| | | * REST 2 LDAP example application. |
| | | * |
| | | * @param args |
| | | * Command line arguments. |
| | | * @throws Exception |
| | | * If an unexpected error occurred. |
| | | */ |
| | | public static void main(final String[] args) throws Exception { |
| | | // All LDAP resources will use this connection factory. |
| | | final ConnectionFactory ldapFactory = newAuthenticatedConnectionFactory( |
| | |
| | | |
| | | // Create user resource. |
| | | final AttributeMapper userMapper = new CompositeAttributeMapper().addMapper( |
| | | new SimpleAttributeMapper("id", "entryUUID").forceSingleValued(true)).addMapper( |
| | | new SimpleAttributeMapper("id", "entryUUID").singleValued(true)).addMapper( |
| | | new DefaultAttributeMapper().includeAttribute("uid", "isMemberOf", |
| | | "modifyTimestamp")).addMapper( |
| | | new ComplexAttributeMapper("name", new DefaultAttributeMapper().includeAttribute( |
| | | "cn", "sn", "givenName"))).addMapper( |
| | | new ComplexAttributeMapper("contactInformation", new CompositeAttributeMapper() |
| | | .addMapper( |
| | | new SimpleAttributeMapper("telephoneNumber").withDecoder( |
| | | Functions.byteStringToString()).forceSingleValued(true)) |
| | | new SimpleAttributeMapper("telephoneNumber").decoder( |
| | | Functions.byteStringToString()).singleValued(true)) |
| | | .addMapper( |
| | | new SimpleAttributeMapper("emailAddress", "mail") |
| | | .forceSingleValued(true)))); |
| | | .singleValued(true)))); |
| | | final LDAPCollectionResourceProvider userResource = new LDAPCollectionResourceProvider( |
| | | userContainer, userMapper); |
| | | |
| | |
| | | groupContainer, groupMapper); |
| | | |
| | | // Create the router. |
| | | Router router = new Router(); |
| | | final Router router = new Router(); |
| | | router.addRoute(RoutingMode.EQUALS, "/users", userResource); |
| | | router.addRoute(RoutingMode.EQUALS, "/groups", groupResource); |
| | | |