Source code: org/apache/derby/impl/sql/conn/GenericLanguageConnectionFactory.java
1 /*
2
3 Derby - Class org.apache.derby.impl.sql.conn.GenericLanguageConnectionFactory
4
5 Copyright 1997, 2004 The Apache Software Foundation or its licensors, as applicable.
6
7 Licensed under the Apache License, Version 2.0 (the "License");
8 you may not use this file except in compliance with the License.
9 You may obtain a copy of the License at
10
11 http://www.apache.org/licenses/LICENSE-2.0
12
13 Unless required by applicable law or agreed to in writing, software
14 distributed under the License is distributed on an "AS IS" BASIS,
15 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 See the License for the specific language governing permissions and
17 limitations under the License.
18
19 */
20
21 package org.apache.derby.impl.sql.conn;
22
23 import org.apache.derby.iapi.reference.JDBC20Translation;
24 import org.apache.derby.iapi.reference.JDBC30Translation;
25
26 import org.apache.derby.iapi.sql.conn.LanguageConnectionFactory;
27 import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
28 import org.apache.derby.iapi.sql.compile.CompilerContext;
29
30 import org.apache.derby.iapi.sql.LanguageFactory;
31 import org.apache.derby.impl.sql.GenericStatement;
32
33 import org.apache.derby.impl.sql.conn.CachedStatement;
34
35 import org.apache.derby.iapi.services.uuid.UUIDFactory;
36 import org.apache.derby.iapi.services.compiler.JavaFactory;
37 import org.apache.derby.iapi.services.loader.ClassFactory;
38
39 import org.apache.derby.iapi.db.Database;
40
41 import org.apache.derby.iapi.store.access.TransactionController;
42
43 import org.apache.derby.iapi.sql.compile.TypeCompilerFactory;
44
45 import org.apache.derby.iapi.error.StandardException;
46
47 import org.apache.derby.iapi.sql.compile.NodeFactory;
48 import org.apache.derby.iapi.sql.compile.Parser;
49
50 import org.apache.derby.iapi.sql.Activation;
51
52 import org.apache.derby.iapi.store.access.AccessFactory;
53 import org.apache.derby.iapi.services.property.PropertyFactory;
54
55 import org.apache.derby.iapi.sql.Statement;
56 import org.apache.derby.iapi.sql.compile.OptimizerFactory;
57 import org.apache.derby.iapi.sql.dictionary.DataDictionary;
58 import org.apache.derby.iapi.types.DataValueFactory;
59 import org.apache.derby.iapi.sql.execute.ExecutionFactory;
60 import org.apache.derby.iapi.sql.dictionary.SchemaDescriptor;
61
62 import org.apache.derby.iapi.services.sanity.SanityManager;
63
64 import org.apache.derby.iapi.services.monitor.Monitor;
65 import org.apache.derby.iapi.services.monitor.ModuleControl;
66 import org.apache.derby.iapi.services.monitor.ModuleSupportable;
67 import org.apache.derby.iapi.services.monitor.ModuleFactory;
68 import org.apache.derby.iapi.services.context.ContextManager;
69
70 import org.apache.derby.iapi.services.cache.CacheFactory;
71 import org.apache.derby.iapi.services.cache.CacheManager;
72 import org.apache.derby.iapi.services.cache.CacheableFactory;
73 import org.apache.derby.iapi.services.cache.Cacheable;
74
75 import org.apache.derby.iapi.services.property.PropertyUtil;
76 import org.apache.derby.iapi.services.property.PropertySetCallback;
77
78 import org.apache.derby.iapi.services.i18n.LocaleFinder;
79 import org.apache.derby.iapi.reference.SQLState;
80 import org.apache.derby.iapi.reference.Property;
81 import org.apache.derby.iapi.reference.EngineType;
82
83 import java.util.Properties;
84 import java.util.Locale;
85 import java.util.Dictionary;
86 import java.io.Serializable;
87 import org.apache.derby.iapi.util.IdUtil;
88 import org.apache.derby.iapi.services.daemon.Serviceable;
89 import org.apache.derby.iapi.util.StringUtil;
90
91 /**
92 * LanguageConnectionFactory generates all of the items
93 * a language system needs that is specific to a particular
94 * connection. Alot of these are other factories.
95 *
96 * @author ames
97 */
98 public class GenericLanguageConnectionFactory
99 implements LanguageConnectionFactory, CacheableFactory, PropertySetCallback, ModuleControl, ModuleSupportable {
100
101 /*
102 fields
103 */
104 protected DataDictionary dd;
105 private ExecutionFactory ef;
106 private OptimizerFactory of;
107 private TypeCompilerFactory tcf;
108 private DataValueFactory dvf;
109 private UUIDFactory uuidFactory;
110 private JavaFactory javaFactory;
111 private ClassFactory classFactory;
112 private NodeFactory nodeFactory;
113 private AccessFactory af;
114 private PropertyFactory pf;
115
116 private int nextLCCInstanceNumber;
117
118 /*
119 for caching prepared statements
120 */
121 private int cacheSize = org.apache.derby.iapi.reference.Property.STATEMENT_CACHE_SIZE_DEFAULT;
122 private CacheManager singleStatementCache;
123
124 /*
125 constructor
126 */
127 public GenericLanguageConnectionFactory() {
128 }
129
130 /*
131 LanguageConnectionFactory interface
132 */
133
134 /*
135 these are the methods that do real work, not just look for factories
136 */
137
138 /**
139 Get a Statement for the connection
140
141 @param statementText the text for the statement
142 @return The Statement
143 */
144 public Statement getStatement(SchemaDescriptor compilationSchema, String statementText)
145 {
146 return new GenericStatement(compilationSchema, statementText);
147 }
148
149 /**
150 Get a LanguageConnectionContext. this holds things
151 we want to remember about activity in the language system,
152 where this factory holds things that are pretty stable,
153 like other factories.
154 <p>
155 The returned LanguageConnectionContext is intended for use
156 only by the connection that requested it.
157
158 @return a language connection context for the context stack.
159 @exception StandardException the usual -- for the subclass
160 */
161
162 public LanguageConnectionContext newLanguageConnectionContext(
163 ContextManager cm,
164 TransactionController tc,
165 LanguageFactory lf,
166 Database db,
167 String userName,
168 String drdaID,
169 String dbname) throws StandardException {
170
171 pushDataDictionaryContext(cm);
172
173 return new GenericLanguageConnectionContext(cm,
174 tc,
175 lf,
176 this,
177 db,
178 userName,
179 getNextLCCInstanceNumber(),
180 drdaID,
181 dbname);
182 }
183
184 public Cacheable newCacheable(CacheManager cm) {
185 return new CachedStatement();
186 }
187
188 /*
189 these methods all look for factories that we booted.
190 */
191
192 /**
193 Get the UUIDFactory to use with this language connection
194 REMIND: this is only used by the compiler; should there be
195 a compiler module control class to boot compiler-only stuff?
196 */
197 public UUIDFactory getUUIDFactory()
198 {
199 return uuidFactory;
200 }
201
202 /**
203 Get the ClassFactory to use with this language connection
204 */
205 public ClassFactory getClassFactory()
206 {
207 return classFactory;
208 }
209
210 /**
211 Get the JavaFactory to use with this language connection
212 REMIND: this is only used by the compiler; should there be
213 a compiler module control class to boot compiler-only stuff?
214 */
215 public JavaFactory getJavaFactory()
216 {
217 return javaFactory;
218 }
219
220 /**
221 Get the NodeFactory to use with this language connection
222 REMIND: is this only used by the compiler?
223 */
224 public NodeFactory getNodeFactory()
225 {
226 return nodeFactory;
227 }
228
229 /**
230 Get the ExecutionFactory to use with this language connection
231 */
232 public ExecutionFactory getExecutionFactory() {
233 return ef;
234 }
235
236 /**
237 Get the AccessFactory to use with this language connection
238 */
239 public AccessFactory getAccessFactory()
240 {
241 return af;
242 }
243
244 /**
245 Get the PropertyFactory to use with this language connection
246 */
247 public PropertyFactory getPropertyFactory()
248 {
249 return pf;
250 }
251
252 /**
253 Get the OptimizerFactory to use with this language connection
254 */
255 public OptimizerFactory getOptimizerFactory() {
256 return of;
257 }
258 /**
259 Get the TypeCompilerFactory to use with this language connection
260 */
261 public TypeCompilerFactory getTypeCompilerFactory() {
262 return tcf;
263 }
264
265 /**
266 Get the DataValueFactory to use with this language connection
267 */
268 public DataValueFactory getDataValueFactory() {
269 return dvf;
270 }
271
272 protected void pushDataDictionaryContext(ContextManager cm) {
273 // we make sure there is a data dictionary context in place.
274 dd.pushDataDictionaryContext(cm, false);
275 }
276
277 /*
278 ModuleControl interface
279 */
280
281 /**
282 this implementation will not support caching of statements.
283 */
284 public boolean canSupport(Properties startParams) {
285
286 return Monitor.isDesiredType( startParams, EngineType.STANDALONE_DB);
287 }
288
289 private int statementCacheSize(Properties startParams)
290 {
291 String wantCacheProperty = null;
292
293 wantCacheProperty =
294 PropertyUtil.getPropertyFromSet(startParams, org.apache.derby.iapi.reference.Property.STATEMENT_CACHE_SIZE);
295
296 if (SanityManager.DEBUG)
297 SanityManager.DEBUG("StatementCacheInfo", "Cacheing implementation chosen if null or 0<"+wantCacheProperty);
298
299 if (wantCacheProperty != null) {
300 try {
301 cacheSize = Integer.parseInt(wantCacheProperty);
302 } catch (NumberFormatException nfe) {
303 cacheSize = org.apache.derby.iapi.reference.Property.STATEMENT_CACHE_SIZE_DEFAULT;
304 }
305 }
306
307 return cacheSize;
308 }
309
310 /**
311 * Start-up method for this instance of the language connection factory.
312 * Note these are expected to be booted relative to a Database.
313 *
314 * @param startParams The start-up parameters (ignored in this case)
315 *
316 * @exception StandardException Thrown on failure to boot
317 */
318 public void boot(boolean create, Properties startParams)
319 throws StandardException {
320
321 dvf = (DataValueFactory) Monitor.bootServiceModule(create, this, org.apache.derby.iapi.reference.ClassName.DataValueFactory, startParams);
322 javaFactory = (JavaFactory) Monitor.startSystemModule(org.apache.derby.iapi.reference.Module.JavaFactory);
323 uuidFactory = Monitor.getMonitor().getUUIDFactory();
324 classFactory = (ClassFactory) Monitor.getServiceModule(this, org.apache.derby.iapi.reference.Module.ClassFactory);
325 if (classFactory == null)
326 classFactory = (ClassFactory) Monitor.findSystemModule(org.apache.derby.iapi.reference.Module.ClassFactory);
327
328 bootDataDictionary(create, startParams);
329
330 //set the property validation module needed to do propertySetCallBack
331 //register and property validation
332 setValidation();
333
334 setStore();
335
336 ef = (ExecutionFactory) Monitor.bootServiceModule(create, this, ExecutionFactory.MODULE, startParams);
337 of = (OptimizerFactory) Monitor.bootServiceModule(create, this, OptimizerFactory.MODULE, startParams);
338 tcf =
339 (TypeCompilerFactory) Monitor.startSystemModule(TypeCompilerFactory.MODULE);
340 nodeFactory = (NodeFactory) Monitor.bootServiceModule(create, this, NodeFactory.MODULE, startParams);
341
342 // If the system supports statement caching boot the CacheFactory module.
343 int cacheSize = statementCacheSize(startParams);
344 if (cacheSize > 0) {
345 CacheFactory cacheFactory = (CacheFactory) Monitor.startSystemModule(org.apache.derby.iapi.reference.Module.CacheFactory);
346 singleStatementCache = cacheFactory.newCacheManager(this,
347 "StatementCache",
348 cacheSize/4,
349 cacheSize);
350 }
351
352 }
353
354 protected void bootDataDictionary(boolean create, Properties startParams) throws StandardException {
355 dd = (DataDictionary) Monitor.bootServiceModule(create, this, DataDictionary.MODULE, startParams);
356 }
357
358 /**
359 * returns the statement cache that this connection should use; currently
360 * there is a statement cache per connection.
361 */
362
363
364 public CacheManager getStatementCache()
365 {
366 return singleStatementCache;
367 }
368
369 /**
370 * Stop this module. In this case, nothing needs to be done.
371 *
372 * @return Nothing
373 */
374 public void stop() {
375 }
376
377 /*
378 ** Methods of PropertySetCallback
379 */
380
381 public void init(boolean dbOnly, Dictionary p) {
382 // not called yet ...
383 }
384
385 /**
386 @see PropertySetCallback#validate
387 @exception StandardException Thrown on error.
388 */
389 public boolean validate(String key,
390 Serializable value,
391 Dictionary p)
392 throws StandardException {
393 if (value == null)
394 return true;
395 else if (key.equals(Property.DEFAULT_CONNECTION_MODE_PROPERTY))
396 {
397 String value_s = (String)value;
398 if (value_s != null &&
399 !StringUtil.SQLEqualsIgnoreCase(value_s, Property.NO_ACCESS) &&
400 !StringUtil.SQLEqualsIgnoreCase(value_s, Property.READ_ONLY_ACCESS) &&
401 !StringUtil.SQLEqualsIgnoreCase(value_s, Property.FULL_ACCESS))
402 throw StandardException.newException(SQLState.AUTH_INVALID_AUTHORIZATION_PROPERTY , key,value_s);
403
404 return true;
405 }
406 else if (key.equals(Property.READ_ONLY_ACCESS_USERS_PROPERTY) ||
407 key.equals(Property.FULL_ACCESS_USERS_PROPERTY))
408 {
409 String value_s = (String)value;
410
411 /** Parse the new userIdList to verify its syntax. */
412 String[] newList_a;
413 try {newList_a = IdUtil.parseIdList(value_s);}
414 catch (StandardException se) {
415 throw StandardException.newException(SQLState.AUTH_INVALID_AUTHORIZATION_PROPERTY, key,value_s,se);
416 }
417
418 /** Check the new list userIdList for duplicates. */
419 String dups = IdUtil.dups(newList_a);
420 if (dups != null) throw StandardException.newException(SQLState.AUTH_DUPLICATE_USERS, key,dups);
421
422 /** Check for users with both read and full access permission. */
423 String[] otherList_a;
424 String otherList;
425 if (key.equals(Property.READ_ONLY_ACCESS_USERS_PROPERTY))
426 otherList = (String)p.get(Property.FULL_ACCESS_USERS_PROPERTY);
427 else
428 otherList = (String)p.get(Property.READ_ONLY_ACCESS_USERS_PROPERTY);
429 otherList_a = IdUtil.parseIdList(otherList);
430 String both = IdUtil.intersect(newList_a,otherList_a);
431 if (both != null) throw StandardException.newException(SQLState.AUTH_USER_IN_READ_AND_WRITE_LISTS, both);
432
433 return true;
434 }
435
436 return false;
437 }
438 /** @see PropertySetCallback#apply */
439 public Serviceable apply(String key,
440 Serializable value,
441 Dictionary p)
442 {
443 return null;
444 }
445 /** @see PropertySetCallback#map */
446 public Serializable map(String key, Serializable value, Dictionary p)
447 {
448 return null;
449 }
450
451 protected void setValidation() throws StandardException {
452 pf = (PropertyFactory) Monitor.findServiceModule(this,
453 org.apache.derby.iapi.reference.Module.PropertyFactory);
454 pf.addPropertySetNotification(this);
455 }
456
457 protected void setStore() throws StandardException {
458 af = (AccessFactory) Monitor.findServiceModule(this,AccessFactory.MODULE);
459 }
460
461 public Parser newParser(CompilerContext cc)
462 {
463 return new org.apache.derby.impl.sql.compile.ParserImpl(cc);
464 }
465
466 // Class methods
467
468 /**
469 * Get the instance # for the next LCC.
470 * (Useful for logStatementText=true output.
471 *
472 * @return instance # of next LCC.
473 */
474 protected synchronized int getNextLCCInstanceNumber()
475 {
476 return nextLCCInstanceNumber++;
477 }
478 }