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 }