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.jdbc.kernel;
20
21 import java.util.Arrays;
22 import java.util.Collection;
23 import java.util.Iterator;
24 import java.util.Properties;
25 import java.util.Map;
26
27 import org.apache.commons.lang.StringUtils;
28 import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
29 import org.apache.openjpa.jdbc.conf.JDBCConfigurationImpl;
30 import org.apache.openjpa.jdbc.meta.MappingRepository;
31 import org.apache.openjpa.jdbc.meta.MappingTool;
32 import org.apache.openjpa.kernel.AbstractBrokerFactory;
33 import org.apache.openjpa.kernel.Bootstrap;
34 import org.apache.openjpa.kernel.BrokerImpl;
35 import org.apache.openjpa.kernel.StoreManager;
36 import org.apache.openjpa.lib.conf.ConfigurationProvider;
37 import org.apache.openjpa.lib.conf.Configurations;
38 import org.apache.openjpa.lib.util.Localizer;
39 import org.apache.openjpa.util.UserException;
40
41 /**
42 * BrokerFactory type for use with the JDBC runtime.
43 *
44 * @author Abe White
45 * @author Marc Prud'hommeaux
46 */
47 public class JDBCBrokerFactory
48 extends AbstractBrokerFactory {
49
50 private static final Localizer _loc = Localizer.forPackage
51 (JDBCBrokerFactory.class);
52
53 private boolean _synchronizedMappings = false;
54
55 /**
56 * Factory method for constructing a factory from properties. Invoked from
57 * {@link Bootstrap#newBrokerFactory}.
58 */
59 public static JDBCBrokerFactory newInstance(ConfigurationProvider cp) {
60 JDBCConfigurationImpl conf = new JDBCConfigurationImpl();
61 cp.setInto(conf);
62 return new JDBCBrokerFactory(conf);
63 }
64
65 /**
66 * Factory method for obtaining a possibly-pooled factory from properties.
67 * Invoked from {@link Bootstrap#getBrokerFactory}.
68 */
69 public static JDBCBrokerFactory getInstance(ConfigurationProvider cp) {
70 Map props = cp.getProperties();
71 Object key = toPoolKey(props);
72 JDBCBrokerFactory factory = (JDBCBrokerFactory)
73 getPooledFactoryForKey(key);
74 if (factory != null)
75 return factory;
76
77 factory = newInstance(cp);
78 pool(key, factory);
79 return factory;
80 }
81
82 /**
83 * Construct the factory with the given option settings; however, the
84 * factory construction methods are recommended.
85 */
86 public JDBCBrokerFactory(JDBCConfiguration conf) {
87 super(conf);
88 }
89
90 public Properties getProperties() {
91 // add platform property
92 Properties props = super.getProperties();
93 String db = "Unknown";
94 try {
95 JDBCConfiguration conf = (JDBCConfiguration) getConfiguration();
96 db = conf.getDBDictionaryInstance().platform;
97 } catch (RuntimeException re) {
98 }
99 props.setProperty("Platform",
100 "OpenJPA JDBC Edition: " + db + " Database");
101
102 return props;
103 }
104
105 protected StoreManager newStoreManager() {
106 return new JDBCStoreManager();
107 }
108
109 protected BrokerImpl newBrokerImpl(String user, String pass) {
110 BrokerImpl broker = super.newBrokerImpl(user, pass);
111
112 lock();
113 try {
114 // synchronize mappings; we wait until now to do this so that
115 // we can use the first broker user/pass for connection if no
116 // global login is given
117 if (!_synchronizedMappings) {
118 _synchronizedMappings = true;
119 synchronizeMappings(broker.getClassLoader());
120 }
121
122 return broker;
123 } finally {
124 unlock();
125 }
126 }
127
128 /**
129 * Synchronize the mappings of the classes listed in the configuration.
130 */
131 protected void synchronizeMappings(ClassLoader loader) {
132 JDBCConfiguration conf = (JDBCConfiguration) getConfiguration();
133 String action = conf.getSynchronizeMappings();
134 if (StringUtils.isEmpty(action))
135 return;
136
137 MappingRepository repo = conf.getMappingRepositoryInstance();
138 Collection classes = repo.loadPersistentTypes(false, loader);
139 if (classes.isEmpty())
140 return;
141
142 String props = Configurations.getProperties(action);
143 action = Configurations.getClassName(action);
144 MappingTool tool = new MappingTool(conf, action, false);
145 Configurations.configureInstance(tool, conf, props,
146 "SynchronizeMappings");
147
148 // initialize the schema
149 Class cls;
150 for (Iterator itr = classes.iterator(); itr.hasNext();) {
151 cls = (Class) itr.next();
152 try {
153 tool.run(cls);
154 } catch (IllegalArgumentException iae) {
155 throw new UserException(_loc.get("bad-synch-mappings",
156 action, Arrays.asList(MappingTool.ACTIONS)));
157 }
158 }
159 tool.record();
160 }
161 }