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.session;
031:
032: import com.caucho.config.ConfigContext;
033: import com.caucho.ejb.AbstractContext;
034: import com.caucho.ejb.EJBExceptionWrapper;
035: import java.util.*;
036:
037: import com.caucho.ejb.manager.EjbContainer;
038: import com.caucho.ejb.protocol.AbstractHandle;
039: import com.caucho.util.LruCache;
040: import com.caucho.webbeans.component.*;
041: import java.lang.reflect.Constructor;
042: import java.util.logging.Level;
043: import java.util.logging.Logger;
044: import javax.ejb.FinderException;
045: import javax.ejb.NoSuchEJBException;
046:
047: /**
048: * Server container for a session bean.
049: */
050: public class StatefulServer extends SessionServer {
051: private static final Logger log = Logger
052: .getLogger(StatefulServer.class.getName());
053:
054: private StatefulContext _homeContext;
055:
056: // XXX: need real lifecycle
057: private LruCache<String, StatefulObject> _remoteSessions;
058:
059: public StatefulServer(EjbContainer ejbContainer) {
060: super (ejbContainer);
061: }
062:
063: @Override
064: protected String getType() {
065: return "stateful:";
066: }
067:
068: @Override
069: public AbstractSessionContext getSessionContext() {
070: return getStatefulContext();
071: }
072:
073: private StatefulContext getStatefulContext() {
074: synchronized (this ) {
075: if (_homeContext == null) {
076: try {
077: Class[] param = new Class[] { StatefulServer.class };
078: Constructor cons = _contextImplClass
079: .getConstructor(param);
080:
081: _homeContext = (StatefulContext) cons
082: .newInstance(this );
083: } catch (Exception e) {
084: throw new EJBExceptionWrapper(e);
085: }
086: }
087: }
088:
089: return _homeContext;
090: }
091:
092: /**
093: * Returns the JNDI proxy object to create instances of the
094: * local interface.
095: */
096: @Override
097: public Object getLocalProxy(Class api) {
098: StatefulProvider provider = getStatefulContext().getProvider(
099: api);
100:
101: return new StatefulProviderProxy(provider);
102: }
103:
104: /**
105: * Returns the object implementation
106: */
107: @Override
108: public Object getLocalObject(Class api) {
109: StatefulProvider provider = getStatefulContext().getProvider(
110: api);
111:
112: return provider.__caucho_createNew(new ConfigContext());
113: }
114:
115: protected ComponentImpl createSessionComponent(Class api) {
116: StatefulProvider provider = getStatefulContext().getProvider(
117: api);
118:
119: return new StatefulComponent(provider);
120: }
121:
122: /**
123: * Creates a handle for a new session.
124: */
125: AbstractHandle createHandle(AbstractContext context) {
126: throw new UnsupportedOperationException(getClass().getName());
127: /*
128: String key = ((StatelessContext) context).getPrimaryKey();
129:
130: return getHandleEncoder().createHandle(key);
131: */
132: }
133:
134: public void addSession(StatefulObject remoteObject) {
135: createSessionKey(remoteObject);
136: }
137:
138: /**
139: * Finds the remote bean by its key.
140: *
141: * @param key the remote key
142: *
143: * @return the remote interface of the entity.
144: */
145: @Override
146: public AbstractContext getContext(Object key, boolean forceLoad)
147: throws FinderException {
148: throw new NoSuchEJBException("no matching object:" + key);
149: /*
150: if (key == null)
151: return null;
152:
153: StatefulContext cxt = _sessions.get(key);
154:
155: // ejb/0fe4
156: if (cxt == null)
157: throw new NoSuchEJBException("no matching object:" + key);
158: // XXX ejb/0fe-: needs refactoring of 2.1/3.0 interfaces.
159: // throw new FinderException("no matching object:" + key);
160:
161: return cxt;
162: */
163: }
164:
165: /**
166: * Returns the remote object.
167: */
168: @Override
169: public Object getRemoteObject(Object key) {
170: StatefulObject remote = null;
171: if (_remoteSessions != null) {
172: remote = _remoteSessions.get(String.valueOf(key));
173: }
174:
175: return remote;
176: }
177:
178: /**
179: * Creates a handle for a new session.
180: */
181: public String createSessionKey(StatefulObject remote) {
182: String key = getHandleEncoder().createRandomStringKey();
183:
184: if (_remoteSessions == null)
185: _remoteSessions = new LruCache<String, StatefulObject>(8192);
186:
187: _remoteSessions.put(key, remote);
188:
189: return key;
190: }
191:
192: /**
193: * Returns the remote stub for the container
194: */
195: @Override
196: public Object getRemoteObject(Class api, String protocol) {
197: StatefulProvider provider = getStatefulContext().getProvider(
198: api);
199:
200: if (provider != null) {
201: Object value = provider.__caucho_createNew(null);
202:
203: return value;
204: } else
205: return null;
206: }
207:
208: /**
209: * Remove an object by its handle.
210: */
211: @Override
212: public Object remove(AbstractHandle handle) {
213: if (_remoteSessions != null)
214: return _remoteSessions.remove(handle.getObjectId());
215: else
216: return null;
217: // _ejbManager.remove(handle);
218: }
219:
220: /**
221: * Remove an object.
222: */
223: @Override
224: public void remove(Object key) {
225: if (_remoteSessions != null) {
226: _remoteSessions.remove(String.valueOf(key));
227:
228: /*
229: // ejb/0fe2
230: if (cxt == null)
231: throw new NoSuchEJBException("no matching object:" + key);
232: */
233: }
234: }
235:
236: /**
237: * Cleans up the entity server nicely.
238: */
239: @Override
240: public void destroy() {
241: super .destroy();
242:
243: ArrayList<StatefulObject> values = new ArrayList<StatefulObject>();
244:
245: if (_remoteSessions != null) {
246: Iterator<StatefulObject> iter = _remoteSessions.values();
247: while (iter.hasNext()) {
248: values.add(iter.next());
249: }
250: }
251:
252: _remoteSessions = null;
253:
254: for (StatefulObject obj : values) {
255: try {
256: obj.remove();
257: } catch (Throwable e) {
258: log.log(Level.WARNING, e.toString(), e);
259: }
260: }
261:
262: log.fine(this + " closed");
263: }
264: }
|