| /* |
| * 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.directory.api.ldap.codec.factory; |
| |
| import java.util.Iterator; |
| import java.util.List; |
| |
| import org.apache.directory.api.asn1.ber.tlv.BerValue; |
| import org.apache.directory.api.asn1.util.Asn1Buffer; |
| import org.apache.directory.api.ldap.codec.api.LdapApiService; |
| import org.apache.directory.api.ldap.codec.api.LdapCodecConstants; |
| import org.apache.directory.api.ldap.model.filter.AndNode; |
| import org.apache.directory.api.ldap.model.filter.ApproximateNode; |
| import org.apache.directory.api.ldap.model.filter.BranchNode; |
| import org.apache.directory.api.ldap.model.filter.EqualityNode; |
| import org.apache.directory.api.ldap.model.filter.ExprNode; |
| import org.apache.directory.api.ldap.model.filter.ExtensibleNode; |
| import org.apache.directory.api.ldap.model.filter.GreaterEqNode; |
| import org.apache.directory.api.ldap.model.filter.LessEqNode; |
| import org.apache.directory.api.ldap.model.filter.NotNode; |
| import org.apache.directory.api.ldap.model.filter.OrNode; |
| import org.apache.directory.api.ldap.model.filter.PresenceNode; |
| import org.apache.directory.api.ldap.model.filter.SimpleNode; |
| import org.apache.directory.api.ldap.model.filter.SubstringNode; |
| import org.apache.directory.api.ldap.model.message.Message; |
| import org.apache.directory.api.ldap.model.message.SearchRequest; |
| import org.apache.directory.api.util.Strings; |
| |
| /** |
| * The SearchRequest factory. |
| * |
| * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> |
| */ |
| public final class SearchRequestFactory implements Messagefactory |
| { |
| /** The static instance */ |
| public static final SearchRequestFactory INSTANCE = new SearchRequestFactory(); |
| |
| private SearchRequestFactory() |
| { |
| // Nothing to do |
| } |
| |
| /** |
| * Recursively encode the children of a connector node (AND, OR, NOT) |
| * |
| * @param buffer The buffer where to put the PDU |
| * @param children The children to encode |
| */ |
| private void encodeFilters( Asn1Buffer buffer, Iterator<ExprNode> children ) |
| { |
| if ( children.hasNext() ) |
| { |
| ExprNode child = children.next(); |
| |
| // Recurse |
| encodeFilters( buffer, children ); |
| |
| // And finally the child, at the right position |
| encodeFilter( buffer, child ); |
| } |
| } |
| |
| |
| /** |
| * Encode a BranchNode. |
| * <br> |
| * BranchFilter : |
| * <pre> |
| * 0xA1/0xA2/0xA3 LL |
| * filter.encode() ... filter.encode() |
| * </pre> |
| * |
| * @param buffer The buffer where to put the PDU |
| * @param node The Branch filter to encode |
| * @param tag the ASN.1 type |
| */ |
| private void encodeFilter( Asn1Buffer buffer, BranchNode node, byte tag ) |
| { |
| int start = buffer.getPos(); |
| |
| // encode each filter |
| List<ExprNode> children = node.getChildren(); |
| |
| if ( ( children != null ) && ( !children.isEmpty() ) ) |
| { |
| encodeFilters( buffer, children.iterator() ); |
| } |
| |
| // The BranchNode sequence |
| BerValue.encodeSequence( buffer, tag, start ); |
| } |
| |
| |
| /** |
| * Encode a SimpleNode. |
| * <br> |
| * SimpleFilter : |
| * <pre> |
| * 0xA3/0xA5/0xA6/A8 LL |
| * 0x04 LL attributeDesc |
| * 0x04 LL assertionValue |
| * </pre> |
| * |
| * @param buffer The buffer where to put the PDU |
| * @param node The Simple filter to encode |
| * @param tag the ASN.1 type |
| */ |
| private void encodeFilter( Asn1Buffer buffer, SimpleNode<?> node, byte tag ) |
| { |
| int start = buffer.getPos(); |
| |
| // The attribute desc |
| BerValue.encodeOctetString( buffer, node.getValue().getBytes() ); |
| |
| // The assertion desc |
| BerValue.encodeOctetString( buffer, node.getAttribute() ); |
| |
| // The EqualityNode sequence |
| BerValue.encodeSequence( buffer, tag, start ); |
| } |
| |
| |
| /** |
| * Encode a PresenceNode. |
| * <br> |
| * PresentFilter : |
| * <pre> |
| * 0x87 L1 present |
| * </pre> |
| * |
| * @param buffer The buffer where to put the PDU |
| * @param node The Presence filter to encode |
| */ |
| private void encodeFilter( Asn1Buffer buffer, PresenceNode node ) |
| { |
| // The PresentFilter Tag |
| BerValue.encodeOctetString( buffer, ( byte ) LdapCodecConstants.PRESENT_FILTER_TAG, |
| Strings.getBytesUtf8( node.getAttribute() ) ); |
| } |
| |
| |
| /** |
| * Encode a SubstringNode. |
| * <br> |
| * Substrings Filter : |
| * <pre> |
| * 0xA4 LL |
| * 0x04 LL type |
| * 0x30 LL substrings sequence |
| * | 0x80 LL initial |
| * | / [0x81 LL any]* |
| * |/ [0x82 LL final] |
| * +--[0x81 LL any]+ |
| * \ [0x82 LL final] |
| * \ |
| * 0x82 LL final |
| * </pre> |
| * |
| * @param buffer The buffer where to put the PDU |
| * @param node The Substring filter to encode |
| */ |
| private void encodeFilter( Asn1Buffer buffer, SubstringNode node ) |
| { |
| int start = buffer.getPos(); |
| |
| // The final |
| if ( node.getFinal() != null ) |
| { |
| BerValue.encodeOctetString( buffer, ( byte ) LdapCodecConstants.SUBSTRINGS_FILTER_FINAL_TAG, |
| Strings.getBytesUtf8( node.getFinal() ) ); |
| } |
| |
| // The any |
| List<String> any = node.getAny(); |
| |
| if ( any != null ) |
| { |
| for ( int i = any.size(); i > 0; i-- ) |
| { |
| BerValue.encodeOctetString( buffer, ( byte ) LdapCodecConstants.SUBSTRINGS_FILTER_ANY_TAG, |
| Strings.getBytesUtf8( any.get( i - 1 ) ) ); |
| } |
| } |
| |
| // The initial |
| if ( node.getInitial() != null ) |
| { |
| BerValue.encodeOctetString( buffer, ( byte ) LdapCodecConstants.SUBSTRINGS_FILTER_INITIAL_TAG, |
| Strings.getBytesUtf8( node.getInitial() ) ); |
| } |
| |
| // The Substring sequence |
| BerValue.encodeSequence( buffer, start ); |
| |
| // The type |
| BerValue.encodeOctetString( buffer, node.getAttribute() ); |
| |
| // The EqualityNode sequence |
| BerValue.encodeSequence( buffer, ( byte ) LdapCodecConstants.SUBSTRINGS_FILTER_TAG, start ); |
| } |
| |
| |
| /** |
| * Encode an ExtensibleNode. |
| * <br> |
| * ExtensibleMatch filter : |
| * <pre> |
| * 0xA9 L1 |
| * | |
| * [+--> 0x81 L3 matchingRule] |
| * [+--> 0x82 L4 type] |
| * [+--> 0x83 L5 matchValue] |
| * [+--> 0x01 0x01 dnAttributes] |
| * </pre> |
| * |
| * @param buffer The buffer where to put the PDU |
| * @param node The ExtensibleMatch filter to encode |
| */ |
| private void encodeFilter( Asn1Buffer buffer, ExtensibleNode node ) |
| { |
| int start = buffer.getPos(); |
| |
| // The dnAttributes flag, if true only |
| if ( node.hasDnAttributes() ) |
| { |
| BerValue.encodeBoolean( buffer, ( byte ) LdapCodecConstants.DN_ATTRIBUTES_FILTER_TAG, true ); |
| } |
| |
| // The matching value |
| if ( node.getValue() != null ) |
| { |
| BerValue.encodeOctetString( buffer, ( byte ) LdapCodecConstants.MATCH_VALUE_TAG, |
| node.getValue().getBytes() ); |
| } |
| |
| // The type |
| if ( node.getAttribute() != null ) |
| { |
| BerValue.encodeOctetString( buffer, ( byte ) LdapCodecConstants.MATCHING_RULE_TYPE_TAG, |
| Strings.getBytesUtf8( node.getAttribute() ) ); |
| } |
| |
| // The matching rule |
| if ( node.getMatchingRuleId() != null ) |
| { |
| BerValue.encodeOctetString( buffer, ( byte ) LdapCodecConstants.MATCHING_RULE_ID_TAG, |
| Strings.getBytesUtf8( node.getMatchingRuleId() ) ); |
| } |
| |
| // The EqualityNode sequence |
| BerValue.encodeSequence( buffer, ( byte ) LdapCodecConstants.EXTENSIBLE_MATCH_FILTER_TAG, start ); |
| } |
| |
| |
| /** |
| * Encode a Search Filter |
| * |
| * @param buffer The buffer where to put the PDU |
| * @param node The top filter |
| */ |
| private void encodeFilter( Asn1Buffer buffer, ExprNode node ) |
| { |
| switch ( node.getClass().getSimpleName() ) |
| { |
| case "AndNode" : |
| encodeFilter( buffer, ( AndNode ) node, ( byte ) LdapCodecConstants.AND_FILTER_TAG ); |
| break; |
| |
| case "ApproximateNode" : |
| encodeFilter( buffer, ( ApproximateNode<?> ) node, ( byte ) LdapCodecConstants.APPROX_MATCH_FILTER_TAG ); |
| break; |
| |
| case "EqualityNode" : |
| encodeFilter( buffer, ( EqualityNode<?> ) node, ( byte ) LdapCodecConstants.EQUALITY_MATCH_FILTER_TAG ); |
| break; |
| |
| case "ExtensibleNode" : |
| encodeFilter( buffer, ( ExtensibleNode ) node ); |
| break; |
| |
| case "GreaterEqNode" : |
| encodeFilter( buffer, ( GreaterEqNode<?> ) node, ( byte ) LdapCodecConstants.GREATER_OR_EQUAL_FILTER_TAG ); |
| break; |
| |
| case "LessEqNode" : |
| encodeFilter( buffer, ( LessEqNode<?> ) node, ( byte ) LdapCodecConstants.LESS_OR_EQUAL_FILTER_TAG ); |
| break; |
| |
| case "NotNode" : |
| encodeFilter( buffer, ( NotNode ) node, ( byte ) LdapCodecConstants.NOT_FILTER_TAG ); |
| break; |
| |
| case "OrNode" : |
| encodeFilter( buffer, ( OrNode ) node, ( byte ) LdapCodecConstants.OR_FILTER_TAG ); |
| break; |
| |
| case "PresenceNode" : |
| encodeFilter( buffer, ( PresenceNode ) node ); |
| break; |
| |
| case "SubstringNode" : |
| encodeFilter( buffer, ( SubstringNode ) node ); |
| break; |
| |
| default: |
| break; |
| } |
| } |
| |
| /** |
| * Encode the SearchRequest message to a PDU. |
| * <br> |
| * SearchRequest : |
| * <pre> |
| * 0x63 LL |
| * 0x04 LL baseObject |
| * 0x0A 01 scope |
| * 0x0A 01 derefAliases |
| * 0x02 0N sizeLimit |
| * 0x02 0N timeLimit |
| * 0x01 0x01 typesOnly |
| * filter.encode() |
| * 0x30 LL attributeDescriptionList |
| * 0x04 LL attributeDescription |
| * ... |
| * 0x04 LL attributeDescription |
| * </pre> |
| * |
| * @param codec The LdapApiService instance |
| * @param buffer The buffer where to put the PDU |
| * @param message the ModifyRequest to encode |
| */ |
| @Override |
| public void encodeReverse( LdapApiService codec, Asn1Buffer buffer, Message message ) |
| { |
| int start = buffer.getPos(); |
| SearchRequest searchRequest = ( SearchRequest ) message; |
| |
| // The attributes, if any |
| List<String> attributes = searchRequest.getAttributes(); |
| |
| if ( ( attributes != null ) && ( !attributes.isEmpty() ) ) |
| { |
| for ( int i = attributes.size(); i > 0; i-- ) |
| { |
| BerValue.encodeOctetString( buffer, attributes.get( i - 1 ) ); |
| } |
| } |
| |
| // The attributes sequence |
| BerValue.encodeSequence( buffer, start ); |
| |
| // The filter |
| encodeFilter( buffer, searchRequest.getFilter() ); |
| |
| // The typesOnly |
| BerValue.encodeBoolean( buffer, searchRequest.getTypesOnly() ); |
| |
| // The timeLimit |
| BerValue.encodeInteger( buffer, searchRequest.getTimeLimit() ); |
| |
| // The sizeLimit |
| BerValue.encodeInteger( buffer, searchRequest.getSizeLimit() ); |
| |
| // The derefAliases |
| BerValue.encodeEnumerated( buffer, searchRequest.getDerefAliases().getValue() ); |
| |
| // The scope |
| BerValue.encodeEnumerated( buffer, searchRequest.getScope().getScope() ); |
| |
| // The base object |
| BerValue.encodeOctetString( buffer, Strings.getBytesUtf8( searchRequest.getBase().getName() ) ); |
| |
| // The SearchRequest tag |
| BerValue.encodeSequence( buffer, LdapCodecConstants.SEARCH_REQUEST_TAG, start ); |
| } |
| } |