1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19 package org.apache.openjpa.persistence;
20
21 import java.io.ByteArrayInputStream;
22 import java.io.ByteArrayOutputStream;
23 import java.io.Externalizable;
24 import java.io.IOException;
25 import java.io.ObjectInput;
26 import java.io.ObjectInputStream;
27 import java.io.ObjectOutput;
28 import java.io.ObjectOutputStream;
29 import java.io.ObjectStreamClass;
30 import java.lang.reflect.Array;
31 import java.util.Arrays;
32 import java.util.Collection;
33 import java.util.EnumSet;
34 import java.util.Map;
35 import java.util.HashMap;
36 import java.util.IdentityHashMap;
37 import javax.persistence.EntityManager;
38 import javax.persistence.FlushModeType;
39 import javax.persistence.LockModeType;
40 import javax.persistence.Query;
41
42 import org.apache.commons.lang.StringUtils;
43 import org.apache.openjpa.conf.OpenJPAConfiguration;
44 import org.apache.openjpa.ee.ManagedRuntime;
45 import org.apache.openjpa.enhance.PCEnhancer;
46 import org.apache.openjpa.enhance.PCRegistry;
47 import org.apache.openjpa.kernel.AbstractBrokerFactory;
48 import org.apache.openjpa.kernel.Broker;
49 import org.apache.openjpa.kernel.DelegatingBroker;
50 import org.apache.openjpa.kernel.FindCallbacks;
51 import org.apache.openjpa.kernel.LockLevels;
52 import org.apache.openjpa.kernel.OpCallbacks;
53 import org.apache.openjpa.kernel.OpenJPAStateManager;
54 import org.apache.openjpa.kernel.QueryFlushModes;
55 import org.apache.openjpa.kernel.QueryLanguages;
56 import org.apache.openjpa.kernel.Seq;
57 import org.apache.openjpa.kernel.FetchConfiguration;
58 import org.apache.openjpa.kernel.jpql.JPQLParser;
59 import org.apache.openjpa.lib.util.Closeable;
60 import org.apache.openjpa.lib.util.Localizer;
61 import org.apache.openjpa.meta.ClassMetaData;
62 import org.apache.openjpa.meta.FieldMetaData;
63 import org.apache.openjpa.meta.QueryMetaData;
64 import org.apache.openjpa.meta.SequenceMetaData;
65 import org.apache.openjpa.util.Exceptions;
66 import org.apache.openjpa.util.ImplHelper;
67 import org.apache.openjpa.util.RuntimeExceptionTranslator;
68 import org.apache.openjpa.util.UserException;
69
70 /**
71 * Implementation of {@link EntityManager} interface.
72 *
73 * @author Patrick Linskey
74 * @author Abe White
75 * @nojavadoc
76 */
77 public class EntityManagerImpl
78 implements OpenJPAEntityManagerSPI, Externalizable,
79 FindCallbacks, OpCallbacks, Closeable, OpenJPAEntityTransaction {
80
81 private static final Localizer _loc = Localizer.forPackage
82 (EntityManagerImpl.class);
83 private static final Object[] EMPTY_OBJECTS = new Object[0];
84
85 private DelegatingBroker _broker;
86 private EntityManagerFactoryImpl _emf;
87 private Map<FetchConfiguration,FetchPlan> _plans =
88 new IdentityHashMap<FetchConfiguration,FetchPlan>(1);
89
90 private RuntimeExceptionTranslator ret =
91 PersistenceExceptions.getRollbackTranslator(this);
92
93 public EntityManagerImpl() {
94 // for Externalizable
95 }
96
97 /**
98 * Constructor; supply factory and delegate.
99 */
100 public EntityManagerImpl(EntityManagerFactoryImpl factory,
101 Broker broker) {
102 initialize(factory, broker);
103 }
104
105 private void initialize(EntityManagerFactoryImpl factory, Broker broker) {
106 _emf = factory;
107 _broker = new DelegatingBroker(broker, ret);
108 _broker.setImplicitBehavior(this, ret);
109 }
110
111 /**
112 * Broker delegate.
113 */
114 public Broker getBroker() {
115 return _broker.getDelegate();
116 }
117
118 public OpenJPAEntityManagerFactory getEntityManagerFactory() {
119 return _emf;
120 }
121
122 public OpenJPAConfiguration getConfiguration() {
123 return _broker.getConfiguration();
124 }
125
126 public FetchPlan getFetchPlan() {
127 assertNotCloseInvoked();
128 _broker.lock();
129 try {
130 FetchConfiguration fc = _broker.getFetchConfiguration();
131 FetchPlan fp = _plans.get(fc);
132 if (fp == null) {
133 fp = _emf.toFetchPlan(_broker, fc);
134 _plans.put(fc, fp);
135 }
136 return fp;
137 } finally {
138 _broker.unlock();
139 }
140 }
141
142 public FetchPlan pushFetchPlan() {
143 assertNotCloseInvoked();
144 _broker.lock();
145 try {
146 _broker.pushFetchConfiguration();
147 return getFetchPlan();
148 } finally {
149 _broker.unlock();
150 }
151 }
152
153 public void popFetchPlan() {
154 assertNotCloseInvoked();
155 _broker.lock();
156 try {
157 _broker.popFetchConfiguration();
158 } finally {
159 _broker.unlock();
160 }
161 }
162
163 public ConnectionRetainMode getConnectionRetainMode() {
164 return ConnectionRetainMode.fromKernelConstant(
165 _broker.getConnectionRetainMode());
166 }
167
168 public boolean isTransactionManaged() {
169 return _broker.isManaged();
170 }
171
172 public boolean isManaged() {
173 return _broker.isManaged();
174 }
175
176 public ManagedRuntime getManagedRuntime() {
177 return _broker.getManagedRuntime();
178 }
179
180 public boolean getSyncWithManagedTransactions() {
181 return _broker.getSyncWithManagedTransactions();
182 }
183
184 public void setSyncWithManagedTransactions(boolean sync) {
185 assertNotCloseInvoked();
186 _broker.setSyncWithManagedTransactions(sync);
187 }
188
189 public ClassLoader getClassLoader() {
190 return _broker.getClassLoader();
191 }
192
193 public String getConnectionUserName() {
194 return _broker.getConnectionUserName();
195 }
196
197 public String getConnectionPassword() {
198 return _broker.getConnectionPassword();
199 }
200
201 public boolean getMultithreaded() {
202 return _broker.getMultithreaded();
203 }
204
205 public void setMultithreaded(boolean multithreaded) {
206 assertNotCloseInvoked();
207 _broker.setMultithreaded(multithreaded);
208 }
209
210 public boolean getIgnoreChanges() {
211 return _broker.getIgnoreChanges();
212 }
213
214 public void setIgnoreChanges(boolean val) {
215 assertNotCloseInvoked();
216 _broker.setIgnoreChanges(val);
217 }
218
219 public boolean getNontransactionalRead() {
220 return _broker.getNontransactionalRead();
221 }
222
223 public void setNontransactionalRead(boolean val) {
224 assertNotCloseInvoked();
225 _broker.setNontransactionalRead(val);
226 }
227
228 public boolean getNontransactionalWrite() {
229 return _broker.getNontransactionalWrite();
230 }
231
232 public void setNontransactionalWrite(boolean val) {
233 assertNotCloseInvoked();
234 _broker.setNontransactionalWrite(val);
235 }
236
237 public boolean getOptimistic() {
238 return _broker.getOptimistic();
239 }
240
241 public void setOptimistic(boolean val) {
242 assertNotCloseInvoked();
243 _broker.setOptimistic(val);
244 }
245
246 public RestoreStateType getRestoreState() {
247 return RestoreStateType.fromKernelConstant(_broker.getRestoreState());
248 }
249
250 public void setRestoreState(RestoreStateType val) {
251 assertNotCloseInvoked();
252 _broker.setRestoreState(val.toKernelConstant());
253 }
254
255 public void setRestoreState(int restore) {
256 assertNotCloseInvoked();
257 _broker.setRestoreState(restore);
258 }
259
260 public boolean getRetainState() {
261 return _broker.getRetainState();
262 }
263
264 public void setRetainState(boolean val) {
265 assertNotCloseInvoked();
266 _broker.setRetainState(val);
267 }
268
269 public AutoClearType getAutoClear() {
270 return AutoClearType.fromKernelConstant(_broker.getAutoClear());
271 }
272
273 public void setAutoClear(AutoClearType val) {
274 assertNotCloseInvoked();
275 _broker.setAutoClear(val.toKernelConstant());
276 }
277
278 public void setAutoClear(int autoClear) {
279 assertNotCloseInvoked();
280 _broker.setAutoClear(autoClear);
281 }
282
283 public DetachStateType getDetachState() {
284 return DetachStateType.fromKernelConstant(_broker.getDetachState());
285 }
286
287 public void setDetachState(DetachStateType type) {
288 assertNotCloseInvoked();
289 _broker.setDetachState(type.toKernelConstant());
290 }
291
292 public void setDetachState(int detach) {
293 assertNotCloseInvoked();
294 _broker.setDetachState(detach);
295 }
296
297 public EnumSet<AutoDetachType> getAutoDetach() {
298 return AutoDetachType.toEnumSet(_broker.getAutoDetach());
299 }
300
301 public void setAutoDetach(AutoDetachType flag) {
302 assertNotCloseInvoked();
303 _broker.setAutoDetach(AutoDetachType.fromEnumSet(EnumSet.of(flag)));
304 }
305
306 public void setAutoDetach(EnumSet<AutoDetachType> flags) {
307 assertNotCloseInvoked();
308 _broker.setAutoDetach(AutoDetachType.fromEnumSet(flags));
309 }
310
311 public void setAutoDetach(int autoDetachFlags) {
312 assertNotCloseInvoked();
313 _broker.setAutoDetach(autoDetachFlags);
314 }
315
316 public void setAutoDetach(AutoDetachType value, boolean on) {
317 assertNotCloseInvoked();
318 _broker.setAutoDetach(AutoDetachType.fromEnumSet(EnumSet.of(value)),on);
319 }
320
321 public void setAutoDetach(int flag, boolean on) {
322 assertNotCloseInvoked();
323 _broker.setAutoDetach(flag, on);
324 }
325
326 public boolean getEvictFromStoreCache() {
327 return _broker.getEvictFromDataCache();
328 }
329
330 public void setEvictFromStoreCache(boolean evict) {
331 assertNotCloseInvoked();
332 _broker.setEvictFromDataCache(evict);
333 }
334
335 public boolean getPopulateStoreCache() {
336 return _broker.getPopulateDataCache();
337 }
338
339 public void setPopulateStoreCache(boolean cache) {
340 assertNotCloseInvoked();
341 _broker.setPopulateDataCache(cache);
342 }
343
344 public boolean isTrackChangesByType() {
345 return _broker.isTrackChangesByType();
346 }
347
348 public void setTrackChangesByType(boolean trackByType) {
349 assertNotCloseInvoked();
350 _broker.setTrackChangesByType(trackByType);
351 }
352
353 public boolean isLargeTransaction() {
354 return isTrackChangesByType();
355 }
356
357 public void setLargeTransaction(boolean value) {
358 setTrackChangesByType(value);
359 }
360
361 public Object getUserObject(Object key) {
362 return _broker.getUserObject(key);
363 }
364
365 public Object putUserObject(Object key, Object val) {
366 assertNotCloseInvoked();
367 return _broker.putUserObject(key, val);
368 }
369
370 public void addTransactionListener(Object listener) {
371 assertNotCloseInvoked();
372 _broker.addTransactionListener(listener);
373 }
374
375 public void removeTransactionListener(Object listener) {
376 assertNotCloseInvoked();
377 _broker.removeTransactionListener(listener);
378 }
379
380 public EnumSet<CallbackMode> getTransactionListenerCallbackModes() {
381 return CallbackMode.toEnumSet(
382 _broker.getTransactionListenerCallbackMode());
383 }
384
385 public void setTransactionListenerCallbackMode(CallbackMode mode) {
386 assertNotCloseInvoked();
387 _broker.setTransactionListenerCallbackMode(
388 CallbackMode.fromEnumSet(EnumSet.of(mode)));
389 }
390
391 public void setTransactionListenerCallbackMode(EnumSet<CallbackMode> modes){
392 assertNotCloseInvoked();
393 _broker.setTransactionListenerCallbackMode(
394 CallbackMode.fromEnumSet(modes));
395 }
396
397 public int getTransactionListenerCallbackMode() {
398 return _broker.getTransactionListenerCallbackMode();
399 }
400
401 public void setTransactionListenerCallbackMode(int callbackMode) {
402 throw new UnsupportedOperationException();
403 }
404
405 public void addLifecycleListener(Object listener, Class... classes) {
406 assertNotCloseInvoked();
407 _broker.addLifecycleListener(listener, classes);
408 }
409
410 public void removeLifecycleListener(Object listener) {
411 assertNotCloseInvoked();
412 _broker.removeLifecycleListener(listener);
413 }
414
415 public EnumSet<CallbackMode> getLifecycleListenerCallbackModes() {
416 return CallbackMode.toEnumSet(
417 _broker.getLifecycleListenerCallbackMode());
418 }
419
420 public void setLifecycleListenerCallbackMode(CallbackMode mode) {
421 assertNotCloseInvoked();
422 _broker.setLifecycleListenerCallbackMode(
423 CallbackMode.fromEnumSet(EnumSet.of(mode)));
424 }
425
426 public void setLifecycleListenerCallbackMode(EnumSet<CallbackMode> modes) {
427 assertNotCloseInvoked();
428 _broker.setLifecycleListenerCallbackMode(
429 CallbackMode.fromEnumSet(modes));
430 }
431
432 public int getLifecycleListenerCallbackMode() {
433 return _broker.getLifecycleListenerCallbackMode();
434 }
435
436 public void setLifecycleListenerCallbackMode(int callbackMode) {
437 assertNotCloseInvoked();
438 _broker.setLifecycleListenerCallbackMode(callbackMode);
439 }
440
441 @SuppressWarnings("unchecked")
442 public <T> T getReference(Class<T> cls, Object oid) {
443 assertNotCloseInvoked();
444 oid = _broker.newObjectId(cls, oid);
445 return (T) _broker.find(oid, false, this);
446 }
447
448 @SuppressWarnings("unchecked")
449 public <T> T find(Class<T> cls, Object oid) {
450 assertNotCloseInvoked();
451 oid = _broker.newObjectId(cls, oid);
452 return (T) _broker.find(oid, true, this);
453 }
454
455 @SuppressWarnings("unchecked")
456 public <T> T[] findAll(Class<T> cls, Object... oids) {
457 if (oids.length == 0)
458 return (T[]) Array.newInstance(cls, 0);
459 Collection<T> ret = findAll(cls, Arrays.asList(oids));
460 return ret.toArray((T[]) Array.newInstance(cls, ret.size()));
461 }
462
463 @SuppressWarnings("unchecked")
464 public <T> Collection<T> findAll(final Class<T> cls, Collection oids) {
465 assertNotCloseInvoked();
466 Object[] objs = _broker.findAll(oids, true, new FindCallbacks() {
467 public Object processArgument(Object oid) {
468 return _broker.newObjectId(cls, oid);
469 }
470
471 public Object processReturn(Object oid, OpenJPAStateManager sm) {
472 return EntityManagerImpl.this.processReturn(oid, sm);
473 }
474 });
475 return (Collection<T>) Arrays.asList(objs);
476 }
477
478 @SuppressWarnings("unchecked")
479 public <T> T findCached(Class<T> cls, Object oid) {
480 assertNotCloseInvoked();
481 return (T) _broker.findCached(_broker.newObjectId(cls, oid), this);
482 }
483
484 public Class getObjectIdClass(Class cls) {
485 assertNotCloseInvoked();
486 if (cls == null)
487 return null;
488 return JPAFacadeHelper.fromOpenJPAObjectIdClass
489 (_broker.getObjectIdType(cls));
490 }
491
492 public OpenJPAEntityTransaction getTransaction() {
493 if (_broker.isManaged())
494 throw new InvalidStateException(_loc.get("get-managed-trans"),
495 null, null, false);
496 return this;
497 }
498
499 public void joinTransaction() {
500 assertNotCloseInvoked();
501 if (!_broker.syncWithManagedTransaction())
502 throw new TransactionRequiredException(_loc.get
503 ("no-managed-trans"), null, null, false);
504 }
505
506 public void begin() {
507 _broker.begin();
508 }
509
510 public void commit() {
511 try {
512 _broker.commit();
513 } catch (RollbackException e) {
514 throw e;
515 } catch (IllegalStateException e) {
516 throw e;
517 } catch (Exception e) {
518 // RollbackExceptions are special and aren't handled by the
519 // normal exception translator, since the spec says they
520 // should be thrown whenever the commit fails for any reason at
521 // all, wheras the exception translator handles exceptions that
522 // are caused for specific reasons
523 throw new RollbackException(e);
524 }
525 }
526
527 public void rollback() {
528 _broker.rollback();
529 }
530
531 public void commitAndResume() {
532 _broker.commitAndResume();
533 }
534
535 public void rollbackAndResume() {
536 _broker.rollbackAndResume();
537 }
538
539 public Throwable getRollbackCause() {
540 if (!isActive())
541 throw new IllegalStateException(_loc.get("no-transaction")
542 .getMessage());
543
544 return _broker.getRollbackCause();
545 }
546
547 public boolean getRollbackOnly() {
548 if (!isActive())
549 throw new IllegalStateException(_loc.get("no-transaction")
550 .getMessage());
551
552 return _broker.getRollbackOnly();
553 }
554
555 public void setRollbackOnly() {
556 _broker.setRollbackOnly();
557 }
558
559 public void setRollbackOnly(Throwable cause) {
560 _broker.setRollbackOnly(cause);
561 }
562
563 public void setSavepoint(String name) {
564 assertNotCloseInvoked();
565 _broker.setSavepoint(name);
566 }
567
568 public void rollbackToSavepoint() {
569 assertNotCloseInvoked();
570 _broker.rollbackToSavepoint();
571 }
572
573 public void rollbackToSavepoint(String name) {
574 assertNotCloseInvoked();
575 _broker.rollbackToSavepoint(name);
576 }
577
578 public void releaseSavepoint() {
579 assertNotCloseInvoked();
580 _broker.releaseSavepoint();
581 }
582
583 public void releaseSavepoint(String name) {
584 assertNotCloseInvoked();
585 _broker.releaseSavepoint(name);
586 }
587
588 public void flush() {
589 assertNotCloseInvoked();
590 _broker.assertOpen();
591 _broker.assertActiveTransaction();
592 _broker.flush();
593 }
594
595 public void preFlush() {
596 assertNotCloseInvoked();
597 _broker.preFlush();
598 }
599
600 public void validateChanges() {
601 assertNotCloseInvoked();
602 _broker.validateChanges();
603 }
604
605 public boolean isActive() {
606 return isOpen() && _broker.isActive();
607 }
608
609 public boolean isStoreActive() {
610 return _broker.isStoreActive();
611 }
612
613 public void beginStore() {
614 _broker.beginStore();
615 }
616
617 public boolean contains(Object entity) {
618 assertNotCloseInvoked();
619 if (entity == null)
620 return false;
621 OpenJPAStateManager sm = _broker.getStateManager(entity);
622 if (sm == null
623 && !ImplHelper.isManagedType(getConfiguration(), entity.getClass()))
624 throw new ArgumentException(_loc.get("not-entity",
625 entity.getClass()), null, null, true);
626 return sm != null && !sm.isDeleted();
627 }
628
629 public boolean containsAll(Object... entities) {
630 for (Object entity : entities)
631 if (!contains(entity))
632 return false;
633 return true;
634 }
635
636 public boolean containsAll(Collection entities) {
637 for (Object entity : entities)
638 if (!contains(entity))
639 return false;
640 return true;
641 }
642
643 public void persist(Object entity) {
644 assertNotCloseInvoked();
645 _broker.persist(entity, this);
646 }
647
648 public void persistAll(Object... entities) {
649 persistAll(Arrays.asList(entities));
650 }
651
652 public void persistAll(Collection entities) {
653 assertNotCloseInvoked();
654 _broker.persistAll(entities, this);
655 }
656
657 public void remove(Object entity) {
658 assertNotCloseInvoked();
659 _broker.delete(entity, this);
660 }
661
662 public void removeAll(Object... entities) {
663 removeAll(Arrays.asList(entities));
664 }
665
666 public void removeAll(Collection entities) {
667 assertNotCloseInvoked();
668 _broker.deleteAll(entities, this);
669 }
670
671 public void release(Object entity) {
672 assertNotCloseInvoked();
673 _broker.release(entity, this);
674 }
675
676 public void releaseAll(Collection entities) {
677 assertNotCloseInvoked();
678 _broker.releaseAll(entities, this);
679 }
680
681 public void releaseAll(Object... entities) {
682 releaseAll(Arrays.asList(entities));
683 }
684
685 public void refresh(Object entity) {
686 assertNotCloseInvoked();
687 _broker.assertWriteOperation();
688 _broker.refresh(entity, this);
689 }
690
691 public void refreshAll() {
692 assertNotCloseInvoked();
693 _broker.assertWriteOperation();
694 _broker.refreshAll(_broker.getTransactionalObjects(), this);
695 }
696
697 public void refreshAll(Collection entities) {
698 assertNotCloseInvoked();
699 _broker.assertWriteOperation();
700 _broker.refreshAll(entities, this);
701 }
702
703 public void refreshAll(Object... entities) {
704 refreshAll(Arrays.asList(entities));
705 }
706
707 public void retrieve(Object entity) {
708 assertNotCloseInvoked();
709 _broker.retrieve(entity, true, this);
710 }
711
712 public void retrieveAll(Collection entities) {
713 assertNotCloseInvoked();
714 _broker.retrieveAll(entities, true, this);
715 }
716
717 public void retrieveAll(Object... entities) {
718 retrieveAll(Arrays.asList(entities));
719 }
720
721 public void evict(Object entity) {
722 assertNotCloseInvoked();
723 _broker.evict(entity, this);
724 }
725
726 public void evictAll(Collection entities) {
727 assertNotCloseInvoked();
728 _broker.evictAll(entities, this);
729 }
730
731 public void evictAll(Object... entities) {
732 evictAll(Arrays.asList(entities));
733 }
734
735 public void evictAll() {
736 assertNotCloseInvoked();
737 _broker.evictAll(this);
738 }
739
740 public void evictAll(Class cls) {
741 assertNotCloseInvoked();
742 _broker.evictAll(_broker.newExtent(cls, true), this);
743 }
744
745 public void evictAll(Extent extent) {
746 assertNotCloseInvoked();
747 _broker.evictAll(((ExtentImpl) extent).getDelegate(), this);
748 }
749
750 @SuppressWarnings("unchecked")
751 public <T> T detach(T entity) {
752 assertNotCloseInvoked();
753 return (T) _broker.detach(entity, this);
754 }
755
756 public Object[] detachAll(Object... entities) {
757 assertNotCloseInvoked();
758 return _broker.detachAll(Arrays.asList(entities), this);
759 }
760
761 public Collection detachAll(Collection entities) {
762 assertNotCloseInvoked();
763 return Arrays.asList(_broker.detachAll(entities, this));
764 }
765
766 @SuppressWarnings("unchecked")
767 public <T> T merge(T entity) {
768 assertNotCloseInvoked();
769 return (T) _broker.attach(entity, true, this);
770 }
771
772 public Object[] mergeAll(Object... entities) {
773 if (entities.length == 0)
774 return EMPTY_OBJECTS;
775 return mergeAll(Arrays.asList(entities)).toArray();
776 }
777
778 public Collection mergeAll(Collection entities) {
779 assertNotCloseInvoked();
780 return Arrays.asList(_broker.attachAll(entities, true, this));
781 }
782
783 public void transactional(Object entity, boolean updateVersion) {
784 assertNotCloseInvoked();
785 _broker.transactional(entity, updateVersion, this);
786 }
787
788 public void transactionalAll(Collection objs, boolean updateVersion) {
789 assertNotCloseInvoked();
790 _broker.transactionalAll(objs, updateVersion, this);
791 }
792
793 public void transactionalAll(Object[] objs, boolean updateVersion) {
794 assertNotCloseInvoked();
795 _broker.transactionalAll(Arrays.asList(objs), updateVersion, this);
796 }
797
798 public void nontransactional(Object entity) {
799 assertNotCloseInvoked();
800 _broker.nontransactional(entity, this);
801 }
802
803 public void nontransactionalAll(Collection objs) {
804 assertNotCloseInvoked();
805 _broker.nontransactionalAll(objs, this);
806 }
807
808 public void nontransactionalAll(Object[] objs) {
809 assertNotCloseInvoked();
810 _broker.nontransactionalAll(Arrays.asList(objs), this);
811 }
812
813 public Generator getNamedGenerator(String name) {
814 assertNotCloseInvoked();
815 try {
816 SequenceMetaData meta = _broker.getConfiguration().
817 getMetaDataRepositoryInstance().getSequenceMetaData(name,
818 _broker.getClassLoader(), true);
819 Seq seq = meta.getInstance(_broker.getClassLoader());
820 return new GeneratorImpl(seq, name, _broker, null);
821 } catch (RuntimeException re) {
822 throw PersistenceExceptions.toPersistenceException(re);
823 }
824 }
825
826 public Generator getIdGenerator(Class forClass) {
827 assertNotCloseInvoked();
828 try {
829 ClassMetaData meta = _broker.getConfiguration().
830 getMetaDataRepositoryInstance().getMetaData(forClass,
831 _broker.getClassLoader(), true);
832 Seq seq = _broker.getIdentitySequence(meta);
833 return (seq == null) ? null : new GeneratorImpl(seq, null, _broker,
834 meta);
835 } catch (Exception e) {
836 throw PersistenceExceptions.toPersistenceException(e);
837 }
838 }
839
840 public Generator getFieldGenerator(Class forClass, String fieldName) {
841 assertNotCloseInvoked();
842 try {
843 ClassMetaData meta = _broker.getConfiguration().
844 getMetaDataRepositoryInstance().getMetaData(forClass,
845 _broker.getClassLoader(), true);
846 FieldMetaData fmd = meta.getField(fieldName);
847 if (fmd == null)
848 throw new ArgumentException(_loc.get("no-named-field",
849 forClass, fieldName), null, null, false);
850
851 Seq seq = _broker.getValueSequence(fmd);
852 return (seq == null) ? null : new GeneratorImpl(seq, null, _broker,
853 meta);
854 } catch (Exception e) {
855 throw PersistenceExceptions.toPersistenceException(e);
856 }
857 }
858
859 public <T> Extent<T> createExtent(Class<T> cls, boolean subclasses) {
860 assertNotCloseInvoked();
861 return new ExtentImpl<T>(this, _broker.newExtent(cls, subclasses));
862 }
863
864 public OpenJPAQuery createQuery(String query) {
865 return createQuery(JPQLParser.LANG_JPQL, query);
866 }
867
868 public OpenJPAQuery createQuery(String language, String query) {
869 assertNotCloseInvoked();
870 return new QueryImpl(this, ret, _broker.newQuery(language, query));
871 }
872
873 public OpenJPAQuery createQuery(Query query) {
874 if (query == null)
875 return createQuery((String) null);
876 assertNotCloseInvoked();
877 org.apache.openjpa.kernel.Query q = ((QueryImpl) query).getDelegate();
878 return new QueryImpl(this, ret, _broker.newQuery(q.getLanguage(),
879 q));
880 }
881
882 public OpenJPAQuery createNamedQuery(String name) {
883 assertNotCloseInvoked();
884 _broker.assertOpen();
885 try {
886 QueryMetaData meta = _broker.getConfiguration().
887 getMetaDataRepositoryInstance().getQueryMetaData(null, name,
888 _broker.getClassLoader(), true);
889 org.apache.openjpa.kernel.Query del =
890 _broker.newQuery(meta.getLanguage(), null);
891 meta.setInto(del);
892 del.compile();
893
894 OpenJPAQuery q = new QueryImpl(this, ret, del);
895 String[] hints = meta.getHintKeys();
896 Object[] values = meta.getHintValues();
897 for (int i = 0; i < hints.length; i++)
898 q.setHint(hints[i], values[i]);
899 return q;
900 } catch (RuntimeException re) {
901 throw PersistenceExceptions.toPersistenceException(re);
902 }
903 }
904
905 public OpenJPAQuery createNativeQuery(String query) {
906 validateSQL(query);
907 return createQuery(QueryLanguages.LANG_SQL, query);
908 }
909
910 public OpenJPAQuery createNativeQuery(String query, Class cls) {
911 return createNativeQuery(query).setResultClass(cls);
912 }
913
914 public OpenJPAQuery createNativeQuery(String query, String mappingName) {
915 assertNotCloseInvoked();
916 validateSQL(query);
917 org.apache.openjpa.kernel.Query kernelQuery = _broker.newQuery(
918 QueryLanguages.LANG_SQL, query);
919 kernelQuery.setResultMapping(null, mappingName);
920 return new QueryImpl(this, ret, kernelQuery);
921 }
922
923 /**
924 * Validate that the user provided SQL.
925 */
926 private static void validateSQL(String query) {
927 if (StringUtils.trimToNull(query) == null)
928 throw new ArgumentException(_loc.get("no-sql"), null, null, false);
929 }
930
931 public void setFlushMode(FlushModeType flushMode) {
932 assertNotCloseInvoked();
933 _broker.assertOpen();
934 _broker.getFetchConfiguration().setFlushBeforeQueries
935 (toFlushBeforeQueries(flushMode));
936 }
937
938 public FlushModeType getFlushMode() {
939 assertNotCloseInvoked();
940 _broker.assertOpen();
941 return fromFlushBeforeQueries(_broker.getFetchConfiguration().
942 getFlushBeforeQueries());
943 }
944
945 /**
946 * Translate our internal flush constant to a flush mode enum value.
947 */
948 static FlushModeType fromFlushBeforeQueries(int flush) {
949 switch (flush) {
950 case QueryFlushModes.FLUSH_TRUE:
951 return FlushModeType.AUTO;
952 case QueryFlushModes.FLUSH_FALSE:
953 return FlushModeType.COMMIT;
954 default:
955 return null;
956 }
957 }
958
959 /**
960 * Translate a flush mode enum value to our internal flush constant.
961 */
962 static int toFlushBeforeQueries(FlushModeType flushMode) {
963 // choose default for null
964 if (flushMode == null)
965 return QueryFlushModes.FLUSH_WITH_CONNECTION;
966 if (flushMode == FlushModeType.AUTO)
967 return QueryFlushModes.FLUSH_TRUE;
968 if (flushMode == FlushModeType.COMMIT)
969 return QueryFlushModes.FLUSH_FALSE;
970 throw new ArgumentException(flushMode.toString(), null, null, false);
971 }
972
973 public void clear() {
974 assertNotCloseInvoked();
975 _broker.detachAll(this, false);
976 }
977
978 public Object getDelegate() {
979 _broker.assertOpen();
980 assertNotCloseInvoked();
981 return this;
982 }
983
984 public LockModeType getLockMode(Object entity) {
985 assertNotCloseInvoked();
986 return fromLockLevel(_broker.getLockLevel(entity));
987 }
988
989 public void lock(Object entity, LockModeType mode) {
990 assertNotCloseInvoked();
991 _broker.lock(entity, toLockLevel(mode), -1, this);
992 }
993
994 public void lock(Object entity) {
995 assertNotCloseInvoked();
996 _broker.lock(entity, this);
997 }
998
999 public void lock(Object entity, LockModeType mode, int timeout) {
1000 assertNotCloseInvoked();
1001 _broker.lock(entity, toLockLevel(mode), timeout, this);
1002 }
1003
1004 public void lockAll(Collection entities) {
1005 assertNotCloseInvoked();
1006 _broker.lockAll(entities, this);
1007 }
1008
1009 public void lockAll(Collection entities, LockModeType mode, int timeout) {
1010 assertNotCloseInvoked();
1011 _broker.lockAll(entities, toLockLevel(mode), timeout, this);
1012 }
1013
1014 public void lockAll(Object... entities) {
1015 lockAll(Arrays.asList(entities));
1016 }
1017
1018 public void lockAll(Object[] entities, LockModeType mode, int timeout) {
1019 lockAll(Arrays.asList(entities), mode, timeout);
1020 }
1021
1022 /**
1023 * Translate our internal lock level to a javax.persistence enum value.
1024 */
1025 static LockModeType fromLockLevel(int level) {
1026 if (level < LockLevels.LOCK_READ)
1027 return null;
1028 if (level < LockLevels.LOCK_WRITE)
1029 return LockModeType.READ;
1030 return LockModeType.WRITE;
1031 }
1032
1033 /**
1034 * Translate the javax.persistence enum value to our internal lock level.
1035 */
1036 static int toLockLevel(LockModeType mode) {
1037 if (mode == null)
1038 return LockLevels.LOCK_NONE;
1039 if (mode == LockModeType.READ)
1040 return LockLevels.LOCK_READ;
1041 if (mode == LockModeType.WRITE)
1042 return LockLevels.LOCK_WRITE;
1043 throw new ArgumentException(mode.toString(), null, null, true);
1044 }
1045
1046 public boolean cancelAll() {
1047 return _broker.cancelAll();
1048 }
1049
1050 public Object getConnection() {
1051 return _broker.getConnection();
1052 }
1053
1054 public Collection getManagedObjects() {
1055 return _broker.getManagedObjects();
1056 }
1057
1058 public Collection getTransactionalObjects() {
1059 return _broker.getTransactionalObjects();
1060 }
1061
1062 public Collection getPendingTransactionalObjects() {
1063 return _broker.getPendingTransactionalObjects();
1064 }
1065
1066 public Collection getDirtyObjects() {
1067 return _broker.getDirtyObjects();
1068 }
1069
1070 public boolean getOrderDirtyObjects() {
1071 return _broker.getOrderDirtyObjects();
1072 }
1073
1074 public void setOrderDirtyObjects(boolean order) {
1075 assertNotCloseInvoked();
1076 _broker.setOrderDirtyObjects(order);
1077 }
1078
1079 public void dirtyClass(Class cls) {
1080 assertNotCloseInvoked();
1081 _broker.dirtyType(cls);
1082 }
1083
1084 @SuppressWarnings("unchecked")
1085 public Collection<Class> getPersistedClasses() {
1086 return (Collection<Class>) _broker.getPersistedTypes();
1087 }
1088
1089 @SuppressWarnings("unchecked")
1090 public Collection<Class> getUpdatedClasses() {
1091 return (Collection<Class>) _broker.getUpdatedTypes();
1092 }
1093
1094 @SuppressWarnings("unchecked")
1095 public Collection<Class> getRemovedClasses() {
1096 return (Collection<Class>) _broker.getDeletedTypes();
1097 }
1098
1099 public <T> T createInstance(Class<T> cls) {
1100 assertNotCloseInvoked();
1101 return (T) _broker.newInstance(cls);
1102 }
1103
1104 public void close() {
1105 assertNotCloseInvoked();
1106 _broker.close();
1107 }
1108
1109 public boolean isOpen() {
1110 return !_broker.isCloseInvoked();
1111 }
1112
1113 public void dirty(Object o, String field) {
1114 assertNotCloseInvoked();
1115 OpenJPAStateManager sm = _broker.getStateManager(o);
1116 try {
1117 if (sm != null)
1118 sm.dirty(field);
1119 } catch (Exception e) {
1120 throw PersistenceExceptions.toPersistenceException(e);
1121 }
1122 }
1123
1124 public Object getObjectId(Object o) {
1125 assertNotCloseInvoked();
1126 return JPAFacadeHelper.fromOpenJPAObjectId(_broker.getObjectId(o));
1127 }
1128
1129 public boolean isDirty(Object o) {
1130 assertNotCloseInvoked();
1131 return _broker.isDirty(o);
1132 }
1133
1134 public boolean isTransactional(Object o) {
1135 assertNotCloseInvoked();
1136 return _broker.isTransactional(o);
1137 }
1138
1139 public boolean isPersistent(Object o) {
1140 assertNotCloseInvoked();
1141 return _broker.isPersistent(o);
1142 }
1143
1144 public boolean isNewlyPersistent(Object o) {
1145 assertNotCloseInvoked();
1146 return _broker.isNew(o);
1147 }
1148
1149 public boolean isRemoved(Object o) {
1150 assertNotCloseInvoked();
1151 return _broker.isDeleted(o);
1152 }
1153
1154 public boolean isDetached(Object entity) {
1155 assertNotCloseInvoked();
1156 return _broker.isDetached(entity);
1157 }
1158
1159 public Object getVersion(Object o) {
1160 assertNotCloseInvoked();
1161 return _broker.getVersion(o);
1162 }
1163
1164 /**
1165 * Throw appropriate exception if close has been invoked but the broker
1166 * is still open. We test only for this because if the broker is already
1167 * closed, it will throw its own more informative exception when we
1168 * delegate the pending operation to it.
1169 */
1170 void assertNotCloseInvoked() {
1171 if (!_broker.isClosed() && _broker.isCloseInvoked())
1172 throw new InvalidStateException(_loc.get("close-invoked"), null,
1173 null, true);
1174 }
1175
1176 ////////////////////////////////
1177 // FindCallbacks implementation
1178 ////////////////////////////////
1179
1180 public Object processArgument(Object arg) {
1181 return arg;
1182 }
1183
1184 public Object processReturn(Object oid, OpenJPAStateManager sm) {
1185 return (sm == null || sm.isDeleted()) ? null : sm.getManagedInstance();
1186 }
1187
1188 //////////////////////////////
1189 // OpCallbacks implementation
1190 //////////////////////////////
1191
1192 public int processArgument(int op, Object obj, OpenJPAStateManager sm) {
1193 switch (op) {
1194 case OP_DELETE:
1195 // cascade through non-persistent non-detached instances
1196 if (sm == null && !_broker.isDetached(obj))
1197 return ACT_CASCADE;
1198 if (sm != null && !sm.isDetached() && !sm.isPersistent())
1199 return ACT_CASCADE;
1200 // ignore deleted instances
1201 if (sm != null && sm.isDeleted())
1202 return ACT_NONE;
1203 break;
1204 case OP_ATTACH:
1205 // die on removed
1206 if (sm != null && sm.isDeleted())
1207 throw new UserException(_loc.get("removed",
1208 Exceptions.toString(obj))).setFailedObject(obj);
1209 // cascade through managed instances
1210 if (sm != null && !sm.isDetached())
1211 return ACT_CASCADE;
1212 break;
1213 case OP_REFRESH:
1214 // die on unmanaged instances
1215 if (sm == null)
1216 throw new UserException(_loc.get("not-managed",
1217 Exceptions.toString(obj))).setFailedObject(obj);
1218 break;
1219 }
1220 return ACT_RUN | ACT_CASCADE;
1221 }
1222
1223 public int hashCode() {
1224 return _broker.hashCode();
1225 }
1226
1227 public boolean equals(Object other) {
1228 if (other == this)
1229 return true;
1230 if (!(other instanceof EntityManagerImpl))
1231 return false;
1232 return _broker.equals(((EntityManagerImpl) other)._broker);
1233 }
1234
1235 public void readExternal(ObjectInput in)
1236 throws IOException, ClassNotFoundException {
1237 try {
1238 ret = PersistenceExceptions.getRollbackTranslator(this);
1239
1240 // this assumes that serialized Brokers are from something
1241 // that extends AbstractBrokerFactory.
1242 Object factoryKey = in.readObject();
1243 AbstractBrokerFactory factory =
1244 AbstractBrokerFactory.getPooledFactoryForKey(factoryKey);
1245 byte[] brokerBytes = (byte[]) in.readObject();
1246 ObjectInputStream innerIn = new BrokerBytesInputStream(brokerBytes,
1247 factory.getConfiguration());
1248
1249 Broker broker = (Broker) innerIn.readObject();
1250 EntityManagerFactoryImpl emf = (EntityManagerFactoryImpl)
1251 JPAFacadeHelper.toEntityManagerFactory(
1252 broker.getBrokerFactory());
1253 broker.putUserObject(JPAFacadeHelper.EM_KEY, this);
1254 initialize(emf, broker);
1255 } catch (RuntimeException re) {
1256 try {
1257 re = ret.translate(re);
1258 } catch (Exception e) {
1259 // ignore
1260 }
1261 throw re;
1262 }
1263 }
1264
1265 public void writeExternal(ObjectOutput out) throws IOException {
1266 try {
1267 // this requires that only AbstractBrokerFactory-sourced
1268 // brokers can be serialized
1269 Object factoryKey = ((AbstractBrokerFactory) _broker
1270 .getBrokerFactory()).getPoolKey();
1271 out.writeObject(factoryKey);
1272 ByteArrayOutputStream baos = new ByteArrayOutputStream();
1273 ObjectOutputStream innerOut = new ObjectOutputStream(baos);
1274 innerOut.writeObject(_broker.getDelegate());
1275 innerOut.flush();
1276 out.writeObject(baos.toByteArray());
1277 } catch (RuntimeException re) {
1278 try {
1279 re = ret.translate(re);
1280 } catch (Exception e) {
1281 // ignore
1282 }
1283 throw re;
1284 }
1285 }
1286
1287 private static class BrokerBytesInputStream extends ObjectInputStream {
1288
1289 private OpenJPAConfiguration conf;
1290
1291 BrokerBytesInputStream(byte[] bytes, OpenJPAConfiguration conf)
1292 throws IOException {
1293 super(new ByteArrayInputStream(bytes));
1294 if (conf == null)
1295 throw new IllegalArgumentException(
1296 "Illegal null argument to ObjectInputStreamWithLoader");
1297 this.conf = conf;
1298 }
1299
1300 /**
1301 * Make a primitive array class
1302 */
1303 private Class primitiveType(char type) {
1304 switch (type) {
1305 case 'B': return byte.class;
1306 case 'C': return char.class;
1307 case 'D': return double.class;
1308 case 'F': return float.class;
1309 case 'I': return int.class;
1310 case 'J': return long.class;
1311 case 'S': return short.class;
1312 case 'Z': return boolean.class;
1313 default: return null;
1314 }
1315 }
1316
1317 protected Class resolveClass(ObjectStreamClass classDesc)
1318 throws IOException, ClassNotFoundException {
1319
1320 String cname = classDesc.getName();
1321 if (cname.startsWith("[")) {
1322 // An array
1323 Class component; // component class
1324 int dcount; // dimension
1325 for (dcount=1; cname.charAt(dcount)=='['; dcount++) ;
1326 if (cname.charAt(dcount) == 'L') {
1327 component = lookupClass(cname.substring(dcount+1,
1328 cname.length()-1));
1329 } else {
1330 if (cname.length() != dcount+1) {
1331 throw new ClassNotFoundException(cname);// malformed
1332 }
1333 component = primitiveType(cname.charAt(dcount));
1334 }
1335 int dim[] = new int[dcount];
1336 for (int i=0; i<dcount; i++) {
1337 dim[i]=0;
1338 }
1339 return Array.newInstance(component, dim).getClass();
1340 } else {
1341 return lookupClass(cname);
1342 }
1343 }
1344
1345 /**
1346 * If this is a generated subclass, look up the corresponding Class
1347 * object via metadata.
1348 */
1349 private Class lookupClass(String className)
1350 throws ClassNotFoundException {
1351 try {
1352 return Class.forName(className);
1353 } catch (ClassNotFoundException e) {
1354 if (PCEnhancer.isPCSubclassName(className)) {
1355 String superName = PCEnhancer.toManagedTypeName(className);
1356 ClassMetaData[] metas = conf.getMetaDataRepositoryInstance()
1357 .getMetaDatas();
1358 for (int i = 0; i < metas.length; i++) {
1359 if (superName.equals(
1360 metas[i].getDescribedType().getName())) {
1361 return PCRegistry.getPCType(
1362 metas[i].getDescribedType());
1363 }
1364 }
1365
1366 // if it's not found, try to look for it anyways
1367 return Class.forName(className);
1368 } else {
1369 throw e;
1370 }
1371 }
1372 }
1373 }
1374 }