001: /*
002:
003: Derby - Class org.apache.derby.impl.sql.conn.GenericLanguageConnectionFactory
004:
005: Licensed to the Apache Software Foundation (ASF) under one or more
006: contributor license agreements. See the NOTICE file distributed with
007: this work for additional information regarding copyright ownership.
008: The ASF licenses this file to you under the Apache License, Version 2.0
009: (the "License"); you may not use this file except in compliance with
010: the License. You may obtain a copy of the License at
011:
012: http://www.apache.org/licenses/LICENSE-2.0
013:
014: Unless required by applicable law or agreed to in writing, software
015: distributed under the License is distributed on an "AS IS" BASIS,
016: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: See the License for the specific language governing permissions and
018: limitations under the License.
019:
020: */
021:
022: package org.apache.derby.impl.sql.conn;
023:
024: import org.apache.derby.iapi.reference.JDBC20Translation;
025: import org.apache.derby.iapi.reference.JDBC30Translation;
026:
027: import org.apache.derby.iapi.sql.conn.LanguageConnectionFactory;
028: import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
029: import org.apache.derby.iapi.sql.compile.CompilerContext;
030:
031: import org.apache.derby.iapi.sql.LanguageFactory;
032: import org.apache.derby.impl.sql.GenericStatement;
033:
034: import org.apache.derby.impl.sql.conn.CachedStatement;
035:
036: import org.apache.derby.iapi.services.uuid.UUIDFactory;
037: import org.apache.derby.iapi.services.compiler.JavaFactory;
038: import org.apache.derby.iapi.services.loader.ClassFactory;
039:
040: import org.apache.derby.iapi.db.Database;
041:
042: import org.apache.derby.iapi.store.access.TransactionController;
043:
044: import org.apache.derby.iapi.sql.compile.TypeCompilerFactory;
045:
046: import org.apache.derby.iapi.error.StandardException;
047:
048: import org.apache.derby.iapi.sql.compile.NodeFactory;
049: import org.apache.derby.iapi.sql.compile.Parser;
050:
051: import org.apache.derby.iapi.sql.Activation;
052:
053: import org.apache.derby.iapi.store.access.AccessFactory;
054: import org.apache.derby.iapi.services.property.PropertyFactory;
055:
056: import org.apache.derby.iapi.sql.Statement;
057: import org.apache.derby.iapi.sql.compile.OptimizerFactory;
058: import org.apache.derby.iapi.sql.dictionary.DataDictionary;
059: import org.apache.derby.iapi.types.DataValueFactory;
060: import org.apache.derby.iapi.sql.execute.ExecutionFactory;
061: import org.apache.derby.iapi.sql.dictionary.SchemaDescriptor;
062:
063: import org.apache.derby.iapi.services.sanity.SanityManager;
064:
065: import org.apache.derby.iapi.services.monitor.Monitor;
066: import org.apache.derby.iapi.services.monitor.ModuleControl;
067: import org.apache.derby.iapi.services.monitor.ModuleSupportable;
068: import org.apache.derby.iapi.services.monitor.ModuleFactory;
069: import org.apache.derby.iapi.services.context.ContextManager;
070:
071: import org.apache.derby.iapi.services.cache.CacheFactory;
072: import org.apache.derby.iapi.services.cache.CacheManager;
073: import org.apache.derby.iapi.services.cache.CacheableFactory;
074: import org.apache.derby.iapi.services.cache.Cacheable;
075:
076: import org.apache.derby.iapi.services.property.PropertyUtil;
077: import org.apache.derby.iapi.services.property.PropertySetCallback;
078:
079: import org.apache.derby.iapi.services.i18n.LocaleFinder;
080: import org.apache.derby.iapi.reference.SQLState;
081: import org.apache.derby.iapi.reference.Property;
082: import org.apache.derby.iapi.reference.EngineType;
083:
084: import java.util.Properties;
085: import java.util.Locale;
086: import java.util.Dictionary;
087: import java.io.Serializable;
088: import org.apache.derby.iapi.util.IdUtil;
089: import org.apache.derby.iapi.services.daemon.Serviceable;
090: import org.apache.derby.iapi.util.StringUtil;
091:
092: /**
093: * LanguageConnectionFactory generates all of the items
094: * a language system needs that is specific to a particular
095: * connection. Alot of these are other factories.
096: *
097: * @author ames
098: */
099: public class GenericLanguageConnectionFactory implements
100: LanguageConnectionFactory, CacheableFactory,
101: PropertySetCallback, ModuleControl, ModuleSupportable {
102:
103: /*
104: fields
105: */
106: protected DataDictionary dd;
107: private ExecutionFactory ef;
108: private OptimizerFactory of;
109: private TypeCompilerFactory tcf;
110: private DataValueFactory dvf;
111: private UUIDFactory uuidFactory;
112: private JavaFactory javaFactory;
113: private ClassFactory classFactory;
114: private NodeFactory nodeFactory;
115: private AccessFactory af;
116: private PropertyFactory pf;
117:
118: private int nextLCCInstanceNumber;
119:
120: /*
121: for caching prepared statements
122: */
123: private int cacheSize = org.apache.derby.iapi.reference.Property.STATEMENT_CACHE_SIZE_DEFAULT;
124: private CacheManager singleStatementCache;
125:
126: /*
127: constructor
128: */
129: public GenericLanguageConnectionFactory() {
130: }
131:
132: /*
133: LanguageConnectionFactory interface
134: */
135:
136: /*
137: these are the methods that do real work, not just look for factories
138: */
139:
140: /**
141: Get a Statement for the connection
142: @param compilationSchema schema
143: @param statementText the text for the statement
144: @param forReadOnly if concurrency is CONCUR_READ_ONLY
145: @return The Statement
146: */
147: public Statement getStatement(SchemaDescriptor compilationSchema,
148: String statementText, boolean forReadOnly) {
149: return new GenericStatement(compilationSchema, statementText,
150: forReadOnly);
151: }
152:
153: /**
154: Get a LanguageConnectionContext. this holds things
155: we want to remember about activity in the language system,
156: where this factory holds things that are pretty stable,
157: like other factories.
158: <p>
159: The returned LanguageConnectionContext is intended for use
160: only by the connection that requested it.
161:
162: @return a language connection context for the context stack.
163: @exception StandardException the usual -- for the subclass
164: */
165:
166: public LanguageConnectionContext newLanguageConnectionContext(
167: ContextManager cm, TransactionController tc,
168: LanguageFactory lf, Database db, String userName,
169: String drdaID, String dbname) throws StandardException {
170:
171: pushDataDictionaryContext(cm);
172:
173: return new GenericLanguageConnectionContext(cm, tc, lf, this ,
174: db, userName, getNextLCCInstanceNumber(), drdaID,
175: dbname);
176: }
177:
178: public Cacheable newCacheable(CacheManager cm) {
179: return new CachedStatement();
180: }
181:
182: /*
183: these methods all look for factories that we booted.
184: */
185:
186: /**
187: Get the UUIDFactory to use with this language connection
188: REMIND: this is only used by the compiler; should there be
189: a compiler module control class to boot compiler-only stuff?
190: */
191: public UUIDFactory getUUIDFactory() {
192: return uuidFactory;
193: }
194:
195: /**
196: Get the ClassFactory to use with this language connection
197: */
198: public ClassFactory getClassFactory() {
199: return classFactory;
200: }
201:
202: /**
203: Get the JavaFactory to use with this language connection
204: REMIND: this is only used by the compiler; should there be
205: a compiler module control class to boot compiler-only stuff?
206: */
207: public JavaFactory getJavaFactory() {
208: return javaFactory;
209: }
210:
211: /**
212: Get the NodeFactory to use with this language connection
213: REMIND: is this only used by the compiler?
214: */
215: public NodeFactory getNodeFactory() {
216: return nodeFactory;
217: }
218:
219: /**
220: Get the ExecutionFactory to use with this language connection
221: */
222: public ExecutionFactory getExecutionFactory() {
223: return ef;
224: }
225:
226: /**
227: Get the AccessFactory to use with this language connection
228: */
229: public AccessFactory getAccessFactory() {
230: return af;
231: }
232:
233: /**
234: Get the PropertyFactory to use with this language connection
235: */
236: public PropertyFactory getPropertyFactory() {
237: return pf;
238: }
239:
240: /**
241: Get the OptimizerFactory to use with this language connection
242: */
243: public OptimizerFactory getOptimizerFactory() {
244: return of;
245: }
246:
247: /**
248: Get the TypeCompilerFactory to use with this language connection
249: */
250: public TypeCompilerFactory getTypeCompilerFactory() {
251: return tcf;
252: }
253:
254: /**
255: Get the DataValueFactory to use with this language connection
256: */
257: public DataValueFactory getDataValueFactory() {
258: return dvf;
259: }
260:
261: protected void pushDataDictionaryContext(ContextManager cm) {
262: // we make sure there is a data dictionary context in place.
263: dd.pushDataDictionaryContext(cm);
264: }
265:
266: /*
267: ModuleControl interface
268: */
269:
270: /**
271: this implementation will not support caching of statements.
272: */
273: public boolean canSupport(Properties startParams) {
274:
275: return Monitor.isDesiredType(startParams,
276: EngineType.STANDALONE_DB);
277: }
278:
279: private int statementCacheSize(Properties startParams) {
280: String wantCacheProperty = null;
281:
282: wantCacheProperty = PropertyUtil
283: .getPropertyFromSet(
284: startParams,
285: org.apache.derby.iapi.reference.Property.STATEMENT_CACHE_SIZE);
286:
287: if (SanityManager.DEBUG)
288: SanityManager.DEBUG("StatementCacheInfo",
289: "Cacheing implementation chosen if null or 0<"
290: + wantCacheProperty);
291:
292: if (wantCacheProperty != null) {
293: try {
294: cacheSize = Integer.parseInt(wantCacheProperty);
295: } catch (NumberFormatException nfe) {
296: cacheSize = org.apache.derby.iapi.reference.Property.STATEMENT_CACHE_SIZE_DEFAULT;
297: }
298: }
299:
300: return cacheSize;
301: }
302:
303: /**
304: * Start-up method for this instance of the language connection factory.
305: * Note these are expected to be booted relative to a Database.
306: *
307: * @param startParams The start-up parameters (ignored in this case)
308: *
309: * @exception StandardException Thrown on failure to boot
310: */
311: public void boot(boolean create, Properties startParams)
312: throws StandardException {
313:
314: dvf = (DataValueFactory) Monitor
315: .bootServiceModule(
316: create,
317: this ,
318: org.apache.derby.iapi.reference.ClassName.DataValueFactory,
319: startParams);
320: javaFactory = (JavaFactory) Monitor
321: .startSystemModule(org.apache.derby.iapi.reference.Module.JavaFactory);
322: uuidFactory = Monitor.getMonitor().getUUIDFactory();
323: classFactory = (ClassFactory) Monitor.getServiceModule(this ,
324: org.apache.derby.iapi.reference.Module.ClassFactory);
325: if (classFactory == null)
326: classFactory = (ClassFactory) Monitor
327: .findSystemModule(org.apache.derby.iapi.reference.Module.ClassFactory);
328:
329: bootDataDictionary(create, startParams);
330:
331: //set the property validation module needed to do propertySetCallBack
332: //register and property validation
333: setValidation();
334:
335: setStore();
336:
337: ef = (ExecutionFactory) Monitor.bootServiceModule(create, this ,
338: ExecutionFactory.MODULE, startParams);
339: of = (OptimizerFactory) Monitor.bootServiceModule(create, this ,
340: OptimizerFactory.MODULE, startParams);
341: tcf = (TypeCompilerFactory) Monitor
342: .startSystemModule(TypeCompilerFactory.MODULE);
343: nodeFactory = (NodeFactory) Monitor.bootServiceModule(create,
344: this , NodeFactory.MODULE, startParams);
345:
346: // If the system supports statement caching boot the CacheFactory module.
347: int cacheSize = statementCacheSize(startParams);
348: if (cacheSize > 0) {
349: CacheFactory cacheFactory = (CacheFactory) Monitor
350: .startSystemModule(org.apache.derby.iapi.reference.Module.CacheFactory);
351: singleStatementCache = cacheFactory.newCacheManager(this ,
352: "StatementCache", cacheSize / 4, cacheSize);
353: }
354:
355: }
356:
357: protected void bootDataDictionary(boolean create,
358: Properties startParams) throws StandardException {
359: dd = (DataDictionary) Monitor.bootServiceModule(create, this ,
360: DataDictionary.MODULE, startParams);
361: }
362:
363: /**
364: * returns the statement cache that this connection should use; currently
365: * there is a statement cache per connection.
366: */
367:
368: public CacheManager getStatementCache() {
369: return singleStatementCache;
370: }
371:
372: /**
373: * Stop this module. In this case, nothing needs to be done.
374: */
375: public void stop() {
376: }
377:
378: /*
379: ** Methods of PropertySetCallback
380: */
381:
382: public void init(boolean dbOnly, Dictionary p) {
383: // not called yet ...
384: }
385:
386: /**
387: @see PropertySetCallback#validate
388: @exception StandardException Thrown on error.
389: */
390: public boolean validate(String key, Serializable value, Dictionary p)
391: throws StandardException {
392: if (value == null)
393: return true;
394: else if (key.equals(Property.DEFAULT_CONNECTION_MODE_PROPERTY)) {
395: String value_s = (String) value;
396: if (value_s != null
397: && !StringUtil.SQLEqualsIgnoreCase(value_s,
398: Property.NO_ACCESS)
399: && !StringUtil.SQLEqualsIgnoreCase(value_s,
400: Property.READ_ONLY_ACCESS)
401: && !StringUtil.SQLEqualsIgnoreCase(value_s,
402: Property.FULL_ACCESS))
403: throw StandardException.newException(
404: SQLState.AUTH_INVALID_AUTHORIZATION_PROPERTY,
405: key, value_s);
406:
407: return true;
408: } else if (key.equals(Property.READ_ONLY_ACCESS_USERS_PROPERTY)
409: || key.equals(Property.FULL_ACCESS_USERS_PROPERTY)) {
410: String value_s = (String) value;
411:
412: /** Parse the new userIdList to verify its syntax. */
413: String[] newList_a;
414: try {
415: newList_a = IdUtil.parseIdList(value_s);
416: } catch (StandardException se) {
417: throw StandardException.newException(
418: SQLState.AUTH_INVALID_AUTHORIZATION_PROPERTY,
419: se, key, value_s);
420: }
421:
422: /** Check the new list userIdList for duplicates. */
423: String dups = IdUtil.dups(newList_a);
424: if (dups != null)
425: throw StandardException.newException(
426: SQLState.AUTH_DUPLICATE_USERS, key, dups);
427:
428: /** Check for users with both read and full access permission. */
429: String[] otherList_a;
430: String otherList;
431: if (key.equals(Property.READ_ONLY_ACCESS_USERS_PROPERTY))
432: otherList = (String) p
433: .get(Property.FULL_ACCESS_USERS_PROPERTY);
434: else
435: otherList = (String) p
436: .get(Property.READ_ONLY_ACCESS_USERS_PROPERTY);
437: otherList_a = IdUtil.parseIdList(otherList);
438: String both = IdUtil.intersect(newList_a, otherList_a);
439: if (both != null)
440: throw StandardException.newException(
441: SQLState.AUTH_USER_IN_READ_AND_WRITE_LISTS,
442: both);
443:
444: return true;
445: }
446:
447: return false;
448: }
449:
450: /** @see PropertySetCallback#apply */
451: public Serviceable apply(String key, Serializable value,
452: Dictionary p) {
453: return null;
454: }
455:
456: /** @see PropertySetCallback#map */
457: public Serializable map(String key, Serializable value, Dictionary p) {
458: return null;
459: }
460:
461: protected void setValidation() throws StandardException {
462: pf = (PropertyFactory) Monitor.findServiceModule(this ,
463: org.apache.derby.iapi.reference.Module.PropertyFactory);
464: pf.addPropertySetNotification(this );
465: }
466:
467: protected void setStore() throws StandardException {
468: af = (AccessFactory) Monitor.findServiceModule(this ,
469: AccessFactory.MODULE);
470: }
471:
472: public Parser newParser(CompilerContext cc) {
473: return new org.apache.derby.impl.sql.compile.ParserImpl(cc);
474: }
475:
476: // Class methods
477:
478: /**
479: * Get the instance # for the next LCC.
480: * (Useful for logStatementText=true output.
481: *
482: * @return instance # of next LCC.
483: */
484: protected synchronized int getNextLCCInstanceNumber() {
485: return nextLCCInstanceNumber++;
486: }
487: }
|