001: /*
002: Copyright (C) 2007 Mobixess Inc. http://www.java-objects-database.com
003:
004: This file is part of the JODB (Java Objects Database) open source project.
005:
006: JODB is free software; you can redistribute it and/or modify it under
007: the terms of version 2 of the GNU General Public License as published
008: by the Free Software Foundation.
009:
010: JODB is distributed in the hope that it will be useful, but WITHOUT ANY
011: WARRANTY; without even the implied warranty of MERCHANTABILITY or
012: FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
013: for more details.
014:
015: You should have received a copy of the GNU General Public License along
016: with this program; if not, write to the Free Software Foundation, Inc.,
017: 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
018: */
019: package com.mobixess.jodb.core;
020:
021: import java.io.File;
022: import java.io.IOException;
023: import java.lang.reflect.Field;
024: import java.net.URI;
025: import java.util.Enumeration;
026: import java.util.Vector;
027:
028: import com.mobixess.jodb.core.index.JODBIndexingAgent;
029: import com.mobixess.jodb.core.index.JODBIndexingRootAgent;
030: import com.mobixess.jodb.core.io.IOBase;
031: import com.mobixess.jodb.core.io.IOTicket;
032: import com.mobixess.jodb.core.io.JODBIOBase;
033: import com.mobixess.jodb.core.io.JODBOperationContext;
034: import com.mobixess.jodb.core.io.rmi.JODBIOBaseProxy;
035: import com.mobixess.jodb.core.query.QueryNode;
036: import com.mobixess.jodb.core.transaction.JODBQueryList;
037: import com.mobixess.jodb.core.transaction.JODBSession;
038: import com.mobixess.jodb.core.transaction.TransactionContainer;
039: import com.mobixess.jodb.soda.api.ObjectContainer;
040: import com.mobixess.jodb.soda.api.ObjectSet;
041: import com.mobixess.jodb.soda.api.Query;
042:
043: public class JODBSessionContainer implements ObjectContainer {
044:
045: private IOBase _base;
046: private JODBSession _session;
047: private TransactionContainer _transactionContainer;
048: private int _openRequestsCounter;
049: private Vector<ISessionCloseListener> _closedListener = new Vector<ISessionCloseListener>();
050:
051: /*package*/JODBSessionContainer(File file) throws IOException {
052: _base = new JODBIOBase(file);
053: _session = new JODBSession(_base);
054: _transactionContainer = new TransactionContainer(_session);
055: if (_base.isNewDatabase()) {
056: JODBIndexingRootAgent agent = new JODBIndexingRootAgent();
057: try {
058: _transactionContainer.enableAgentMode();
059: _transactionContainer.set(agent, Integer.MAX_VALUE);
060: } catch (IllegalClassTypeException e) {
061: throw new JodbIOException(e);
062: } finally {
063: _transactionContainer.disableAgentMode();
064: }
065: commit(agent);
066: }
067: }
068:
069: /*package*/JODBSessionContainer(URI serverURI) throws IOException {
070: _base = new JODBIOBaseProxy(serverURI);
071: _session = new JODBSession(_base);
072: _transactionContainer = new TransactionContainer(_session);
073: }
074:
075: public void printFileMap() throws IOException {
076: _base.printFileMap(_session, System.err);
077: }
078:
079: URI getDbIdentificator() {
080: return _base.getDbIdentificator();
081: }
082:
083: IOBase getIoBase() {
084: return _base;
085: }
086:
087: JODBSession getSession() {
088: return _session;
089: }
090:
091: public void configureIndex(Class clazz, String fieldName,
092: boolean enable) throws SecurityException,
093: NoSuchFieldException, IOException {
094: Field field = clazz.getDeclaredField(fieldName);
095: configureIndex(field, enable);
096: }
097:
098: public JODBIndexingAgent getIndexingAgent(Field field)
099: throws IOException {
100: JODBIndexingRootAgent indexingRootAgent = _session
101: .getIndexingRootAgent();
102: return indexingRootAgent.getIndexingAgent(field, _base);
103: }
104:
105: public void configureIndex(Field field, boolean enable)
106: throws IOException {
107: if (!_transactionContainer.isEmpty()) {
108: throw new IllegalStateException(
109: "Cannot create index with transaction in progress");
110: }
111: JODBIndexingRootAgent indexingRootAgent = _session
112: .getIndexingRootAgent();
113: JODBIndexingAgent indexingAgent = indexingRootAgent
114: .getIndexingAgent(field, _base);
115: if ((indexingAgent != null && enable)
116: || (indexingAgent == null && !enable)) {
117: return;
118: }
119:
120: IOTicket writeTicket = _base.getIOTicket(true, true);
121: try {
122: JODBOperationContext context = new JODBOperationContext(
123: _session, writeTicket, null, _transactionContainer,
124: indexingRootAgent);
125: writeTicket.lock(true);
126:
127: if (!enable) {
128: indexingRootAgent.removeAgent(field, context);
129: return;
130: }
131:
132: indexingAgent = indexingRootAgent.enableIndex(field,
133: context);
134:
135: _base.applyTransaction(_transactionContainer, _session,
136: writeTicket, indexingRootAgent);
137:
138: } finally {
139: writeTicket.unlock();//should be already released in "applyTransaction()", just to play safe
140: }
141: }
142:
143: public void activate(Object obj, int depth) throws IOException {
144: _session.activate(obj, depth);
145: }
146:
147: public int getCachedObjectsCount() {
148: return _session.getCachedObjectsCount();
149: }
150:
151: public synchronized boolean close() throws IOException {
152: if (_base.isClosed()) {
153: return true;
154: }
155: try {
156: commit();
157: } finally {
158: _openRequestsCounter--;
159: if (_openRequestsCounter == 0) {
160: JODB.removeSessionFromCache(_base.getDbIdentificator());//TODO better damage control over concurrent close/open
161: _base.close();
162: _session.close();
163: }
164: if (_openRequestsCounter == 0) {
165: fireSessionClosed();
166: }
167: }
168: return _openRequestsCounter == 0;
169: }
170:
171: public void addCloseListener(ISessionCloseListener closeListener) {
172: _closedListener.add(closeListener);
173: }
174:
175: public void removeCloseListener(ISessionCloseListener closeListener) {
176: _closedListener.remove(closeListener);
177: }
178:
179: private void fireSessionClosed() {
180: Enumeration<ISessionCloseListener> enumeration = _closedListener
181: .elements();
182: while (enumeration.hasMoreElements()) {
183: ISessionCloseListener sessionCloseListener = enumeration
184: .nextElement();
185: sessionCloseListener.sessionClosed(this );
186: }
187: }
188:
189: public void commit() throws IOException {
190: commit(_session.getIndexingRootAgent());
191: }
192:
193: public void commit(JODBIndexingRootAgent indexingRootAgent)
194: throws IOException {
195: _base.applyTransaction(_transactionContainer, _session, null,
196: indexingRootAgent);
197: }
198:
199: public Object getSyncObject(Object activeObject) {
200: return _session.getHandleForActiveObject(activeObject);
201: }
202:
203: public void deactivate(Object obj, int depth) {
204: _session.deactivate(obj, depth);
205: }
206:
207: public void delete(Object obj) throws IOException {
208: delete(obj, JODBConfig.getDefaultDeleteDepth());
209: }
210:
211: public void delete(Object obj, int depth) throws IOException {
212: if (_base.isClosed()) {
213: throw new JodbIOException("Container closed");
214: }
215: try {
216: _transactionContainer.delete(obj, depth);
217: } catch (IllegalClassTypeException e) {
218: e.printStackTrace();//no reason to release this Exception
219: }
220: }
221:
222: public <T> ObjectSet<T> get(Object template) throws IOException,
223: IllegalClassTypeException {
224: if (template == null) {
225: return _session.getAllObjects();
226: } else {
227: Query query = query();
228: query.constrain(template);
229: return query.execute();
230: }
231: }
232:
233: public Query query() {
234: return new QueryNode("", _session, null);
235: }
236:
237: public <Type> ObjectSet<Type> query(Class<Type> clazz)
238: throws IOException, IllegalClassTypeException {
239: Query query = query();
240: query.constrain(clazz);
241: return query.execute();
242: }
243:
244: public void rollback() {
245: _transactionContainer.reset();
246: }
247:
248: public void set(Object obj) throws IllegalClassTypeException,
249: IOException {
250: set(obj, JODBConfig.getDefaultSetDepth());
251: }
252:
253: public void set(Object obj, int depth)
254: throws IllegalClassTypeException, IOException {
255: if (_base.isClosed()) {
256: throw new JodbIOException("Container closed");
257: }
258: _transactionContainer.set(obj, depth);
259: }
260:
261: public JODBQueryList getAllObjects() throws IOException {
262: return _session.getAllObjects();
263: }
264:
265: public IPersistentObjectStatistics getPersistenceStatistics(
266: Object object) throws IOException {
267: return _session.getPersistenceStatistics(object);
268: }
269:
270: public IDatabaseStatistics getDatabaseStatistics()
271: throws IOException {
272: return _base.getDatabaseStatistics();
273: }
274:
275: public void setClassLoader(ClassLoader classLoader) {
276: _session.setClassLoader(classLoader);
277: }
278:
279: @Override
280: protected void finalize() throws Throwable {
281: if (!_base.isClosed()) {
282: close();
283: }
284: }
285:
286: synchronized void incOpenCounter() {
287: _openRequestsCounter++;
288: }
289: }
|