View Javadoc

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  
20  //
21  // This source code implements specifications defined by the Java
22  // Community Process. In order to remain compliant with the specification
23  // DO NOT add / change / or delete method signatures!
24  //
25  package javax.persistence;
26  
27  import java.io.BufferedReader;
28  import java.io.IOException;
29  import java.io.InputStreamReader;
30  import java.net.URL;
31  import java.util.Collections;
32  import java.util.Enumeration;
33  import java.util.Map;
34  import java.util.HashSet;
35  import java.util.Set;
36  
37  import javax.persistence.spi.PersistenceProvider;
38  
39  /**
40   * @version $Rev: 529834 $ $Date: 2007-04-17 19:32:23 -0700 (Tue, 17 Apr 2007) $
41   */
42  
43  /**
44   * Bootstrap class that is used to obtain {@link javax.persistence.EntityManagerFactory}
45   * references.
46   */
47  public class Persistence {
48  
49      protected static final Set<PersistenceProvider> providers = new HashSet<PersistenceProvider>();
50      // Changed to the hard coded PERSISTENCE_PROVIDER value to pass signature tests.
51      // public static final java.lang.String PERSISTENCE_PROVIDER = PersistenceProvider.class.getName(); 
52      public static final java.lang.String PERSISTENCE_PROVIDER = "javax.persistence.spi.PeristenceProvider";
53      static final String PERSISTENCE_PROVIDER_PROPERTY = "javax.persistence.provider";
54      static final String PERSISTENCE_PROVIDER_SERVICE = "META-INF/services/"
55          + PersistenceProvider.class.getName();
56  
57      /**
58       * Create and return an EntityManagerFactory for the named persistence unit.
59       *
60       * @param persistenceUnitName The name of the persistence unit
61       * @return The factory that creates EntityManagers configured according to the
62       *         specified persistence unit
63       */
64      public static EntityManagerFactory createEntityManagerFactory(
65              String persistenceUnitName) {
66          return createEntityManagerFactory(persistenceUnitName, Collections.EMPTY_MAP);
67              }
68  
69      /**
70       * Create and return an EntityManagerFactory for the named persistence unit using the
71       * given properties.
72       *
73       * @param persistenceUnitName The name of the persistence unit
74       * @param properties          Additional properties to use when creating the factory. The values of
75       *                            these properties override any values that may have been configured
76       *                            elsewhere.
77       * @return The factory that creates EntityManagers configured according to the
78       *         specified persistence unit.
79       */
80      public static EntityManagerFactory createEntityManagerFactory(
81              String persistenceUnitName,
82              Map properties) {
83  
84          if (properties == null) {
85              properties = Collections.EMPTY_MAP;
86          }
87  
88          // start by loading a provider explicitly specified in properties. The spec
89          // doesn't seem to forbid providers that are not deployed as a service
90          Object providerName = properties.get(PERSISTENCE_PROVIDER_PROPERTY);
91          if (providerName instanceof String) {
92              EntityManagerFactory factory = createFactory(
93                      providerName.toString(),
94                      persistenceUnitName,
95                      properties);
96              if (factory != null) {
97                  return factory;
98              }
99          }
100 
101         // load correctly deployed providers
102         ClassLoader loader = Thread.currentThread().getContextClassLoader();
103         try {
104             Enumeration<URL> providers = loader
105                 .getResources(PERSISTENCE_PROVIDER_SERVICE);
106             while (providers.hasMoreElements()) {
107 
108                 String name = getProviderName(providers.nextElement());
109 
110                 if (name != null) {
111 
112                     EntityManagerFactory factory = createFactory(
113                             name,
114                             persistenceUnitName,
115                             properties);
116 
117                     if (factory != null) {
118                         return factory;
119                     }
120                 }
121             }
122         }
123         catch (IOException e) {
124             // spec doesn't mention any exceptions thrown by this method
125         }
126 
127         return null;
128             }
129 
130     static String getProviderName(URL url) throws IOException {
131 
132         BufferedReader in = new BufferedReader(new InputStreamReader(
133                     url.openStream(),
134                     "UTF-8"));
135 
136         String providerName;
137 
138         try {
139             providerName = in.readLine();
140         }
141         finally {
142             in.close();
143         }
144 
145         if (providerName != null) {
146             providerName = providerName.trim();
147         }
148 
149         return providerName;
150     }
151 
152     static EntityManagerFactory createFactory(
153             String providerName,
154             String persistenceUnitName,
155             Map properties)
156         throws PersistenceException {
157 
158         Class providerClass;
159         try {
160             providerClass = Class.forName(providerName, true, Thread
161                     .currentThread().getContextClassLoader());
162         } 
163         catch (Exception e) {
164             throw new PersistenceException(
165                     "Invalid or inaccessible provider class: " + providerName,
166                     e);
167         }
168 
169         try {
170             PersistenceProvider provider = (PersistenceProvider) providerClass
171                 .newInstance();
172             return provider.createEntityManagerFactory(persistenceUnitName,
173                     properties);
174         }
175         catch (Exception e) {
176             throw new PersistenceException("Provider error. Provider: "
177                     + providerName, e);
178         }
179     }
180 }