Skip to contentMethod: unwrap(Class)
1: /**
2: * Copyright (C) 2016 Czech Technical University in Prague
3: * <p>
4: * This program is free software: you can redistribute it and/or modify it under
5: * the terms of the GNU General Public License as published by the Free Software
6: * Foundation, either version 3 of the License, or (at your option) any
7: * later version.
8: * <p>
9: * This program is distributed in the hope that it will be useful, but WITHOUT
10: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11: * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12: * details. You should have received a copy of the GNU General Public License
13: * along with this program. If not, see <http://www.gnu.org/licenses/>.
14: */
15: package cz.cvut.kbss.jopa.sessions;
16:
17: import cz.cvut.kbss.jopa.accessors.DefaultStorageAccessor;
18: import cz.cvut.kbss.jopa.accessors.StorageAccessor;
19: import cz.cvut.kbss.jopa.model.AbstractEntityManager;
20: import cz.cvut.kbss.jopa.model.MetamodelImpl;
21: import cz.cvut.kbss.jopa.model.metamodel.EntityType;
22: import cz.cvut.kbss.jopa.model.metamodel.Metamodel;
23: import cz.cvut.kbss.jopa.model.metamodel.Type;
24: import cz.cvut.kbss.jopa.query.NamedQueryManager;
25: import cz.cvut.kbss.jopa.sessions.cache.CacheFactory;
26: import cz.cvut.kbss.jopa.transactions.EntityTransaction;
27: import cz.cvut.kbss.jopa.utils.Wrapper;
28: import cz.cvut.kbss.ontodriver.OntologyStorageProperties;
29: import cz.cvut.kbss.ontodriver.exception.OntoDriverException;
30:
31: import java.net.URI;
32: import java.util.*;
33: import java.util.stream.Collectors;
34:
35: /**
36: * The ServerSession is the primary interface for accessing the ontology.
37: * <p>
38: * It manages an accessor object, which performs the queries.
39: */
40: public class ServerSession extends AbstractSession implements Wrapper {
41:
42: private final MetamodelImpl metamodel;
43: private final Set<Class<?>> managedClasses;
44:
45: private CacheManager liveObjectCache;
46: private StorageAccessor storageAccessor;
47:
48: private Map<EntityTransaction, AbstractEntityManager> runningTransactions;
49: private Map<Object, UnitOfWorkImpl> activePersistenceContexts;
50: private Map<UnitOfWork, Set<Object>> uowsToEntities;
51:
52: ServerSession() {
53: this.metamodel = null;
54: this.managedClasses = null;
55: }
56:
57: public ServerSession(OntologyStorageProperties storageProperties, Map<String, String> properties,
58: MetamodelImpl metamodel) {
59: this.metamodel = metamodel;
60: this.managedClasses = processTypes(metamodel.getEntities());
61: initialize(storageProperties, properties, metamodel);
62: }
63:
64: /**
65: * Process the entity types and extract simple Java classes from them.
66: *
67: * @param entities Set of managed entity types.
68: * @return Set of managed entity classes.
69: */
70: private Set<Class<?>> processTypes(Set<EntityType<?>> entities) {
71: Set<Class<?>> types = new HashSet<>(entities.size());
72: types.addAll(entities.stream().map(Type::getJavaType).collect(Collectors.toList()));
73: return types;
74: }
75:
76: /**
77: * Initializes this ServerSession. This in particular means initialization of the ontology accessor and live object
78: * cache.
79: *
80: * @param storageProperties Storage properties
81: * @param properties Map of setup properties
82: * @param metamodel Metamodel of the managed classes and their attributes.
83: */
84: private void initialize(OntologyStorageProperties storageProperties,
85: Map<String, String> properties, Metamodel metamodel) {
86: assert properties != null;
87: assert metamodel != null;
88: this.runningTransactions = new HashMap<>();
89: this.activePersistenceContexts = new IdentityHashMap<>();
90: this.uowsToEntities = new HashMap<>();
91: this.liveObjectCache = CacheFactory.createCache(properties);
92: liveObjectCache.setInferredClasses(metamodel.getInferredClasses());
93: this.storageAccessor = new DefaultStorageAccessor(storageProperties, properties);
94: }
95:
96: protected ConnectionWrapper acquireConnection() {
97: return new ConnectionWrapper(storageAccessor.acquireConnection());
98: }
99:
100: @Override
101: public UnitOfWork acquireUnitOfWork() {
102: return new UnitOfWorkImpl(this);
103: }
104:
105: public CacheManager getLiveObjectCache() {
106: return liveObjectCache;
107: }
108:
109: public boolean transactionStarted(EntityTransaction t, AbstractEntityManager em) {
110: if (!t.isActive() || t.isRollbackOnly()) {
111: return false;
112: }
113: runningTransactions.put(t, em);
114: return true;
115: }
116:
117: public void transactionFinished(EntityTransaction t) {
118: if (t == null) {
119: return;
120: }
121: AbstractEntityManager em = runningTransactions.remove(t);
122: if (em == null) {
123: return;
124: }
125: UnitOfWorkImpl uow = (UnitOfWorkImpl) em.getCurrentPersistenceContext();
126: if (uow != null && uow.hasChanges()) {
127: getLiveObjectCache().clearInferredObjects();
128: }
129: releasePersistenceContext(uow);
130: }
131:
132: /**
133: * Close the server session and all connections to the underlying data source.
134: */
135: public void close() {
136: if (!runningTransactions.isEmpty()) {
137: LOG.warn("There are still transactions running. Marking them for rollback.");
138: runningTransactions.keySet().stream().filter(EntityTransaction::isActive)
139: .forEach(EntityTransaction::setRollbackOnly);
140: }
141: if (storageAccessor != null && storageAccessor.isOpen()) {
142: try {
143: storageAccessor.close();
144: } catch (OntoDriverException e) {
145: LOG.error("Exception caught when closing the storage accessor.", e);
146: }
147: }
148: liveObjectCache.close();
149: }
150:
151: @Override
152: public void removeObjectFromCache(Object object, URI context) {
153: // do nothing
154: }
155:
156: @Override
157: public MetamodelImpl getMetamodel() {
158: return metamodel;
159: }
160:
161: @Override
162: public boolean isTypeManaged(Class<?> cls) {
163: return cls != null && managedClasses.contains(cls);
164: }
165:
166: /**
167: * Register the specified entity as managed in the specified {@code UnitOfWork}. </p>
168: * <p>
169: * Registering loaded entities with their owning {@code UnitOfWork} is highly recommended, since it speeds up
170: * persistence context lookup when entity attributes are modified.
171: *
172: * @param entity The entity to register
173: * @param uow Persistence context of the specified entity
174: */
175: protected synchronized void registerEntityWithPersistenceContext(Object entity, UnitOfWorkImpl uow) {
176: assert entity != null;
177: assert uow != null;
178:
179: activePersistenceContexts.put(entity, uow);
180: if (!uowsToEntities.containsKey(uow)) {
181: uowsToEntities.put(uow, new HashSet<>());
182: }
183: uowsToEntities.get(uow).add(entity);
184: }
185:
186: @Override
187: synchronized void deregisterEntityFromPersistenceContext(Object entity, UnitOfWork uow) {
188: assert entity != null;
189: assert uow != null;
190: activePersistenceContexts.remove(entity);
191: if (uowsToEntities.containsKey(uow)) {
192: uowsToEntities.get(uow).remove(entity);
193: }
194: }
195:
196: @Override
197: public NamedQueryManager getNamedQueryManager() {
198: return metamodel.getNamedQueryManager();
199: }
200:
201: /**
202: * Get persistence context for the specified entity. </p>
203: *
204: * @param entity The entity
205: * @return Persistence context of the specified entity or null, if it cannot be found
206: */
207: public synchronized UnitOfWorkImpl getPersistenceContext(Object entity) {
208: if (entity == null) {
209: return null;
210: }
211: return activePersistenceContexts.get(entity);
212: }
213:
214: /**
215: * Remove the specified {@code UnitOfWork} from the list of currently active persistence contexts.
216: * <p>
217: * Also remove all the objects associated with this persistence context.
218: *
219: * @param uow The persistence context to remove
220: */
221: @Override
222: synchronized void releasePersistenceContext(UnitOfWork uow) {
223: if (uowsToEntities.containsKey(uow)) {
224: for (Object entity : uowsToEntities.get(uow)) {
225: activePersistenceContexts.remove(entity);
226: }
227: }
228: uowsToEntities.remove(uow);
229: }
230:
231: @Override
232: public <T> T unwrap(Class<T> cls) {
233: Objects.requireNonNull(cls);
234:• if (cls.isAssignableFrom(getClass())) {
235: return cls.cast(this);
236: }
237: return storageAccessor.unwrap(cls);
238: }
239: }