001: /*
002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: *
023: * Free Software Foundation, Inc.
024: * 59 Temple Place, Suite 330
025: * Boston, MA 02111-1307 USA
026: *
027: * @author Scott Ferguson
028: */
029:
030: package com.caucho.ejb;
031:
032: import com.caucho.amber.cfg.EntityIntrospector;
033: import com.caucho.amber.manager.AmberContainer;
034: import com.caucho.amber.manager.PersistenceEnvironmentListener;
035: import com.caucho.config.ConfigException;
036: import com.caucho.config.types.FileSetType;
037: import com.caucho.config.types.JndiBuilder;
038: import com.caucho.config.types.PathPatternType;
039: import com.caucho.config.types.Period;
040: import com.caucho.ejb.cfg.EjbMethod;
041: import com.caucho.ejb.cfg.MessageDestination;
042: import com.caucho.ejb.manager.EjbContainer;
043: import com.caucho.ejb.manager.EjbEnvironmentListener;
044: import com.caucho.ejb.metadata.Bean;
045: import com.caucho.ejb.protocol.ProtocolContainer;
046: import com.caucho.loader.Environment;
047: import com.caucho.loader.EnvironmentBean;
048: import com.caucho.loader.EnvironmentClassLoader;
049: import com.caucho.loader.EnvironmentListener;
050: import com.caucho.loader.EnvironmentLocal;
051: import com.caucho.log.Log;
052: import com.caucho.naming.Jndi;
053: import com.caucho.util.L10N;
054: import com.caucho.vfs.JarPath;
055: import com.caucho.vfs.MergePath;
056: import com.caucho.vfs.Path;
057: import com.caucho.vfs.Vfs;
058:
059: import javax.annotation.PostConstruct;
060: import javax.jms.ConnectionFactory;
061: import javax.naming.NameNotFoundException;
062: import javax.naming.NamingException;
063: import javax.sql.DataSource;
064: import java.util.ArrayList;
065: import java.util.Iterator;
066: import java.util.logging.Level;
067: import java.util.logging.Logger;
068:
069: /**
070: * Server containing all the EJBs for a given configuration.
071: *
072: * <p>Each protocol will extend the container to override Handle creation.
073: */
074: public class EJBServer implements EnvironmentBean {
075: static final L10N L = new L10N(EJBServer.class);
076: protected static final Logger log = Log.open(EJBServer.class);
077:
078: private static EnvironmentLocal<EJBServer> _localServer = new EnvironmentLocal<EJBServer>(
079: "caucho.ejb-server");
080:
081: protected static EnvironmentLocal<String> _localURL = new EnvironmentLocal<String>(
082: "caucho.url");
083:
084: private EjbContainer _ejbContainer;
085: private AmberContainer _amberContainer;
086:
087: private String _localJndiPrefix; // = "java:comp/env/cmp";
088: private String _remoteJndiPrefix; // = "java:comp/env/ejb";
089:
090: private String _entityManagerJndiName = "java:comp/EntityManager";
091: private ArrayList<Path> _ejbJars = new ArrayList<Path>();
092:
093: private ArrayList<Bean> _beanList = new ArrayList<Bean>();
094:
095: private MergePath _mergePath;
096:
097: private String _urlPrefix;
098:
099: private ArrayList<FileSetType> _configFileSetList = new ArrayList<FileSetType>();
100:
101: private DataSource _dataSource;
102: private boolean _validateDatabaseSchema = true;
103:
104: private String _resinIsolation;
105: private String _jdbcIsolation;
106:
107: private ConnectionFactory _jmsConnectionFactory;
108:
109: private boolean _forbidJVMCall;
110: private boolean _autoCompile = true;
111: private boolean _isAllowPOJO = false;
112:
113: private String _startupMode;
114:
115: private long _transactionTimeout = 0;
116:
117: /**
118: * Create a server with the given prefix name.
119: */
120: public EJBServer() throws ConfigException {
121: _ejbContainer = EjbContainer.create();
122: _amberContainer = AmberContainer.create();
123:
124: _urlPrefix = _localURL.get();
125:
126: _mergePath = new MergePath();
127: _mergePath.addMergePath(Vfs.lookup());
128: _mergePath.addClassPath();
129: }
130:
131: public void addJarUrls(EnvironmentClassLoader loader, Path root)
132: throws java.io.IOException {
133: Iterator<String> it = root.iterator();
134:
135: while (it.hasNext()) {
136:
137: String s = it.next();
138:
139: Path path = root.lookup(s);
140:
141: if (path.isDirectory()) {
142: addJarUrls(loader, path);
143: } else if (s.endsWith(".jar")) {
144: JarPath jarPath = JarPath.create(path);
145:
146: loader.addURL(jarPath);
147: }
148: }
149: }
150:
151: /**
152: * Returns the local EJB server.
153: */
154: /*
155: public static EnvServerManager getLocalManager()
156: {
157: return EnvServerManager.getLocal();
158: }
159: */
160:
161: /**
162: * Gets the environment class loader.
163: */
164: public EnvironmentClassLoader getClassLoader() {
165: return _ejbContainer.getClassLoader();
166: }
167:
168: /**
169: * Sets the environment class loader.
170: */
171: public void setEnvironmentClassLoader(EnvironmentClassLoader env) {
172: }
173:
174: /**
175: * Sets the JNDI name.
176: */
177: public void setName(String name) {
178: setJndiName(name);
179: }
180:
181: /**
182: * Sets the JNDI name.
183: */
184: public void setJndiName(String name) {
185: setJndiPrefix(name);
186: }
187:
188: /**
189: * Sets the JNDI name.
190: */
191: public void setJndiPrefix(String name) {
192: _ejbContainer.getProtocolManager().setJndiPrefix(name);
193: }
194:
195: /**
196: * Gets the JNDI name.
197: */
198: public void setJndiLocalPrefix(String name) {
199: _ejbContainer.getProtocolManager().setLocalJndiPrefix(name);
200: }
201:
202: /**
203: * Gets the remote JNDI name.
204: */
205: public void setJndiRemotePrefix(String name) {
206: _ejbContainer.getProtocolManager().setRemoteJndiPrefix(name);
207: }
208:
209: /**
210: * Sets the EntityManager JNDI name.
211: */
212: public void setEntityManagerJndiName(String name) {
213: _entityManagerJndiName = name;
214: }
215:
216: /**
217: * Gets the EntityManager JNDI name.
218: */
219: public String getEntityManagerJndiName() {
220: return _entityManagerJndiName;
221: }
222:
223: /**
224: * Sets the URL-prefix for all external beans.
225: */
226: public void setURLPrefix(String urlPrefix) {
227: _urlPrefix = urlPrefix;
228: }
229:
230: /**
231: * Gets the URL-prefix for all external beans.
232: */
233: public String getURLPrefix() {
234: return _urlPrefix;
235: }
236:
237: /**
238: * Sets the directory for the *.ejb files.
239: */
240: public void setConfigDirectory(Path dir) throws ConfigException {
241: FileSetType fileSet = new FileSetType();
242:
243: fileSet.setDir(dir);
244:
245: fileSet.addInclude(new PathPatternType("**/*.ejb"));
246:
247: Path pwd = Vfs.lookup();
248:
249: String dirPath = dir.getPath();
250: String pwdPath = pwd.getPath();
251:
252: if (dirPath.startsWith(pwdPath)) {
253: String prefix = dirPath.substring(pwdPath.length());
254:
255: fileSet.setUserPathPrefix(prefix);
256: }
257:
258: _ejbContainer.getConfigManager().addFileSet(fileSet);
259: }
260:
261: /**
262: * Adds an ejb descriptor.
263: */
264: public void addEJBDescriptor(String ejbDescriptor) {
265: Path path = _mergePath.lookup(ejbDescriptor);
266:
267: _ejbContainer.getConfigManager().addEjbPath(path);
268: }
269:
270: /**
271: * Adds an ejb jar.
272: */
273: public void addEJBJar(Path ejbJar) throws ConfigException {
274: if (!ejbJar.canRead() || !ejbJar.isFile())
275: throw new ConfigException(L.l(
276: "<ejb-jar> {0} must refer to a valid jar file.",
277: ejbJar.getURL()));
278:
279: // tck: sanity check
280: if (_ejbJars.contains(ejbJar)) {
281: log.fine("EJBServer.addEJBJar already added: " + ejbJar);
282: return;
283: }
284:
285: _ejbJars.add(ejbJar);
286: }
287:
288: /**
289: * Adds a bean.
290: */
291: public Bean createBean() {
292: return new Bean(_ejbContainer);
293: }
294:
295: /**
296: * Adds a bean.
297: */
298: public void addBean(Bean bean) {
299: _beanList.add(bean);
300: }
301:
302: /**
303: * Sets the data-source
304: */
305: public void setDataSource(DataSource dataSource)
306: throws ConfigException {
307: _dataSource = dataSource;
308:
309: if (_dataSource == null)
310: throw new ConfigException(
311: L
312: .l("<ejb-server> data-source must be a valid DataSource."));
313:
314: _amberContainer.setDataSource(_dataSource);
315: }
316:
317: /**
318: * Sets the data-source
319: */
320: public void setReadDataSource(DataSource dataSource)
321: throws ConfigException {
322: _amberContainer.setReadDataSource(dataSource);
323: }
324:
325: /**
326: * Sets the xa data-source
327: */
328: public void setXADataSource(DataSource dataSource)
329: throws ConfigException {
330: _amberContainer.setXADataSource(dataSource);
331: }
332:
333: /**
334: * Sets true if database schema should be generated automatically.
335: */
336: public void setCreateDatabaseSchema(boolean create) {
337: _amberContainer.setCreateDatabaseTables(create);
338: }
339:
340: /**
341: * True if database schema should be generated automatically.
342: */
343: public boolean getCreateDatabaseSchema() {
344: return _amberContainer.getCreateDatabaseTables();
345: }
346:
347: /**
348: * Sets true if database schema should be validated automatically.
349: */
350: public void setValidateDatabaseSchema(boolean validate) {
351: _validateDatabaseSchema = validate;
352: }
353:
354: /**
355: * True if database schema should be validated automatically.
356: */
357: public boolean getValidateDatabaseSchema() {
358: return _validateDatabaseSchema;
359: }
360:
361: /**
362: * Sets true if database schema should be validated automatically.
363: */
364: public void setLoadLazyOnTransaction(boolean isLazy) {
365: // _ejbContainer.setEntityLoadLazyOnTransaction(isLazy);
366: }
367:
368: /**
369: * Sets the jndi name of the jmsConnectionFactory
370: */
371: public void setJMSConnectionFactory(JndiBuilder factory)
372: throws ConfigException, NamingException {
373: Object obj = factory.getObject();
374:
375: if (!(obj instanceof ConnectionFactory))
376: throw new ConfigException(L.l(
377: "'{0}' must be a JMS ConnectionFactory.", obj));
378:
379: _ejbContainer.setJmsConnectionFactory((ConnectionFactory) obj);
380: }
381:
382: /**
383: * Gets the jndi name of the jmsQueueConnectionFactory
384: */
385: public ConnectionFactory getConnectionFactory() {
386: return _jmsConnectionFactory;
387: }
388:
389: /**
390: * Sets consumer max
391: */
392: public void setMessageConsumerMax(int consumerMax)
393: throws ConfigException, NamingException {
394: _ejbContainer.setMessageConsumerMax(consumerMax);
395: }
396:
397: /**
398: * Gets the entity cache size.
399: */
400: public int getEntityCacheSize() {
401: return _ejbContainer.getEntityCache().getCacheSize();
402: }
403:
404: /**
405: * Sets the entity cache size.
406: */
407: public void setCacheSize(int size) {
408: _ejbContainer.getEntityCache().setCacheSize(size);
409: }
410:
411: /**
412: * Gets the entity cache timeout.
413: */
414: public long getEntityCacheTimeout() {
415: return _ejbContainer.getEntityCache().getCacheTimeout();
416: }
417:
418: /**
419: * Sets the entity cache timeout.
420: */
421: public void setCacheTimeout(Period timeout) {
422: _ejbContainer.getEntityCache().setCacheTimeout(
423: timeout.getPeriod());
424: }
425:
426: /**
427: * Gets transaction timeout.
428: */
429: public long getTransactionTimeout() {
430: return _transactionTimeout;
431: }
432:
433: /**
434: * Sets the transaction timeout.
435: */
436: public void setTransactionTimeout(Period timeout) {
437: _transactionTimeout = timeout.getPeriod();
438: }
439:
440: /**
441: * Gets the Resin isolation.
442: */
443: public String getResinIsolation() {
444: return _resinIsolation;
445: }
446:
447: /**
448: * Sets the Resin isolation.
449: */
450: public void setResinIsolation(String resinIsolation) {
451: _resinIsolation = resinIsolation;
452: }
453:
454: /**
455: * Gets the JDBC isolation.
456: */
457: public String getJdbcIsolation() {
458: return _jdbcIsolation;
459: }
460:
461: /**
462: * Sets the JDBC isolation.
463: */
464: public void setJdbcIsolation(String jdbcIsolation) {
465: _jdbcIsolation = jdbcIsolation;
466: }
467:
468: /**
469: * If true, JVM calls are forbidden.
470: */
471: public void setForbidJvmCall(boolean forbid) {
472: _forbidJVMCall = forbid;
473: }
474:
475: /**
476: * If true, automatically compile old EJBs.
477: */
478: public boolean isAutoCompile() {
479: return _autoCompile;
480: }
481:
482: /**
483: * Set true to automatically compile old EJBs.
484: */
485: public void setAutoCompile(boolean autoCompile) {
486: _autoCompile = autoCompile;
487: }
488:
489: /**
490: * If true, allow POJO beans
491: */
492: public boolean isAllowPOJO() {
493: return _isAllowPOJO;
494: }
495:
496: /**
497: * Set true to allow POJO beans
498: */
499: public void setAllowPOJO(boolean allowPOJO) {
500: _isAllowPOJO = allowPOJO;
501: }
502:
503: /**
504: * Sets the EJB server startup mode.
505: */
506: public void setStartupMode(String startupMode) {
507: _startupMode = startupMode;
508: }
509:
510: public static EJBServer getLocal() {
511: return _localServer.get();
512: }
513:
514: /**
515: * Initialize the container.
516: */
517: @PostConstruct
518: public void init() throws Exception {
519: /*
520: try {
521: if (_localJndiName != null)
522: Jndi.rebindDeepShort(_localJndiName, this);
523: } catch (NamingException e) {
524: log.log(Level.FINER, e.toString(), e);
525: }
526: */
527:
528: /*
529: if (_localServer.getLevel() == null
530: || "java:comp/env/cmp".equals(_localJndiPrefix)) {
531: _localServer.set(this);
532: _localManager.set(_ejbManager);
533: }
534:
535: try {
536: if (_localJndiPrefix != null)
537: Jndi.bindDeepShort(_localJndiPrefix + "/resin-ejb-server", _ejbManager);
538: } catch (NamingException e) {
539: log.log(Level.WARNING, e.toString(), e);
540: }
541:
542: try {
543: if (_localJndiPrefix != null)
544: Jndi.bindDeepShort(_localJndiPrefix + "/caucho-ejb-admin", _ejbManager);
545: } catch (NamingException e) {
546: log.log(Level.WARNING, e.toString(), e);
547: }
548:
549: try {
550: if (_entityManagerJndiName != null
551: && _ejbManager.getAmberManager() != null) {
552: Jndi.rebindDeepShort(_entityManagerJndiName,
553: _ejbManager.getAmberManager().getEntityManager());
554: }
555: } catch (NamingException e) {
556: log.log(Level.FINER, e.toString(), e);
557: }
558: */
559:
560: Environment
561: .addChildLoaderListener(new PersistenceEnvironmentListener());
562:
563: // _ejbContainer.start();
564:
565: if ("manual".equals(_startupMode))
566: return;
567:
568: manualInit();
569: }
570:
571: /**
572: * Initialize the container.
573: */
574: public void manualInit() throws Exception {
575: try {
576: log.fine("Initializing ejb-server : local-jndi="
577: + _localJndiPrefix + " remote-jndi="
578: + _remoteJndiPrefix);
579:
580: Environment
581: .addChildLoaderListener(new PersistenceEnvironmentListener());
582: Environment
583: .addChildLoaderListener(new EjbEnvironmentListener());
584:
585: /*
586: ProtocolContainer protocol = new ProtocolContainer();
587: if (_urlPrefix != null)
588: protocol.setURLPrefix(_urlPrefix);
589:
590: protocol.setServerManager(_ejbManager); // .getEnvServerManager());
591:
592: _ejbManager.getProtocolManager().setProtocolContainer(protocol);
593: _ejbManager.setLocalJndiPrefix(_localJndiPrefix);
594: _ejbManager.setRemoteJndiPrefix(_remoteJndiPrefix);
595:
596: //_ejbManager.setDataSource(_dataSource);
597: //_ejbManager.setCreateDatabaseSchema(_createDatabaseSchema);
598: _ejbManager.setValidateDatabaseSchema(_validateDatabaseSchema);
599: _ejbManager.setJMSConnectionFactory(_jmsConnectionFactory);
600: _ejbManager.setTransactionTimeout(_transactionTimeout);
601: _ejbManager.setAllowJVMCall(! _forbidJVMCall);
602: _ejbManager.setAutoCompile(_autoCompile);
603: _ejbManager.setAllowPOJO(isAllowPOJO());
604:
605: int resinIsolation = -1;
606:
607: if (_resinIsolation == null) {
608: }
609: else if (_resinIsolation.equals("row-locking"))
610: resinIsolation = EjbMethod.RESIN_ROW_LOCKING;
611: else if (_resinIsolation.equals("database"))
612: resinIsolation = EjbMethod.RESIN_DATABASE;
613: else {
614: throw new ConfigException(L.l("resin-isolation may only be `row-locking' or `database' in EJBServer, not `{0}'", _resinIsolation));
615: }
616:
617: _ejbManager.setResinIsolation(resinIsolation);
618:
619: int jdbcIsolation = -1;
620:
621: if (_jdbcIsolation == null) {
622: }
623: else if (_jdbcIsolation.equals("none"))
624: jdbcIsolation = java.sql.Connection.TRANSACTION_NONE;
625: else if (_jdbcIsolation.equals("read-committed"))
626: jdbcIsolation = java.sql.Connection.TRANSACTION_READ_COMMITTED;
627: else if (_jdbcIsolation.equals("read-uncommitted"))
628: jdbcIsolation = java.sql.Connection.TRANSACTION_READ_UNCOMMITTED;
629: else if (_jdbcIsolation.equals("repeatable-read"))
630: jdbcIsolation = java.sql.Connection.TRANSACTION_REPEATABLE_READ;
631: else if (_jdbcIsolation.equals("serializable"))
632: jdbcIsolation = java.sql.Connection.TRANSACTION_SERIALIZABLE;
633: else
634: throw new ConfigException(L.l("unknown value for jdbc-isolation at `{0}'",
635: _jdbcIsolation));
636:
637: _ejbManager.setJDBCIsolation(jdbcIsolation);
638: */
639:
640: /*
641: for (int i = 0; i < _beanList.size(); i++)
642: _beanList.get(i).init();
643:
644: // _entityIntrospector.init();
645:
646: initAllEjbs();
647:
648: _ejbManager.init();
649: */
650:
651: /*
652: String name = _jndiName;
653: if (! name.startsWith("java:"))
654: name = "java:comp/env/" + name;
655:
656: Jndi.bindDeep(name, this);
657: */
658:
659: // Environment.addEnvironmentListener(this);
660: } catch (Exception e) {
661: log.log(Level.WARNING, e.toString(), e);
662:
663: throw e;
664: }
665: }
666:
667: /**
668: * Initialize all EJBs for any *.ejb or ejb-jar.xml in the WEB-INF or
669: * in a META-INF in the classpath.
670: */
671: public void initEJBs() throws Exception {
672: manualInit();
673: }
674:
675: /**
676: * Initialize all EJBs for any *.ejb or ejb-jar.xml in the WEB-INF or
677: * in a META-INF in the classpath.
678: */
679: /*
680: private void initAllEjbs()
681: throws Exception
682: {
683: addEJBJars();
684:
685: if (_descriptors != null) {
686: for (int i = 0; i < _descriptors.size(); i++) {
687: Path path = _descriptors.get(i);
688:
689: // XXX: app.addDepend(path);
690: _ejbContainer.getConfigManager().addEJBPath(path, path);
691: }
692: }
693: }
694: */
695:
696: /*
697: private void addEJBJars()
698: throws Exception
699: {
700: for (int i = 0; i < _ejbJars.size(); i++) {
701: Path path = _ejbJars.get(i);
702:
703: Environment.addDependency(path);
704:
705: JarPath jar = JarPath.create(path);
706:
707: _ejbManager.getEjbConfig().addEJBJar(jar);
708: }
709: }
710: */
711:
712: /*
713: public MessageDestination getMessageDestination(Path path, String name)
714: {
715: return _ejbManager.getMessageDestination(path, name);
716: }
717:
718: public MessageDestination getMessageDestination(String name)
719: {
720: return _ejbManager.getMessageDestination(name);
721: }
722: */
723: }
|