KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectstyle > cayenne > modeler > pref > PreferencesDataSourceFactory


1 /* ====================================================================
2  *
3  * The ObjectStyle Group Software License, version 1.1
4  * ObjectStyle Group - http://objectstyle.org/
5  *
6  * Copyright (c) 2002-2005, Andrei (Andrus) Adamchik and individual authors
7  * of the software. All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * 1. Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  *
16  * 2. Redistributions in binary form must reproduce the above copyright
17  * notice, this list of conditions and the following disclaimer in
18  * the documentation and/or other materials provided with the
19  * distribution.
20  *
21  * 3. The end-user documentation included with the redistribution, if any,
22  * must include the following acknowlegement:
23  * "This product includes software developed by independent contributors
24  * and hosted on ObjectStyle Group web site (http://objectstyle.org/)."
25  * Alternately, this acknowlegement may appear in the software itself,
26  * if and wherever such third-party acknowlegements normally appear.
27  *
28  * 4. The names "ObjectStyle Group" and "Cayenne" must not be used to endorse
29  * or promote products derived from this software without prior written
30  * permission. For written permission, email
31  * "andrus at objectstyle dot org".
32  *
33  * 5. Products derived from this software may not be called "ObjectStyle"
34  * or "Cayenne", nor may "ObjectStyle" or "Cayenne" appear in their
35  * names without prior written permission.
36  *
37  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
38  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
39  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40  * DISCLAIMED. IN NO EVENT SHALL THE OBJECTSTYLE GROUP OR
41  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
42  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
43  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
44  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
45  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
46  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
47  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
48  * SUCH DAMAGE.
49  * ====================================================================
50  *
51  * This software consists of voluntary contributions made by many
52  * individuals and hosted on ObjectStyle Group web site. For more
53  * information on the ObjectStyle Group, please see
54  * <http://objectstyle.org/>.
55  */

56 package org.objectstyle.cayenne.modeler.pref;
57
58 import java.io.File JavaDoc;
59 import java.sql.SQLException JavaDoc;
60 import java.util.ArrayList JavaDoc;
61 import java.util.Collection JavaDoc;
62 import java.util.Collections JavaDoc;
63 import java.util.Iterator JavaDoc;
64 import java.util.List JavaDoc;
65 import java.util.Map JavaDoc;
66
67 import javax.sql.DataSource JavaDoc;
68
69 import org.apache.log4j.Level;
70 import org.objectstyle.cayenne.CayenneRuntimeException;
71 import org.objectstyle.cayenne.DataObjectUtils;
72 import org.objectstyle.cayenne.access.DataContext;
73 import org.objectstyle.cayenne.conf.Configuration;
74 import org.objectstyle.cayenne.conf.DataSourceFactory;
75 import org.objectstyle.cayenne.conn.PoolManager;
76 import org.objectstyle.cayenne.exp.Expression;
77 import org.objectstyle.cayenne.exp.ExpressionFactory;
78 import org.objectstyle.cayenne.modeler.Application;
79 import org.objectstyle.cayenne.pref.DomainPreference;
80 import org.objectstyle.cayenne.pref.HSQLEmbeddedPreferenceService;
81 import org.objectstyle.cayenne.project.CayenneUserDir;
82 import org.objectstyle.cayenne.query.SelectQuery;
83
84 /**
85  * A DataSourceFactory that loads DataSources from CayenneModeler preferences. Allows
86  * integrating Cayenne runtime with preferences engine. Currently JNDIDataSourceFactory
87  * uses this factory as a failover loading mechanism, instantiating it via reflection.
88  *
89  * @since 1.2
90  * @author Andrus Adamchik
91  */

