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 * http://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 */
020 package org.apache.directory.shared.ldap.name;
021
022 import java.io.IOException;
023 import java.io.ObjectInput;
024 import java.io.ObjectOutput;
025
026 import org.apache.directory.shared.ldap.entry.Value;
027 import org.apache.directory.shared.ldap.entry.client.ClientBinaryValue;
028 import org.apache.directory.shared.ldap.entry.client.ClientStringValue;
029 import org.apache.directory.shared.ldap.util.StringTools;
030 import org.slf4j.Logger;
031 import org.slf4j.LoggerFactory;
032
033 /**
034 * A helper class which serialize and deserialize an AttributeTypeAndValue
035 *
036 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
037 * @version $Rev$, $Date$
038 */
039 public class AtavSerializer
040 {
041 /** The LoggerFactory used by this class */
042 protected static final Logger LOG = LoggerFactory.getLogger( AtavSerializer.class );
043
044 /**
045 * Serialize an AttributeTypeAndValue object.
046 *
047 * An AttributeTypeAndValue is composed of a type and a value.
048 * The data are stored following the structure :
049 *
050 * <li>upName</li> The User provided ATAV
051 * <li>start</li> The position of this ATAV in the DN
052 * <li>length</li> The ATAV length
053 * <li>upType</li> The user Provided Type
054 * <li>normType</li> The normalized AttributeType
055 * <li>isHR<li> Tells if the value is a String or not
056 * <p>
057 * if the value is a String :
058 * <li>upValue</li> The User Provided value.
059 * <li>value</li> The normalized value.
060 * <p>
061 * if the value is binary :
062 * <li>upValueLength</li>
063 * <li>upValue</li> The User Provided value.
064 * <li>valueLength</li>
065 * <li>value</li> The normalized value.
066 *
067 * @param atav the AttributeTypeAndValue to serialize
068 * @param out the OutputStream in which the atav will be serialized
069 * @throws IOException If we can't serialize the atav
070 */
071 public static void serialize( AttributeTypeAndValue atav, ObjectOutput out ) throws IOException
072 {
073 if ( StringTools.isEmpty( atav.getUpName() ) ||
074 StringTools.isEmpty( atav.getUpType() ) ||
075 StringTools.isEmpty( atav.getNormType() ) ||
076 ( atav.getStart() < 0 ) ||
077 ( atav.getLength() < 2 ) || // At least a type and '='
078 ( atav.getUpValue().isNull() ) ||
079 ( atav.getNormValue().isNull() ) )
080 {
081 String message = "Cannot serialize an wrong ATAV, ";
082
083 if ( StringTools.isEmpty( atav.getUpName() ) )
084 {
085 message += "the upName should not be null or empty";
086 }
087 else if ( StringTools.isEmpty( atav.getUpType() ) )
088 {
089 message += "the upType should not be null or empty";
090 }
091 else if ( StringTools.isEmpty( atav.getNormType() ) )
092 {
093 message += "the normType should not be null or empty";
094 }
095 else if ( atav.getStart() < 0 )
096 {
097 message += "the start should not be < 0";
098 }
099 else if ( atav.getLength() < 2 )
100 {
101 message += "the length should not be < 2";
102 }
103 else if ( atav.getUpValue().isNull() )
104 {
105 message += "the upValue should not be null";
106 }
107 else if ( atav.getNormValue().isNull() )
108 {
109 message += "the value should not be null";
110 }
111
112 LOG.error( message );
113 throw new IOException( message );
114 }
115
116 out.writeUTF( atav.getUpName() );
117 out.writeInt( atav.getStart() );
118 out.writeInt( atav.getLength() );
119 out.writeUTF( atav.getUpType() );
120 out.writeUTF( atav.getNormType() );
121
122 boolean isHR = !atav.getNormValue().isBinary();
123
124 out.writeBoolean( isHR );
125
126 if ( isHR )
127 {
128 out.writeUTF( atav.getUpValue().getString() );
129 out.writeUTF( atav.getNormValue().getString() );
130 }
131 else
132 {
133 out.writeInt( atav.getUpValue().length() );
134 out.write( atav.getUpValue().getBytes() );
135 out.writeInt( atav.getNormValue().length() );
136 out.write( atav.getNormValue().getBytes() );
137 }
138 }
139
140
141 /**
142 * Deserialize an AttributeTypeAndValue object
143 *
144 * We read back the data to create a new ATAV. The structure
145 * read is exposed in the {@link AttributeTypeAndValue#writeExternal(ObjectOutput)}
146 * method<p>
147 *
148 * @param in the input stream
149 * @throws IOException If the input stream can't be read
150 * @return The constructed AttributeTypeAndValue
151 */
152 public static AttributeTypeAndValue deserialize( ObjectInput in ) throws IOException
153 {
154 String upName = in.readUTF();
155 int start = in.readInt();
156 int length = in.readInt();
157 String upType = in.readUTF();
158 String normType = in.readUTF();
159
160 boolean isHR = in.readBoolean();
161
162 if ( isHR )
163 {
164 Value<String> upValue = new ClientStringValue( in.readUTF() );
165 Value<String> normValue = new ClientStringValue( in.readUTF() );
166 AttributeTypeAndValue atav =
167 new AttributeTypeAndValue( upType, normType, upValue, normValue, start, length, upName );
168
169 return atav;
170 }
171 else
172 {
173 int upValueLength = in.readInt();
174 byte[] upValue = new byte[upValueLength];
175 in.readFully( upValue );
176
177 int valueLength = in.readInt();
178 byte[] normValue = new byte[valueLength];
179 in.readFully( normValue );
180
181 AttributeTypeAndValue atav =
182 new AttributeTypeAndValue( upType, normType,
183 new ClientBinaryValue( upValue) ,
184 new ClientBinaryValue( normValue ), start, length, upName );
185
186 return atav;
187 }
188 }
189 }