1 /*
2 * Hibernate, Relational Persistence for Idiomatic Java
3 *
4 * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
5 * indicated by the @author tags or express copyright attribution
6 * statements applied by the authors. All third-party contributions are
7 * distributed under license by Red Hat Middleware LLC.
8 *
9 * This copyrighted material is made available to anyone wishing to use, modify,
10 * copy, or redistribute it subject to the terms and conditions of the GNU
11 * Lesser General Public License, as published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
16 * for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this distribution; if not, write to:
20 * Free Software Foundation, Inc.
21 * 51 Franklin Street, Fifth Floor
22 * Boston, MA 02110-1301 USA
23 *
24 */
25 package org.hibernate.proxy;
26
27 import java.io.Serializable;
28
29 import org.hibernate.HibernateException;
30 import org.hibernate.LazyInitializationException;
31 import org.hibernate.engine.EntityKey;
32 import org.hibernate.engine.SessionImplementor;
33
34 /**
35 * Convenience base class for lazy initialization handlers. Centralizes the
36 * basic plumbing of doing lazy initialization freeing subclasses to
37 * acts as essentially adapters to their intended entity mode and/or
38 * proxy generation strategy.
39 *
40 * @author Gavin King
41 */
42 public abstract class AbstractLazyInitializer implements LazyInitializer {
43
44 private Object target;
45 private boolean initialized;
46 private String entityName;
47 private Serializable id;
48 private transient SessionImplementor session;
49 private boolean unwrap;
50
51 /**
52 * For serialization from the non-pojo initializers (HHH-3309)
53 */
54 protected AbstractLazyInitializer() {
55 }
56
57 protected AbstractLazyInitializer(String entityName, Serializable id, SessionImplementor session) {
58 this.id = id;
59 this.session = session;
60 this.entityName = entityName;
61 }
62
63 public final Serializable getIdentifier() {
64 return id;
65 }
66
67 public final void setIdentifier(Serializable id) {
68 this.id = id;
69 }
70
71 public final String getEntityName() {
72 return entityName;
73 }
74
75 public final boolean isUninitialized() {
76 return !initialized;
77 }
78
79 public final SessionImplementor getSession() {
80 return session;
81 }
82
83 public final void initialize() throws HibernateException {
84 if (!initialized) {
85 if ( session==null ) {
86 throw new LazyInitializationException("could not initialize proxy - no Session");
87 }
88 else if ( !session.isOpen() ) {
89 throw new LazyInitializationException("could not initialize proxy - the owning Session was closed");
90 }
91 else if ( !session.isConnected() ) {
92 throw new LazyInitializationException("could not initialize proxy - the owning Session is disconnected");
93 }
94 else {
95 target = session.immediateLoad(entityName, id);
96 initialized = true;
97 checkTargetState();
98 }
99 }
100 else {
101 checkTargetState();
102 }
103 }
104
105 private void checkTargetState() {
106 if ( !unwrap ) {
107 if ( target == null ) {
108 getSession().getFactory().getEntityNotFoundDelegate().handleEntityNotFound( entityName, id );
109 }
110 }
111 }
112
113 public final void setSession(SessionImplementor s) throws HibernateException {
114 if (s!=session) {
115 if ( isConnectedToSession() ) {
116 //TODO: perhaps this should be some other RuntimeException...
117 throw new HibernateException("illegally attempted to associate a proxy with two open Sessions");
118 }
119 else {
120 session = s;
121 }
122 }
123 }
124
125 protected final boolean isConnectedToSession() {
126 return session!=null &&
127 session.isOpen() &&
128 session.getPersistenceContext().containsProxy(this);
129 }
130
131 public final void setImplementation(Object target) {
132 this.target = target;
133 initialized = true;
134 }
135
136 /**
137 * Return the underlying persistent object, initializing if necessary
138 */
139 public final Object getImplementation() {
140 initialize();
141 return target;
142 }
143
144 /**
145 * Return the underlying persistent object in the given <tt>Session</tt>, or null,
146 * do not initialize the proxy
147 */
148 public final Object getImplementation(SessionImplementor s) throws HibernateException {
149 final EntityKey entityKey = new EntityKey(
150 getIdentifier(),
151 s.getFactory().getEntityPersister( getEntityName() ),
152 s.getEntityMode()
153 );
154 return s.getPersistenceContext().getEntity( entityKey );
155 }
156
157 protected final Object getTarget() {
158 return target;
159 }
160
161 public boolean isUnwrap() {
162 return unwrap;
163 }
164
165 public void setUnwrap(boolean unwrap) {
166 this.unwrap = unwrap;
167 }
168
169 }