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: * Free SoftwareFoundation, Inc.
023: * 59 Temple Place, Suite 330
024: * Boston, MA 02111-1307 USA
025: *
026: * @author Scott Ferguson
027: */
028:
029: package com.caucho.jca;
030:
031: import com.caucho.config.ConfigException;
032: import com.caucho.loader.*;
033: import com.caucho.util.L10N;
034:
035: import javax.naming.Context;
036: import javax.naming.InitialContext;
037: import javax.resource.spi.BootstrapContext;
038: import javax.resource.spi.ResourceAdapter;
039: import javax.resource.spi.XATerminator;
040: import javax.resource.spi.work.WorkManager;
041: import java.lang.ref.SoftReference;
042: import java.util.ArrayList;
043: import java.util.Timer;
044: import java.util.logging.Level;
045: import java.util.logging.Logger;
046:
047: /**
048: * Implementation of the resource manager.
049: */
050: public class ResourceManagerImpl implements BootstrapContext {
051: private static final L10N L = new L10N(ResourceManagerImpl.class);
052: private static final Logger log = Logger
053: .getLogger(ResourceManagerImpl.class.getName());
054:
055: private static EnvironmentLocal<ResourceManagerImpl> _localManager = new EnvironmentLocal<ResourceManagerImpl>();
056:
057: private final EnvironmentClassLoader _loader;
058:
059: private UserTransactionProxy _tm;
060:
061: private ArrayList<ResourceAdapter> _resources = new ArrayList<ResourceAdapter>();
062:
063: private ArrayList<ConnectionPool> _connectionManagers = new ArrayList<ConnectionPool>();
064:
065: private ArrayList<SoftReference<Timer>> _timers = new ArrayList<SoftReference<Timer>>();
066:
067: private WorkManagerImpl _workManager;
068:
069: private boolean _isInit;
070: private boolean _isClosed;
071:
072: /**
073: * Constructor.
074: */
075: private ResourceManagerImpl() {
076: _loader = Environment.getEnvironmentClassLoader();
077:
078: Environment.addClassLoaderListener(new CloseListener(this ));
079:
080: _tm = UserTransactionProxy.getInstance();
081:
082: if (_tm == null)
083: throw new IllegalStateException();
084: }
085:
086: /**
087: * Returns the impl.
088: */
089: public static ResourceManagerImpl createLocalManager() {
090: return create();
091: }
092:
093: /**
094: * Returns the impl.
095: */
096: public static ResourceManagerImpl create() {
097: ResourceManagerImpl rm;
098:
099: synchronized (_localManager) {
100: rm = _localManager.getLevel();
101:
102: if (rm == null) {
103: rm = new ResourceManagerImpl();
104: _localManager.set(rm);
105: }
106: }
107:
108: return rm;
109: }
110:
111: /**
112: * Returns the impl.
113: */
114: public static ResourceManagerImpl getLocalManager() {
115: return _localManager.getLevel();
116: }
117:
118: /**
119: * Adds a resource to the manager.
120: */
121: public static void addResource(ResourceAdapter resource)
122: throws ConfigException {
123: ResourceManagerImpl rm = createLocalManager();
124:
125: rm.addResourceImpl(resource);
126: }
127:
128: /**
129: * Adds a resource to the resource manager.
130: */
131: private void addResourceImpl(ResourceAdapter resource) {
132: try {
133: resource.start(this );
134: } catch (Exception e) {
135: log.log(Level.WARNING, e.toString(), e);
136: }
137:
138: _resources.add(resource);
139: }
140:
141: /**
142: * Returns a connection manager
143: */
144: public ConnectionPool createConnectionPool() {
145: ConnectionPool cm = new ConnectionPool();
146:
147: cm.setTransactionManager(_tm);
148:
149: _connectionManagers.add(cm);
150:
151: return cm;
152: }
153:
154: /**
155: * Returns a WorkManager instance.
156: */
157: public WorkManager getWorkManager() {
158: synchronized (this ) {
159: if (_workManager == null)
160: _workManager = new WorkManagerImpl();
161: }
162:
163: return _workManager;
164: }
165:
166: /**
167: * Returns an XATerminator. The XATerminator could be used for
168: * transaction completion and crash recovery.
169: */
170: public XATerminator getXATerminator() {
171: return null;
172: }
173:
174: /**
175: * Creates a new Timer instance.
176: */
177: public Timer createTimer() {
178: TimerImpl timer = new TimerImpl(this );
179:
180: synchronized (_timers) {
181: SoftReference<Timer> timerRef = new SoftReference<Timer>(
182: timer);
183:
184: _timers.add(timerRef);
185: }
186:
187: return timer;
188: }
189:
190: /**
191: * Removes a new Timer instance.
192: */
193: void removeTimer(Timer timer) {
194: if (_timers == null)
195: return;
196:
197: synchronized (_timers) {
198: for (int i = _timers.size(); i >= 0; i--) {
199: SoftReference<Timer> timerRef = _timers.get(i);
200: Timer oldTimer = timerRef.get();
201:
202: if (oldTimer == null)
203: _timers.remove(i);
204: else if (oldTimer == timer)
205: _timers.remove(i);
206: }
207: }
208: }
209:
210: /**
211: * Handles the case where a class loader is activated.
212: */
213: public void classLoaderInit(DynamicClassLoader loader) {
214: }
215:
216: /**
217: * Handles the case where a class loader is dropped.
218: */
219: public void classLoaderDestroy(DynamicClassLoader loader) {
220: destroy();
221: }
222:
223: /**
224: * Closes the resource manager.
225: */
226: public void destroy() {
227: ArrayList<ConnectionPool> connectionManagers;
228: ArrayList<ResourceAdapter> resources;
229: ArrayList<SoftReference<Timer>> timers;
230:
231: synchronized (this ) {
232: if (_isClosed)
233: return;
234: _isClosed = true;
235:
236: connectionManagers = _connectionManagers;
237: _connectionManagers = null;
238:
239: resources = _resources;
240: _resources = null;
241:
242: timers = _timers;
243: _timers = null;
244: }
245:
246: // Kill timers first, so they won't try to spawn work tasks
247: for (int i = 0; i < timers.size(); i++) {
248: SoftReference<Timer> timerRef = timers.get(i);
249: Timer timer = timerRef.get();
250:
251: try {
252: if (timer != null)
253: timer.cancel();
254: } catch (Throwable e) {
255: log.log(Level.WARNING, e.toString(), e);
256: }
257: }
258:
259: // cancel the work managers
260: if (_workManager != null)
261: _workManager.destroy();
262:
263: for (int i = 0; i < connectionManagers.size(); i++) {
264: ConnectionPool connectionManager = connectionManagers
265: .get(i);
266:
267: try {
268: connectionManager.destroy();
269: } catch (Throwable e) {
270: log.log(Level.WARNING, e.toString(), e);
271: }
272: }
273:
274: // finally, close the resources
275: for (int i = 0; i < resources.size(); i++) {
276: ResourceAdapter resource = resources.get(i);
277:
278: try {
279: resource.stop();
280: } catch (Throwable e) {
281: log.log(Level.WARNING, e.toString(), e);
282: }
283: }
284: }
285:
286: public class TimerImpl extends Timer {
287: private ResourceManagerImpl _rm;
288:
289: TimerImpl(ResourceManagerImpl rm) {
290: super (true);
291:
292: _rm = rm;
293: }
294:
295: public void cancel() {
296: _rm.removeTimer(this );
297:
298: super .cancel();
299: }
300: }
301:
302: public String toString() {
303: if (_loader != null)
304: return getClass().getSimpleName() + "[" + _loader.getId()
305: + "]";
306: else
307: return getClass().getSimpleName() + "[]";
308: }
309: }
|