001 /** 002 * 003 * Licensed to the Apache Software Foundation (ASF) under one or more 004 * contributor license agreements. See the NOTICE file distributed with 005 * this work for additional information regarding copyright ownership. 006 * The ASF licenses this file to You under the Apache License, Version 2.0 007 * (the "License"); you may not use this file except in compliance with 008 * 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, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 package org.apache.geronimo.openejb; 019 020 import javax.naming.Context; 021 import javax.resource.ResourceException; 022 import javax.security.auth.Subject; 023 import javax.security.jacc.PolicyContext; 024 025 import org.apache.commons.logging.Log; 026 import org.apache.commons.logging.LogFactory; 027 import org.apache.geronimo.connector.outbound.connectiontracking.ConnectorInstanceContext; 028 import org.apache.geronimo.connector.outbound.connectiontracking.ConnectorInstanceContextImpl; 029 import org.apache.geronimo.connector.outbound.connectiontracking.TrackedConnectionAssociator; 030 import org.apache.geronimo.naming.java.RootContext; 031 import org.apache.geronimo.security.Callers; 032 import org.apache.geronimo.security.ContextManager; 033 import org.apache.openejb.core.CoreDeploymentInfo; 034 import org.apache.openejb.core.ThreadContext; 035 import org.apache.openejb.core.ThreadContextListener; 036 037 /** 038 * @version $Rev$ $Date$ 039 */ 040 public class GeronimoThreadContextListener implements ThreadContextListener { 041 private static final Log log = LogFactory.getLog(GeronimoThreadContextListener.class); 042 043 // A single stateless listener is used for Geronimo 044 private static final GeronimoThreadContextListener instance = new GeronimoThreadContextListener(); 045 046 static { 047 ThreadContext.addThreadContextListener(instance); 048 } 049 050 public static void init() { 051 // do nothing.. the goal here is to kick off the onetime init above 052 } 053 054 private GeronimoThreadContextListener() { 055 } 056 057 public void contextEntered(ThreadContext oldContext, ThreadContext newContext) { 058 CoreDeploymentInfo deploymentInfo = newContext.getDeploymentInfo(); 059 if (deploymentInfo == null) return; 060 061 EjbDeployment ejbDeployment = deploymentInfo.get(EjbDeployment.class); 062 if (ejbDeployment == null) return; 063 064 // Geronimo call context is used to track old state that must be restored 065 GeronimoCallContext geronimoCallContext = new GeronimoCallContext(); 066 067 // Get the jndi context 068 Context jndiContext = ejbDeployment.getComponentContext(); 069 geronimoCallContext.oldJndiContext = RootContext.getComponentContext(); 070 071 // Demark component boundries for connection tracking if we have a tracker 072 TrackedConnectionAssociator trackedConnectionAssociator = ejbDeployment.getTrackedConnectionAssociator(); 073 if (trackedConnectionAssociator != null) { 074 // create the connector context... this only works with a TrackedConnectionAssociator using lazy association 075 ConnectorInstanceContext connectorContext = new ConnectorInstanceContextImpl(ejbDeployment.getUnshareableResources(), 076 ejbDeployment.getApplicationManagedSecurityResources()); 077 078 // Set connector context 079 try { 080 geronimoCallContext.oldConnectorContext = trackedConnectionAssociator.enter(connectorContext); 081 } catch (ResourceException e) { 082 log.error("Error while entering TrackedConnectionAssociator"); 083 return; 084 } 085 } 086 087 // Set the jndi context into Geronimo's root context 088 RootContext.setComponentContext(jndiContext); 089 090 // set the policy (security) context id 091 String moduleID = newContext.getDeploymentInfo().getModuleID(); 092 PolicyContext.setContextID(moduleID); 093 094 // set the default subject if needed 095 if (ContextManager.getCurrentCaller() == null) { 096 Subject defaultSubject = ejbDeployment.getDefaultSubject(); 097 098 if (defaultSubject != null) { 099 ContextManager.setCallers(defaultSubject, defaultSubject); 100 geronimoCallContext.clearCallers = true; 101 } 102 } 103 104 // apply run as 105 Subject runAsSubject = ejbDeployment.getRunAs(); 106 geronimoCallContext.callers = ContextManager.pushNextCaller(runAsSubject); 107 108 newContext.set(GeronimoCallContext.class, geronimoCallContext); 109 } 110 111 public void contextExited(ThreadContext exitedContext, ThreadContext reenteredContext) { 112 CoreDeploymentInfo deploymentInfo = exitedContext.getDeploymentInfo(); 113 if (deploymentInfo == null) return; 114 115 EjbDeployment ejbDeployment = deploymentInfo.get(EjbDeployment.class); 116 if (ejbDeployment == null) return; 117 118 // Geronimo call context is used to track old state that must be restored 119 GeronimoCallContext geronimoCallContext = exitedContext.get(GeronimoCallContext.class); 120 if (geronimoCallContext == null) return; 121 122 // reset run as 123 ContextManager.popCallers(geronimoCallContext.callers); 124 125 // reset default subject 126 if (geronimoCallContext.clearCallers) { 127 ContextManager.clearCallers(); 128 } 129 130 // reset Geronimo's root jndi context 131 RootContext.setComponentContext(geronimoCallContext.oldJndiContext); 132 133 // reset old connector context 134 TrackedConnectionAssociator trackedConnectionAssociator = ejbDeployment.getTrackedConnectionAssociator(); 135 if (trackedConnectionAssociator != null) { 136 try { 137 trackedConnectionAssociator.exit(geronimoCallContext.oldConnectorContext); 138 } catch (ResourceException e) { 139 log.error("Error while exiting TrackedConnectionAssociator"); 140 } 141 } 142 } 143 144 private static final class GeronimoCallContext { 145 private Context oldJndiContext; 146 private ConnectorInstanceContext oldConnectorContext; 147 private boolean clearCallers; 148 private Callers callers; 149 } 150 }