POAPolicyMediatorImpl_R_USM.java revision 608:7e06bf1dcb09
1/* 2 * Copyright (c) 2002, 2004, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26package com.sun.corba.se.impl.oa.poa ; 27 28import java.util.Set ; 29 30import org.omg.CORBA.SystemException ; 31 32import org.omg.PortableServer.ServantActivator ; 33import org.omg.PortableServer.Servant ; 34import org.omg.PortableServer.ServantManager ; 35import org.omg.PortableServer.ForwardRequest ; 36import org.omg.PortableServer.POAPackage.WrongPolicy ; 37import org.omg.PortableServer.POAPackage.ObjectNotActive ; 38import org.omg.PortableServer.POAPackage.ServantNotActive ; 39import org.omg.PortableServer.POAPackage.ObjectAlreadyActive ; 40import org.omg.PortableServer.POAPackage.ServantAlreadyActive ; 41import org.omg.PortableServer.POAPackage.NoServant ; 42 43import com.sun.corba.se.impl.orbutil.concurrent.SyncUtil ; 44import com.sun.corba.se.impl.orbutil.ORBUtility ; 45import com.sun.corba.se.impl.orbutil.ORBConstants ; 46 47import com.sun.corba.se.impl.oa.NullServantImpl ; 48 49import com.sun.corba.se.impl.javax.rmi.CORBA.Util ; 50 51import com.sun.corba.se.spi.oa.OAInvocationInfo ; 52import com.sun.corba.se.spi.oa.NullServant ; 53 54/** Implementation of POARequesHandler that provides policy specific 55 * operations on the POA. 56 */ 57public class POAPolicyMediatorImpl_R_USM extends POAPolicyMediatorBase_R { 58 protected ServantActivator activator ; 59 60 POAPolicyMediatorImpl_R_USM( Policies policies, POAImpl poa ) 61 { 62 // assert policies.retainServants() 63 super( policies, poa ) ; 64 activator = null ; 65 66 if (!policies.useServantManager()) 67 throw poa.invocationWrapper().policyMediatorBadPolicyInFactory() ; 68 } 69 70 /* This handles a rather subtle bug (4939892). The problem is that 71 * enter will wait on the entry if it is being etherealized. When the 72 * deferred state transition completes, the entry is no longer in the 73 * AOM, and so we need to get a new entry, otherwise activator.incarnate 74 * will be called twice, once for the old entry, and again when a new 75 * entry is created. This fix also required extending the FSM StateEngine 76 * to allow actions to throw exceptions, and adding a new state in the 77 * AOMEntry FSM to detect this condition. 78 */ 79 private AOMEntry enterEntry( ActiveObjectMap.Key key ) 80 { 81 AOMEntry result = null ; 82 boolean failed ; 83 do { 84 failed = false ; 85 result = activeObjectMap.get(key) ; 86 87 try { 88 result.enter() ; 89 } catch (Exception exc) { 90 failed = true ; 91 } 92 } while (failed) ; 93 94 return result ; 95 } 96 97 protected java.lang.Object internalGetServant( byte[] id, 98 String operation ) throws ForwardRequest 99 { 100 if (poa.getDebug()) { 101 ORBUtility.dprint( this, 102 "Calling POAPolicyMediatorImpl_R_USM.internalGetServant " + 103 "for poa " + poa + " operation=" + operation ) ; 104 } 105 106 try { 107 ActiveObjectMap.Key key = new ActiveObjectMap.Key( id ) ; 108 AOMEntry entry = enterEntry(key) ; 109 java.lang.Object servant = activeObjectMap.getServant( entry ) ; 110 if (servant != null) { 111 if (poa.getDebug()) { 112 ORBUtility.dprint( this, 113 "internalGetServant: servant already activated" ) ; 114 } 115 116 return servant ; 117 } 118 119 if (activator == null) { 120 if (poa.getDebug()) { 121 ORBUtility.dprint( this, 122 "internalGetServant: no servant activator in POA" ) ; 123 } 124 125 entry.incarnateFailure() ; 126 throw poa.invocationWrapper().poaNoServantManager() ; 127 } 128 129 // Drop the POA lock during the incarnate call and 130 // re-acquire it afterwards. The entry state machine 131 // prevents more than one thread from executing the 132 // incarnate method at a time within the same POA. 133 try { 134 if (poa.getDebug()) { 135 ORBUtility.dprint( this, 136 "internalGetServant: upcall to incarnate" ) ; 137 } 138 139 poa.unlock() ; 140 141 servant = activator.incarnate(id, poa); 142 143 if (servant == null) 144 servant = new NullServantImpl( 145 poa.omgInvocationWrapper().nullServantReturned() ) ; 146 } catch (ForwardRequest freq) { 147 if (poa.getDebug()) { 148 ORBUtility.dprint( this, 149 "internalGetServant: incarnate threw ForwardRequest" ) ; 150 } 151 152 throw freq ; 153 } catch (SystemException exc) { 154 if (poa.getDebug()) { 155 ORBUtility.dprint( this, 156 "internalGetServant: incarnate threw SystemException " + exc ) ; 157 } 158 159 throw exc ; 160 } catch (Throwable exc) { 161 if (poa.getDebug()) { 162 ORBUtility.dprint( this, 163 "internalGetServant: incarnate threw Throwable " + exc ) ; 164 } 165 166 throw poa.invocationWrapper().poaServantActivatorLookupFailed( 167 exc ) ; 168 } finally { 169 poa.lock() ; 170 171 // servant == null means incarnate threw an exception, 172 // while servant instanceof NullServant means incarnate returned a 173 // null servant. Either case is an incarnate failure to the 174 // entry state machine. 175 if ((servant == null) || (servant instanceof NullServant)) { 176 if (poa.getDebug()) { 177 ORBUtility.dprint( this, 178 "internalGetServant: incarnate failed" ) ; 179 } 180 181 // XXX Does the AOM leak in this case? Yes, 182 // but the problem is hard to fix. There may be 183 // a number of threads waiting for the state to change 184 // from INCARN to something else, which is VALID or 185 // INVALID, depending on the incarnate result. 186 // The activeObjectMap.get() call above creates an 187 // ActiveObjectMap.Entry if one does not already exist, 188 // and stores it in the keyToEntry map in the AOM. 189 entry.incarnateFailure() ; 190 } else { 191 // here check for unique_id policy, and if the servant 192 // is already registered for a different ID, then throw 193 // OBJ_ADAPTER exception, else activate it. Section 11.3.5.1 194 // 99-10-07.pdf 195 if (isUnique) { 196 // check if the servant already is associated with some id 197 if (activeObjectMap.contains((Servant)servant)) { 198 if (poa.getDebug()) { 199 ORBUtility.dprint( this, 200 "internalGetServant: servant already assigned to ID" ) ; 201 } 202 203 entry.incarnateFailure() ; 204 throw poa.invocationWrapper().poaServantNotUnique() ; 205 } 206 } 207 208 if (poa.getDebug()) { 209 ORBUtility.dprint( this, 210 "internalGetServant: incarnate complete" ) ; 211 } 212 213 entry.incarnateComplete() ; 214 activateServant(key, entry, (Servant)servant); 215 } 216 } 217 218 return servant ; 219 } finally { 220 if (poa.getDebug()) { 221 ORBUtility.dprint( this, 222 "Exiting POAPolicyMediatorImpl_R_USM.internalGetServant " + 223 "for poa " + poa ) ; 224 } 225 } 226 } 227 228 public void returnServant() 229 { 230 OAInvocationInfo info = orb.peekInvocationInfo(); 231 byte[] id = info.id() ; 232 ActiveObjectMap.Key key = new ActiveObjectMap.Key( id ) ; 233 AOMEntry entry = activeObjectMap.get( key ) ; 234 entry.exit() ; 235 } 236 237 public void etherealizeAll() 238 { 239 if (activator != null) { 240 Set keySet = activeObjectMap.keySet() ; 241 242 // Copy the elements in the set to an array to avoid 243 // changes in the set due to concurrent modification 244 ActiveObjectMap.Key[] keys = 245 (ActiveObjectMap.Key[])keySet.toArray( 246 new ActiveObjectMap.Key[ keySet.size() ] ) ; 247 248 for (int ctr=0; ctr<keySet.size(); ctr++) { 249 ActiveObjectMap.Key key = keys[ctr] ; 250 AOMEntry entry = activeObjectMap.get( key ) ; 251 Servant servant = activeObjectMap.getServant( entry ) ; 252 if (servant != null) { 253 boolean remainingActivations = 254 activeObjectMap.hasMultipleIDs(entry) ; 255 256 // Here we etherealize in the thread that called this 257 // method, rather than etherealizing in a new thread 258 // as in the deactivate case. We still inform the 259 // entry state machine so that only one thread at a 260 // time can call the etherealize method. 261 entry.startEtherealize( null ) ; 262 try { 263 poa.unlock() ; 264 try { 265 activator.etherealize(key.id, poa, servant, true, 266 remainingActivations); 267 } catch (Exception exc) { 268 // ignore all exceptions 269 } 270 } finally { 271 poa.lock() ; 272 entry.etherealizeComplete() ; 273 } 274 } 275 } 276 } 277 } 278 279 public ServantManager getServantManager() throws WrongPolicy 280 { 281 return activator; 282 } 283 284 public void setServantManager( 285 ServantManager servantManager ) throws WrongPolicy 286 { 287 if (activator != null) 288 throw poa.invocationWrapper().servantManagerAlreadySet() ; 289 290 if (servantManager instanceof ServantActivator) 291 activator = (ServantActivator)servantManager; 292 else 293 throw poa.invocationWrapper().servantManagerBadType() ; 294 } 295 296 public Servant getDefaultServant() throws NoServant, WrongPolicy 297 { 298 throw new WrongPolicy(); 299 } 300 301 public void setDefaultServant( Servant servant ) throws WrongPolicy 302 { 303 throw new WrongPolicy(); 304 } 305 306 class Etherealizer extends Thread { 307 private POAPolicyMediatorImpl_R_USM mediator ; 308 private ActiveObjectMap.Key key ; 309 private AOMEntry entry ; 310 private Servant servant ; 311 private boolean debug ; 312 313 public Etherealizer( POAPolicyMediatorImpl_R_USM mediator, 314 ActiveObjectMap.Key key, AOMEntry entry, Servant servant, 315 boolean debug ) 316 { 317 this.mediator = mediator ; 318 this.key = key ; 319 this.entry = entry; 320 this.servant = servant; 321 this.debug = debug ; 322 } 323 324 public void run() { 325 if (debug) { 326 ORBUtility.dprint( this, "Calling Etherealizer.run on key " + 327 key ) ; 328 } 329 330 try { 331 try { 332 mediator.activator.etherealize( key.id, mediator.poa, servant, 333 false, mediator.activeObjectMap.hasMultipleIDs( entry ) ); 334 } catch (Exception exc) { 335 // ignore all exceptions 336 } 337 338 try { 339 mediator.poa.lock() ; 340 341 entry.etherealizeComplete() ; 342 mediator.activeObjectMap.remove( key ) ; 343 344 POAManagerImpl pm = (POAManagerImpl)mediator.poa.the_POAManager() ; 345 POAFactory factory = pm.getFactory() ; 346 factory.unregisterPOAForServant( mediator.poa, servant); 347 } finally { 348 mediator.poa.unlock() ; 349 } 350 } finally { 351 if (debug) { 352 ORBUtility.dprint( this, "Exiting Etherealizer.run" ) ; 353 } 354 } 355 } 356 } 357 358 public void deactivateHelper( ActiveObjectMap.Key key, AOMEntry entry, 359 Servant servant ) throws ObjectNotActive, WrongPolicy 360 { 361 if (activator == null) 362 throw poa.invocationWrapper().poaNoServantManager() ; 363 364 Etherealizer eth = new Etherealizer( this, key, entry, servant, poa.getDebug() ) ; 365 entry.startEtherealize( eth ) ; 366 } 367 368 public Servant idToServant( byte[] id ) 369 throws WrongPolicy, ObjectNotActive 370 { 371 ActiveObjectMap.Key key = new ActiveObjectMap.Key( id ) ; 372 AOMEntry entry = activeObjectMap.get(key); 373 374 Servant servant = activeObjectMap.getServant( entry ) ; 375 if (servant != null) 376 return servant ; 377 else 378 throw new ObjectNotActive() ; 379 } 380} 381