Source Code Cross Referenced for JFactory.java in  » J2EE » JOnAS-4.8.6 » org » objectweb » jonas_ejb » container » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » J2EE » JOnAS 4.8.6 » org.objectweb.jonas_ejb.container 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /**
0002:         * JOnAS: Java(TM) Open Application Server
0003:         * Copyright (C) 1999-2005 Bull S.A.
0004:         * Contact: jonas-team@objectweb.org
0005:         *
0006:         * This library is free software; you can redistribute it and/or
0007:         * modify it under the terms of the GNU Lesser General Public
0008:         * License as published by the Free Software Foundation; either
0009:         * version 2.1 of the License, or any later version.
0010:         *
0011:         * This library is distributed in the hope that it will be useful,
0012:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
0013:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0014:         * Lesser General Public License for more details.
0015:         *
0016:         * You should have received a copy of the GNU Lesser General Public
0017:         * License along with this library; if not, write to the Free Software
0018:         * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
0019:         * USA
0020:         *
0021:         * --------------------------------------------------------------------------
0022:         * $Id: JFactory.java 10144 2007-04-05 06:48:57Z durieuxp $
0023:         * --------------------------------------------------------------------------
0024:         */package org.objectweb.jonas_ejb.container;
0025:
0026:        import java.io.File;
0027:        import java.io.FileInputStream;
0028:        import java.io.IOException;
0029:        import java.lang.reflect.Field;
0030:        import java.net.URLClassLoader;
0031:        import java.rmi.NoSuchObjectException;
0032:        import java.rmi.RemoteException;
0033:        import java.util.Enumeration;
0034:        import java.util.Hashtable;
0035:        import java.util.Properties;
0036:
0037:        import javax.ejb.EJBException;
0038:        import javax.ejb.Timer;
0039:        import javax.ejb.TimerService;
0040:        import javax.ejb.TransactionRequiredLocalException;
0041:        import javax.ejb.TransactionRolledbackLocalException;
0042:        import javax.naming.Context;
0043:        import javax.naming.InitialContext;
0044:        import javax.naming.NamingException;
0045:        import javax.resource.spi.work.WorkManager;
0046:        import javax.transaction.NotSupportedException;
0047:        import javax.transaction.RollbackException;
0048:        import javax.transaction.Status;
0049:        import javax.transaction.SystemException;
0050:        import javax.transaction.Transaction;
0051:        import javax.transaction.TransactionRequiredException;
0052:        import javax.transaction.TransactionRolledbackException;
0053:
0054:        import org.objectweb.carol.cmi.configuration.TraceCmi;
0055:        import org.objectweb.carol.cmi.ha.RequestId;
0056:        import org.objectweb.carol.rmi.exception.NoSuchObjectExceptionHelper;
0057:        import org.objectweb.carol.util.configuration.ConfigurationRepository;
0058:        import org.objectweb.jonas.ha.interceptor.HACurrentDelegateImpl;
0059:        import org.objectweb.jonas_ejb.deployment.api.BeanDesc;
0060:        import org.objectweb.jonas_ejb.deployment.api.MethodDesc;
0061:        import org.objectweb.jonas_ejb.lib.EJBInvocation;
0062:        import org.objectweb.jonas_lib.files.FileUtils;
0063:        import org.objectweb.jonas_lib.naming.ContainerNaming;
0064:        import org.objectweb.jonas_lib.version.Version;
0065:        import org.objectweb.jonas_timer.TraceTimer;
0066:        import org.objectweb.jotm.TransactionContext;
0067:        import org.objectweb.security.context.SecurityContext;
0068:        import org.objectweb.security.context.SecurityCurrent;
0069:        import org.objectweb.transaction.jta.TransactionManager;
0070:        import org.objectweb.util.monolog.api.BasicLevel;
0071:
0072:        /**
0073:         * This class is a factory for beans.
0074:         * @author Philippe Durieux
0075:         * @author Florent Benoit (JACC security)
0076:         */
0077:        public abstract class JFactory implements  BeanFactory {
0078:
0079:            protected JContainer cont;
0080:
0081:            protected boolean stopped = false;
0082:
0083:            protected ContainerNaming naming = null;
0084:
0085:            protected TransactionManager tm = null;
0086:
0087:            protected WorkManager wm = null;
0088:
0089:            protected Context JNDICtx = null; // JNDI Context for this component
0090:
0091:            protected String ejbname = null;
0092:
0093:            protected BeanDesc dd;
0094:
0095:            protected Properties ejb10Env = null;
0096:
0097:            protected TimerService myTimerService = null;
0098:
0099:            protected boolean txbeanmanaged = false; // always false if entity bean
0100:
0101:            protected Class beanclass = null; // class of the bean instance
0102:
0103:            protected File passivationDir;
0104:
0105:            /**
0106:             * initial value for pool size
0107:             */
0108:            protected int minPoolSize;
0109:
0110:            protected int maxCacheSize;
0111:
0112:            protected boolean isClusterReplicated;
0113:
0114:            /**
0115:             * Need for checking transaction interoperability which is only needs when
0116:             * using iiop
0117:             */
0118:            private boolean iiopProtocolAvailable = false;
0119:
0120:            /**
0121:             * Transational attribute for ejbTimeout method.
0122:             * default is TX_REQUIRES_NEW
0123:             */
0124:            protected int timerTxAttr;
0125:
0126:            /**
0127:             * Signature for ejbTimeout
0128:             */
0129:            protected String ejbTimeoutSignature;
0130:
0131:            /**
0132:             * constructor (for entity) must be without parameters (required by Jorm)
0133:             */
0134:            public JFactory() {
0135:                if (TraceEjb.isDebugIc()) {
0136:                    TraceEjb.interp.log(BasicLevel.DEBUG, ejbname);
0137:                }
0138:            }
0139:
0140:            public void stopContainer() {
0141:                stopped = true;
0142:            }
0143:
0144:            public boolean isStopped() {
0145:                return stopped;
0146:            }
0147:
0148:            /**
0149:             * Get the directory where to store stateful state and timers
0150:             */
0151:            public File getPassivationDir() {
0152:                return passivationDir;
0153:            }
0154:
0155:            /**
0156:             * constructor (for session)
0157:             * @param dd The bean deployment descriptor
0158:             * @param cont the container for this bean
0159:             */
0160:            public JFactory(BeanDesc dd, JContainer cont) {
0161:                if (TraceEjb.isDebugIc()) {
0162:                    TraceEjb.interp.log(BasicLevel.DEBUG, "");
0163:                }
0164:                init(dd, cont);
0165:            }
0166:
0167:            /**
0168:             * Init this object
0169:             * @param dd the deployment descriptor
0170:             * @param cont the Container
0171:             */
0172:            public void init(BeanDesc dd, JContainer cont) {
0173:                this .cont = cont;
0174:                this .dd = dd;
0175:                naming = cont.getContainerNaming();
0176:                tm = cont.getTransactionManager();
0177:                wm = cont.getWorkManager();
0178:                ejbname = dd.getEjbName();
0179:                ejb10Env = dd.getEjb10Environment();
0180:                maxCacheSize = dd.getCacheMax();
0181:                minPoolSize = dd.getPoolMin();
0182:                isClusterReplicated = dd.isClusterReplicated();
0183:
0184:                // Check the JOnAS version used for deployment in case of Session or
0185:                // Entity
0186:                String cln = dd.getFullWrpHomeName() != null ? dd
0187:                        .getFullWrpHomeName() : dd.getFullWrpLocalHomeName();
0188:                if (cln != null) {
0189:                    checkJonasVersion(cln);
0190:                }
0191:
0192:                // Create a JNDI context for this bean component
0193:                try {
0194:                    JNDICtx = naming.createEnvironmentContext(ejbname);
0195:                    cont.setBeanEnvironment(JNDICtx, dd);
0196:                } catch (NamingException e) {
0197:                    TraceEjb.logger.log(BasicLevel.ERROR,
0198:                            "cannot build naming for this component", e);
0199:                    throw new EJBException(
0200:                            "Cannot build naming for this component", e);
0201:                }
0202:
0203:                // Get the class of the bean instance (for ejbCreate, ejbRemove, ...)
0204:                String cn = null;
0205:                try {
0206:                    cn = dd.getFullDerivedBeanName();
0207:                    beanclass = cont.getClassLoader().loadClass(cn);
0208:                    /*
0209:                     * This is currently being commented out. The spec doesn't exclude
0210:                     * having the same class multiple times, just that the first class
0211:                     * will be the one that is loaded. With this code included, this
0212:                     * precludes a user from using the same bean classes but with
0213:                     * different transactional attributes for example within the same
0214:                     * ear file. // prevent from generated class name collision in a
0215:                     * J2EE application if (!isClassAvailable(cn, true)) { throw new
0216:                     * EJBException("Container has detected duplicated class " + cn); }
0217:                     */
0218:                } catch (ClassNotFoundException e) {
0219:                    TraceEjb.logger.log(BasicLevel.ERROR,
0220:                            "failed to find class " + cn + e);
0221:                    throw new EJBException("Container failed to find class "
0222:                            + cn, e);
0223:                }
0224:
0225:                timerTxAttr = dd.getTimerTxAttribute();
0226:                ejbTimeoutSignature = dd.getEjbTimeoutSignature();
0227:
0228:                // check TX interop if using iiop.
0229:                String protocol = ConfigurationRepository
0230:                        .getCurrentConfiguration().getProtocol().getName();
0231:                if (protocol.equals("iiop")) {
0232:                    iiopProtocolAvailable = true;
0233:                }
0234:
0235:                // mkdir a passivation directory if not exist yet.
0236:                String pds = cont.getTmpDirName() + File.separator
0237:                        + dd.getIdentifier();
0238:                passivationDir = new File(pds);
0239:                if (!passivationDir.isDirectory()) {
0240:                    passivationDir.mkdir();
0241:                    TraceEjb.factory.log(BasicLevel.DEBUG, "created: " + pds);
0242:                }
0243:            }
0244:
0245:            /**
0246:             * Return the WorkManager
0247:             */
0248:            public WorkManager getWorkManager() {
0249:                return wm;
0250:            }
0251:
0252:            /**
0253:             * Init the pool of instances. Not used for stateful beans
0254:             */
0255:            public abstract void initInstancePool();
0256:
0257:            /**
0258:             * Restart Timers
0259:             */
0260:            public void restartTimers() {
0261:                // Look for passivated Timers to reactivate.
0262:                String[] timerList = FileUtils.getFileList(passivationDir,
0263:                        null, ".tim");
0264:                for (int i = 0; i < timerList.length; i++) {
0265:                    File file = new File(passivationDir, timerList[i]);
0266:                    Timer timer = null;
0267:                    JObjectInputStream ois = null;
0268:                    try {
0269:                        TraceTimer.logger.log(BasicLevel.DEBUG, "restarting: "
0270:                                + timerList[i]);
0271:                        ois = new JObjectInputStream(new FileInputStream(file),
0272:                                cont.getClassLoader());
0273:                        JTimerHandle th = (JTimerHandle) ois.readObject();
0274:                        timer = th.restartTimer();
0275:                        file.delete();
0276:                        ois.close();
0277:                    } catch (Exception e) {
0278:                        // A Timer that cannot be restarted should not prevent the
0279:                        // Container
0280:                        // to be started. So, don't throw exception here.
0281:                        TraceTimer.logger.log(BasicLevel.ERROR,
0282:                                "Cannot restart timer: " + timerList[i]);
0283:                        TraceTimer.logger.log(BasicLevel.ERROR, "For bean: "
0284:                                + passivationDir);
0285:                        TraceTimer.logger.log(BasicLevel.ERROR, "Exception: "
0286:                                + e);
0287:                        if (timer != null) {
0288:                            try {
0289:                                timer.cancel();
0290:                            } catch (Exception ign) {
0291:                                TraceTimer.logger.log(BasicLevel.ERROR,
0292:                                        "Cancel timer: " + e);
0293:                            }
0294:                        }
0295:                    } finally {
0296:                        if (ois != null) {
0297:                            try {
0298:                                ois.close();
0299:                            } catch (Exception ig) {
0300:                                TraceTimer.logger
0301:                                        .log(BasicLevel.WARN,
0302:                                                "Cannot close ObjectInputStream: "
0303:                                                        + ig);
0304:                            }
0305:                        }
0306:                    }
0307:                }
0308:            }
0309:
0310:            /**
0311:             * Assess availability of a class in a given class loader
0312:             * @param className the name of the class without the .class extension
0313:             * @param unique flag indicating if the class should be found only once in
0314:             *        the classloader
0315:             * @return True if class is available in the current class loader.
0316:             */
0317:            protected boolean isClassAvailable(String className, boolean unique) {
0318:                className = className.replace('.', '/') + ".class";
0319:                Enumeration e = null;
0320:                try {
0321:                    e = ((URLClassLoader) cont.getClassLoader())
0322:                            .findResources(className);
0323:                } catch (IOException e1) {
0324:                    return false;
0325:                }
0326:                if (e.hasMoreElements()) {
0327:                    e.nextElement();
0328:                    return unique ? !e.hasMoreElements() : true;
0329:                } else {
0330:                    return false;
0331:                }
0332:            }
0333:
0334:            // ---------------------------------------------------------------
0335:            // BeanFactory implementation
0336:            // ---------------------------------------------------------------
0337:
0338:            /**
0339:             * @return the bean name
0340:             */
0341:            public String getEJBName() {
0342:                return ejbname;
0343:            }
0344:
0345:            /**
0346:             * @return the Instance pool size for this Ejb
0347:             */
0348:            public abstract int getPoolSize();
0349:
0350:            /**
0351:             * Get the Deployement descriptor of this Ejb
0352:             * @return BeanDesc The bean deployment descriptor
0353:             */
0354:            public BeanDesc getDeploymentDescriptor() {
0355:                return dd;
0356:            }
0357:
0358:            /**
0359:             * @return the TransactionManager
0360:             */
0361:            public TransactionManager getTransactionManager() {
0362:                return tm;
0363:            }
0364:
0365:            /**
0366:             * @return the JContainer object
0367:             */
0368:            public JContainer getContainer() {
0369:                return cont;
0370:            }
0371:
0372:            /**
0373:             * @return A Hashtable containing the JNDI Environment
0374:             */
0375:            public Hashtable getEnv() {
0376:                return naming.getEnv();
0377:            }
0378:
0379:            /**
0380:             * @return the InitialContext
0381:             */
0382:            public InitialContext getInitialContext() {
0383:                return naming.getInitialContext();
0384:            }
0385:
0386:            // ---------------------------------------------------------------
0387:            // other public methods
0388:            // ---------------------------------------------------------------
0389:
0390:            /**
0391:             * @return the TimerService for this bean.
0392:             * This works only for stateless or message driven beans.
0393:             */
0394:            public abstract TimerService getTimerService();
0395:
0396:            /**
0397:             * @return the EJB 1.0 style environment associated with the Bean
0398:             */
0399:            public Properties getEjb10Environment() {
0400:                return ejb10Env;
0401:            }
0402:
0403:            /**
0404:             * @return true if transactions are managed inside the bean false if
0405:             *         transactions are managed by the container
0406:             */
0407:            public boolean isTxBeanManaged() {
0408:                return txbeanmanaged;
0409:            }
0410:
0411:            /**
0412:             * set the Component Context for JNDI environment
0413:             * @return previous Context
0414:             */
0415:            public Context setComponentContext() {
0416:                Context oldctx = naming.setComponentContext(JNDICtx);
0417:                if (TraceEjb.isDebugLoaderLog() && oldctx == null) {
0418:                    TraceEjb.loaderlog.log(BasicLevel.DEBUG,
0419:                            "previous ctx was null");
0420:                }
0421:                return oldctx;
0422:            }
0423:
0424:            /**
0425:             * reset old Component Context for JNDI environment
0426:             * @param oldctx previous Component Context to restore.
0427:             */
0428:            public void resetComponentContext(Context oldctx) {
0429:                if (TraceEjb.isDebugLoaderLog() && oldctx == null) {
0430:                    TraceEjb.loaderlog.log(BasicLevel.DEBUG, "to null");
0431:                }
0432:                naming.resetComponentContext(oldctx);
0433:            }
0434:
0435:            /**
0436:             * @return the transaction attribute for ejbTimeout method
0437:             */
0438:            public int getTimerTxAttribute() {
0439:                return timerTxAttr;
0440:            }
0441:
0442:            /**
0443:             * @return the security signature for ejbTimeout method.
0444:             */
0445:            public String getEjbTimeoutSignature() {
0446:                return ejbTimeoutSignature;
0447:            }
0448:
0449:            /**
0450:             * @return min pool size for Jmx
0451:             */
0452:            public int getMinPoolSize() {
0453:                return minPoolSize;
0454:            }
0455:
0456:            /**
0457:             * @return max cache size for Jmx
0458:             */
0459:            public int getMaxCacheSize() {
0460:                return maxCacheSize;
0461:            }
0462:
0463:            /**
0464:             * @return max cache size for Jmx
0465:             */
0466:            public int getCacheSize() {
0467:                throw new IllegalStateException();
0468:            }
0469:
0470:            /**
0471:             * Check if the access to the bean is authorized
0472:             * @param ejbInv object containing security signature of the method, args of
0473:             *        method, etc
0474:             */
0475:            public void checkSecurity(EJBInvocation ejbInv) {
0476:
0477:                String runAsRoleDD = null;
0478:
0479:                try {
0480:                    // security controls (except for Message Driven Beans)
0481:                    if (ejbInv != null
0482:                            && ejbInv.methodPermissionSignature != null) {
0483:                        // Check the security with the identities of the callers
0484:                        // Establishing a run-as identity for an enterprise bean does
0485:                        // not affect the
0486:                        // identities of its callers, which are the identities tested
0487:                        // for the permission
0488:                        // to access the methods of the enterprise bean.
0489:                        // The run-as identity establishes the identity the enterprise
0490:                        // bean will
0491:                        // use when it makes calls
0492:                        // see 21.3.4.1 EJB 2.0 (Security Management / Run-as)
0493:                        if (ejbInv.methodPermissionSignature.length() != 0) {
0494:                            cont.checkSecurity(ejbname, ejbInv, (dd
0495:                                    .getRunAsRole() != null));
0496:                        }
0497:                    }
0498:
0499:                    runAsRoleDD = dd.getRunAsRole();
0500:                    // And now, push the run-as role if any
0501:                    // This role will be used for the calls of the bean
0502:                    if (runAsRoleDD != null) {
0503:                        SecurityCurrent current = SecurityCurrent.getCurrent();
0504:                        if (current != null) {
0505:                            SecurityContext sctx = current.getSecurityContext();
0506:                            if (sctx == null) {
0507:                                if (TraceEjb.isDebugSecurity()) {
0508:                                    TraceEjb.security.log(BasicLevel.DEBUG,
0509:                                            "runas : Security context is null, create a new one"
0510:                                                    + " in ejb " + ejbname);
0511:                                }
0512:                                sctx = new SecurityContext();
0513:                                current.setSecurityContext(sctx);
0514:                            }
0515:                            String principalName = dd.getRunAsPrincipalName();
0516:                            String[] runAsRoles = dd.getDeploymentDesc()
0517:                                    .getRolesForRunAsPrincipal(principalName);
0518:                            if (runAsRoles == null) {
0519:                                runAsRoles = new String[] { runAsRoleDD };
0520:                            }
0521:                            if (TraceEjb.isDebugSecurity()) {
0522:                                TraceEjb.security.log(BasicLevel.DEBUG,
0523:                                        "runAs roles are ");
0524:                                for (int r = 0; r < runAsRoles.length; r++) {
0525:                                    TraceEjb.security.log(BasicLevel.DEBUG,
0526:                                            "Role[" + r + "] = "
0527:                                                    + runAsRoles[r]);
0528:                                }
0529:                                TraceEjb.security.log(BasicLevel.DEBUG,
0530:                                        "RunAs principal name = "
0531:                                                + principalName);
0532:                            }
0533:                            sctx.pushRunAs(runAsRoleDD, principalName,
0534:                                    runAsRoles);
0535:                        } else {
0536:                            TraceEjb.security.log(BasicLevel.ERROR,
0537:                                    "Can't push runas role as security current is null"
0538:                                            + " in ejb " + ejbname);
0539:                        }
0540:                    }
0541:                } catch (RuntimeException re) {
0542:                    // pop run-as role
0543:                    if (runAsRoleDD != null) {
0544:                        SecurityCurrent current = SecurityCurrent.getCurrent();
0545:                        if (current != null) {
0546:                            SecurityContext sctx = current.getSecurityContext();
0547:                            if (sctx == null) {
0548:                                if (TraceEjb.isDebugSecurity()) {
0549:                                    TraceEjb.security.log(BasicLevel.DEBUG,
0550:                                            "runas : Security context is  null "
0551:                                                    + " in ejb " + ejbname);
0552:                                }
0553:                            } else {
0554:                                sctx.popRunAs();
0555:                            }
0556:                        } else {
0557:                            if (TraceEjb.isDebugSecurity()) {
0558:                                TraceEjb.security.log(BasicLevel.DEBUG,
0559:                                        "Can't pop runas role as security current is null"
0560:                                                + " in ejb " + ejbname);
0561:                            }
0562:                        }
0563:                    }
0564:                    if (TraceEjb.isDebugSecurity()) {
0565:                        TraceEjb.logger.log(BasicLevel.DEBUG,
0566:                                "Security Runtime Exception", re);
0567:                    }
0568:                    throw re;
0569:                }
0570:
0571:            }
0572:
0573:            /**
0574:             * Common preInvoke
0575:             * @param txa Transaction Attribute (Supports, Required, ...)
0576:             * @return A RequestCtx object
0577:             * @throws EJBException
0578:             */
0579:            public RequestCtx preInvoke(int txa) {
0580:
0581:                if (TraceEjb.isDebugIc()) {
0582:                    TraceEjb.interp.log(BasicLevel.DEBUG, "");
0583:                }
0584:                RequestCtx rctx = null;
0585:
0586:                try {
0587:                    // Build a RequestCtx to save information about this request
0588:                    // until the postInvoke time.
0589:                    rctx = new RequestCtx(txa);
0590:
0591:                    // Set classLoader to the correct value and save the previous one
0592:                    // in the RequestCtx to restore it at the end of the Request.
0593:                    rctx.cloader = Thread.currentThread()
0594:                            .getContextClassLoader();
0595:                    Thread.currentThread().setContextClassLoader(
0596:                            myClassLoader());
0597:
0598:                    // Set bean context for JNDI and save the previous one in the
0599:                    // RequestCtx to restore it at the end of the Request.
0600:                    rctx.jndiCtx = setComponentContext();
0601:
0602:                    // Check Transaction conformance to bean settings
0603:                    checkTransaction(rctx);
0604:
0605:                } catch (RuntimeException e) {
0606:                    // Log RuntimeException before rethrowing it
0607:                    // -> Print Stack Trace to see where the problem is.
0608:                    TraceEjb.logger.log(BasicLevel.ERROR,
0609:                            "unexpected Runtime Exception", e);
0610:                    throw e;
0611:                }
0612:                return rctx;
0613:            }
0614:
0615:            /**
0616:             * Send commit/abort message
0617:             * @param reqId the request id
0618:             * @param committed true if the transaction has commited
0619:             */
0620:            private void replicateCommit(RequestId reqId, boolean committed) {
0621:                if (reqId != null) {
0622:                    try {
0623:                        JRepUtil.getRepMgr().replicateCommit(reqId, committed);
0624:                    } catch (Exception e) {
0625:                        TraceCmi.error("Unable to replicate commit/abor", e);
0626:                    }
0627:                }
0628:            }
0629:
0630:            /**
0631:             * Common postInvoke
0632:             * @param rctx The RequestCtx that was returned at preInvoke()
0633:             * @throws EJBException
0634:             */
0635:            public void postInvoke(RequestCtx rctx) {
0636:
0637:                if (TraceEjb.isDebugIc()) {
0638:                    TraceEjb.interp.log(BasicLevel.DEBUG, "");
0639:                }
0640:
0641:                // WARNING: All exceptions raised here will overload those raised
0642:                // in the caller. (postInvoke is usually in a "finally" block)
0643:                try {
0644:                    String runAsRoleDD = dd.getRunAsRole();
0645:                    // Pop the run-as role if any
0646:                    if (runAsRoleDD != null) {
0647:                        // Pop run-as role
0648:                        SecurityCurrent current = SecurityCurrent.getCurrent();
0649:                        if (current != null) {
0650:                            SecurityContext sctx = current.getSecurityContext();
0651:                            if (sctx == null) {
0652:                                TraceEjb.security.log(BasicLevel.ERROR,
0653:                                        "runas: Security context is null "
0654:                                                + " in ejb " + ejbname);
0655:                            } else {
0656:                                sctx.popRunAs();
0657:                            }
0658:                        } else {
0659:                            TraceEjb.security.log(BasicLevel.ERROR,
0660:                                    "Can't pop runas role as security current is null"
0661:                                            + " in ejb " + ejbname);
0662:                        }
0663:                    }
0664:
0665:                    // Commit the transaction started in preInvoke
0666:                    if (rctx.mustCommit) {
0667:                        // Sanity check : transaction should be the same
0668:                        try {
0669:                            Transaction t = tm.getTransaction();
0670:                            if (t == null) {
0671:                                TraceEjb.logger.log(BasicLevel.ERROR,
0672:                                        "Transaction disappeared: "
0673:                                                + rctx.currTx);
0674:                                Thread.dumpStack();
0675:                                throw new EJBException("null transaction");
0676:                            }
0677:                            if (rctx.currTx != t) {
0678:                                TraceEjb.logger.log(BasicLevel.ERROR,
0679:                                        "Transaction changed: " + rctx.currTx);
0680:                                Thread.dumpStack();
0681:                                throw new EJBException("bad transaction :" + t);
0682:                            }
0683:                        } catch (Exception e) {
0684:                            throw new EJBException(
0685:                                    "Cannot get current transaction:", e);
0686:                        }
0687:                        if (rctx.sysExc != null) {
0688:                            TraceEjb.logger.log(BasicLevel.ERROR,
0689:                                    "system exception raised by request:",
0690:                                    rctx.sysExc);
0691:                            // rollback the transaction
0692:                            try {
0693:                                tm.rollback();
0694:                            } catch (Exception e) {
0695:                                TraceEjb.logger.log(BasicLevel.ERROR,
0696:                                        "exception during rollback:", e);
0697:                            }
0698:                        } else {
0699:                            /*** REPLICATION CODE ***/
0700:                            // COMPLETE: Send and abort message if the transaction has aborted
0701:                            RequestId reqId = null;
0702:                            if (isClusterReplicated) {
0703:                                HACurrentDelegateImpl current = HACurrentDelegateImpl
0704:                                        .getCurrent();
0705:                                if (current.getRequests().size() == 1) {
0706:                                    reqId = (RequestId) current.getRequests()
0707:                                            .peek();
0708:                                }
0709:                            }
0710:
0711:                            try {
0712:                                // Check status to avoid returning RollbackException to
0713:                                // the client
0714:                                // instead of the application exception
0715:                                switch (tm.getStatus()) {
0716:                                case Status.STATUS_ACTIVE:
0717:                                    /*** REPLICATION CODE ***/
0718:                                    if (reqId != null) {
0719:                                        try {
0720:                                            JRepUtil.getRepMgr().replicate(
0721:                                                    reqId);
0722:                                        } catch (Exception e) {
0723:                                            TraceCmi.error(
0724:                                                    "Unable to replicate", e);
0725:                                        }
0726:                                    }
0727:
0728:                                    /*** REPLICATION CODE ***/
0729:
0730:                                    if (TraceEjb.isDebugTx()) {
0731:                                        TraceEjb.tx.log(BasicLevel.DEBUG,
0732:                                                "committing transaction: "
0733:                                                        + rctx.currTx);
0734:                                    }
0735:                                    tm.commit();
0736:                                    /*** REPLICATION CODE ***/
0737:                                    replicateCommit(reqId, true);
0738:                                    /*** REPLICATION CODE ***/
0739:                                    break;
0740:                                case Status.STATUS_MARKED_ROLLBACK:
0741:                                    if (TraceEjb.isDebugTx()) {
0742:                                        TraceEjb.tx.log(BasicLevel.DEBUG,
0743:                                                "rolling back transaction: "
0744:                                                        + rctx.currTx);
0745:                                    }
0746:                                    tm.rollback();
0747:                                    /*** REPLICATION CODE ***/
0748:                                    replicateCommit(reqId, false);
0749:                                    /*** REPLICATION CODE ***/
0750:                                    break;
0751:                                default:
0752:                                    TraceEjb.logger.log(BasicLevel.ERROR,
0753:                                            "unexpected transaction status "
0754:                                                    + tm.getStatus());
0755:                                    TraceEjb.logger.log(BasicLevel.ERROR,
0756:                                            "transaction: " + rctx.currTx);
0757:                                    Thread.dumpStack();
0758:                                    /*** REPLICATION CODE ***/
0759:                                    replicateCommit(reqId, false);
0760:                                    /*** REPLICATION CODE ***/
0761:                                    throw new EJBException(
0762:                                            "unexpected transaction status :"
0763:                                                    + tm.getStatus());
0764:                                }
0765:                            } catch (RollbackException e) {
0766:                                TraceEjb.logger
0767:                                        .log(BasicLevel.WARN,
0768:                                                "Could not commit transaction (rolled back)");
0769:                                /*** REPLICATION CODE ***/
0770:                                replicateCommit(reqId, false);
0771:                                /*** REPLICATION CODE ***/
0772:                                throw new TransactionRolledbackLocalException(
0773:                                        "Could not commit transaction", e);
0774:                            } catch (Exception e) {
0775:                                TraceEjb.logger.log(BasicLevel.WARN,
0776:                                        "Could not commit transaction:" + e);
0777:                                /*** REPLICATION CODE ***/
0778:                                replicateCommit(reqId, false);
0779:                                /*** REPLICATION CODE ***/
0780:                                throw new EJBException("Container exception", e);
0781:                            }
0782:                        }
0783:                    }
0784:
0785:                    // Reset class loader to the original value
0786:                    Thread.currentThread().setContextClassLoader(rctx.cloader);
0787:
0788:                    // Resume client transaction suspended in preInvoke
0789:                    Transaction tx = rctx.clientTx;
0790:                    if (tx != null) {
0791:                        try {
0792:                            if (TraceEjb.isDebugTx()) {
0793:                                TraceEjb.tx.log(BasicLevel.DEBUG,
0794:                                        "resuming transaction");
0795:                            }
0796:                            tm.resume(tx);
0797:                        } catch (Exception e) {
0798:                            TraceEjb.logger.log(BasicLevel.ERROR,
0799:                                    "cannot resume transaction", e);
0800:                        }
0801:                    }
0802:
0803:                    // Reset bean context for JNDI
0804:                    resetComponentContext(rctx.jndiCtx);
0805:
0806:                    // We got a system Exception in business method:
0807:                    // - log exception
0808:                    // - discard instance
0809:                    // - set client transaction rollback only
0810:                    // - throw EJBException
0811:                    if (rctx.sysExc != null) {
0812:                        // Log system exception
0813:                        TraceEjb.logger.log(BasicLevel.ERROR,
0814:                                "system exception in business method:",
0815:                                rctx.sysExc);
0816:
0817:                        // If client transaction: set it rollback only and throw
0818:                        // TransactionRolledBackLocalException
0819:                        Transaction currentTx = null;
0820:                        try {
0821:                            currentTx = tm.getTransaction();
0822:                            // Must not rollback a suspended transaction just resumed (bug #306840)
0823:                            if (currentTx != null && rctx.clientTx == null) {
0824:                                TraceEjb.logger.log(BasicLevel.WARN,
0825:                                        "Client transaction will rollback");
0826:                                currentTx.setRollbackOnly();
0827:                                // See spec EJB 18.3.1 + 18.4.2.3
0828:                                if (rctx.bmcalled) {
0829:                                    throw (TransactionRolledbackLocalException) new TransactionRolledbackLocalException(
0830:                                            rctx.sysExc.getMessage())
0831:                                            .initCause(rctx.sysExc);
0832:                                }
0833:                            }
0834:                        } catch (SystemException e) {
0835:                            TraceEjb.logger.log(BasicLevel.ERROR,
0836:                                    "cannot set rollback only current tx:", e);
0837:                        }
0838:                        return;
0839:                    }
0840:
0841:                } catch (TransactionRolledbackLocalException e) {
0842:                    throw e;
0843:                } catch (EJBException e) {
0844:                    TraceEjb.logger.log(BasicLevel.ERROR, "ejbexception: ", e);
0845:                    throw e;
0846:                } catch (RuntimeException e) {
0847:                    // Log RuntimeException before rethrowing it
0848:                    // -> Print Stack Trace to see where the problem is.
0849:                    TraceEjb.logger.log(BasicLevel.ERROR,
0850:                            "unexpected runtime exception: ", e);
0851:                    throw e;
0852:                }
0853:            }
0854:
0855:            /**
0856:             * preInvoke for Remote access
0857:             * @param txa Transaction Attribute (Supports, Required, ...)
0858:             * @return A RequestCtx object
0859:             * @throws java.rmi.TransactionRequiredException
0860:             * @throws java.rmi.TransactionRolledbackException
0861:             * @throws java.rmi.NoSuchObjectException
0862:             * @throws RemoteException preinvoke raised an EJBException
0863:             */
0864:            public RequestCtx preInvokeRemote(int txa) throws RemoteException {
0865:                if (TraceEjb.isDebugIc()) {
0866:                    TraceEjb.interp.log(BasicLevel.DEBUG, "");
0867:                }
0868:                try {
0869:                    return preInvoke(txa);
0870:                } catch (javax.ejb.TransactionRequiredLocalException e) {
0871:                    TransactionRequiredException tr = new TransactionRequiredException(
0872:                            e.getMessage());
0873:                    tr.detail = e;
0874:                    throw tr;
0875:                } catch (javax.ejb.TransactionRolledbackLocalException e) {
0876:                    TransactionRolledbackException tr = new TransactionRolledbackException(
0877:                            e.getMessage());
0878:                    tr.detail = e;
0879:                    throw tr;
0880:                } catch (javax.ejb.NoSuchObjectLocalException e) {
0881:                    throw NoSuchObjectExceptionHelper.create(e);
0882:                } catch (javax.ejb.EJBException e) {
0883:                    RemoteException re = new RemoteException(e.getMessage());
0884:                    re.detail = e;
0885:                    throw re;
0886:                }
0887:            }
0888:
0889:            /**
0890:             * postInvoke for Remote access
0891:             * @param rctx The RequestCtx that was returne t preInvoke()
0892:             * @throws TransactionRequiredException
0893:             * @throws TransactionRolledbackException
0894:             * @throws NoSuchObjectException
0895:             * @throws RemoteException postinvoke failed
0896:             */
0897:            public void postInvokeRemote(RequestCtx rctx)
0898:                    throws RemoteException {
0899:                if (TraceEjb.isDebugIc()) {
0900:                    TraceEjb.interp.log(BasicLevel.DEBUG, "");
0901:                }
0902:                try {
0903:                    postInvoke(rctx);
0904:                } catch (javax.ejb.TransactionRequiredLocalException e) {
0905:                    throw new javax.transaction.TransactionRequiredException(e
0906:                            .getMessage());
0907:                } catch (javax.ejb.TransactionRolledbackLocalException e) {
0908:                    throw new javax.transaction.TransactionRolledbackException(
0909:                            e.getMessage());
0910:                } catch (javax.ejb.NoSuchObjectLocalException e) {
0911:                    throw new java.rmi.NoSuchObjectException(e.getMessage());
0912:                } catch (javax.ejb.EJBException e) {
0913:                    throw new java.rmi.RemoteException(e.getMessage(), e);
0914:                }
0915:            }
0916:
0917:            /**
0918:             * check Transaction attribute
0919:             * @param rctx the Request Context
0920:             */
0921:            abstract void checkTransaction(RequestCtx rctx);
0922:
0923:            // ---------------------------------------------------------------
0924:            // private methods
0925:            // ---------------------------------------------------------------
0926:            /**
0927:             * Check Transaction Interoperability requirements if the Tx comes
0928:             * from another vendor.
0929:             * For the moment JOnAS doesn't support tx interop.
0930:             * See EJB 2.1 ?19.6.2.2.2
0931:             *
0932:             * @param txa transaction attribute
0933:             *
0934:             */
0935:            private void checkTransactionInteroperability(int txa) {
0936:
0937:                // tm is never null.
0938:                TransactionContext transContext = ((org.objectweb.jotm.Current) tm)
0939:                        .getPropagationContext(false);
0940:                if (transContext == null) {
0941:                    return;
0942:                }
0943:
0944:                boolean isNullTxCtx = !transContext.isJotmCtx();
0945:
0946:                if (isNullTxCtx) {
0947:                    switch (txa) {
0948:                    // in the cases below, an exception is returned to the client side in order
0949:                    // to rollback the tx
0950:                    case MethodDesc.TX_MANDATORY:
0951:                        TraceEjb.logger.log(BasicLevel.WARN,
0952:                                "mandatory and tx from another vendor");
0953:                        throw new EJBException(
0954:                                "Doesn't support transaction interoperability");
0955:
0956:                    case MethodDesc.TX_REQUIRED:
0957:                        TraceEjb.logger.log(BasicLevel.WARN,
0958:                                "required and tx from another vendor");
0959:                        throw new EJBException(
0960:                                "Doesn't support transaction interoperability");
0961:
0962:                    case MethodDesc.TX_SUPPORTS:
0963:                        TraceEjb.logger.log(BasicLevel.WARN,
0964:                                "supports and tx from another vendor");
0965:                        throw new EJBException(
0966:                                "Doesn't support transaction interoperability");
0967:                    default:
0968:                        // nothing to do in particular for interop requirement
0969:                        break;
0970:                    }
0971:                }
0972:            }
0973:
0974:            /**
0975:             * Process Transaction Attribute before calling a business method
0976:             * @param rctx the Request Context
0977:             * @throws EJBException
0978:             * @throws TransactionRequiredLocalException
0979:             */
0980:            protected void checkTransactionContainer(RequestCtx rctx) {
0981:
0982:                int txa = rctx.txAttr;
0983:
0984:                if (txa == MethodDesc.TX_NOT_SET) {
0985:                    // No check to do (for example: session home)
0986:                    return;
0987:                }
0988:
0989:                rctx.mustCommit = false;
0990:                Transaction cltx = null;
0991:
0992:                // First of all, get the current transaction
0993:                Transaction currtx = null;
0994:                try {
0995:                    currtx = tm.getTransaction();
0996:                } catch (SystemException e) {
0997:                    TraceEjb.logger.log(BasicLevel.ERROR,
0998:                            "system exception while getting transaction:", e);
0999:                }
1000:
1001:                // Check requirements for transaction interoperability (iiop)
1002:                if (iiopProtocolAvailable) {
1003:                    checkTransactionInteroperability(txa);
1004:                }
1005:
1006:                // Raises exception if "Never" and we are in a transaction
1007:                if (txa == MethodDesc.TX_NEVER && currtx != null) {
1008:                    TraceEjb.logger.log(BasicLevel.WARN,
1009:                            "never and transaction not null");
1010:                    throw new EJBException(
1011:                            "Never attribute = caller must not be in a transaction");
1012:                }
1013:
1014:                // Raises exception if "Mandatory" and we are not in a transaction
1015:                if (txa == MethodDesc.TX_MANDATORY && currtx == null) {
1016:                    TraceEjb.logger.log(BasicLevel.WARN,
1017:                            "mandatory and not in transaction");
1018:                    throw new TransactionRequiredLocalException(
1019:                            "Mandatory attribute = caller must be in a transaction");
1020:                }
1021:
1022:                // Suspend transaction if "NotSupported" or "RequiresNew"
1023:                if (currtx != null
1024:                        && (txa == MethodDesc.TX_REQUIRES_NEW || txa == MethodDesc.TX_NOT_SUPPORTED)) {
1025:                    try {
1026:                        cltx = tm.suspend();
1027:                        if (cltx != null && TraceEjb.isDebugTx()) {
1028:                            TraceEjb.tx.log(BasicLevel.DEBUG,
1029:                                    "Suspending client tx:" + cltx);
1030:                        }
1031:                        currtx = null;
1032:                    } catch (SystemException e) {
1033:                        TraceEjb.logger.log(BasicLevel.ERROR,
1034:                                "cannot suspend transaction:\n", e);
1035:                        throw new EJBException("Cannot suspend transaction", e);
1036:                    }
1037:                }
1038:
1039:                // Start a new transaction in 2 cases:
1040:                // - "RequiresNew" attribute
1041:                // - "Required" and no current transaction
1042:                // this transaction will be closed at postInvoke.
1043:                if (txa == MethodDesc.TX_REQUIRES_NEW
1044:                        || (txa == MethodDesc.TX_REQUIRED && currtx == null)) {
1045:                    try {
1046:                        tm.begin();
1047:                        rctx.mustCommit = true;
1048:                        currtx = tm.getTransaction();
1049:                        if (TraceEjb.isDebugTx()) {
1050:                            TraceEjb.tx.log(BasicLevel.DEBUG, "Start tx: "
1051:                                    + currtx);
1052:                        }
1053:                    } catch (NotSupportedException e) {
1054:                        TraceEjb.logger
1055:                                .log(BasicLevel.ERROR,
1056:                                        "cannot start a transaction: NotSupportedException");
1057:                        throw new EJBException(
1058:                                "Nested Transactions Not Supported", e);
1059:                    } catch (SystemException e) {
1060:                        TraceEjb.logger.log(BasicLevel.ERROR,
1061:                                "cannot start a transaction:\n", e);
1062:                        throw new EJBException(
1063:                                "Cannot start a transaction: SystemException",
1064:                                e);
1065:                    }
1066:                }
1067:
1068:                // update RequestCtx
1069:                rctx.currTx = currtx;
1070:                rctx.clientTx = cltx;
1071:            }
1072:
1073:            /**
1074:             * Check if the given class have been generated by GenIC tool with a correct
1075:             * version. Trace an error message, if not.
1076:             * @param clName class name
1077:             */
1078:            protected void checkJonasVersion(String clName) {
1079:                /*
1080:                 * Check if the static 'JONAS_VERSION' variable defined in the given
1081:                 * class (ie GenIC's Version used to deploy the bean), has the same
1082:                 * value as the JOnAS Version.NUMBER variable.
1083:                 */
1084:                String fdName = "JONAS_VERSION";
1085:                String gVersion = null;
1086:                try {
1087:                    // The name of the resource ends with .class and the '.' are replace
1088:                    // with '/'
1089:                    String resourceName = clName.replace('.', '/') + ".class";
1090:
1091:                    // get the list of the resources for this class
1092:                    Enumeration e = null;
1093:                    try {
1094:                        e = cont.getClassLoader().getResources(resourceName);
1095:                    } catch (IOException ioe) {
1096:                        TraceEjb.logger.log(BasicLevel.ERROR,
1097:                                "failed to find class " + clName + ioe);
1098:                        throw new EJBException(
1099:                                "Container failed to find class " + clName, ioe);
1100:                    }
1101:
1102:                    // Count the resources
1103:                    int nbCls = 0;
1104:                    String urls = "";
1105:                    while (e.hasMoreElements()) {
1106:                        nbCls++;
1107:                        urls += e.nextElement() + "\n";
1108:                    }
1109:
1110:                    // More than one resource.
1111:                    if (nbCls > 1) {
1112:                        TraceEjb.logger
1113:                                .log(
1114:                                        BasicLevel.WARN,
1115:                                        "there are "
1116:                                                + nbCls
1117:                                                + " resources for the class "
1118:                                                + clName
1119:                                                + ". Some problems can occur because it's the first resource which will be loaded. The list of resources is : \n"
1120:                                                + urls);
1121:                    }
1122:
1123:                    // Get the class and get the value of the "JONAS_VERSION" static
1124:                    // field
1125:                    Class cl = cont.getClassLoader().loadClass(clName);
1126:                    Field fd = cl.getDeclaredField("JONAS_VERSION");
1127:                    gVersion = (String) fd.get(null);
1128:                } catch (ClassNotFoundException e) {
1129:                    TraceEjb.logger.log(BasicLevel.ERROR,
1130:                            "failed to find class " + clName, e);
1131:                    return;
1132:                } catch (NoSuchFieldException e) {
1133:                    TraceEjb.logger.log(BasicLevel.ERROR,
1134:                            "failed to find field " + fdName + " of class "
1135:                                    + clName, e);
1136:                    return;
1137:                } catch (IllegalAccessException e) {
1138:                    TraceEjb.logger.log(BasicLevel.ERROR,
1139:                            "failed to get the value of the field " + fdName
1140:                                    + " of class " + clName, e);
1141:                    return;
1142:                }
1143:                // Compare the current JOnAS version to the GenIC's Version used to
1144:                // deploy the bean
1145:                if (!Version.getNumber().equals(gVersion)) {
1146:                    TraceEjb.logger
1147:                            .log(
1148:                                    BasicLevel.WARN,
1149:                                    ejbname
1150:                                            + "(Ver. "
1151:                                            + gVersion
1152:                                            + ") bean not deployed with the same JOnAS version("
1153:                                            + Version.getNumber()
1154:                                            + "). You have to redeploy "
1155:                                            + cont.getFileName() + ".");
1156:                }
1157:            }
1158:
1159:            /**
1160:             * @return the classloader for this container.
1161:             */
1162:            public ClassLoader myClassLoader() {
1163:                return cont.getClassLoader();
1164:            }
1165:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.