1 /*
   2  * Copyright (c) 2002, 2009, 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 
  26 package com.sun.corba.se.impl.oa.poa ;
  27 
  28 import java.util.Set ;
  29 import java.util.HashSet ;
  30 import java.util.Collections ;
  31 import java.util.Iterator ;
  32 import java.util.Map ;
  33 import java.util.WeakHashMap ;
  34 
  35 import org.omg.CORBA.OBJECT_NOT_EXIST ;
  36 import org.omg.CORBA.TRANSIENT ;
  37 
  38 import org.omg.CORBA.ORBPackage.InvalidName ;
  39 
  40 import org.omg.PortableServer.Servant ;
  41 import org.omg.PortableServer.POA ;
  42 import org.omg.PortableServer.POAManager ;
  43 
  44 import com.sun.corba.se.spi.oa.ObjectAdapter ;
  45 import com.sun.corba.se.spi.oa.ObjectAdapterFactory ;
  46 
  47 import com.sun.corba.se.spi.ior.ObjectAdapterId ;
  48 
  49 import com.sun.corba.se.spi.orb.ORB ;
  50 
  51 import com.sun.corba.se.spi.orbutil.closure.Closure ;
  52 import com.sun.corba.se.spi.orbutil.closure.ClosureFactory ;
  53 
  54 import com.sun.corba.se.spi.protocol.PIHandler ;
  55 
  56 import com.sun.corba.se.spi.logging.CORBALogDomains ;
  57 
  58 import com.sun.corba.se.impl.logging.POASystemException ;
  59 import com.sun.corba.se.impl.logging.OMGSystemException ;
  60 
  61 import com.sun.corba.se.impl.orbutil.ORBConstants ;
  62 
  63 import com.sun.corba.se.impl.oa.poa.POAManagerImpl ;
  64 
  65 public class POAFactory implements ObjectAdapterFactory
  66 {
  67     // Maps servants to POAs for deactivating servants when unexportObject is called.
  68     // Maintained by POAs activate_object and deactivate_object.
  69     private Map exportedServantsToPOA = new WeakHashMap();
  70 
  71     private Set poaManagers ;
  72     private int poaManagerId ;
  73     private int poaId ;
  74     private POAImpl rootPOA ;
  75     private DelegateImpl delegateImpl;
  76     private ORB orb ;
  77     private POASystemException wrapper ;
  78     private OMGSystemException omgWrapper ;
  79     private boolean isShuttingDown = false;
  80 
  81     public POASystemException getWrapper()
  82     {
  83         return wrapper ;
  84     }
  85 
  86     /** All object adapter factories must have a no-arg constructor.
  87     */
  88     public POAFactory()
  89     {
  90         poaManagers = Collections.synchronizedSet(new HashSet(4));
  91         poaManagerId = 0 ;
  92         poaId = 0 ;
  93         rootPOA = null ;
  94         delegateImpl = null ;
  95         orb = null ;
  96     }
  97 
  98     public synchronized POA lookupPOA (Servant servant)
  99     {
 100         return (POA)exportedServantsToPOA.get(servant);
 101     }
 102 
 103     public synchronized void registerPOAForServant(POA poa, Servant servant)
 104     {
 105         exportedServantsToPOA.put(servant, poa);
 106     }
 107 
 108     public synchronized void unregisterPOAForServant(POA poa, Servant servant)
 109     {
 110         exportedServantsToPOA.remove(servant);
 111     }
 112 
 113 // Implementation of ObjectAdapterFactory interface
 114 
 115     public void init( ORB orb )
 116     {
 117         this.orb = orb ;
 118         wrapper = POASystemException.get( orb,
 119             CORBALogDomains.OA_LIFECYCLE ) ;
 120         omgWrapper = OMGSystemException.get( orb,
 121             CORBALogDomains.OA_LIFECYCLE ) ;
 122         delegateImpl = new DelegateImpl( orb, this ) ;
 123         registerRootPOA() ;
 124 
 125         POACurrent poaCurrent = new POACurrent(orb);
 126         orb.getLocalResolver().register( ORBConstants.POA_CURRENT_NAME,
 127             ClosureFactory.makeConstant( poaCurrent ) ) ;
 128     }
 129 
 130     public ObjectAdapter find( ObjectAdapterId oaid )
 131     {
 132         POA poa=null;
 133         try {
 134             boolean first = true ;
 135             Iterator iter = oaid.iterator() ;
 136             poa = getRootPOA();
 137             while (iter.hasNext()) {
 138                 String name = (String)(iter.next()) ;
 139 
 140                 if (first) {
 141                     if (!name.equals( ORBConstants.ROOT_POA_NAME ))
 142                         throw wrapper.makeFactoryNotPoa( name ) ;
 143                     first = false ;
 144                 } else {
 145                     poa = poa.find_POA( name, true ) ;
 146                 }
 147             }
 148         } catch ( org.omg.PortableServer.POAPackage.AdapterNonExistent ex ){
 149             throw omgWrapper.noObjectAdaptor( ex ) ;
 150         } catch ( OBJECT_NOT_EXIST ex ) {
 151             throw ex;
 152         } catch ( TRANSIENT ex ) {
 153             throw ex;
 154         } catch ( Exception ex ) {
 155             throw wrapper.poaLookupError( ex ) ;
 156         }
 157 
 158         if ( poa == null )
 159             throw wrapper.poaLookupError() ;
 160 
 161         return (ObjectAdapter)poa;
 162     }
 163 
 164     public void shutdown( boolean waitForCompletion )
 165     {
 166         // It is important to copy the list of POAManagers first because
 167         // pm.deactivate removes itself from poaManagers!
 168         Iterator managers = null ;
 169         synchronized (this) {
 170             isShuttingDown = true ;
 171             managers = (new HashSet(poaManagers)).iterator();
 172         }
 173 
 174         while ( managers.hasNext() ) {
 175             try {
 176                 ((POAManager)managers.next()).deactivate(true, waitForCompletion);
 177             } catch ( org.omg.PortableServer.POAManagerPackage.AdapterInactive e ) {}
 178         }
 179     }
 180 
 181 // Special methods used to manipulate global POA related state
 182 
 183     public synchronized void removePoaManager( POAManager manager )
 184     {
 185         poaManagers.remove(manager);
 186     }
 187 
 188     public synchronized void addPoaManager( POAManager manager )
 189     {
 190         poaManagers.add(manager);
 191     }
 192 
 193     synchronized public int newPOAManagerId()
 194     {
 195         return poaManagerId++ ;
 196     }
 197 
 198     public void registerRootPOA()
 199     {
 200         // We delay the evaluation of makeRootPOA until
 201         // a call to resolve_initial_references( "RootPOA" ).
 202         // The Future guarantees that makeRootPOA is only called once.
 203         Closure rpClosure = new Closure() {
 204             public Object evaluate() {
 205                 return POAImpl.makeRootPOA( orb ) ;
 206             }
 207         } ;
 208 
 209         orb.getLocalResolver().register( ORBConstants.ROOT_POA_NAME,
 210             ClosureFactory.makeFuture( rpClosure ) ) ;
 211     }
 212 
 213 
 214     public synchronized POA getRootPOA()
 215     {
 216         if (rootPOA == null) {
 217             // See if we are trying to getRootPOA while shutting down the ORB.
 218             if (isShuttingDown) {
 219                 throw omgWrapper.noObjectAdaptor( ) ;
 220             }
 221 
 222             try {
 223                 Object obj = orb.resolve_initial_references(
 224                     ORBConstants.ROOT_POA_NAME ) ;
 225                 rootPOA = (POAImpl)obj ;
 226             } catch (InvalidName inv) {
 227                 throw wrapper.cantResolveRootPoa( inv ) ;
 228             }
 229         }
 230 
 231         return rootPOA;
 232     }
 233 
 234     public org.omg.PortableServer.portable.Delegate getDelegateImpl()
 235     {
 236         return delegateImpl ;
 237     }
 238 
 239     synchronized public int newPOAId()
 240     {
 241         return poaId++ ;
 242     }
 243 
 244     public ORB getORB()
 245     {
 246         return orb ;
 247     }
 248 }