1 //!-- UTF8 2 /* 3 Oregano Multiuser Server - Version 1.2.0 - January 4th, 2005 4 5 Web: www.oregano-server.org 6 Mail: info@oregano-server.org 7 8 Copyright 2003 - 2004 - 2004 Jens Halm / Cologne, Germany 9 10 This library is free software; you can redistribute it and/or 11 modify it under the terms of the GNU Lesser General Public 12 License as published by the Free Software Foundation; either 13 version 2.1 of the License, or (at your option) any later version. 14 15 This library is distributed in the hope that it will be useful, 16 but WITHOUT ANY WARRANTY; without even the implied warranty of 17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 Lesser General Public License for more details. 19 20 You should have received a copy of the GNU Lesser General Public 21 License along with this library; if not, write to the Free Software 22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23 */ 24 25 /* 26 ------------------------------------------- 27 Classe Locks 28 29 @description : 30 Gestion des verrous de prorpiétés dans un groupe. 31 32 33 @author Jens Halm copyright http://www.spicefactory.org/ 34 @author erixtekila copyleft http://www.v-i-a.net 35 ------------------------------------------- 36 version history : 37 1.2.0 : 04/02/05 38 - Portage en actionscript 2 pour le 39 compile time type checking 40 ------------------------------------------- 41 */ 42 43 import org.omus.util.EventDispatcher; 44 import org.omus.util.iObservable; 45 import org.omus.util._Error; 46 import org.omus.util._Class; 47 48 import org.omus.msg.EnvelopeFactory; 49 import org.omus.msg.Envelope; 50 import org.omus.msg.Message; 51 52 import org.omus.core.Session; 53 54 /** 55 * Cette classe gère des verrous sur certaines propriétés comprises dans une groupe. 56 * <p> 57 * Evénements auxquels s'abonner : 58 * <ul> 59 * <li>onAcquire(lockName:String, success:Boolean) Généré lorsq'une demande de gestion de verrou est effectuée. 60 * _param loockName Nom du verrou. 61 * _param success true pour accepté, false pour refusé. 62 * </li><li>onRelease(lockName:String) Généré lorsqu'un verrou est dévérouillé. 63 * _param lockName Nom du verrou. 64 * </li><li>onReleaseAll Généré lorsque tous les verrous sont ouverts. 65 * </li><li>onError(error:_Error) Généré à cause d'une mauvaise modification de propriété persistante. 66 * </li></ul></p> 67 * Elle est aggrémentée par composition des méthodes des sources d'événements (EventDispatcher). 68 * @see org.omus.util.EventDispatcher 69 * @see org.omus.util.iObservable 70 * 71 * @author Jens Halm copyright http://www.spicefactory.org/ 72 * @author erixtekila copyleft http://www.v-i-a.net 73 * @version 1.2.0 74 */ 75 class org.omus.core.Locks implements iObservable 76 { 77 //-------------------- 78 // PROPRIETES 79 //-------------------- 80 /** 81 * Liste des noms de verrous. 82 */ 83 private var lockNames:Array; 84 85 /** 86 * Référence au système de génération d'événements. 87 */ 88 private var _eventSource:EventDispatcher; 89 90 //-------------------- 91 // CONSTRUCTEUR 92 //-------------------- 93 /** 94 * L'objet Locks dispose des méthodes d'EventDispatcher par composition. 95 * 96 */ 97 public function Locks() 98 { 99 // Composition avec EventDispatcher 100 _eventSource = new EventDispatcher(); 101 102 // Propriétés 103 lockNames = new Array(); 104 105 // trace(this+ " installé."); 106 } 107 108 109 //-------------------- 110 // METHODES PUBLIQUES 111 //-------------------- 112 /** 113 * Utilisé dans un contexte littéral 114 * @return Une chaine définissant l'objet 115 */ 116 public function toString():String 117 { 118 return "[Objet Locks]\norg.omus.Locks: number of acquired locks = " + lockNames.length; 119 } 120 121 /** 122 * Supprime tous les verrous. 123 */ 124 public function reset ():Void 125 { 126 this.lockNames = new Array(); 127 } 128 129 /** 130 * Tente d'obtenir le droit sur une propriété protégée par verrou. 131 * 132 * @param lockName Nom du verrou. 133 */ 134 public function acquire (lockName:String):Void 135 { 136 // TODO : Accès Singleton. 137 var clazz = _Class.getInstance(); 138 var envFactory = EnvelopeFactory.getInstance(); 139 var session = Session.getInstance(); 140 141 if (! clazz.checkArguments("org.omus.core.Locks.acquire", [[lockName, "string", true]])) return; 142 var env = envFactory.getOutgoing(new Message(lockName),"locks.acq"); 143 session.sendMessage(env); 144 } 145 146 /** 147 * Déverouille un verrou. 148 * 149 * @param lockName Nom du verrou. 150 */ 151 public function release (lockName:String):Void 152 { 153 // TODO : Accès Singleton. 154 var clazz = _Class.getInstance(); 155 var envFactory = EnvelopeFactory.getInstance(); 156 var session = Session.getInstance(); 157 158 if (! clazz.checkArguments("org.omus.core.Locks.release", [[lockName, "string", true]])) return; 159 var env = envFactory.getOutgoing(new Message(lockName), "locks.rel"); 160 session.sendMessage(env); 161 } 162 163 /** 164 * Déverouille tous les verrous. 165 */ 166 public function releaseAll ():Void 167 { 168 // TODO : Accès Singleton. 169 var envFactory = EnvelopeFactory.getInstance(); 170 var session = Session.getInstance(); 171 172 var env = envFactory.getOutgoing(new Message(""), "locks.relAll"); 173 session.sendMessage(env); 174 } 175 176 /** 177 * Averti si un verrou a été déposé par un autre utilisateur. 178 * 179 * @param lockName Nom du verrou. 180 * @return true si un verrou est déjà apposé. 181 */ 182 public function isAcquired (lockName:String):Boolean 183 { 184 // TODO : Accès Singleton. 185 var clazz = _Class.getInstance(); 186 var envFactory = EnvelopeFactory.getInstance(); 187 var session = Session.getInstance(); 188 189 if (clazz.checkArguments("org.omus.core.Locks.isAcquired", [[lockName, "string", true]])) 190 { 191 var l = lockNames; 192 var c = l.length; 193 for (var i = 0; i < c; i++) 194 { 195 if (l[i] == lockName) return true; 196 } 197 return false; 198 } 199 } 200 201 /** 202 * Renvoie une liste de tous les verrous actuellement posé par le client. 203 */ 204 public function getAllAcquired ():Array 205 { 206 return lockNames.slice(0, lockNames.length); 207 } 208 209 //*** Implémentation de iObservable ***\ 210 /** 211 * Notifie les observateurs d'un événement. 212 * 213 * @param logLevel Une chaine caractérisant le niveau de logging de l'information. 214 * @param eventName Nom de l'événement. 215 * @param arg1 [option] Autant de paramêtres de voulu. 216 */ 217 private function fireEvent (logLevel:String, eventName:String):Void 218 { 219 _eventSource.fireEvent.apply (_eventSource, arguments); 220 } 221 222 /** 223 * Ajoute un nouvel observateur. 224 * 225 * @param listener Référence de l'observateur. 226 * @return Un booléen indiquant la réussite de l'opération. 227 */ 228 public function addListener (listener:Object):Boolean 229 { 230 return _eventSource.addListener(listener); 231 } 232 233 /** 234 * Supprime un observateur. 235 * 236 * @param listener Référence de l'observateur. 237 * @return Un booléen indiquant la réussite de l'opération. 238 */ 239 public function removeListener (listener:Object):Boolean 240 { 241 return _eventSource.removeListener(listener); 242 } 243 244 /** 245 * Supprime tous les abonnés. 246 */ 247 public function removeAllListeners ():Void 248 { 249 _eventSource.removeAllListeners(); 250 } 251 252 /** 253 * Retourne le nombre d'observateurs. 254 * 255 * @return Le nombre d'observateurs enregistrés. 256 */ 257 public function countListeners ():Number 258 { 259 return _eventSource.countListeners(); 260 } 261 262 //*** Gestionnaire des accusés de réception ***\\ 263 // TODO : Implémenter iMessageHandler ? 264 /* 265 * Gestionnaire de l'accusé de réception de tous les messages serveur. 266 * Génère un événement onAcquire, onRelease, onReleaseAll ou onError aux observateurs. 267 * 268 * @param env Enveloppe du message retourné. 269 */ 270 public function handleMessage (env:Envelope):Void 271 { 272 var type = env.getType(); 273 var msg = env.getMessage(); 274 var lockName = msg.getSubject(); 275 var errCode = msg.getAttachment().error; 276 if (errCode == "ok") 277 { 278 if (type == "locks.acq") 279 { 280 var idx = indexOf(lockName); 281 if (idx == -1) lockNames.push(lockName); 282 // Broadcsat 283 fireEvent("info", "onAcquire", lockName, true); 284 } else 285 { 286 if (type == "locks.rel") 287 { 288 var idx = indexOf(lockName); 289 //!! TODO : Syntaxe. if (idx != -1) l.splice(idx, 1); 290 if (idx != -1) lockNames.splice(idx, 1); 291 // Broadcast 292 fireEvent("info", "onRelease", lockName); 293 } else 294 { 295 var evtName = "onReleaseAll"; 296 lockNames = new Array(); 297 // Broadcast 298 fireEvent("info", "onReleaseAll"); 299 } 300 } 301 } else 302 { 303 var method = (type == "locks.acq") ? "acquire" : (type == "locks.rel") ? "release" : "releaseAll" ; 304 if (method == "acquire" && errCode == "grp-002") 305 { 306 // Broadcast 307 fireEvent("info", "onAcquire", lockName, false); 308 } else 309 { 310 var args = (type == "locks.relAll") ? new Array() : [lockName] ; 311 // Broadcast 312 fireEvent("error","onError",new _Error(errCode, method, args)); 313 } 314 } 315 } 316 317 318 319 //-------------------- 320 // METHODES PRIVEES 321 //-------------------- 322 /** 323 * Retourne l'indice d'un verrou dans la liste 324 * 325 * @param lockName Nom du verrou. 326 * @return L'indice du verrou ou -1 s'il n'existe pas. 327 */ 328 private function indexOf (lockName:String):Number { 329 var l = lockNames; 330 var long = l.length; 331 for (var i = 0; i < long; i++) 332 { 333 if (l[i] == lockName) 334 { 335 return i; 336 } 337 } 338 return -1; 339 } 340 341 //-------------------- 342 // METHODES STATIQUES 343 //-------------------- 344 /** 345 * Utilisé dans un contexte littéral 346 * 347 * @return Une chaine définissant l'objet. 348 */ 349 public static function toLog():String 350 { 351 return "[Objet Locks]"; 352 } 353 } 354