001: /*
002: * JBoss, Home of Professional Open Source.
003: * Copyright 2006, Red Hat Middleware LLC, and individual contributors
004: * as indicated by the @author tags. See the copyright.txt file in the
005: * distribution for a full listing of individual contributors.
006: *
007: * This is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU Lesser General Public License as
009: * published by the Free Software Foundation; either version 2.1 of
010: * the License, or (at your option) any later version.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this software; if not, write to the Free
019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021: */
022: package org.jboss.ejb3;
023:
024: import java.io.Externalizable;
025: import java.io.IOException;
026: import java.io.ObjectInput;
027: import java.io.ObjectOutput;
028: import java.security.Identity;
029: import java.security.Principal;
030: import java.util.Collection;
031: import java.util.HashSet;
032: import java.util.List;
033: import java.util.Properties;
034:
035: import javax.ejb.EJBException;
036: import javax.ejb.EJBHome;
037: import javax.ejb.EJBLocalHome;
038: import javax.ejb.EJBLocalObject;
039: import javax.ejb.EJBObject;
040: import javax.ejb.MessageDrivenContext;
041: import javax.ejb.SessionContext;
042: import javax.ejb.TimerService;
043: import javax.ejb.TransactionManagementType;
044: import javax.naming.InitialContext;
045: import javax.naming.NamingException;
046: import javax.transaction.Status;
047: import javax.transaction.SystemException;
048: import javax.transaction.TransactionManager;
049: import javax.transaction.UserTransaction;
050: import javax.xml.rpc.handler.MessageContext;
051:
052: import org.jboss.annotation.security.SecurityDomain;
053: import org.jboss.aop.Advisor;
054: import org.jboss.ejb3.security.SecurityDomainManager;
055: import org.jboss.ejb3.stateless.StatelessBeanContext;
056: import org.jboss.ejb3.tx.TxUtil;
057: import org.jboss.ejb3.tx.UserTransactionImpl;
058: import org.jboss.logging.Logger;
059: import org.jboss.security.RealmMapping;
060: import org.jboss.security.RunAsIdentity;
061: import org.jboss.security.SecurityAssociation;
062: import org.jboss.security.SimplePrincipal;
063:
064: import org.jboss.metamodel.descriptor.SecurityRoleRef;
065:
066: /**
067: * Comment
068: *
069: * @author <a href="mailto:bill@jboss.org">Bill Burke</a>
070: * @version $Revision: 63839 $
071: */
072: public class BaseSessionContext implements SessionContext,
073: MessageDrivenContext, Externalizable {
074: private static final long serialVersionUID = -2485139227124937217L;
075:
076: private static final Logger log = Logger
077: .getLogger(BaseSessionContext.class);
078: protected transient Container container;
079: protected transient RealmMapping rm;
080: protected BaseContext baseContext;
081:
082: public BaseSessionContext() {
083: }
084:
085: public void setBaseContext(BaseContext baseContext) {
086: this .baseContext = baseContext;
087: }
088:
089: public Container getContainer() {
090: return container;
091: }
092:
093: public void setContainer(Container container) {
094: this .container = container;
095: try {
096: InitialContext ctx = container.getInitialContext();
097: setupSecurityDomain(container, ctx);
098: } catch (NamingException e) {
099: throw new RuntimeException(e);
100: }
101: }
102:
103: private void setupSecurityDomain(Container container,
104: InitialContext ctx) throws NamingException {
105: SecurityDomain securityAnnotation = (SecurityDomain) ((Advisor) container)
106: .resolveAnnotation(SecurityDomain.class);
107: if (securityAnnotation == null)
108: return;
109: Object domain = SecurityDomainManager.getSecurityManager(
110: securityAnnotation.value(), ctx);
111: rm = (RealmMapping) domain;
112: }
113:
114: protected RealmMapping getRm() {
115: return rm;
116: }
117:
118: public void writeExternal(ObjectOutput out) throws IOException {
119: out.writeUTF(container.getObjectName().getCanonicalName());
120: }
121:
122: public void readExternal(ObjectInput in) throws IOException,
123: ClassNotFoundException {
124: container = Ejb3Registry.getContainer(in.readUTF());
125: InitialContext ctx = container.getInitialContext();
126: try {
127: setupSecurityDomain(container, ctx);
128: } catch (NamingException e) {
129: throw new RuntimeException(e);
130: }
131:
132: }
133:
134: //----------------
135:
136: public Object lookup(String name) {
137: String newName;
138: if (name.startsWith("/")) {
139: newName = "env" + name;
140: } else {
141: newName = "env/" + name;
142: }
143: try {
144: return getContainer().getEnc().lookup(newName);
145: } catch (NamingException ignored) {
146: try {
147: return getContainer().getInitialContext().lookup(name);
148: } catch (NamingException ignored2) {
149:
150: }
151: }
152: return null;
153: }
154:
155: public Identity getCallerIdentity() {
156: throw new IllegalStateException("deprecated");
157: }
158:
159: public Principal getCallerPrincipal() {
160: Principal principal = SecurityAssociation.getCallerPrincipal();
161: if (getRm() != null) {
162: principal = getRm().getPrincipal(principal);
163: }
164:
165: // This method never returns null.
166: if (principal == null)
167: throw new java.lang.IllegalStateException(
168: "No valid security context for the caller identity");
169:
170: return principal;
171: }
172:
173: public boolean isCallerInRole(Identity role) {
174: throw new IllegalStateException("deprecated");
175: }
176:
177: public boolean isCallerInRole(String roleName) {
178: // TODO revert to aspects.security.SecurityContext impl when JBoss AOP 1.1 is out.
179: Principal principal = getCallerPrincipal();
180: // Check the caller of this beans run-as identity
181: // todo use priveleged stuff in ejb class
182: RunAsIdentity runAsIdentity = SecurityActions
183: .peekRunAsIdentity(1);
184:
185: if (principal == null && runAsIdentity == null)
186: return false;
187:
188: if (getRm() == null) {
189: String msg = "isCallerInRole() called with no security context. "
190: + "Check that a security-domain has been set for the application.";
191: throw new IllegalStateException(msg);
192: }
193:
194: // Ensure that you go through the security role references that may be configured
195: EJBContainer ejbc = (EJBContainer) container;
196: if (ejbc.getXml() != null) {
197: Collection<SecurityRoleRef> securityRoleRefs = ejbc
198: .getXml().getSecurityRoleRefs();
199: for (SecurityRoleRef roleRef : securityRoleRefs) {
200: String refName = roleRef.getRoleName();
201: if (roleName.equals(refName))
202: roleName = roleRef.getRoleLink();
203: }
204: }
205:
206: HashSet set = new HashSet();
207: set.add(new SimplePrincipal(roleName));
208:
209: if (runAsIdentity == null)
210: return getRm().doesUserHaveRole(principal, set);
211: else
212: return runAsIdentity.doesUserHaveRole(set);
213: }
214:
215: public TimerService getTimerService() throws IllegalStateException {
216: return getContainer().getTimerService();
217: }
218:
219: public UserTransaction getUserTransaction()
220: throws IllegalStateException {
221: TransactionManagementType type = TxUtil
222: .getTransactionManagementType(((Advisor) getContainer()));
223: if (type != TransactionManagementType.BEAN)
224: throw new IllegalStateException(
225: "Container "
226: + getContainer().getEjbName()
227: + ": it is illegal to inject UserTransaction into a CMT bean");
228:
229: return new UserTransactionImpl();
230: }
231:
232: public EJBHome getEJBHome() {
233: throw new EJBException("EJB 3.0 does not have a home type.");
234: }
235:
236: public EJBLocalHome getEJBLocalHome() {
237: throw new EJBException("EJB 3.0 does not have a home type.");
238: }
239:
240: public Properties getEnvironment() {
241: throw new EJBException("Deprecated");
242: }
243:
244: public void setRollbackOnly() throws IllegalStateException {
245: // EJB1.1 11.6.1: Must throw IllegalStateException if BMT
246: TransactionManagementType type = TxUtil
247: .getTransactionManagementType(((Advisor) getContainer()));
248: if (type != TransactionManagementType.CONTAINER)
249: throw new IllegalStateException(
250: "Container "
251: + getContainer().getEjbName()
252: + ": it is illegal to call setRollbackOnly from BMT: "
253: + type);
254:
255: try {
256: TransactionManager tm = TxUtil.getTransactionManager();
257:
258: // The getRollbackOnly and setRollBackOnly method of the SessionContext interface should be used
259: // only in the session bean methods that execute in the context of a transaction.
260: if (tm.getTransaction() == null)
261: throw new IllegalStateException(
262: "setRollbackOnly() not allowed without a transaction.");
263:
264: tm.setRollbackOnly();
265: } catch (SystemException e) {
266: log.warn("failed to set rollback only; ignoring", e);
267: }
268: }
269:
270: public boolean getRollbackOnly() throws IllegalStateException {
271: // EJB1.1 11.6.1: Must throw IllegalStateException if BMT
272: TransactionManagementType type = TxUtil
273: .getTransactionManagementType(((Advisor) getContainer()));
274: if (type != TransactionManagementType.CONTAINER)
275: throw new IllegalStateException(
276: "Container "
277: + getContainer().getEjbName()
278: + ": it is illegal to call getRollbackOnly from BMT: "
279: + type);
280:
281: try {
282: TransactionManager tm = TxUtil.getTransactionManager();
283:
284: // The getRollbackOnly and setRollBackOnly method of the SessionContext interface should be used
285: // only in the session bean methods that execute in the context of a transaction.
286: if (tm.getTransaction() == null)
287: throw new IllegalStateException(
288: "getRollbackOnly() not allowed without a transaction.");
289:
290: // EJBTHREE-805, consider an asynchronous rollback due to timeout
291: int status = tm.getStatus();
292: return status == Status.STATUS_MARKED_ROLLBACK
293: || status == Status.STATUS_ROLLING_BACK
294: || status == Status.STATUS_ROLLEDBACK;
295: } catch (SystemException e) {
296: log.warn("failed to get tx manager status; ignoring", e);
297: return true;
298: }
299: }
300:
301: public EJBLocalObject getEJBLocalObject()
302: throws IllegalStateException {
303: try {
304: Object id = baseContext.getId();
305: EJBLocalObject proxy = (EJBLocalObject) ((SessionContainer) container)
306: .createLocalProxy(id);
307: return proxy;
308: } catch (Exception e) {
309: throw new IllegalStateException(e);
310: }
311: }
312:
313: public EJBObject getEJBObject() throws IllegalStateException {
314: try {
315: Object id = baseContext.getId();
316: EJBObject proxy = (EJBObject) ((SessionContainer) container)
317: .createRemoteProxy(id);
318: return proxy;
319: } catch (Exception e) {
320: throw new IllegalStateException(e);
321: }
322: }
323:
324: public Object getBusinessObject(Class businessInterface)
325: throws IllegalStateException {
326: return ((EJBContainer) container).getBusinessObject(
327: baseContext, businessInterface);
328: }
329:
330: public Class getInvokedBusinessInterface()
331: throws IllegalStateException {
332: return ((SessionContainer) container)
333: .getInvokedBusinessInterface();
334: }
335:
336: public MessageContext getMessageContext()
337: throws IllegalStateException {
338: // disallowed for stateful session beans (EJB3 FR 4.4.1 p 81)
339: if (baseContext instanceof StatelessBeanContext) {
340: MessageContext ctx = ((StatelessBeanContext) baseContext)
341: .getMessageContextJAXRPC();
342: if (ctx == null)
343: throw new IllegalStateException(
344: "No message context found");
345: return ctx;
346: }
347: throw new UnsupportedOperationException(
348: "Only stateless beans can have a message context");
349: }
350:
351: }
|