001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * https://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 * 019 */ 020package org.apache.directory.api.ldap.codec.factory; 021 022import java.util.Iterator; 023 024import org.apache.directory.api.asn1.ber.tlv.BerValue; 025import org.apache.directory.api.asn1.util.Asn1Buffer; 026import org.apache.directory.api.ldap.codec.api.LdapApiService; 027import org.apache.directory.api.ldap.codec.api.LdapCodecConstants; 028import org.apache.directory.api.ldap.model.entry.Attribute; 029import org.apache.directory.api.ldap.model.entry.Entry; 030import org.apache.directory.api.ldap.model.entry.Value; 031import org.apache.directory.api.ldap.model.message.AddRequest; 032import org.apache.directory.api.ldap.model.message.Message; 033import org.apache.directory.api.util.CollectionUtils; 034import org.apache.directory.api.util.Strings; 035 036/** 037 * The AddRequest factory. 038 * 039 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 040 */ 041public final class AddRequestFactory implements Messagefactory 042{ 043 /** The static instance */ 044 public static final AddRequestFactory INSTANCE = new AddRequestFactory(); 045 046 private AddRequestFactory() 047 { 048 // Nothing to do 049 } 050 051 052 /** 053 * Encode an entry's Attribute's values. It's done in reverse order, to have the 054 * last value encoded first in the reverse buffer. 055 * <br> 056 * The values are encoded this way : 057 * <pre> 058 * 0x31 LL attributeValues 059 * 0x04 LL attributeValue 060 * ... 061 * 0x04 LL attributeValue 062 * </pre> 063 * 064 * @param buffer The buffer where to put the PDU 065 * @param iterator The iterator built on top of the values 066 */ 067 private void encodeValueReverse( Asn1Buffer buffer, Iterator<Value> iterator ) 068 { 069 iterator = CollectionUtils.reverse( iterator ); 070 while ( iterator.hasNext() ) 071 { 072 Value value = iterator.next(); 073 074 // Encode the value 075 BerValue.encodeOctetString( buffer, value.getBytes() ); 076 } 077 } 078 079 080 /** 081 * Encode the attributes, starting from the end. We iterate through the list 082 * of attributes in reverse order. The last attribute will be encoded first, when 083 * the end of the list will be reached, which is what we went, as we encode from 084 * the end. 085 * <br> 086 * An attribute is encoded this way: 087 * <pre> 088 * 0x30 LL attribute 089 * 0x04 LL attributeType 090 * 0x31 LL attributeValues 091 * 0x04 LL attributeValue 092 * ... 093 * 0x04 LL attributeValue 094 * </pre> 095 * 096 * @param buffer The buffer where to put the PDU 097 * @param iterator The iterator built on top of the attributes 098 */ 099 private void encodeAttributeReverse( Asn1Buffer buffer, Iterator<Attribute> iterator ) 100 { 101 iterator = CollectionUtils.reverse( iterator ); 102 while ( iterator.hasNext() ) 103 { 104 Attribute attribute = iterator.next(); 105 106 // Remind the current position 107 int start = buffer.getPos(); 108 109 // The attributes values 110 if ( attribute.size() == 0 ) 111 { 112 BerValue.encodeOctetString( buffer, Strings.EMPTY_BYTES ); 113 } 114 else 115 { 116 encodeValueReverse( buffer, attribute.iterator() ); 117 } 118 119 // Then the values' SET 120 BerValue.encodeSet( buffer, start ); 121 122 // The attribute type 123 BerValue.encodeOctetString( buffer, attribute.getUpId() ); 124 125 // The attribute sequence 126 BerValue.encodeSequence( buffer, start ); 127 } 128 } 129 130 /** 131 * Encode the AddRequest message to a PDU. 132 * <br> 133 * AddRequest : 134 * <pre> 135 * 0x68 LL 136 * 0x04 LL entry 137 * 0x30 LL attributesList 138 * 0x30 LL attribute 139 * 0x04 LL attributeDescription 140 * 0x31 LL attributeValues 141 * 0x04 LL attributeValue 142 * ... 143 * 0x04 LL attributeValue 144 * ... 145 * 0x30 LL attribute 146 * 0x04 LL attributeDescription 147 * 0x31 LL attributeValue 148 * 0x04 LL attributeValue 149 * ... 150 * 0x04 LL attributeValue 151 * </pre> 152 * 153 * @param codec The LdapApiService instance 154 * @param buffer The buffer where to put the PDU 155 * @param message the AbandonRequest to encode 156 */ 157 @Override 158 public void encodeReverse( LdapApiService codec, Asn1Buffer buffer, Message message ) 159 { 160 int start = buffer.getPos(); 161 AddRequest addRequest = ( AddRequest ) message; 162 163 // The partial attribute list 164 Entry entry = addRequest.getEntry(); 165 166 if ( entry.size() != 0 ) 167 { 168 // Encode the attributes 169 encodeAttributeReverse( buffer, entry.iterator() ); 170 } 171 172 // The attributes sequence 173 BerValue.encodeSequence( buffer, start ); 174 175 // The entry DN 176 BerValue.encodeOctetString( buffer, entry.getDn().getName() ); 177 178 // The AddRequest Tag 179 BerValue.encodeSequence( buffer, LdapCodecConstants.ADD_REQUEST_TAG, start ); 180 } 181}