|
1 /* |
|
2 * Copyright (c) 2007-2008 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of the License "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 */ |
|
17 package com.nokia.helium.metadata; |
|
18 |
|
19 import java.io.File; |
|
20 import java.util.ArrayList; |
|
21 import java.util.List; |
|
22 import java.util.Map; |
|
23 |
|
24 import javax.persistence.Cache; |
|
25 import javax.persistence.EntityManager; |
|
26 import javax.persistence.EntityManagerFactory; |
|
27 import javax.persistence.PersistenceUnitUtil; |
|
28 import javax.persistence.criteria.CriteriaBuilder; |
|
29 import javax.persistence.metamodel.Metamodel; |
|
30 |
|
31 /** |
|
32 * This singleton class is the main entry point to the Metadata framework. |
|
33 * Developer must use it to get access to the EntityManagerFactory from the |
|
34 * JPA framework. |
|
35 * |
|
36 */ |
|
37 public final class FactoryManager { |
|
38 private static FactoryManager self = new FactoryManager(); |
|
39 private List<EntityManagerFactoryWrapper> wrappers = new ArrayList<EntityManagerFactoryWrapper>(); |
|
40 private EntityManagerFactoryCreator factoryManagerCreator = new DerbyFactoryManagerCreator(); |
|
41 |
|
42 /** |
|
43 * This class must not be instantiated from outside. |
|
44 */ |
|
45 private FactoryManager() { |
|
46 } |
|
47 |
|
48 /** |
|
49 * Get the FactoryManager instance. |
|
50 * @return the FactoryManager instance. |
|
51 */ |
|
52 public static FactoryManager getFactoryManager() { |
|
53 return self; |
|
54 } |
|
55 |
|
56 /** |
|
57 * Get the EntityManagerFactory for the database. |
|
58 * @param database the File object representing the database. |
|
59 * @return an EntityManagerFactory instance. |
|
60 * @throws MetadataException is thrown in case of error. |
|
61 */ |
|
62 public synchronized EntityManagerFactory getEntityManagerFactory(File database) throws MetadataException { |
|
63 EntityManagerFactoryWrapper wrapper = null; |
|
64 for (EntityManagerFactoryWrapper wrp : wrappers) { |
|
65 // Found what we wanted so leaving the loop. |
|
66 if (wrp.getDatabase().equals(database)) { |
|
67 wrapper = wrp; |
|
68 break; |
|
69 } |
|
70 } |
|
71 if (wrapper != null) { |
|
72 wrapper.reference(); |
|
73 return wrapper; |
|
74 } else { |
|
75 // creating a new one. |
|
76 wrapper = |
|
77 new EntityManagerFactoryWrapper(factoryManagerCreator.create(database), this, database); |
|
78 wrappers.add(wrapper); |
|
79 return wrapper; |
|
80 } |
|
81 } |
|
82 |
|
83 /** |
|
84 * Removing the wrapper object from the available database, so no one can |
|
85 * use it anymore. This method is intended to be used by the EntityManagerFactoryWrapper. |
|
86 * @param wrapper |
|
87 */ |
|
88 private synchronized void remove(EntityManagerFactoryWrapper wrapper) { |
|
89 wrappers.remove(wrapper); |
|
90 } |
|
91 |
|
92 /** |
|
93 * Unload the database when not used anymore. |
|
94 * This method is intended to be used by the EntityManagerFactoryWrapper. |
|
95 * @param database the database to unload. |
|
96 */ |
|
97 private void unload(File database) { |
|
98 try { |
|
99 factoryManagerCreator.unload(database); |
|
100 } catch (MetadataException e) { |
|
101 // do nothing in the meantime |
|
102 database = null; |
|
103 } |
|
104 } |
|
105 |
|
106 /** |
|
107 * Internal Factory wrapper object which implements a custom |
|
108 * factory lifecycle management. |
|
109 * |
|
110 */ |
|
111 class EntityManagerFactoryWrapper implements EntityManagerFactory { |
|
112 private EntityManagerFactory factory; |
|
113 private FactoryManager factoryManager; |
|
114 private int counter = 1; |
|
115 private File database; |
|
116 |
|
117 /** |
|
118 * Default constructor. |
|
119 * @param factory the factory to delegate to calls to. |
|
120 * @param factoryManager the factory manager used for the lifecycle management. |
|
121 * @param database the database this object is connected to. |
|
122 */ |
|
123 public EntityManagerFactoryWrapper(EntityManagerFactory factory, |
|
124 FactoryManager factoryManager, File database) { |
|
125 this.factory = factory; |
|
126 this.factoryManager = factoryManager; |
|
127 this.database = database; |
|
128 } |
|
129 |
|
130 /** |
|
131 * Method used by the factoryManager to reference the usage of the |
|
132 * EntityFactoryManager. |
|
133 */ |
|
134 public synchronized void reference() { |
|
135 counter++; |
|
136 } |
|
137 |
|
138 /** |
|
139 * {@inheritDoc} |
|
140 * This method overrides the default close implementation, and will |
|
141 * only close the EntityManagerFactory, if all application have stopped |
|
142 * using the EntityManagerFactory. |
|
143 * It interacts with the factoryManager. |
|
144 */ |
|
145 public synchronized void close() { |
|
146 counter--; |
|
147 if (counter == 0) { |
|
148 factoryManager.remove(this); |
|
149 factory.close(); |
|
150 factoryManager.unload(database); |
|
151 } |
|
152 } |
|
153 |
|
154 /** |
|
155 * {@inheritDoc} |
|
156 */ |
|
157 public EntityManager createEntityManager() { |
|
158 return factory.createEntityManager(); |
|
159 } |
|
160 |
|
161 /** |
|
162 * {@inheritDoc} |
|
163 */ |
|
164 @SuppressWarnings("unchecked") |
|
165 public EntityManager createEntityManager(Map properties) { |
|
166 return factory.createEntityManager(properties); |
|
167 } |
|
168 |
|
169 /** |
|
170 * {@inheritDoc} |
|
171 */ |
|
172 public Cache getCache() { |
|
173 return factory.getCache(); |
|
174 } |
|
175 |
|
176 /** |
|
177 * {@inheritDoc} |
|
178 */ |
|
179 public CriteriaBuilder getCriteriaBuilder() { |
|
180 return factory.getCriteriaBuilder(); |
|
181 } |
|
182 |
|
183 /** |
|
184 * {@inheritDoc} |
|
185 */ |
|
186 public Metamodel getMetamodel() { |
|
187 return factory.getMetamodel(); |
|
188 } |
|
189 |
|
190 /** |
|
191 * {@inheritDoc} |
|
192 */ |
|
193 public PersistenceUnitUtil getPersistenceUnitUtil() { |
|
194 return factory.getPersistenceUnitUtil(); |
|
195 } |
|
196 |
|
197 /** |
|
198 * {@inheritDoc} |
|
199 */ |
|
200 public Map<String, Object> getProperties() { |
|
201 return factory.getProperties(); |
|
202 } |
|
203 |
|
204 /** |
|
205 * {@inheritDoc} |
|
206 */ |
|
207 public boolean isOpen() { |
|
208 return factory.isOpen(); |
|
209 } |
|
210 |
|
211 /** |
|
212 * {@inheritDoc} |
|
213 */ |
|
214 public File getDatabase() { |
|
215 return database; |
|
216 } |
|
217 } |
|
218 |
|
219 } |