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.message.internal;
021
022 import java.util.Collections;
023 import java.util.HashMap;
024 import java.util.Iterator;
025 import java.util.Map;
026
027 import org.apache.directory.shared.ldap.codec.MessageTypeEnum;
028 import org.apache.directory.shared.ldap.codec.controls.CodecControl;
029 import org.apache.directory.shared.ldap.message.MessageException;
030 import org.apache.directory.shared.ldap.message.control.Control;
031
032
033
034 /**
035 * Abstract message base class.
036 *
037 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
038 * @version $Rev: 910150 $
039 */
040 public abstract class InternalAbstractMessage implements InternalMessage
041 {
042 static final long serialVersionUID = 7601738291101182094L;
043
044 /** Map of message controls using OID Strings for keys and Control values */
045 private final Map<String, Control> controls;
046
047 /** The session unique message sequence identifier */
048 private final int id;
049
050 /** The message type enumeration */
051 private final MessageTypeEnum type;
052
053 /** Transient Message Parameter Hash */
054 private final Map<Object, Object> parameters;
055
056
057 /**
058 * Completes the instantiation of a Message.
059 *
060 * @param id
061 * the seq id of the message
062 * @param type
063 * the type of the message
064 */
065 protected InternalAbstractMessage( final int id, final MessageTypeEnum type )
066 {
067 this.id = id;
068 this.type = type;
069 controls = new HashMap<String, Control>();
070 parameters = new HashMap<Object, Object>();
071 }
072
073
074 /**
075 * Gets the session unique message sequence id for this message. Requests
076 * and their responses if any have the same message id. Clients at the
077 * initialization of a session start with the first message's id set to 1
078 * and increment it with each transaction.
079 *
080 * @return the session unique message id.
081 */
082 public int getMessageId()
083 {
084 return id;
085 }
086
087
088 /**
089 * Gets the controls associated with this message mapped by OID.
090 *
091 * @return Map of OID strings to Control object instances.
092 * @see CodecControl
093 */
094 public Map<String, Control> getControls()
095 {
096 return Collections.unmodifiableMap( controls );
097 }
098
099
100 /**
101 * @see org.apache.directory.shared.ldap.message.internal.InternalMessage#hasControl(java.lang.String)
102 */
103 public boolean hasControl( String oid )
104 {
105 return controls.containsKey( oid );
106 }
107
108
109 /**
110 * Adds a control to this Message.
111 *
112 * @param control
113 * the control to add.
114 * @throws MessageException
115 * if controls cannot be added to this Message or the control is
116 * not known etc.
117 */
118 public void add( Control control ) throws MessageException
119 {
120 controls.put( control.getOid(), control );
121 }
122
123
124 /**
125 * Deletes a control removing it from this Message.
126 *
127 * @param control
128 * the control to remove.
129 * @throws MessageException
130 * if controls cannot be added to this Message or the control is
131 * not known etc.
132 */
133 public void remove( Control control ) throws MessageException
134 {
135 controls.remove( control.getOid() );
136 }
137
138
139 /**
140 * Gets the LDAP message type code associated with this Message. Each
141 * request and response type has a unique message type code defined by the
142 * protocol in <a href="http://www.faqs.org/rfcs/rfc2251.html">RFC 2251</a>.
143 *
144 * @return the message type code.
145 */
146 public MessageTypeEnum getType()
147 {
148 return type;
149 }
150
151
152 /**
153 * Gets a message scope parameter. Message scope parameters are temporary
154 * variables associated with a message and are set locally to be used to
155 * associate housekeeping information with a request or its processing.
156 * These parameters are never transmitted nor recieved, think of them as
157 * transient data associated with the message or its processing. These
158 * transient parameters are not locked down so modifications can occur
159 * without firing LockExceptions even when this Lockable is in the locked
160 * state.
161 *
162 * @param key
163 * the key used to access a message parameter.
164 * @return the transient message parameter value.
165 */
166 public Object get( Object key )
167 {
168 return parameters.get( key );
169 }
170
171
172 /**
173 * Sets a message scope parameter. These transient parameters are not locked
174 * down so modifications can occur without firing LockExceptions even when
175 * this Lockable is in the locked state.
176 *
177 * @param key
178 * the parameter key
179 * @param value
180 * the parameter value
181 * @return the old value or null
182 */
183 public Object put( Object key, Object value )
184 {
185 return parameters.put( key, value );
186 }
187
188
189 /**
190 * Checks to see if two messages are equivalent. Messages equivalence does
191 * not factor in parameters accessible through the get() and put()
192 * operations, nor do they factor in the Lockable properties of the Message.
193 * Only the type, controls, and the messageId are evaluated for equality.
194 *
195 * @param obj
196 * the object to compare this Message to for equality
197 */
198 public boolean equals( Object obj )
199 {
200 if ( obj == this )
201 {
202 return true;
203 }
204
205 if ( ( obj == null ) || !( obj instanceof InternalMessage ) )
206 {
207 return false;
208 }
209
210 InternalMessage msg = ( InternalMessage ) obj;
211
212 if ( msg.getMessageId() != id )
213 {
214 return false;
215 }
216
217 if ( msg.getType() != type )
218 {
219 return false;
220 }
221
222 Map<String, Control> controls = msg.getControls();
223
224 if ( controls.size() != this.controls.size() )
225 {
226 return false;
227 }
228
229 Iterator<String> list = this.controls.keySet().iterator();
230
231 while ( list.hasNext() )
232 {
233 if ( !controls.containsKey( list.next() ) )
234 {
235 return false;
236 }
237 }
238
239 return true;
240 }
241
242 /**
243 * @see Object#hashCode()
244 * @return the instance's hash code
245 */
246 public int hashCode()
247 {
248 int hash = 37;
249 hash = hash*17 + id;
250 hash = hash*17 + ( type == null ? 0 : type.hashCode() );
251 hash = hash*17 + ( parameters == null ? 0 : parameters.hashCode() );
252 hash = hash*17 + ( controls == null ? 0 : controls.hashCode() );
253
254 return hash;
255 }
256
257
258 public void addAll( Control[] controls ) throws MessageException
259 {
260 for ( Control c : controls )
261 {
262 this.controls.put( c.getOid(), c );
263 }
264 }
265 }