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 }