001    /**
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *     http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.geronimo.corba;
018    
019    import org.apache.commons.logging.Log;
020    import org.apache.commons.logging.LogFactory;
021    import org.apache.geronimo.gbean.GBeanLifecycle;
022    import org.apache.geronimo.gbean.InvalidConfigurationException; 
023    import org.omg.CORBA.Any;
024    import org.omg.CORBA.ORB;
025    import org.omg.CORBA.Policy;
026    import org.omg.CosNaming.NamingContextExt;
027    import org.omg.CosNaming.NamingContextExtHelper;
028    import org.omg.PortableServer.IdAssignmentPolicyValue;
029    import org.omg.PortableServer.ImplicitActivationPolicyValue;
030    import org.omg.PortableServer.LifespanPolicyValue;
031    import org.omg.PortableServer.POA;
032    import org.omg.PortableServer.RequestProcessingPolicyValue;
033    import org.omg.PortableServer.ServantRetentionPolicyValue;
034    import org.apache.geronimo.corba.security.ServerPolicy;
035    import org.apache.geronimo.corba.security.ServerPolicyFactory;
036    import org.apache.geronimo.corba.security.config.tss.TSSConfig;
037    import org.apache.geronimo.corba.security.config.tss.TSSNULLTransportConfig;
038    
039    import java.util.HashMap;
040    import java.util.Map;
041    
042     /**
043      * A TSSBean represents a transport-level security profile for exported EJB objects.  An
044      * exported object is attached to a TSSBean-created named POA.  The TSSBean POA
045      * is created in the context of the ORB controlled by a CORBABean instance.
046      * The parent CORBABean controls the transport-level security of the host connection and
047      * defines the endpoint connnection for the object (host and listener port).
048      * TSSBean may then define additional characteristics that
049      * get encoded in the IOR of the connection.
050      * @version $Revision: 497125 $ $Date: 2007-01-17 10:51:30 -0800 (Wed, 17 Jan 2007) $
051      */
052    public class TSSBean implements GBeanLifecycle {
053    
054        private final Log log = LogFactory.getLog(TSSBean.class);
055    
056        private final ClassLoader classLoader;
057        private final String POAName;
058        private final CORBABean server;
059        private POA localPOA;
060        private NamingContextExt initialContext;
061        private TSSConfig tssConfig;
062        private final Map adapters = new HashMap();
063        private Policy securityPolicy;
064    
065        /**
066         * gbean endpoint constructor
067         */
068        public TSSBean() {
069            classLoader = null;
070            POAName = null;
071            server = null;
072        }
073    
074        public TSSBean(ClassLoader classLoader, String POAName, CORBABean server) {
075            this.classLoader = classLoader;
076            this.POAName = POAName;
077            this.server = server;
078        }
079    
080        public CORBABean getServer() {
081            return server;
082        }
083    
084        public String getPOAName() {
085            return POAName;
086        }
087    
088        public TSSConfig getTssConfig() {
089            return tssConfig;
090        }
091    
092        public void setTssConfig(TSSConfig tssConfig) {
093            if (tssConfig == null) tssConfig = new TSSConfig();
094            this.tssConfig = tssConfig;
095        }
096    
097        /**
098         * TODO: Security policy really shouldn't be inserted if there is not CSI
099         * config to put into it.
100         *
101         * @throws Exception
102         */
103        public void doStart() throws Exception {
104            ClassLoader savedLoader = Thread.currentThread().getContextClassLoader();
105            try {
106                Thread.currentThread().setContextClassLoader(classLoader);
107    
108                ORB orb = server.getORB();
109                POA rootPOA = server.getRootPOA();
110    
111                Any any = orb.create_any();
112                any.insert_Value(new ServerPolicy.Config(createCSIv2Config(), classLoader));
113    
114                securityPolicy = orb.create_policy(ServerPolicyFactory.POLICY_TYPE, any);
115                Policy[] policies = new Policy[]{
116                        securityPolicy,
117                        rootPOA.create_lifespan_policy(LifespanPolicyValue.TRANSIENT),
118                        rootPOA.create_request_processing_policy(RequestProcessingPolicyValue.USE_ACTIVE_OBJECT_MAP_ONLY),
119                        rootPOA.create_servant_retention_policy(ServantRetentionPolicyValue.RETAIN),
120                        rootPOA.create_id_assignment_policy(IdAssignmentPolicyValue.USER_ID),
121                        rootPOA.create_implicit_activation_policy(ImplicitActivationPolicyValue.NO_IMPLICIT_ACTIVATION),
122                };
123                // there may be ORB-specific policy overrides required. 
124                policies = server.addPolicyOverrides(policies); 
125                
126                localPOA = rootPOA.create_POA(POAName, rootPOA.the_POAManager(), policies);
127    
128                localPOA.the_POAManager().activate();
129    
130                org.omg.CORBA.Object obj = server.getORB().resolve_initial_references("NameService");
131                // NB:  This is initial context is never used by the TSSBean, but we request it here
132                // to verify that the server ORB is correctly configured and our target server is accessible.
133                initialContext = NamingContextExtHelper.narrow(obj);
134            } catch (NoSuchMethodError e) {
135                log.error("Incorrect level of org.omg.CORBA classes found.\nLikely cause is an incorrect java.endorsed.dirs configuration"); 
136                throw new InvalidConfigurationException("CORBA usage requires Yoko CORBA spec classes in java.endorsed.dirs classpath", e); 
137            } finally {
138                Thread.currentThread().setContextClassLoader(savedLoader);
139            }
140    
141            log.debug("Started CORBA Target Security Service in POA " + POAName);
142        }
143    
144        public void doStop() throws Exception {
145            if (localPOA != null) {
146                // make sure this POA is destroyed so the bean can be potentially restarted.
147                // NOTE:  we do NOT deactivate() the poa manager, as that will take down any
148                // other POAs attached to the same manager.  Just destroying this POA is sufficient.
149                localPOA.destroy(true, false);
150                localPOA = null;
151            }
152            log.debug("Stopped CORBA Target Security Service in POA " + POAName);
153        }
154    
155        public void doFail() {
156            log.warn("Failed CORBA Target Security Service in POA " + POAName);
157        }
158    
159        private TSSConfig createCSIv2Config() {
160            if (tssConfig == null) return null;
161            if (tssConfig.isInherit()) return server.getTssConfig();
162    
163            TSSConfig config = new TSSConfig();
164    
165            if (server.getTssConfig() != null) {
166                config.setTransport_mech(server.getTssConfig().getTransport_mech());
167            } else {
168                config.setTransport_mech(new TSSNULLTransportConfig());
169            }
170    
171            config.getMechListConfig().setStateful(tssConfig.getMechListConfig().isStateful());
172            for (int i = 0; i < tssConfig.getMechListConfig().size(); i++) {
173                config.getMechListConfig().add(tssConfig.getMechListConfig().mechAt(i));
174            }
175    
176            return config;
177        }
178    
179        public void registerContainer(TSSLink tssLink) throws CORBAException {
180            AdapterWrapper adapterWrapper = new AdapterWrapper(tssLink);
181    
182            adapterWrapper.start(server.getORB(), localPOA, securityPolicy);
183            adapters.put(tssLink.getContainerId(), adapterWrapper);
184    
185            log.debug(POAName + " - Linked container " + tssLink.getContainerId());
186        }
187    
188        public void unregisterContainer(TSSLink tssLink) {
189            AdapterWrapper adapterWrapper = (AdapterWrapper) adapters.remove(tssLink.getContainerId());
190            if (adapterWrapper != null) {
191                try {
192                    adapterWrapper.stop();
193                    log.debug(POAName + " - Unlinked container " + tssLink.getContainerId());
194                } catch (CORBAException e) {
195                    log.error(POAName + " - Error unlinking container " + tssLink.getContainerId(), e);
196                }
197            }
198        }
199        
200        /**
201         * Add the policy overrides (if any) to the list 
202         * of policies used to create a POA instance.
203         * 
204         * @param policies The base set of policies.
205         * 
206         * @return A new Policy array with the overrides added.  Returns
207         *         the same array if no overrides are required.
208         */
209        public Policy[] addPolicyOverrides(Policy[] policies) {
210            return server.addPolicyOverrides(policies); 
211        }
212    }