View Javadoc
1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *  
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   *  
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License. 
18   *  
19   */
20  package org.apache.directory.api.ldap.model.message;
21  
22  
23  import java.util.Collections;
24  import java.util.HashMap;
25  import java.util.Map;
26  
27  
28  /**
29   * Abstract message base class.
30   * 
31   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
32   */
33  public abstract class AbstractMessage implements Message
34  {
35      /** Map of message controls using OID Strings for keys and Control values */
36      protected final Map<String, Control> controls;
37  
38      /** The session unique message sequence identifier */
39      private int id;
40  
41      /** The message type enumeration */
42      private final MessageTypeEnum type;
43  
44      /** Transient Message Parameter Hash */
45      private final Map<Object, Object> parameters;
46  
47  
48      /**
49       * Completes the instantiation of a Message.
50       * 
51       * @param id the seq id of the message
52       * @param type the type of the message
53       */
54      protected AbstractMessage( final int id, final MessageTypeEnum type )
55      {
56          this.id = id;
57          this.type = type;
58          controls = new HashMap<>();
59          parameters = new HashMap<>();
60      }
61  
62  
63      /**
64       * Gets the session unique message sequence id for this message. Requests
65       * and their responses if any have the same message id. Clients at the
66       * initialization of a session start with the first message's id set to 1
67       * and increment it with each transaction.
68       * 
69       * @return the session unique message id.
70       */
71      @Override
72      public int getMessageId()
73      {
74          return id;
75      }
76  
77  
78      /**
79       * {@inheritDoc}
80       */
81      @Override
82      public Message setMessageId( int id )
83      {
84          this.id = id;
85  
86          return this;
87      }
88  
89  
90      /**
91       * {@inheritDoc}
92       */
93      @Override
94      public Map<String, Control> getControls()
95      {
96          return Collections.unmodifiableMap( controls );
97      }
98  
99  
100     /**
101      * {@inheritDoc}
102      */
103     @Override
104     public Control getControl( String oid )
105     {
106         return controls.get( oid );
107     }
108 
109 
110     /**
111      * {@inheritDoc}
112      */
113     @Override
114     public boolean hasControl( String oid )
115     {
116         return controls.containsKey( oid );
117     }
118 
119 
120     /**
121      * {@inheritDoc}
122      */
123     @Override
124     public Message addControl( Control control )
125     {
126         controls.put( control.getOid(), control );
127 
128         return this;
129     }
130 
131 
132     /**
133      * Deletes a control removing it from this Message.
134      * 
135      * @param control the control to remove.
136      */
137     @Override
138     public Message removeControl( Control control )
139     {
140         controls.remove( control.getOid() );
141 
142         return this;
143     }
144 
145 
146     /**
147      * Gets the LDAP message type code associated with this Message. Each
148      * request and response type has a unique message type code defined by the
149      * protocol in <a href="http://www.faqs.org/rfcs/rfc2251.html">RFC 2251</a>.
150      * 
151      * @return the message type code.
152      */
153     @Override
154     public MessageTypeEnum getType()
155     {
156         return type;
157     }
158 
159 
160     /**
161      * Gets a message scope parameter. Message scope parameters are temporary
162      * variables associated with a message and are set locally to be used to
163      * associate housekeeping information with a request or its processing.
164      * These parameters are never transmitted nor received, think of them as
165      * transient data associated with the message or its processing. These
166      * transient parameters are not locked down so modifications can occur
167      * without firing LockExceptions even when this Lockable is in the locked
168      * state.
169      * 
170      * @param key the key used to access a message parameter.
171      * @return the transient message parameter value.
172      */
173     @Override
174     public Object get( Object key )
175     {
176         return parameters.get( key );
177     }
178 
179 
180     /**
181      * Sets a message scope parameter. These transient parameters are not locked
182      * down so modifications can occur without firing LockExceptions even when
183      * this Lockable is in the locked state.
184      * 
185      * @param key the parameter key
186      * @param value the parameter value
187      * @return the old value or null
188      */
189     @Override
190     public Object put( Object key, Object value )
191     {
192         return parameters.put( key, value );
193     }
194 
195 
196     /**
197      * Checks to see if two messages are equivalent. Messages equivalence does
198      * not factor in parameters accessible through the get() and put()
199      * operations, nor do they factor in the Lockable properties of the Message.
200      * Only the type, controls, and the messageId are evaluated for equality.
201      * 
202      * @param obj the object to compare this Message to for equality
203      */
204     @Override
205     public boolean equals( Object obj )
206     {
207         if ( obj == this )
208         {
209             return true;
210         }
211 
212         if ( ( obj == null ) || !( obj instanceof Message ) )
213         {
214             return false;
215         }
216 
217         Message msg = ( Message ) obj;
218 
219         if ( msg.getMessageId() != id )
220         {
221             return false;
222         }
223 
224         if ( msg.getType() != type )
225         {
226             return false;
227         }
228 
229         Map<String, Control> controlMap = msg.getControls();
230 
231         if ( controlMap.size() != controls.size() )
232         {
233             return false;
234         }
235 
236         for ( String key : controls.keySet() )
237         {
238             if ( !controlMap.containsKey( key ) )
239             {
240                 return false;
241             }
242         }
243 
244         return true;
245     }
246 
247 
248     /**
249      * @see Object#hashCode()
250      * @return the instance's hash code 
251      */
252     @Override
253     public int hashCode()
254     {
255         int hash = 37;
256         hash = hash * 17 + id;
257         hash = hash * 17 + ( type == null ? 0 : type.hashCode() );
258         hash = hash * 17 + ( parameters == null ? 0 : parameters.hashCode() );
259         hash = hash * 17 + ( controls == null ? 0 : controls.hashCode() );
260 
261         return hash;
262     }
263 
264 
265     /**
266      * {@inheritDoc}
267      */
268     @Override
269     public Message addAllControls( Control[] controls )
270     {
271         for ( Control c : controls )
272         {
273             this.controls.put( c.getOid(), c );
274         }
275 
276         return this;
277     }
278 
279 
280     /**
281      * Get a String representation of a LdapMessage
282      * 
283      * @param message The message to print
284      * @return A LdapMessage String
285      */
286     public String toString( String message )
287     {
288         StringBuilder sb = new StringBuilder();
289 
290         sb.append( "MessageType : " ).append( type ).append( '\n' );
291         sb.append( "Message ID : " ).append( id ).append( '\n' );
292 
293         sb.append( message );
294 
295         if ( controls != null )
296         {
297             for ( Control control : controls.values() )
298             {
299                 sb.append( control );
300             }
301         }
302 
303         return sb.toString();
304     }
305 }