001: /*
002:
003: Derby - Class org.apache.derby.impl.db.BasicDatabase
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.db;
023:
024: import org.apache.derby.iapi.error.PublicAPI;
025:
026: import org.apache.derby.iapi.reference.Property;
027: import org.apache.derby.iapi.reference.SQLState;
028: import org.apache.derby.iapi.reference.EngineType;
029: import org.apache.derby.iapi.util.DoubleProperties;
030: import org.apache.derby.iapi.util.IdUtil;
031: import org.apache.derby.iapi.services.info.JVMInfo;
032:
033: import org.apache.derby.iapi.services.property.PropertyUtil;
034: import org.apache.derby.iapi.services.loader.ClassFactory;
035: import org.apache.derby.iapi.services.loader.JarReader;
036: import org.apache.derby.iapi.services.context.ContextManager;
037: import org.apache.derby.iapi.services.context.ContextService;
038: import org.apache.derby.iapi.services.daemon.Serviceable;
039: import org.apache.derby.iapi.services.monitor.ModuleControl;
040: import org.apache.derby.iapi.services.monitor.ModuleSupportable;
041: import org.apache.derby.iapi.services.monitor.Monitor;
042: import org.apache.derby.iapi.services.monitor.ModuleFactory;
043: import org.apache.derby.iapi.services.sanity.SanityManager;
044: import org.apache.derby.iapi.services.property.PersistentSet;
045: import org.apache.derby.iapi.db.Database;
046: import org.apache.derby.iapi.db.DatabaseContext;
047: import org.apache.derby.iapi.error.StandardException;
048: import org.apache.derby.iapi.sql.execute.ExecutionFactory;
049: import org.apache.derby.iapi.types.DataValueFactory;
050: import org.apache.derby.iapi.sql.compile.OptimizerFactory;
051: import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
052: import org.apache.derby.iapi.sql.conn.ConnectionUtil;
053:
054: import org.apache.derby.iapi.sql.conn.LanguageConnectionFactory;
055:
056: import org.apache.derby.iapi.sql.dictionary.DataDictionary;
057: import org.apache.derby.iapi.sql.dictionary.DataDictionaryContext;
058: import org.apache.derby.iapi.sql.dictionary.FileInfoDescriptor;
059: import org.apache.derby.iapi.sql.dictionary.SchemaDescriptor;
060: import org.apache.derby.iapi.sql.dictionary.SPSDescriptor;
061:
062: import org.apache.derby.iapi.sql.depend.DependencyManager;
063: import org.apache.derby.iapi.reference.SQLState;
064: import org.apache.derby.iapi.sql.LanguageFactory;
065: import org.apache.derby.iapi.sql.ResultSet;
066: import org.apache.derby.iapi.store.access.AccessFactory;
067: import org.apache.derby.iapi.store.access.FileResource;
068: import org.apache.derby.iapi.services.property.PropertyFactory;
069: import org.apache.derby.iapi.services.property.PropertySetCallback;
070: import org.apache.derby.iapi.store.access.TransactionController;
071: import org.apache.derby.iapi.jdbc.AuthenticationService;
072: import org.apache.derby.iapi.services.uuid.UUIDFactory;
073: import org.apache.derby.catalog.UUID;
074:
075: import java.io.InputStream;
076: import java.io.OutputStream;
077: import java.io.Serializable;
078: import java.io.File;
079: import java.sql.Date;
080: import java.sql.Timestamp;
081: import java.sql.SQLException;
082: import java.util.Properties;
083: import java.util.Dictionary;
084: import java.util.Enumeration;
085: import java.util.Hashtable;
086: import java.util.Locale;
087: import java.lang.reflect.Method;
088: import java.text.Collator;
089: import java.text.RuleBasedCollator;
090: import java.text.DateFormat;
091:
092: /**
093: * The Database interface provides control over the physical database
094: * (that is, the stored data and the files the data are stored in),
095: * connections to the database, operations on the database such as
096: * backup and recovery, and all other things that are associated
097: * with the database itself.
098: * <p>
099: * The Database interface does not provide control over things that are part of
100: * the Domain, such as users.
101: * <p>
102: * I'm not sure what this will hold in a real system, for now
103: * it simply provides connection-creation for us. Perhaps when it boots,
104: * it creates the datadictionary object for the database, which all users
105: * will then interact with?
106: *
107: * @author ames
108: */
109:
110: public class BasicDatabase implements ModuleControl, ModuleSupportable,
111: PropertySetCallback, Database, JarReader {
112: private boolean active;
113: private AuthenticationService authenticationService;
114: protected AccessFactory af;
115: protected PropertyFactory pf;
116: protected ClassFactory cfDB; // classFactory but only set when per-database
117: protected LanguageConnectionFactory lcf;
118: protected LanguageFactory lf;
119: // hold resourceAdapter in an Object instead of a ResourceAdapter
120: // so that XA class use can be isolated to XA modules.
121: protected Object resourceAdapter;
122: private Locale databaseLocale;
123: private RuleBasedCollator ruleBasedCollator;
124: private int spaceInt;
125: private boolean spaceIntSet;
126: private DateFormat dateFormat;
127: private DateFormat timeFormat;
128: private DateFormat timestampFormat;
129: private UUID myUUID;
130: private boolean normalizeToUpper = true;
131:
132: protected boolean lastToBoot; // is this class last to boot
133:
134: /*
135: * ModuleControl interface
136: */
137:
138: public boolean canSupport(Properties startParams) {
139:
140: return Monitor.isDesiredCreateType(startParams,
141: org.apache.derby.iapi.reference.EngineType.NONE);
142:
143: }
144:
145: protected Properties allParams; // properties to be used *only* while booting.
146:
147: public void boot(boolean create, Properties startParams)
148: throws StandardException {
149: ModuleFactory monitor = Monitor.getMonitor();
150: if (create) {
151: if (startParams.getProperty(Property.CREATE_WITH_NO_LOG) == null)
152: startParams.put(Property.CREATE_WITH_NO_LOG, "true");
153:
154: String localeID = startParams
155: .getProperty(org.apache.derby.iapi.reference.Attribute.TERRITORY);
156:
157: if (localeID == null) {
158: localeID = Locale.getDefault().toString();
159: }
160: databaseLocale = monitor.setLocale(startParams, localeID);
161:
162: } else {
163: databaseLocale = monitor.getLocale(this );
164: }
165: setLocale(databaseLocale);
166:
167: normalizeToUpper = true;
168:
169: // boot the validation needed to do property validation, now property
170: // validation is separated from AccessFactory, therefore from store
171: bootValidation(create, startParams);
172:
173: // boot the type factpry before store to ensure any dynamically
174: // registered types (DECIMAL) are there before logical undo recovery might need them.
175: Monitor
176: .bootServiceModule(
177: create,
178: this ,
179: org.apache.derby.iapi.reference.ClassName.DataValueFactory,
180: startParams);
181:
182: bootStore(create, startParams);
183:
184: // create a database ID if one doesn't already exist
185: myUUID = makeDatabaseID(create, startParams);
186:
187: allParams = new DoubleProperties(getAllDatabaseProperties(),
188: startParams);
189:
190: if (pf != null)
191: pf.addPropertySetNotification(this );
192:
193: // Boot the ClassFactory, will be per-database or per-system.
194: // reget the tc in case someone inadverdently destroyed it
195: bootClassFactory(create, allParams);
196:
197: lcf = (LanguageConnectionFactory) Monitor.bootServiceModule(
198: create, this , LanguageConnectionFactory.MODULE,
199: allParams);
200: lf = (LanguageFactory) Monitor.bootServiceModule(create, this ,
201: LanguageFactory.MODULE, allParams);
202:
203: bootResourceAdapter(create, startParams);
204:
205: // may also want to set up a check that we are a singleton,
206: // or that there isn't already a database object in the system
207: // for the same database?
208:
209: //
210: // We boot the authentication service. There should at least be one
211: // per database (even if authentication is turned off) .
212: //
213: authenticationService = bootAuthenticationService(create,
214: allParams);
215: if (SanityManager.DEBUG) {
216: SanityManager
217: .ASSERT(authenticationService != null,
218: "Failed to set the Authentication service for the database");
219: }
220:
221: // Lastly, let store knows that database creation is done and turn
222: // on logging
223: if (create
224: && lastToBoot
225: && (startParams
226: .getProperty(Property.CREATE_WITH_NO_LOG) != null)) {
227: createFinished();
228: }
229:
230: active = true;
231:
232: if (lastToBoot)
233: allParams = null; // should not be used anymore
234: }
235:
236: public void stop() {
237: active = false;
238: }
239:
240: /*
241: ** Methods related to ModuleControl
242: */
243:
244: /*
245: * Database interface
246: */
247:
248: /**
249: * @return one of the values from EngineType.java:
250: *
251: */
252: public int getEngineType() {
253: return org.apache.derby.iapi.reference.EngineType.NONE;
254: }
255:
256: public boolean isReadOnly() {
257: //
258: //Notice if no full users?
259: //RESOLVE: (Make access factory check?)
260: return af.isReadOnly();
261: }
262:
263: public LanguageConnectionContext setupConnection(ContextManager cm,
264: String user, String drdaID, String dbname)
265: throws StandardException {
266:
267: TransactionController tc = getConnectionTransaction(cm);
268:
269: cm.setLocaleFinder(this );
270: pushDbContext(cm);
271:
272: // push a database shutdown context
273: // we also need to push a language connection context.
274: LanguageConnectionContext lctx = lcf
275: .newLanguageConnectionContext(cm, tc, lf, this , user,
276: drdaID, dbname);
277:
278: // push the context that defines our class factory
279: pushClassFactoryContext(cm, lcf.getClassFactory());
280:
281: // we also need to push an execution context.
282: ExecutionFactory ef = lcf.getExecutionFactory();
283:
284: ef.newExecutionContext(cm);
285: //
286: //Initialize our language connection context. Note: This is
287: //a bit of a hack. Unfortunately, we can't initialize this
288: //when we push it. We first must push a few more contexts.
289: lctx.initialize(true);
290:
291: // Need to commit this to release locks gotten in initialize.
292: // Commit it but make sure transaction not have any updates.
293: lctx
294: .internalCommitNoSync(TransactionController.RELEASE_LOCKS
295: | TransactionController.READONLY_TRANSACTION_INITIALIZATION);
296:
297: return lctx;
298:
299: }
300:
301: public void pushDbContext(ContextManager cm) {
302: /* We cache the locale in the DatabaseContext
303: * so that the Datatypes can get to it easily.
304: */
305: DatabaseContext dc = new DatabaseContextImpl(cm, this );
306: }
307:
308: public final AuthenticationService getAuthenticationService() {
309:
310: // Expected to find one - Sanity check being done at
311: // DB boot-up.
312:
313: // We should have a Authentication Service
314: //
315: if (SanityManager.DEBUG) {
316: SanityManager
317: .ASSERT(this .authenticationService != null,
318: "Unexpected - There is no valid authentication service for the database!");
319: }
320: return this .authenticationService;
321: }
322:
323: public void freeze() throws SQLException {
324: try {
325: af.freeze();
326: } catch (StandardException se) {
327: throw PublicAPI.wrapStandardException(se);
328: }
329: }
330:
331: public void unfreeze() throws SQLException {
332: try {
333: af.unfreeze();
334: } catch (StandardException se) {
335: throw PublicAPI.wrapStandardException(se);
336: }
337: }
338:
339: public void backup(String backupDir, boolean wait)
340: throws SQLException {
341: try {
342: af.backup(backupDir, wait);
343: } catch (StandardException se) {
344: throw PublicAPI.wrapStandardException(se);
345: }
346: }
347:
348: public void backupAndEnableLogArchiveMode(String backupDir,
349: boolean deleteOnlineArchivedLogFiles, boolean wait)
350: throws SQLException {
351: try {
352: af.backupAndEnableLogArchiveMode(backupDir,
353: deleteOnlineArchivedLogFiles, wait);
354: } catch (StandardException se) {
355: throw PublicAPI.wrapStandardException(se);
356: }
357: }
358:
359: public void disableLogArchiveMode(
360: boolean deleteOnlineArchivedLogFiles) throws SQLException {
361: try {
362: af.disableLogArchiveMode(deleteOnlineArchivedLogFiles);
363: } catch (StandardException se) {
364: throw PublicAPI.wrapStandardException(se);
365: }
366: }
367:
368: public void checkpoint() throws SQLException {
369: try {
370: af.checkpoint();
371: } catch (StandardException se) {
372: throw PublicAPI.wrapStandardException(se);
373: }
374: }
375:
376: /* Methods from org.apache.derby.database.Database */
377: public Locale getLocale() {
378: return databaseLocale;
379: }
380:
381: /**
382: Return the UUID of this database.
383: */
384: public final UUID getId() {
385: return myUUID;
386: }
387:
388: /* LocaleFinder methods */
389:
390: /** @exception StandardException Thrown on error */
391: public Locale getCurrentLocale() throws StandardException {
392: if (databaseLocale != null)
393: return databaseLocale;
394: throw noLocale();
395: }
396:
397: /** @exception StandardException Thrown on error */
398: public RuleBasedCollator getCollator() throws StandardException {
399: RuleBasedCollator retval = ruleBasedCollator;
400:
401: if (retval == null) {
402: if (databaseLocale != null) {
403: retval = ruleBasedCollator = (RuleBasedCollator) Collator
404: .getInstance(databaseLocale);
405: } else {
406: throw noLocale();
407: }
408: }
409:
410: return retval;
411: }
412:
413: /** @exception StandardException Thrown on error */
414: public DateFormat getDateFormat() throws StandardException {
415: if (databaseLocale != null) {
416: if (dateFormat == null) {
417: dateFormat = DateFormat.getDateInstance(
418: DateFormat.LONG, databaseLocale);
419: }
420:
421: return dateFormat;
422: }
423:
424: throw noLocale();
425: }
426:
427: /** @exception StandardException Thrown on error */
428: public DateFormat getTimeFormat() throws StandardException {
429: if (databaseLocale != null) {
430: if (timeFormat == null) {
431: timeFormat = DateFormat.getTimeInstance(
432: DateFormat.LONG, databaseLocale);
433: }
434:
435: return timeFormat;
436: }
437:
438: throw noLocale();
439: }
440:
441: /** @exception StandardException Thrown on error */
442: public DateFormat getTimestampFormat() throws StandardException {
443: if (databaseLocale != null) {
444: if (timestampFormat == null) {
445: timestampFormat = DateFormat.getDateTimeInstance(
446: DateFormat.LONG, DateFormat.LONG,
447: databaseLocale);
448: }
449:
450: return timestampFormat;
451: }
452:
453: throw noLocale();
454: }
455:
456: private static StandardException noLocale() {
457: return StandardException.newException(SQLState.NO_LOCALE);
458: }
459:
460: public void setLocale(Locale locale) {
461: databaseLocale = locale;
462:
463: dateFormat = null;
464: timeFormat = null;
465: timestampFormat = null;
466: }
467:
468: /**
469: Is the database active (open).
470: */
471: public boolean isActive() {
472: return active;
473: }
474:
475: /*
476: * class interface
477: */
478: public BasicDatabase() {
479: lastToBoot = true;
480: }
481:
482: protected UUID makeDatabaseID(boolean create, Properties startParams)
483: throws StandardException {
484:
485: TransactionController tc = af.getTransaction(ContextService
486: .getFactory().getCurrentContextManager());
487:
488: String upgradeID = null;
489: UUID databaseID;
490:
491: if ((databaseID = (UUID) tc
492: .getProperty(DataDictionary.DATABASE_ID)) == null) {
493:
494: // no property defined in the Transaction set
495: // this could be an upgrade, see if it's stored in the service set
496:
497: UUIDFactory uuidFactory = Monitor.getMonitor()
498: .getUUIDFactory();
499:
500: upgradeID = startParams
501: .getProperty(DataDictionary.DATABASE_ID);
502: if (upgradeID == null) {
503: // just create one
504: databaseID = uuidFactory.createUUID();
505: } else {
506: databaseID = uuidFactory.recreateUUID(upgradeID);
507: }
508:
509: tc
510: .setProperty(DataDictionary.DATABASE_ID,
511: databaseID, true);
512: }
513:
514: // Remove the database identifier from the service.properties
515: // file only if we upgraded it to be stored in the transactional
516: // property set.
517: if (upgradeID != null)
518: startParams.remove(DataDictionary.DATABASE_ID);
519:
520: tc.commit();
521: tc.destroy();
522:
523: return databaseID;
524: }
525:
526: /**
527: * Drop all Stored Prepared Statements that
528: * have been created for JDBC MetaData queries.
529: * Does NOT commit the current transaction
530: * upon completation.
531: *
532: * @exception SQLException on error, most likely
533: * a deadlock or timeout.
534: */
535: public void dropAllJDBCMetaDataSPSes() throws SQLException {
536: try {
537: LanguageConnectionContext lcc = ConnectionUtil
538: .getCurrentLCC();
539:
540: DataDictionary dd = lcc.getDataDictionary();
541:
542: TransactionController tc = lcc.getTransactionExecute();
543:
544: /*
545: ** Inform the data dictionary we are going
546: ** to perform some DDL
547: */
548: dd.startWriting(lcc);
549:
550: for (java.util.ListIterator li = dd.getAllSPSDescriptors()
551: .listIterator(); li.hasNext();) {
552: SPSDescriptor spsd = (SPSDescriptor) li.next();
553:
554: /*
555: ** Is it in SYS? if so, zap it. Can't drop metadata SPS in SYSIBM, JCC depends on it.
556: */
557: if (spsd.getSchemaDescriptor().isSystemSchema()
558: && !spsd.getSchemaDescriptor().isSYSIBM()) {
559: dd.dropSPSDescriptor(spsd, tc);
560: dd.dropDependentsStoredDependencies(spsd.getUUID(),
561: tc);
562: }
563: }
564: } catch (StandardException se) {
565: throw PublicAPI.wrapStandardException(se);
566: }
567: }
568:
569: /*
570: ** Return an Object instead of a ResourceAdapter
571: ** so that XA classes are only used where needed;
572: ** caller must cast to ResourceAdapter.
573: */
574: public Object getResourceAdapter() {
575: return resourceAdapter;
576: }
577:
578: /*
579: ** Methods of PropertySetCallback
580: */
581: public void init(boolean dbOnly, Dictionary p) {
582: // not called yet ...
583: }
584:
585: /**
586: @see PropertySetCallback#validate
587: @exception StandardException Thrown on error.
588: */
589: public boolean validate(String key, Serializable value, Dictionary p)
590: throws StandardException {
591: //
592: //Disallow setting static creation time only configuration properties
593: if (key.equals(EngineType.PROPERTY))
594: throw StandardException.newException(
595: SQLState.PROPERTY_UNSUPPORTED_CHANGE, key, value);
596:
597: // only interested in the classpath
598: if (!key.equals(Property.DATABASE_CLASSPATH))
599: return false;
600:
601: String newClasspath = (String) value;
602: String[][] dbcp = null; //The parsed dbclasspath
603:
604: if (newClasspath != null) {
605: // parse it when it is set to ensure only valid values
606: // are written to the actual conglomerate.
607: dbcp = IdUtil.parseDbClassPath(newClasspath,
608: normalizeToUpper);
609: }
610:
611: DataDictionaryContext ddc = (DataDictionaryContext) ContextService
612: .getContext(DataDictionaryContext.CONTEXT_ID);
613: if (SanityManager.DEBUG)
614: if (ddc == null)
615: SanityManager
616: .THROWASSERT("Class path change with no connection");
617: DataDictionary dd = ddc.getDataDictionary();
618:
619: //
620: //Verify that all jar files on the database classpath are in the data dictionary.
621: if (dbcp != null) {
622: for (int ix = 0; ix < dbcp.length; ix++) {
623: SchemaDescriptor sd = dd.getSchemaDescriptor(
624: dbcp[ix][IdUtil.DBCP_SCHEMA_NAME], null, false);
625:
626: FileInfoDescriptor fid = null;
627: if (sd != null)
628: fid = dd.getFileInfoDescriptor(sd,
629: dbcp[ix][IdUtil.DBCP_SQL_JAR_NAME]);
630:
631: if (fid == null) {
632: throw StandardException
633: .newException(
634: SQLState.LANG_DB_CLASS_PATH_HAS_MISSING_JAR,
635: IdUtil.mkQualifiedName(dbcp[ix]));
636: }
637: }
638: }
639:
640: return true;
641: }
642:
643: /**
644: @see PropertySetCallback#apply
645: @exception StandardException Thrown on error.
646: */
647: public Serviceable apply(String key, Serializable value,
648: Dictionary p) throws StandardException {
649: // only interested in the classpath
650: if (!key.equals(Property.DATABASE_CLASSPATH))
651: return null;
652:
653: // only do the change dynamically if we are already
654: // a per-database classapath.
655: if (cfDB != null) {
656: DataDictionaryContext ddc = (DataDictionaryContext) ContextService
657: .getContext(DataDictionaryContext.CONTEXT_ID);
658: if (SanityManager.DEBUG)
659: if (ddc == null)
660: SanityManager
661: .THROWASSERT("Class path change with no connection");
662: DataDictionary dd = ddc.getDataDictionary();
663:
664: //
665: // Invalidate stored plans.
666: dd.invalidateAllSPSPlans();
667:
668: String newClasspath = (String) value;
669: if (newClasspath == null)
670: newClasspath = "";
671: cfDB.notifyModifyClasspath(newClasspath);
672: }
673: return null;
674: }
675:
676: /**
677: @see PropertySetCallback#map
678: */
679: public Serializable map(String key, Serializable value, Dictionary p) {
680: return null;
681: }
682:
683: /*
684: * methods specific to this class
685: */
686: protected void createFinished() throws StandardException {
687: // find the access factory and tell it that database creation has
688: // finished
689: af.createFinished();
690: }
691:
692: protected String getClasspath(Properties startParams) {
693: String cp = PropertyUtil.getPropertyFromSet(startParams,
694: Property.DATABASE_CLASSPATH);
695: if (cp == null)
696: cp = PropertyUtil.getSystemProperty(
697: Property.DATABASE_CLASSPATH, "");
698: return cp;
699: }
700:
701: protected void bootClassFactory(boolean create,
702: Properties startParams) throws StandardException {
703: String classpath = getClasspath(startParams);
704:
705: // parse the class path and allow 2 part names.
706: boolean normalizeToUpper = true;
707: String[][] elements = IdUtil.parseDbClassPath(classpath,
708: normalizeToUpper);
709:
710: startParams.put(Property.BOOT_DB_CLASSPATH, classpath);
711: cfDB = (ClassFactory) Monitor.bootServiceModule(create, this ,
712: org.apache.derby.iapi.reference.Module.ClassFactory,
713: startParams);
714: }
715:
716: /*
717: ** Methods to allow sub-classes to offer alternate implementations.
718: */
719:
720: protected TransactionController getConnectionTransaction(
721: ContextManager cm) throws StandardException {
722:
723: // start a local transaction
724: return af.getTransaction(cm);
725: }
726:
727: protected AuthenticationService bootAuthenticationService(
728: boolean create, Properties props) throws StandardException {
729: return (AuthenticationService) Monitor.bootServiceModule(
730: create, this , AuthenticationService.MODULE, props);
731: }
732:
733: protected void bootValidation(boolean create, Properties startParams)
734: throws StandardException {
735: pf = (PropertyFactory) Monitor.bootServiceModule(create, this ,
736: org.apache.derby.iapi.reference.Module.PropertyFactory,
737: startParams);
738: }
739:
740: protected void bootStore(boolean create, Properties startParams)
741: throws StandardException {
742: af = (AccessFactory) Monitor.bootServiceModule(create, this ,
743: AccessFactory.MODULE, startParams);
744: }
745:
746: protected Properties getAllDatabaseProperties()
747: throws StandardException {
748:
749: TransactionController tc = af.getTransaction(ContextService
750: .getFactory().getCurrentContextManager());
751: Properties dbProps = tc.getProperties();
752: tc.commit();
753: tc.destroy();
754:
755: return dbProps;
756: }
757:
758: protected void bootResourceAdapter(boolean create,
759: Properties startParams) {
760:
761: // Boot resource adapter - only if we are running Java 2 or
762: // beyondwith JDBC20 extension, JTA and JNDI classes in the classpath
763: //
764: // assume if it doesn't boot it was because the required
765: // classes were missing, and continue without it.
766: // Done this way to work around Chai's need to preload
767: // classes.
768: // Assume both of these classes are in the class path.
769: // Assume we may need a ResourceAdapter since we don't know how
770: // this database is going to be used.
771: try {
772: resourceAdapter = Monitor
773: .bootServiceModule(
774: create,
775: this ,
776: org.apache.derby.iapi.reference.Module.ResourceAdapter,
777: allParams);
778: } catch (StandardException mse) {
779: // OK, resourceAdapter is an optional module
780: }
781: }
782:
783: protected void pushClassFactoryContext(ContextManager cm,
784: ClassFactory cf) {
785: new StoreClassFactoryContext(cm, cf, af, this );
786: }
787:
788: /*
789: ** Methods of JarReader
790: */
791: public Object readJarFile(String schemaName, String sqlName)
792: throws StandardException {
793:
794: DataDictionaryContext ddc = (DataDictionaryContext) ContextService
795: .getContext(DataDictionaryContext.CONTEXT_ID);
796: DataDictionary dd = ddc.getDataDictionary();
797:
798: SchemaDescriptor sd = dd.getSchemaDescriptor(schemaName, null,
799: true);
800: FileInfoDescriptor fid = dd.getFileInfoDescriptor(sd, sqlName);
801: if (fid == null)
802: throw StandardException.newException(
803: SQLState.LANG_FILE_DOES_NOT_EXIST, sqlName,
804: schemaName);
805:
806: long generationId = fid.getGenerationId();
807:
808: FileResource fr = af.getTransaction(ddc.getContextManager())
809: .getFileHandler();
810:
811: String externalName = org.apache.derby.impl.sql.execute.JarDDL
812: .mkExternalName(schemaName, sqlName, fr
813: .getSeparatorChar());
814:
815: Object f = fr.getAsFile(externalName, generationId);
816: if (f instanceof java.io.File)
817: return f;
818:
819: try {
820: return fr.getAsStream(externalName, generationId);
821: } catch (java.io.IOException ioe) {
822: throw StandardException.newException(
823: SQLState.LANG_FILE_ERROR, ioe, ioe.toString());
824: }
825: }
826:
827: }
|