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<String, Control>();
59          parameters = new HashMap<Object, Object>();
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      public int getMessageId()
72      {
73          return id;
74      }
75  
76  
77      /**
78       * {@inheritDoc}
79       */
80      public Message setMessageId( int id )
81      {
82          this.id = id;
83  
84          return this;
85      }
86  
87  
88      /**
89       * {@inheritDoc}
90       */
91      public Map<String, Control> getControls()
92      {
93          return Collections.unmodifiableMap( controls );
94      }
95  
96  
97      /**
98       * {@inheritDoc}
99       */
100     public Control getControl( String oid )
101     {
102         return controls.get( oid );
103     }
104 
105 
106     /**
107      * {@inheritDoc}
108      */
109     public boolean hasControl( String oid )
110     {
111         return controls.containsKey( oid );
112     }
113 
114 
115     /**
116      * {@inheritDoc}
117      */
118     public Message addControl( Control control )
119     {
120         controls.put( control.getOid(), control );
121 
122         return this;
123     }
124 
125 
126     /**
127      * Deletes a control removing it from this Message.
128      * 
129      * @param control the control to remove.
130      */
131     public Message removeControl( Control control )
132     {
133         controls.remove( control.getOid() );
134 
135         return this;
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 received, 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 the key used to access a message parameter.
163      * @return the transient message parameter value.
164      */
165     public Object get( Object key )
166     {
167         return parameters.get( key );
168     }
169 
170 
171     /**
172      * Sets a message scope parameter. These transient parameters are not locked
173      * down so modifications can occur without firing LockExceptions even when
174      * this Lockable is in the locked state.
175      * 
176      * @param key the parameter key
177      * @param value the parameter value
178      * @return the old value or null
179      */
180     public Object put( Object key, Object value )
181     {
182         return parameters.put( key, value );
183     }
184 
185 
186     /**
187      * Checks to see if two messages are equivalent. Messages equivalence does
188      * not factor in parameters accessible through the get() and put()
189      * operations, nor do they factor in the Lockable properties of the Message.
190      * Only the type, controls, and the messageId are evaluated for equality.
191      * 
192      * @param obj the object to compare this Message to for equality
193      */
194     public boolean equals( Object obj )
195     {
196         if ( obj == this )
197         {
198             return true;
199         }
200 
201         if ( ( obj == null ) || !( obj instanceof Message ) )
202         {
203             return false;
204         }
205 
206         Message msg = ( Message ) obj;
207 
208         if ( msg.getMessageId() != id )
209         {
210             return false;
211         }
212 
213         if ( msg.getType() != type )
214         {
215             return false;
216         }
217 
218         Map<String, Control> controls = msg.getControls();
219 
220         if ( controls.size() != this.controls.size() )
221         {
222             return false;
223         }
224 
225         for ( String key : this.controls.keySet() )
226         {
227             if ( !controls.containsKey( key ) )
228             {
229                 return false;
230             }
231         }
232 
233         return true;
234     }
235 
236 
237     /**
238      * @see Object#hashCode()
239      * @return the instance's hash code 
240      */
241     public int hashCode()
242     {
243         int hash = 37;
244         hash = hash * 17 + id;
245         hash = hash * 17 + ( type == null ? 0 : type.hashCode() );
246         hash = hash * 17 + ( parameters == null ? 0 : parameters.hashCode() );
247         hash = hash * 17 + ( controls == null ? 0 : controls.hashCode() );
248 
249         return hash;
250     }
251 
252 
253     /**
254      * {@inheritDoc}
255      */
256     public Message addAllControls( Control[] controls )
257     {
258         for ( Control c : controls )
259         {
260             this.controls.put( c.getOid(), c );
261         }
262 
263         return this;
264     }
265 
266 
267     /**
268      * Get a String representation of a LdapMessage
269      * 
270      * @return A LdapMessage String
271      */
272     public String toString( String message )
273     {
274         StringBuilder sb = new StringBuilder();
275 
276         sb.append( "MessageType : " ).append( type ).append( '\n' );
277         sb.append( "Message ID : " ).append( id ).append( '\n' );
278 
279         sb.append( message );
280 
281         if ( controls != null )
282         {
283             for ( Control control : controls.values() )
284             {
285                 sb.append( control );
286             }
287         }
288 
289         return sb.toString();
290     }
291 }