92 public class PreferencesDataSourceFactory implements DataSourceFactory {
93
94     protected int minPoolSize;
95     protected int maxPoolSize;
96
97     public PreferencesDataSourceFactory() {
98         // init pool size default
99
this(1, 5);
100     }
101
102     public PreferencesDataSourceFactory(int minPoolSize, int maxPoolSize) {
103         this.minPoolSize = minPoolSize;
104         this.maxPoolSize = maxPoolSize;
105     }
106
107     public int getMaxPoolSize() {
108         return maxPoolSize;
109     }
110
111     public int getMinPoolSize() {
112         return minPoolSize;
113     }
114
115     public void initializeWithParentConfiguration(Configuration configuaration) {
116         // noop
117
}
118
119     public DataSource JavaDoc getDataSource(String JavaDoc location) throws Exception JavaDoc {
120         return getDataSource(location, Level.INFO);
121     }
122
123     /**
124      * Attempts to read named DataSource info from preferences and create a DataSource out
125      * of it. If no matching DataSource is found, throws CayenneRuntimeException.
126      */

127     public DataSource JavaDoc getDataSource(final String JavaDoc location, Level logLevel)
128             throws Exception JavaDoc {
129         if (location == null) {
130             throw new NullPointerException JavaDoc("Null location");
131         }
132
133         // figure out preferences DB location...
134

135         // TODO: once prefs package becomes a part of Cayenne, remove dependency on
136
// Application class... also this code is redundant with what Application does in
137
// constructor
138
String JavaDoc configuredName = System.getProperty(Application.APPLICATION_NAME_PROPERTY);
139         String JavaDoc name = (configuredName != null)
140                 ? configuredName
141                 : Application.DEFAULT_APPLICATION_NAME;
142
143         String JavaDoc subdir = System.getProperty(Application.PREFERENCES_VERSION_PROPERTY);
144
145         if (subdir == null) {
146             subdir = Application.PREFERENCES_VERSION;
147         }
148
149         File JavaDoc dbDir = new File JavaDoc(CayenneUserDir.getInstance().resolveFile(
150                 Application.PREFERENCES_DB_SUBDIRECTORY), subdir);
151
152         // check if preferences even exist...
153
if (!dbDir.isDirectory()) {
154             throw new CayenneRuntimeException(
155                     "No preferences database directory exists: " + dbDir);
156         }
157         else if (!new File JavaDoc(dbDir, "db.properties").exists()) {
158             throw new CayenneRuntimeException(
159                     "No preferences database exists in directory " + dbDir);
160         }
161
162         String JavaDoc preferencesDB = new File JavaDoc(dbDir, "db").getAbsolutePath();
163
164         // create custom preferences service...
165
HSQLEmbeddedPreferenceService service = new HSQLEmbeddedPreferenceService(
166                 preferencesDB,
167                 Application.PREFERENCES_MAP_PACKAGE,
168                 name) {
169
170             protected void startTimer() {
171                 // noop: disable commit timer
172
}
173
174             protected void initPreferences() {
175                 // noop: disable commit timer
176
}
177
178             protected void initSchema() {
179                 // throw - no schema means no DataSource data
180
throw new CayenneRuntimeException("No preferences matching location: "
181                         + location);
182             }
183         };
184
185         try {
186             service.startService();
187             return toDataSource(service.getDataContext(), location);
188         }
189         finally {
190             // make sure we cleanup after ourselves...
191
try {
192                 service.stopService();
193             }
194             catch (Throwable JavaDoc th) {
195                 // ignore..
196
}
197         }
198     }
199
200     DataSource JavaDoc toDataSource(DataContext context, String JavaDoc location) throws Exception JavaDoc {
201
202         // grep through all domains ... maybe a bit naive...
203
Expression locationFilter = ExpressionFactory.matchExp(
204                 DomainPreference.KEY_PROPERTY,
205                 location);
206         List JavaDoc preferences = context.performQuery(new SelectQuery(
207                 DomainPreference.class,
208                 locationFilter));
209
210         if (preferences.isEmpty()) {
211             throw new CayenneRuntimeException("No preferences matching location: "
212                     + location);
213         }
214
215         Collection JavaDoc ids = new ArrayList JavaDoc(preferences.size());
216         Iterator JavaDoc it = preferences.iterator();
217         while (it.hasNext()) {
218             DomainPreference pref = (DomainPreference) it.next();
219             ids.add(DataObjectUtils.pkForObject(pref));
220         }
221
222         Expression qualifier = Expression.fromString("db:"
223                 + DBConnectionInfo.ID_PK_COLUMN
224                 + " in $ids");
225         Map JavaDoc params = Collections.singletonMap("ids", ids);
226         SelectQuery query = new SelectQuery(DBConnectionInfo.class, qualifier
227                 .expWithParameters(params));
228
229         // narrow down the results to just DBConnectionInfo
230
List JavaDoc connectionData = context.performQuery(query);
231
232         if (connectionData.isEmpty()) {
233             throw new CayenneRuntimeException("No preferences matching location: "
234                     + location);
235         }
236
237         if (connectionData.size() > 1) {
238             throw new CayenneRuntimeException(
239                     "More than one preference matched location: " + location);
240         }
241
242         DBConnectionInfo info = (DBConnectionInfo) connectionData.get(0);
243
244         if (info.getJdbcDriver() == null) {
245             throw new CayenneRuntimeException(
246                     "Incomplete connection info: no JDBC driver set.");
247         }
248
249         if (info.getUrl() == null) {
250             throw new SQLException JavaDoc("Incomplete connection info: no DB URL set.");
251         }
252
253         // use default values for connection pool ... no info is available from
254
// preferences...
255
return new PoolManager(info.getJdbcDriver(), info.getUrl(), 1, 5, info
256                 .getUserName(), info.getPassword());
257     }
258 }
259
Popular Tags