0001: /*
0002:
0003: Derby - Class org.apache.derby.impl.services.monitor.BaseMonitor
0004:
0005: Licensed to the Apache Software Foundation (ASF) under one or more
0006: contributor license agreements. See the NOTICE file distributed with
0007: this work for additional information regarding copyright ownership.
0008: The ASF licenses this file to you under the Apache License, Version 2.0
0009: (the "License"); you may not use this file except in compliance with
0010: the License. You may obtain a copy of the License at
0011:
0012: http://www.apache.org/licenses/LICENSE-2.0
0013:
0014: Unless required by applicable law or agreed to in writing, software
0015: distributed under the License is distributed on an "AS IS" BASIS,
0016: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0017: See the License for the specific language governing permissions and
0018: limitations under the License.
0019:
0020: */
0021:
0022: package org.apache.derby.impl.services.monitor;
0023:
0024: import org.apache.derby.iapi.services.monitor.Monitor;
0025: import org.apache.derby.iapi.services.monitor.ModuleFactory;
0026: import org.apache.derby.iapi.services.monitor.ModuleControl;
0027: import org.apache.derby.iapi.services.monitor.ModuleSupportable;
0028:
0029: import org.apache.derby.iapi.services.monitor.PersistentService;
0030:
0031: import org.apache.derby.iapi.services.io.FormatIdUtil;
0032: import org.apache.derby.iapi.services.io.RegisteredFormatIds;
0033: import org.apache.derby.iapi.services.io.StoredFormatIds;
0034:
0035: import org.apache.derby.iapi.services.context.ContextManager;
0036: import org.apache.derby.iapi.services.context.Context;
0037: import org.apache.derby.iapi.services.context.ContextService;
0038: import org.apache.derby.iapi.services.context.ShutdownException;
0039:
0040: import org.apache.derby.iapi.services.stream.InfoStreams;
0041: import org.apache.derby.iapi.services.stream.PrintWriterGetHeader;
0042:
0043: import org.apache.derby.iapi.services.sanity.SanityManager;
0044: import org.apache.derby.iapi.error.StandardException;
0045: import org.apache.derby.iapi.services.uuid.UUIDFactory;
0046: import org.apache.derby.iapi.services.timer.TimerFactory;
0047: import org.apache.derby.iapi.reference.Property;
0048: import org.apache.derby.iapi.reference.SQLState;
0049: import org.apache.derby.iapi.reference.Attribute;
0050: import org.apache.derby.iapi.services.property.PropertyUtil;
0051:
0052: import org.apache.derby.iapi.services.io.AccessibleByteArrayOutputStream;
0053: import org.apache.derby.iapi.services.loader.ClassInfo;
0054: import org.apache.derby.iapi.services.loader.InstanceGetter;
0055: import org.apache.derby.iapi.services.io.FormatableInstanceGetter;
0056: import org.apache.derby.iapi.error.ExceptionSeverity;
0057:
0058: import org.apache.derby.io.StorageFactory;
0059:
0060: import org.apache.derby.iapi.services.context.ErrorStringBuilder;
0061:
0062: import org.apache.derby.iapi.services.info.JVMInfo;
0063: import org.apache.derby.iapi.services.i18n.BundleFinder;
0064: import org.apache.derby.iapi.services.i18n.MessageService;
0065:
0066: import org.apache.derby.impl.services.monitor.StorageFactoryService;
0067:
0068: import java.io.IOException;
0069: import java.io.InputStream;
0070: import java.io.StringWriter;
0071: import java.io.BufferedInputStream;
0072: import java.io.PrintWriter;
0073: import java.io.BufferedReader;
0074: import java.io.InputStreamReader;
0075: import java.io.ByteArrayInputStream;
0076: import java.io.PrintStream;
0077:
0078: import java.util.Hashtable;
0079: import java.util.HashMap;
0080: import java.util.Properties;
0081: import java.util.Enumeration;
0082: import java.util.StringTokenizer;
0083: import java.util.Vector;
0084: import java.util.Locale;
0085: import java.util.ResourceBundle;
0086: import java.util.NoSuchElementException;
0087:
0088: import java.lang.reflect.Method;
0089: import java.lang.reflect.Modifier;
0090: import java.lang.reflect.InvocationTargetException;
0091:
0092: import java.security.AccessController;
0093: import java.security.PrivilegedExceptionAction;
0094: import java.security.PrivilegedActionException;
0095:
0096: import java.net.URL;
0097:
0098: /**
0099: Implementation of the monitor that uses the class loader
0100: that the its was loaded in for all class loading.
0101:
0102: */
0103:
0104: abstract class BaseMonitor implements ModuleFactory, BundleFinder {
0105:
0106: /* Fields */
0107:
0108: /**
0109: Hashtable of objects that implement PersistentService keyed by their getType() method.
0110: */
0111: Hashtable serviceProviders;
0112:
0113: // Vector of class objects of implementations, found in the System, application
0114: // and default (modules.properties) properties
0115:
0116: Vector[] implementationSets;
0117:
0118: private Vector services; // Vector of TopServices
0119:
0120: Properties bootProperties; // specifc properties provided by the boot method, override everything else
0121: Properties applicationProperties;
0122:
0123: boolean inShutdown;
0124:
0125: // Here are the list of modules that we always boot
0126: private InfoStreams systemStreams;
0127: private ContextService contextService;
0128: private UUIDFactory uuidFactory;
0129: private TimerFactory timerFactory;
0130:
0131: boolean reportOn;
0132: private PrintStream logging;
0133:
0134: ThreadGroup daemonGroup;
0135:
0136: // anti GC stuff
0137: AntiGC dontGC;
0138:
0139: // class registry
0140: /* one byte format identifiers never used
0141: private InstanceGetter[] rc1;
0142: */
0143: private InstanceGetter[] rc2;
0144:
0145: // private InstanceGetter[] rc4;
0146:
0147: /* Constructor */
0148: BaseMonitor() {
0149: super ();
0150:
0151: services = new Vector(0, 1);
0152: services.addElement(new TopService(this )); // first element is always the free-floating service
0153: }
0154:
0155: /* Methods of ModuleFactory includes BootStrap and Runnable */
0156:
0157: public InfoStreams getSystemStreams() {
0158: return systemStreams;
0159: }
0160:
0161: public void shutdown() {
0162:
0163: // allow only one caller to shut the monitor down
0164: synchronized (this ) {
0165: if (inShutdown)
0166: return;
0167: inShutdown = true;
0168: }
0169:
0170: if (SanityManager.DEBUG && reportOn) {
0171: report("Shutdown request");
0172: }
0173:
0174: // Shutdown all threads by iterrupting them
0175: contextService.notifyAllActiveThreads((Context) null);
0176:
0177: for (;;) {
0178:
0179: TopService ts;
0180: int position;
0181: synchronized (this ) {
0182: position = services.size() - 1;
0183: if (position == 0)
0184: break;
0185:
0186: ts = (TopService) services.elementAt(position);
0187: }
0188:
0189: // push a new context manager
0190: ContextManager cm = contextService.newContextManager();
0191: try {
0192: // pop the default shutdown context, we are shutting down
0193: cm.popContext();
0194:
0195: contextService.setCurrentContextManager(cm);
0196:
0197: shutdown(ts.getService());
0198:
0199: } finally {
0200: contextService.resetCurrentContextManager(cm);
0201: }
0202:
0203: }
0204: ((TopService) services.elementAt(0)).shutdown();
0205:
0206: synchronized (dontGC) {
0207:
0208: dontGC.goAway = true;
0209: dontGC.notifyAll();
0210: }
0211:
0212: ContextService.stop();
0213: Monitor.clearMonitor();
0214: }
0215:
0216: /**
0217: Shut down a service that was started by this Monitor. Will
0218: cause the stop() method to be called on each loaded module.
0219: */
0220: public void shutdown(Object serviceModule) {
0221: if (serviceModule == null)
0222: return;
0223:
0224: TopService ts = findTopService(serviceModule);
0225: if (ts == null)
0226: return;
0227:
0228: // shutdown() returns false if the service is already being shutdown
0229: boolean removeService = true;
0230: try {
0231: removeService = ts.shutdown();
0232: } finally {
0233: synchronized (this ) {
0234: if (removeService) {
0235: boolean found = services.removeElement(ts);
0236: if (SanityManager.DEBUG) {
0237: SanityManager.ASSERT(found,
0238: "service was not found "
0239: + serviceModule);
0240: }
0241: }
0242: }
0243: }
0244: }
0245:
0246: protected final void runWithState(Properties properties,
0247: PrintStream log) {
0248:
0249: bootProperties = properties;
0250: logging = log;
0251:
0252: // false indicates the full monitor is required, not the lite.
0253: if (!initialize(false))
0254: return;
0255:
0256: // if monitor is already set then the system is already
0257: // booted or in the process of booting or shutting down.
0258: if (!Monitor.setMonitor(this ))
0259: return;
0260:
0261: Object msgService = MessageService.setFinder(this );
0262:
0263: // start a backgorund thread which keeps a reference to this
0264: // this monitor, and an instance of the Monitor class to ensure
0265: // that the monitor instance and the class is not garbage collected
0266: // See Sun's bug 4057924 in Java Developer Section 97/08/06
0267:
0268: Object[] keepItems = new Object[3];
0269: keepItems[0] = this ;
0270: keepItems[1] = new Monitor();
0271: keepItems[2] = msgService;
0272: dontGC = new AntiGC(keepItems);
0273:
0274: Thread dontGCthread = getDaemonThread(dontGC, "antiGC", true);
0275: dontGCthread.start();
0276:
0277: if (SanityManager.DEBUG) {
0278: reportOn = Boolean
0279: .valueOf(
0280: PropertyUtil
0281: .getSystemProperty("derby.monitor.verbose"))
0282: .booleanValue();
0283: }
0284:
0285: // Set up the application properties
0286: applicationProperties = readApplicationProperties();
0287:
0288: // The security manager may not let us get the System properties
0289: // object itself, although it may let us look at the properties in it.
0290: Properties systemProperties = null;
0291:
0292: if (SanityManager.DEBUG) {
0293: // In a production system having this call would
0294: // mean would we have to document it for security
0295: // permission reasons. Since we don't require it and
0296: // its a big security hole to allow external code to
0297: // overwrite our own implementations we just support
0298: // it for debugging. This means VM executions such as
0299: // java -Dderby.module.javaCompiler=com.ibm.db2j.impl.BasicServices.JavaCompiler.JavaLang.JLJava ...
0300: // would only work with a sane codeline.
0301: try {
0302: systemProperties = System.getProperties();
0303: } catch (SecurityException se) {
0304: }
0305: }
0306:
0307: Vector bootImplementations = getImplementations(bootProperties,
0308: false);
0309:
0310: Vector systemImplementations = null;
0311: Vector applicationImplementations = null;
0312:
0313: // TEMP - making this sanity only breaks the unit test code
0314: // I will fix soon, djd.
0315: if (true || SanityManager.DEBUG) {
0316: // Don't allow external code to override our implementations.
0317: systemImplementations = getImplementations(
0318: systemProperties, false);
0319: applicationImplementations = getImplementations(
0320: applicationProperties, false);
0321: }
0322:
0323: Vector defaultImplementations = getDefaultImplementations();
0324:
0325: int implementationCount = 0;
0326: if (bootImplementations != null)
0327: implementationCount++;
0328:
0329: // TEMP - making this sanity only breaks the unit test code
0330: if (true || SanityManager.DEBUG) {
0331: // Don't allow external code to override our implementations.
0332: if (systemImplementations != null)
0333: implementationCount++;
0334: if (applicationImplementations != null)
0335: implementationCount++;
0336: }
0337:
0338: if (defaultImplementations != null)
0339: implementationCount++;
0340: implementationSets = new Vector[implementationCount];
0341:
0342: implementationCount = 0;
0343: if (bootImplementations != null)
0344: implementationSets[implementationCount++] = bootImplementations;
0345:
0346: if (true || SanityManager.DEBUG) {
0347: // Don't allow external code to override our implementations.
0348: if (systemImplementations != null)
0349: implementationSets[implementationCount++] = systemImplementations;
0350: if (applicationImplementations != null)
0351: implementationSets[implementationCount++] = applicationImplementations;
0352: }
0353:
0354: if (defaultImplementations != null)
0355: implementationSets[implementationCount++] = defaultImplementations;
0356:
0357: if (SanityManager.DEBUG) {
0358: // Look for the derby.debug.* properties.
0359: if (applicationProperties != null) {
0360: addDebugFlags(applicationProperties
0361: .getProperty(Monitor.DEBUG_FALSE), false);
0362: addDebugFlags(applicationProperties
0363: .getProperty(Monitor.DEBUG_TRUE), true);
0364: }
0365:
0366: addDebugFlags(PropertyUtil
0367: .getSystemProperty(Monitor.DEBUG_FALSE), false);
0368: addDebugFlags(PropertyUtil
0369: .getSystemProperty(Monitor.DEBUG_TRUE), true);
0370: }
0371:
0372: try {
0373: systemStreams = (InfoStreams) Monitor
0374: .startSystemModule("org.apache.derby.iapi.services.stream.InfoStreams");
0375:
0376: if (SanityManager.DEBUG) {
0377: SanityManager.SET_DEBUG_STREAM(systemStreams.stream()
0378: .getPrintWriter());
0379: }
0380:
0381: contextService = new ContextService();
0382:
0383: uuidFactory = (UUIDFactory) Monitor
0384: .startSystemModule("org.apache.derby.iapi.services.uuid.UUIDFactory");
0385:
0386: timerFactory = (TimerFactory) Monitor
0387: .startSystemModule("org.apache.derby.iapi.services.timer.TimerFactory");
0388: } catch (StandardException se) {
0389:
0390: // if we can't create an error log or a context then there's no point going on
0391: reportException(se);
0392: // dump any messages we have been saving ...
0393: dumpTempWriter(true);
0394:
0395: return;
0396: }
0397:
0398: // switch cover to the real error stream and
0399: // dump any messages we have been saving ...
0400: dumpTempWriter(false);
0401:
0402: if (SanityManager.DEBUG && reportOn) {
0403: dumpProperties("-- Boot Properties --", bootProperties);
0404: dumpProperties("-- System Properties --", systemProperties);
0405: dumpProperties("-- Application Properties --",
0406: applicationProperties);
0407: }
0408:
0409: // bootup all the service providers
0410: bootServiceProviders();
0411:
0412: // See if automatic booting of persistent services is required
0413: boolean bootAll = Boolean.valueOf(
0414: PropertyUtil.getSystemProperty(Property.BOOT_ALL))
0415: .booleanValue();
0416:
0417: startServices(bootProperties, bootAll);
0418: startServices(systemProperties, bootAll);
0419: startServices(applicationProperties, bootAll);
0420:
0421: if (bootAll) // only if automatic booting is required
0422: bootPersistentServices();
0423: }
0424:
0425: public Object findService(String factoryInterface,
0426: String serviceName) {
0427:
0428: if (serviceName == null)
0429: return null;
0430:
0431: ProtocolKey key;
0432:
0433: try {
0434: key = ProtocolKey.create(factoryInterface, serviceName);
0435: } catch (StandardException se) {
0436: return null;
0437: }
0438:
0439: TopService myts = null;
0440: synchronized (this ) {
0441: for (int i = 1; i < services.size(); i++) {
0442: TopService ts = (TopService) services.elementAt(i);
0443: if (ts.isPotentialService(key)) {
0444: myts = ts;
0445: break;
0446: }
0447: }
0448: }
0449:
0450: // the isActiveService() call may sleep
0451: // so don't hold the 'this' synchronization
0452: if (myts != null) {
0453: if (myts.isActiveService(key))
0454: return myts.getService();
0455: }
0456:
0457: return null;
0458: }
0459:
0460: public Locale getLocale(Object serviceModule) {
0461:
0462: TopService ts = findTopService(serviceModule);
0463:
0464: if (ts == null)
0465: return null;
0466:
0467: return ts.serviceLocale;
0468:
0469: }
0470:
0471: public Locale getLocaleFromString(String localeDescription)
0472: throws StandardException {
0473: return staticGetLocaleFromString(localeDescription);
0474: }
0475:
0476: /**
0477: Return the name of the service that the passed in module lives in.
0478: */
0479: public String getServiceName(Object serviceModule) {
0480:
0481: TopService ts = findTopService(serviceModule);
0482:
0483: if (ts == null)
0484: return null;
0485:
0486: return ts.getServiceType().getUserServiceName(
0487: ts.getKey().getIdentifier());
0488: }
0489:
0490: /**
0491: Set the locale for the service *outside* of boot time.
0492:
0493: @exception StandardException Standard Cloudscape error.
0494: */
0495: public Locale setLocale(Object serviceModule,
0496: String userDefinedLocale) throws StandardException {
0497:
0498: TopService ts = findTopService(serviceModule);
0499:
0500: if (ts == null)
0501: return null;
0502:
0503: PersistentService provider = ts.getServiceType();
0504: if (provider == null)
0505: return null;
0506:
0507: String serviceName = ts.getKey().getIdentifier();
0508:
0509: Properties properties = provider.getServiceProperties(
0510: serviceName, (Properties) null);
0511:
0512: properties = new UpdateServiceProperties(provider, serviceName,
0513: properties, true);
0514:
0515: return setLocale(properties, userDefinedLocale);
0516:
0517: }
0518:
0519: /**
0520: Set the locale for the service at boot time. The passed in
0521: properties must be the one passed to the boot method.
0522:
0523: @exception StandardException Standard Cloudscape error.
0524: */
0525: public Locale setLocale(Properties serviceProperties,
0526: String userDefinedLocale) throws StandardException {
0527:
0528: Locale locale = staticGetLocaleFromString(userDefinedLocale);
0529:
0530: // this will write the property through to the service.properties file.
0531: serviceProperties.put(Property.SERVICE_LOCALE, locale
0532: .toString());
0533:
0534: return locale;
0535: }
0536:
0537: /**
0538: Return the PersistentService object for a service.
0539: Will return null if the service does not exist.
0540: */
0541: public PersistentService getServiceType(Object serviceModule) {
0542: TopService ts = findTopService(serviceModule);
0543:
0544: if (ts == null)
0545: return null;
0546:
0547: return ts.getServiceType();
0548: }
0549:
0550: /**
0551: Start a module.
0552:
0553: @exception StandardException se An attempt to start the module failed.
0554:
0555: @see ModuleFactory#startModule
0556: */
0557: public Object startModule(boolean create, Object serviceModule,
0558: String factoryInterface, String identifier,
0559: Properties properties) throws StandardException {
0560:
0561: ProtocolKey key = ProtocolKey.create(factoryInterface,
0562: identifier);
0563:
0564: TopService ts = findTopService(serviceModule);
0565:
0566: Object instance = ts.bootModule(create, serviceModule, key,
0567: properties);
0568:
0569: if (instance == null)
0570: throw Monitor.missingImplementation(factoryInterface);
0571:
0572: return instance;
0573: }
0574:
0575: private synchronized TopService findTopService(Object serviceModule) {
0576:
0577: if (serviceModule == null)
0578: return (TopService) services.elementAt(0);
0579:
0580: for (int i = 1; i < services.size(); i++) {
0581: TopService ts = (TopService) services.elementAt(i);
0582: if (ts.inService(serviceModule))
0583: return ts;
0584: }
0585:
0586: return null;
0587: }
0588:
0589: public Object findModule(Object serviceModule,
0590: String factoryInterface, String identifier) {
0591:
0592: ProtocolKey key;
0593:
0594: try {
0595: key = ProtocolKey.create(factoryInterface, identifier);
0596: } catch (StandardException se) {
0597: return null;
0598: }
0599:
0600: TopService ts = findTopService(serviceModule);
0601: if (ts == null)
0602: return null;
0603:
0604: return ts.findModule(key, true, null);
0605: }
0606:
0607: /**
0608: Obtain a class that supports the given identifier.
0609:
0610: @param fmtId identifer to associate with class
0611:
0612: @return a reference InstanceGetter
0613:
0614: @exception StandardException See Monitor.classFromIdentifier
0615:
0616: @see ModuleFactory#classFromIdentifier
0617: */
0618: public InstanceGetter classFromIdentifier(int fmtId)
0619: throws StandardException {
0620:
0621: String className;
0622: int off;
0623: InstanceGetter[] iga;
0624: InstanceGetter ig;
0625:
0626: try {
0627:
0628: off = fmtId - StoredFormatIds.MIN_TWO_BYTE_FORMAT_ID;
0629: iga = rc2;
0630: if (iga == null) {
0631: iga = rc2 = new InstanceGetter[RegisteredFormatIds.TwoByte.length];
0632: }
0633:
0634: ig = iga[off];
0635: if (ig != null) {
0636: return ig;
0637: }
0638: className = RegisteredFormatIds.TwoByte[off];
0639:
0640: } catch (ArrayIndexOutOfBoundsException aioobe) {
0641: className = null;
0642: iga = null;
0643: off = 0;
0644: }
0645:
0646: if (className != null) {
0647:
0648: Throwable t;
0649: try {
0650: Class clazz = Class.forName(className);
0651:
0652: // See if it is a FormatableInstanceGetter
0653: if (FormatableInstanceGetter.class
0654: .isAssignableFrom(clazz)) {
0655: FormatableInstanceGetter tfig = (FormatableInstanceGetter) clazz
0656: .newInstance();
0657: tfig.setFormatId(fmtId);
0658: return iga[off] = tfig;
0659: }
0660:
0661: return iga[off] = new ClassInfo(clazz);
0662:
0663: } catch (ClassNotFoundException cnfe) {
0664: t = cnfe;
0665: } catch (IllegalAccessException iae) {
0666: t = iae;
0667: } catch (InstantiationException ie) {
0668: t = ie;
0669: } catch (LinkageError le) {
0670: t = le;
0671: }
0672: throw StandardException.newException(
0673: SQLState.REGISTERED_CLASS_LINAKGE_ERROR, t,
0674: FormatIdUtil.formatIdToString(fmtId), className);
0675: }
0676:
0677: throw StandardException.newException(
0678: SQLState.REGISTERED_CLASS_NONE, FormatIdUtil
0679: .formatIdToString(fmtId));
0680: }
0681:
0682: /**
0683: Obtain an new instance of a class that supports the given identifier.
0684:
0685: @return a reference to a newly created object or null if a matching class
0686: cannot be found.
0687: */
0688: public Object newInstanceFromIdentifier(int identifier)
0689: throws StandardException {
0690:
0691: InstanceGetter ci = classFromIdentifier(identifier);
0692:
0693: Throwable t;
0694: try {
0695: Object result = ci.getNewInstance();
0696: /*
0697: if (SanityManager.DEBUG) {
0698: if(SanityManager.DEBUG_ON(Monitor.NEW_INSTANCE_FROM_ID_TRACE_DEBUG_FLAG))
0699: {
0700: String traceResult = "null";
0701:
0702: if (result != null) traceResult = "not null";
0703:
0704: SanityManager.DEBUG(Monitor.NEW_INSTANCE_FROM_ID_TRACE_DEBUG_FLAG,
0705: "newInstanceFromIdentifier("+identifier+") "+
0706: " ClassName: "+
0707: result.getClass().getName() +
0708: " returned "+
0709: traceResult);
0710: }
0711: }
0712: */
0713: return result;
0714: } catch (InstantiationException ie) {
0715: t = ie;
0716: } catch (IllegalAccessException iae) {
0717: t = iae;
0718: } catch (InvocationTargetException ite) {
0719: t = ite;
0720: } catch (LinkageError le) {
0721: t = le;
0722: }
0723: throw StandardException.newException(
0724: SQLState.REGISTERED_CLASS_INSTANCE_ERROR, t,
0725: new Integer(identifier), "XX" /*ci.getClassName()*/);
0726: }
0727:
0728: private Boolean exceptionTrace;
0729:
0730: /**
0731: load a module instance.
0732:
0733: Look through the implementations for a module that implements the
0734: required factory interface and can handle the properties given.
0735:
0736: The module's start or create method is not called.
0737: */
0738:
0739: protected Object loadInstance(Class factoryInterface,
0740: Properties properties) {
0741:
0742: Object instance = null;
0743:
0744: Vector localImplementations = getImplementations(properties,
0745: false);
0746: if (localImplementations != null) {
0747: instance = loadInstance(localImplementations,
0748: factoryInterface, properties);
0749: }
0750:
0751: for (int i = 0; i < implementationSets.length; i++) {
0752: instance = loadInstance(implementationSets[i],
0753: factoryInterface, properties);
0754: if (instance != null)
0755: break;
0756: }
0757:
0758: return instance;
0759: }
0760:
0761: private Object loadInstance(Vector implementations,
0762: Class factoryInterface, Properties properties) {
0763:
0764: for (int index = 0; true; index++) {
0765:
0766: // find an implementation
0767: index = findImplementation(implementations, index,
0768: factoryInterface);
0769: if (index < 0)
0770: return null;
0771:
0772: // try to create an instance
0773: Object instance = newInstance((Class) implementations
0774: .elementAt(index));
0775:
0776: if (BaseMonitor.canSupport(instance, properties))
0777: return instance;
0778: }
0779: }
0780:
0781: /**
0782: Find a class that implements the required index, return the index
0783: into the implementations vecotr of that class. Returns -1 if no class
0784: could be found.
0785: */
0786: private static int findImplementation(Vector implementations,
0787: int startIndex, Class factoryInterface) {
0788:
0789: for (int i = startIndex; i < implementations.size(); i++) {
0790:
0791: //try {
0792: Class factoryClass = (Class) implementations.elementAt(i);
0793: if (!factoryInterface.isAssignableFrom(factoryClass)) {
0794: continue;
0795: }
0796:
0797: return i;
0798: //}
0799: //catch (ClassNotFoundException e) {
0800: // report("Class not found " + (String) implementations.elementAt(i));
0801: // continue;
0802: //}
0803: }
0804:
0805: return -1;
0806: }
0807:
0808: /**
0809: */
0810: private Object newInstance(String className) {
0811:
0812: try {
0813:
0814: Class factoryClass = Class.forName(className);
0815: return factoryClass.newInstance();
0816: } catch (ClassNotFoundException e) {
0817: report(className + " " + e.toString());
0818: } catch (InstantiationException e) {
0819: report(className + " " + e.toString());
0820: } catch (IllegalAccessException e) {
0821: report(className + " " + e.toString());
0822: } catch (LinkageError le) {
0823: report(className + " " + le.toString());
0824: reportException(le);
0825: }
0826:
0827: return null;
0828: }
0829:
0830: /**
0831: */
0832: private Object newInstance(Class classObject) {
0833:
0834: try {
0835: return classObject.newInstance();
0836: } catch (InstantiationException e) {
0837: report(classObject.getName() + " " + e.toString());
0838: } catch (IllegalAccessException e) {
0839: report(classObject.getName() + " " + e.toString());
0840: } catch (LinkageError le) {
0841: report(classObject.getName() + " " + le.toString());
0842: reportException(le);
0843: }
0844:
0845: return null;
0846: }
0847:
0848: public Properties getApplicationProperties() {
0849: return applicationProperties;
0850: }
0851:
0852: /**
0853: Return an array of the service identifiers that are running and
0854: implement the passed in protocol (java interface class name).
0855:
0856: @return The list of service names, if no services exist that
0857: implement the protocol an array with zero elements is returned.
0858:
0859: @see ModuleFactory#getServiceList
0860: */
0861: public String[] getServiceList(String protocol) {
0862:
0863: TopService ts;
0864:
0865: synchronized (this ) {
0866: int count = 0;
0867:
0868: // count the number of services that implement the required protocol
0869: for (int i = 1; i < services.size(); i++) {
0870: ts = (TopService) services.elementAt(i);
0871: if (ts.isActiveService()) {
0872: if (ts.getKey().getFactoryInterface().getName()
0873: .equals(protocol))
0874: count++;
0875: }
0876: }
0877:
0878: // and then fill in the newly allocated string array
0879: String[] list = new String[count];
0880: if (count != 0) {
0881: int j = 0;
0882: for (int i = 1; i < services.size(); i++) {
0883: ts = (TopService) services.elementAt(i);
0884: if (ts.isActiveService()) {
0885: if (ts.getKey().getFactoryInterface().getName()
0886: .equals(protocol)) {
0887: list[j++] = ts
0888: .getServiceType()
0889: .getUserServiceName(
0890: ts.getKey().getIdentifier());
0891: if (j == count)
0892: break;
0893: }
0894: }
0895: }
0896: }
0897: return list;
0898: }
0899: }
0900:
0901: /*
0902: ** non-public methods.
0903: */
0904:
0905: void dumpProperties(String title, Properties props) {
0906: if (SanityManager.DEBUG) {
0907: // this method is only called if reportOn is true, so no need to check it here
0908: report(title);
0909: if (props != null) {
0910: for (Enumeration e = props.propertyNames(); e
0911: .hasMoreElements();) {
0912: String key = (String) e.nextElement();
0913: // Get property as object in case of non-string properties
0914: report(key + "=" + props.getProperty(key));
0915: }
0916: }
0917: report("-- end --");
0918: }
0919:
0920: }
0921:
0922: /**
0923: Should only be called if reportOn is true
0924: apart from report/Exception().
0925: */
0926: protected void report(String message) {
0927:
0928: PrintWriter tpw = getTempWriter();
0929:
0930: if (tpw != null)
0931: tpw.println(message);
0932:
0933: if (systemStreams != null)
0934: systemStreams.stream().printlnWithHeader(message);
0935: }
0936:
0937: protected void reportException(Throwable t) {
0938:
0939: PrintWriterGetHeader pwgh = null;
0940: if (systemStreams != null)
0941: pwgh = systemStreams.stream().getHeader();
0942:
0943: ErrorStringBuilder esb = new ErrorStringBuilder(pwgh);
0944:
0945: esb.appendln(t.getMessage());
0946: esb.stackTrace(t);
0947:
0948: report(esb.get().toString());
0949: }
0950:
0951: private void addDebugFlags(String flags, boolean set) {
0952: if (SanityManager.DEBUG) {
0953: if (flags == null)
0954: return;
0955:
0956: StringTokenizer st = new StringTokenizer(flags, ",");
0957: for (; st.hasMoreTokens();) {
0958: String flag = st.nextToken();
0959:
0960: if (set)
0961: SanityManager.DEBUG_SET(flag);
0962: else
0963: SanityManager.DEBUG_CLEAR(flag);
0964: }
0965: }
0966: }
0967:
0968: /**
0969: Look for any services in the a properties set and the application
0970: property set and then start them.
0971:
0972: A service is defined by derby.service.name=protocol
0973: */
0974: private static final String SERVICE = "derby.service.";
0975:
0976: public void startServices(Properties properties, boolean bootAll) {
0977:
0978: if (properties == null)
0979: return;
0980:
0981: for (Enumeration e = properties.propertyNames(); e
0982: .hasMoreElements();) {
0983:
0984: String key = (String) e.nextElement();
0985: if (key.startsWith(SERVICE)) {
0986: String name = key.substring(SERVICE.length());
0987:
0988: String protocolOrType = properties.getProperty(key);
0989:
0990: try {
0991: if (protocolOrType
0992: .equals(Monitor.SERVICE_TYPE_DIRECTORY)) {
0993: if (bootAll) // only if automatic booting is required
0994: findProviderAndStartService(name,
0995: properties, true);
0996: } else {
0997: bootService((PersistentService) null,
0998: protocolOrType, name,
0999: (Properties) null, false);
1000: }
1001:
1002: } catch (StandardException se) {
1003: // error already in error log, just continue booting
1004: // for persistent services, but non-persistent ones
1005: // will not have put the error in the log
1006: if (!protocolOrType
1007: .equals(Monitor.SERVICE_TYPE_DIRECTORY))
1008: reportException(se);
1009: }
1010: }
1011: }
1012: }
1013:
1014: /**
1015: Start a peristent service.
1016:
1017: @see ModuleFactory#startPersistentService
1018: @see Monitor#startPersistentService
1019: */
1020: public final boolean startPersistentService(String name,
1021: Properties properties) throws StandardException {
1022:
1023: return findProviderAndStartService(name, properties, false);
1024:
1025: }
1026:
1027: /**
1028: Create a persistent service.
1029:
1030: @return The module from the service if it was created successfully, null if a service already existed.
1031:
1032: @exception StandardException An exception was thrown trying to create the service.
1033:
1034: @see Monitor#createPersistentService
1035: */
1036:
1037: public Object createPersistentService(String factoryInterface,
1038: String name, Properties properties)
1039: throws StandardException {
1040:
1041: PersistentService provider = findProviderForCreate(name);
1042: if (provider == null) {
1043: throw StandardException.newException(
1044: SQLState.PROTOCOL_UNKNOWN, name);
1045: }
1046:
1047: return bootService(provider, factoryInterface, name,
1048: properties, true);
1049: }
1050:
1051: /**
1052: * Removes a PersistentService.
1053: * Could be used for drop database.
1054: @param name : Service name to be removed.
1055:
1056: */
1057: public void removePersistentService(String name)
1058: throws StandardException {
1059: PersistentService provider = null;
1060: provider = findProviderForCreate(name);
1061: String serviceName = provider.getCanonicalServiceName(name);
1062: boolean removed = provider.removeServiceRoot(serviceName);
1063: if (removed == false)
1064: throw StandardException.newException(
1065: SQLState.SERVICE_DIRECTORY_REMOVE_ERROR,
1066: serviceName);
1067: }
1068:
1069: /**
1070: Start a non-persistent service.
1071:
1072: @see Monitor#startNonPersistentService
1073: @see ModuleFactory#startNonPersistentService
1074: */
1075: public Object startNonPersistentService(String factoryInterface,
1076: String serviceName, Properties properties)
1077: throws StandardException {
1078:
1079: return bootService((PersistentService) null, factoryInterface,
1080: serviceName, properties, false);
1081: }
1082:
1083: /**
1084: Create an implementation set.
1085: Look through the properties object for all properties that
1086: start with derby.module and add the value into the vector.
1087:
1088: If no implementations are listed in the properties object
1089: then null is returned.
1090: */
1091: private Vector getImplementations(Properties moduleList,
1092: boolean actualModuleList) {
1093:
1094: if (moduleList == null)
1095: return null;
1096:
1097: Vector implementations = actualModuleList ? new Vector(
1098: moduleList.size()) : new Vector(0, 1);
1099:
1100: // Get my current JDK environment
1101: int theJDKId = JVMInfo.JDK_ID;
1102:
1103: int[] envModuleCount = new int[theJDKId + 1];
1104:
1105: nextModule: for (Enumeration e = moduleList.propertyNames(); e
1106: .hasMoreElements();) {
1107:
1108: String key = (String) e.nextElement();
1109:
1110: // module tagged name in the modules.properties file.
1111: // used as the tag for dependent properties.
1112: String tag;
1113:
1114: // Dynamically loaded code is defined by a property of
1115: // the form:
1116: // derby.module.<modulename>=<class name>
1117: // or
1118: // derby.subSubProtocol.<modulename>=<classname>
1119:
1120: if (key.startsWith(Property.MODULE_PREFIX)) {
1121: tag = key.substring(Property.MODULE_PREFIX.length());
1122: } else if (key.startsWith(Property.SUB_SUB_PROTOCOL_PREFIX)) {
1123: tag = key.substring(Property.MODULE_PREFIX.length());
1124: } else {
1125: continue nextModule;
1126: }
1127:
1128: // Check to see if it has any environment requirements
1129:
1130: // derby.env.jdk.<modulename> - Any JDK requirements.
1131: String envKey = Property.MODULE_ENV_JDK_PREFIX.concat(tag);
1132: String envJDK = moduleList.getProperty(envKey);
1133: int envJDKId = 0;
1134:
1135: if (envJDK != null) {
1136: envJDKId = Integer.parseInt(envJDK.trim());
1137: if (envJDKId > theJDKId) {
1138: continue nextModule;
1139: }
1140: }
1141:
1142: // derby.env.classes.<tag> - Any class requirements
1143: envKey = Property.MODULE_ENV_CLASSES_PREFIX.concat(tag);
1144: String envClasses = moduleList.getProperty(envKey);
1145: if (envClasses != null) {
1146:
1147: StringTokenizer st = new StringTokenizer(envClasses,
1148: ",");
1149: for (; st.hasMoreTokens();) {
1150: try {
1151: Class.forName(st.nextToken().trim());
1152: } catch (ClassNotFoundException cnfe) {
1153: continue nextModule;
1154: } catch (LinkageError le) {
1155: continue nextModule;
1156: }
1157: }
1158: }
1159:
1160: // Try to load the class
1161: // if we can't load the class or create an instance then
1162: // we don't use this calls as a valid module implementation
1163: String className = moduleList.getProperty(key);
1164:
1165: if (SanityManager.DEBUG && reportOn) {
1166: report("Accessing module " + className
1167: + " to run initializers at boot time");
1168: }
1169:
1170: try {
1171: Class possibleModule = Class.forName(className);
1172:
1173: // Look for the monitors special modules, PersistentService ones.
1174: if (getPersistentServiceImplementation(possibleModule))
1175: continue;
1176:
1177: if (StorageFactory.class
1178: .isAssignableFrom(possibleModule)) {
1179: storageFactories.put(tag, className);
1180: continue;
1181: }
1182:
1183: // If this is a specific JDK version (environment) module
1184: // then it must be ordered in the implementation list by envJDKId.
1185: // Those with a higher number are at the front, e.g.
1186: //
1187: // JDK 1.4 modules (envJDKId == 4)
1188: // JDK 1.2/1.3 modules (envJDKId == 2)
1189: // JDK 1.1 modules (envJDKId == 1)
1190: // generic modules (envJDKId == 0 (not set in modules.properties)
1191: //
1192: // Note modules with envJDKId > theJDKId do not get here
1193:
1194: if (envJDKId != 0) {
1195:
1196: // total how many modules with a higher envJDKId are ahead of us
1197: int offset = 0;
1198: for (int eji = theJDKId; eji > envJDKId; eji--) {
1199: offset += envModuleCount[eji];
1200: }
1201:
1202: implementations.insertElementAt(possibleModule,
1203: offset);
1204: envModuleCount[envJDKId]++;
1205:
1206: } else {
1207: // just add to the end of the vector
1208: implementations.addElement(possibleModule);
1209: }
1210:
1211: // Since ModuleControl and ModuleSupportable are not called directly
1212: // check that if the have the methods then the class implements the
1213: // interface.
1214: if (SanityManager.DEBUG) {
1215: // ModuleSupportable
1216: Class[] csParams = { new java.util.Properties()
1217: .getClass() };
1218: try {
1219: possibleModule
1220: .getMethod("canSupport", csParams);
1221: if (!ModuleSupportable.class
1222: .isAssignableFrom(possibleModule)) {
1223: SanityManager
1224: .THROWASSERT("Module does not implement ModuleSupportable but has canSupport() - "
1225: + className);
1226: }
1227: } catch (NoSuchMethodException nsme) {/* ok*/
1228: }
1229:
1230: // ModuleControl
1231: boolean eitherMethod = false;
1232:
1233: Class[] bootParams = { Boolean.TYPE,
1234: new java.util.Properties().getClass() };
1235: try {
1236: possibleModule.getMethod("boot", bootParams);
1237: eitherMethod = true;
1238: } catch (NoSuchMethodException nsme) {/*ok*/
1239: }
1240:
1241: Class[] stopParams = {};
1242: try {
1243: possibleModule.getMethod("stop", stopParams);
1244: eitherMethod = true;
1245: } catch (NoSuchMethodException nsme) {/*ok*/
1246: }
1247:
1248: if (eitherMethod) {
1249: if (!ModuleControl.class
1250: .isAssignableFrom(possibleModule)) {
1251: SanityManager
1252: .THROWASSERT("Module does not implement ModuleControl but has its methods - "
1253: + className);
1254: }
1255: }
1256: }
1257:
1258: } catch (ClassNotFoundException cnfe) {
1259: report("Class " + className + " " + cnfe.toString()
1260: + ", module ignored.");
1261: } catch (LinkageError le) {
1262: report("Class " + className + " " + le.toString()
1263: + ", module ignored.");
1264: }
1265: }
1266:
1267: if (implementations.isEmpty())
1268: return null;
1269: implementations.trimToSize();
1270:
1271: return implementations;
1272: }
1273:
1274: private boolean getPersistentServiceImplementation(
1275: Class possibleModule) {
1276: if (!PersistentService.class.isAssignableFrom(possibleModule))
1277: return false;
1278:
1279: PersistentService ps = (PersistentService) newInstance(possibleModule);
1280: if (ps == null) {
1281: report("Class " + possibleModule.getName()
1282: + " cannot create instance, module ignored.");
1283: } else {
1284: if (serviceProviders == null)
1285: serviceProviders = new Hashtable(3, (float) 1.0);
1286: serviceProviders.put(ps.getType(), ps);
1287: }
1288: return true;
1289: } // end of getPersistentServiceImplementation
1290:
1291: private Vector getDefaultImplementations() {
1292:
1293: Properties moduleList = getDefaultModuleProperties();
1294:
1295: return getImplementations(moduleList, true);
1296: } // end of getDefaultImplementations
1297:
1298: /**
1299: * Get the complete set of module properties by
1300: * loading in contents of all the org/apache/derby/modules.properties
1301: * files. This must be executed in a privileged block otherwise
1302: * when running in a security manager environment no properties will
1303: * be returned.
1304: */
1305: Properties getDefaultModuleProperties() {
1306: // SECURITY PERMISSION - IP1 for modules in this jar
1307: // or other jars shipped with the Derby release.
1308: Properties moduleList = new Properties();
1309: boolean firstList = true;
1310:
1311: ClassLoader cl = getClass().getClassLoader();
1312: try {
1313: Enumeration e = cl == null ? ClassLoader
1314: .getSystemResources("org/apache/derby/modules.properties")
1315: : cl
1316: .getResources("org/apache/derby/modules.properties");
1317: while (e.hasMoreElements()) {
1318: URL modulesPropertiesURL = (URL) e.nextElement();
1319: InputStream is = null;
1320: try {
1321: is = modulesPropertiesURL.openStream();
1322: if (firstList) {
1323: moduleList.load(is);
1324: firstList = false;
1325: } else {
1326: // Check for duplicates
1327: Properties otherList = new Properties();
1328: otherList.load(is);
1329: for (Enumeration newKeys = otherList.keys(); newKeys
1330: .hasMoreElements();) {
1331: String key = (String) newKeys.nextElement();
1332: if (moduleList.contains(key))
1333: // RESOLVE how do we localize messages before we have finished initialization?
1334: report("Ignored duplicate property "
1335: + key
1336: + " in "
1337: + modulesPropertiesURL
1338: .toString());
1339: else
1340: moduleList.setProperty(key, otherList
1341: .getProperty(key));
1342: }
1343: }
1344: } catch (IOException ioe) {
1345: if (SanityManager.DEBUG)
1346: report("Can't load implementation list "
1347: + modulesPropertiesURL.toString()
1348: + ": " + ioe.toString());
1349: } finally {
1350: try {
1351: if (is != null)
1352: is.close();
1353: } catch (IOException ioe2) {
1354: }
1355: }
1356: }
1357: } catch (IOException ioe) {
1358: if (SanityManager.DEBUG)
1359: report("Can't load implementation list: "
1360: + ioe.toString());
1361: }
1362: if (SanityManager.DEBUG) {
1363: if (firstList)
1364: report("Default implementation list not found");
1365: }
1366:
1367: return moduleList;
1368: }
1369:
1370: /*
1371: ** Class methods
1372: */
1373:
1374: /**
1375: Return a property set that has the runtime properties removed.
1376: */
1377: protected static Properties removeRuntimeProperties(
1378: Properties properties) {
1379:
1380: Properties subset = new Properties();
1381:
1382: for (Enumeration e = properties.keys(); e.hasMoreElements();) {
1383:
1384: String key = (String) e.nextElement();
1385: if (key.startsWith(Property.PROPERTY_RUNTIME_PREFIX))
1386: continue;
1387:
1388: subset.put(key, properties.get(key));
1389: }
1390:
1391: return subset;
1392: }
1393:
1394: /**
1395: Get InputStream for application properties file Returns nul if it does not exist.
1396: */
1397: abstract InputStream applicationPropertiesStream()
1398: throws IOException;
1399:
1400: /**
1401: */
1402: protected Properties readApplicationProperties() {
1403:
1404: InputStream is = null;
1405:
1406: try {
1407: // SECURITY PERMISSION - OP3
1408: is = applicationPropertiesStream();
1409: if (is == null)
1410: return null;
1411:
1412: Properties properties = new Properties();
1413:
1414: // Trim off excess whitespace from properties file, if any,
1415: // and then load the properties into 'properties'.
1416: org.apache.derby.iapi.util.PropertyUtil
1417: .loadWithTrimmedValues(new BufferedInputStream(is),
1418: properties);
1419:
1420: return properties;
1421:
1422: } catch (SecurityException se) {
1423: return null;
1424: } catch (IOException ioe) {
1425: report(ioe.toString() + " (" + Property.PROPERTIES_FILE
1426: + ")");
1427: reportException(ioe);
1428: return null;
1429:
1430: } finally {
1431:
1432: try {
1433: if (is != null) {
1434: is.close();
1435: is = null;
1436: }
1437:
1438: } catch (IOException e) {
1439: }
1440: }
1441: }
1442:
1443: /*
1444: ** Methods related to service providers.
1445: **
1446: ** A service provider implements PersistentService and
1447: ** abstracts out:
1448: **
1449: ** Finding all serivces that should be started at boot time.
1450: ** Finding the service.properties file for a service
1451: ** Creating a service's root.
1452: **
1453: ** A monitor can have any number of service providers installed,
1454: ** any module that implements PersistentService is treated specially
1455: ** and stored only in the serviceProviders hashtable, indexed by
1456: ** its getType() method.
1457: **
1458: ** Once all the implementations have loaded the service providers
1459: ** are booted. If they fail to boot then they aare discarded.
1460: ** E.g. a marimba service provider may detect that its not in
1461: ** a channel so it refuses to boot.
1462: */
1463:
1464: /**
1465: Boot all the service providers, ie. any module that implemented
1466: PersistentService. Upon entry to this call is the hashtable has
1467: PersistentService objects that have been created but not booted.
1468: */
1469: protected void bootServiceProviders() {
1470:
1471: if (serviceProviders == null) {
1472: return;
1473: }
1474:
1475: for (Enumeration e = serviceProviders.keys(); e
1476: .hasMoreElements();) {
1477:
1478: String serviceType = (String) e.nextElement();
1479: Object provider = serviceProviders.get(serviceType);
1480:
1481: // see if this provider can live in this environment
1482: if (!BaseMonitor.canSupport(provider, (Properties) null)) {
1483: serviceProviders.remove(serviceType);
1484: continue;
1485: }
1486: }
1487: }
1488:
1489: /**
1490: Boot all persistent services that can be located at run time.
1491:
1492: <BR>
1493: This method enumerates through all the service providers that
1494: are active and calls bootPersistentServices(PersistentService)
1495: to boot all the services that that provider knows about.
1496: */
1497: protected void bootPersistentServices() {
1498: Enumeration e = new ProviderEnumeration(applicationProperties);
1499: while (e.hasMoreElements()) {
1500: PersistentService provider = (PersistentService) e
1501: .nextElement();
1502: bootProviderServices(provider);
1503: }
1504:
1505: }
1506:
1507: /**
1508: Boot all persistent services that can be located by a single service provider
1509:
1510: <BR>
1511: This method enumerates through all the service providers that
1512: are active and calls bootPersistentServices(PersistentService)
1513: to boot all the services that that provider knows about.
1514: */
1515: protected void bootProviderServices(PersistentService provider) {
1516:
1517: if (SanityManager.DEBUG && reportOn) {
1518: report("Booting persistent services for provider: "
1519: + provider.getType());
1520: }
1521:
1522: for (Enumeration e = provider.getBootTimeServices(); (e != null)
1523: && e.hasMoreElements();) {
1524:
1525: String serviceName = (String) e.nextElement();
1526:
1527: Properties serviceProperties;
1528: try {
1529: serviceProperties = provider.getServiceProperties(
1530: serviceName, null);
1531: } catch (StandardException mse) {
1532: report("Failed to load service properties, name: "
1533: + serviceName + ", type = "
1534: + provider.getType());
1535: reportException(mse);
1536: continue;
1537: }
1538:
1539: // see if this service does not want to be auto-booted.
1540: if (Boolean.valueOf(
1541: serviceProperties
1542: .getProperty(Property.NO_AUTO_BOOT))
1543: .booleanValue())
1544: continue;
1545:
1546: try {
1547: startProviderService(provider, serviceName,
1548: serviceProperties);
1549: } catch (StandardException mse) {
1550: report("Service failed to boot, name: " + serviceName
1551: + ", type = " + provider.getType());
1552: reportException(mse);
1553: continue;
1554: }
1555: }
1556: }
1557:
1558: /**
1559: Find a provider and start a service.
1560: */
1561: private boolean findProviderAndStartService(String name,
1562: Properties properties, boolean bootTime)
1563: throws StandardException {
1564:
1565: PersistentService actualProvider = null;
1566:
1567: Properties serviceProperties = null;
1568: String serviceName = null;
1569:
1570: // see if the name already includes a service type
1571: int colon = name.indexOf(':');
1572: if (colon != -1) {
1573: actualProvider = findProviderFromName(name, colon);
1574:
1575: // if null is returned here then its a sub-sub protocol/provider
1576: // that we don't understand. Attempt to load it as an untyped name.
1577: // If we have a protool
1578: // that we do understand and we can't open the service we will
1579: // throw an exception
1580: if (actualProvider != null) {
1581:
1582: serviceName = actualProvider
1583: .getCanonicalServiceName(name);
1584: if (serviceName == null)
1585: return true; // we understand the type, but the service does not exist
1586:
1587: serviceProperties = actualProvider
1588: .getServiceProperties(serviceName, properties);
1589:
1590: if (serviceProperties == null)
1591: return true; // we understand the type, but the service does not exist
1592:
1593: // see if this service does not want to be auto-booted.
1594: if (bootTime
1595: && Boolean
1596: .valueOf(
1597: serviceProperties
1598: .getProperty(Property.NO_AUTO_BOOT))
1599: .booleanValue())
1600: return true;
1601:
1602: startProviderService(actualProvider, serviceName,
1603: serviceProperties);
1604: return true; // we understand the type
1605: }
1606: }
1607:
1608: StandardException savedMse = null;
1609:
1610: for (Enumeration e = new ProviderEnumeration(properties); e
1611: .hasMoreElements();) {
1612:
1613: PersistentService provider = (PersistentService) e
1614: .nextElement();
1615:
1616: String sn = provider.getCanonicalServiceName(name);
1617: if (sn == null)
1618: continue;
1619:
1620: Properties p = null;
1621: try {
1622: p = provider.getServiceProperties(sn, properties);
1623: // service does not exist.
1624: if (p == null)
1625: continue;
1626:
1627: } catch (StandardException mse) {
1628: savedMse = mse;
1629: }
1630:
1631: // yes we can attempt to boot this service
1632: if (actualProvider == null) {
1633: actualProvider = provider;
1634: serviceName = sn;
1635: serviceProperties = p;
1636: continue;
1637: }
1638:
1639: // we have an ambigious service name
1640: throw StandardException.newException(
1641: SQLState.AMBIGIOUS_PROTOCOL, name);
1642: }
1643:
1644: // no such service, if this was a name with no type, ie just name instead of type:name.
1645: // the monitor claims to always understand these.
1646: if (actualProvider == null)
1647: return colon == -1;
1648:
1649: if (savedMse != null)
1650: throw savedMse;
1651:
1652: // see if this service does not want to be auto-booted.
1653: if (bootTime
1654: && Boolean.valueOf(
1655: serviceProperties
1656: .getProperty(Property.NO_AUTO_BOOT))
1657: .booleanValue())
1658: return true;
1659:
1660: startProviderService(actualProvider, serviceName,
1661: serviceProperties);
1662: return true;
1663: }
1664:
1665: protected PersistentService findProviderForCreate(String name)
1666: throws StandardException {
1667: // RESOLVE - hard code creating databases in directories for now.
1668: return (PersistentService) findProviderFromName(name, name
1669: .indexOf(':'));
1670: }
1671:
1672: /**
1673: Find the service provider from a name that includes a service type,
1674: ie. is of the form 'type:name'. If type is less than 3 characters
1675: then it is assumed to be of type directory, i.e. a windows driver letter.
1676: */
1677: private PersistentService findProviderFromName(String name,
1678: int colon) throws StandardException {
1679: // empty type, treat as a unknown protocol
1680: if (colon == 0)
1681: return null;
1682:
1683: String serviceType;
1684: if (colon < 2) {
1685: // assume it's a windows path (a:/foo etc.) and set the type to be DIRECTORY
1686: serviceType = PersistentService.DIRECTORY;
1687: } else {
1688: serviceType = name.substring(0, colon);
1689: }
1690: return getServiceProvider(serviceType);
1691: }
1692:
1693: public PersistentService getServiceProvider(String subSubProtocol)
1694: throws StandardException {
1695: if (subSubProtocol == null)
1696: return null;
1697: if (serviceProviders != null) {
1698: PersistentService ps = (PersistentService) serviceProviders
1699: .get(subSubProtocol);
1700: if (ps != null)
1701: return ps;
1702: }
1703: return getPersistentService(subSubProtocol);
1704: } // end of getServiceProvider
1705:
1706: /**
1707: * Return a PersistentService implementation to handle the subSubProtocol.
1708: * @return Valid PersistentService or null if the protocol is not handled.
1709: */
1710: private PersistentService getPersistentService(String subSubProtocol)
1711: throws StandardException {
1712: String className = getStorageFactoryClassName(subSubProtocol);
1713: return getPersistentService(className, subSubProtocol);
1714: }
1715:
1716: private PersistentService getPersistentService(
1717: final String className, String subSubProtocol)
1718: throws StandardException {
1719: if (className == null)
1720: return null;
1721: Class storageFactoryClass = null;
1722: try {
1723: storageFactoryClass = Class.forName(className);
1724: } catch (Throwable e) {
1725: throw StandardException.newException(
1726: SQLState.INSTANTIATE_STORAGE_FACTORY_ERROR, e,
1727: subSubProtocol, className);
1728: }
1729: return new StorageFactoryService(subSubProtocol,
1730: storageFactoryClass);
1731: } // end of getPersistentService
1732:
1733: /**
1734: * Find the StorageFactory class name that handles the subSub protocol.
1735: * Looks in the system property set and the set defined during boot.
1736:
1737: * @return Valid class name, or null if no StorageFactory handles the protocol.
1738: */
1739: private String getStorageFactoryClassName(String subSubProtocol) {
1740: String propertyName = Property.SUB_SUB_PROTOCOL_PREFIX
1741: + subSubProtocol;
1742: String className = PropertyUtil.getSystemProperty(propertyName);
1743: if (className != null)
1744: return className;
1745: return (String) storageFactories.get(subSubProtocol);
1746: } // end of getStorageFactoryClassName
1747:
1748: private static final HashMap storageFactories = new HashMap();
1749: static {
1750: String dirStorageFactoryClass;
1751: if (JVMInfo.JDK_ID >= JVMInfo.J2SE_14)
1752: dirStorageFactoryClass = "org.apache.derby.impl.io.DirStorageFactory4";
1753: else
1754: dirStorageFactoryClass = "org.apache.derby.impl.io.DirStorageFactory";
1755:
1756: storageFactories.put(PersistentService.DIRECTORY,
1757: dirStorageFactoryClass);
1758: storageFactories.put(PersistentService.CLASSPATH,
1759: "org.apache.derby.impl.io.CPStorageFactory");
1760: storageFactories.put(PersistentService.JAR,
1761: "org.apache.derby.impl.io.JarStorageFactory");
1762: storageFactories.put(PersistentService.HTTP,
1763: "org.apache.derby.impl.io.URLStorageFactory");
1764: storageFactories.put(PersistentService.HTTPS,
1765: "org.apache.derby.impl.io.URLStorageFactory");
1766: }
1767:
1768: /**
1769: Boot a service under the control of the provider
1770: */
1771: protected void startProviderService(PersistentService provider,
1772: String serviceName, Properties serviceProperties)
1773: throws StandardException {
1774:
1775: String protocol = serviceProperties
1776: .getProperty(Property.SERVICE_PROTOCOL);
1777:
1778: if (protocol == null) {
1779: throw StandardException.newException(
1780: SQLState.PROPERTY_MISSING,
1781: Property.SERVICE_PROTOCOL);
1782: }
1783:
1784: bootService(provider, protocol, serviceName, serviceProperties,
1785: false);
1786: }
1787:
1788: /**
1789: Boot (start or create) a service (persistent or non-persistent).
1790: */
1791: protected Object bootService(PersistentService provider,
1792: String factoryInterface, String serviceName,
1793: Properties properties, boolean create)
1794: throws StandardException {
1795:
1796: //reget the canonical service name in case if it was recreated
1797: //after we got service name.(like in case of restoring from backup).
1798: if (provider != null)
1799: serviceName = provider.getCanonicalServiceName(serviceName);
1800: ProtocolKey serviceKey = ProtocolKey.create(factoryInterface,
1801: serviceName);
1802: if (SanityManager.DEBUG && reportOn) {
1803: report("Booting service " + serviceKey + " create = "
1804: + create);
1805: }
1806:
1807: ContextManager previousCM = contextService
1808: .getCurrentContextManager();
1809: ContextManager cm = previousCM;
1810: Object instance;
1811: TopService ts = null;
1812: Context sb = null;
1813:
1814: try {
1815:
1816: synchronized (this ) {
1817:
1818: if (inShutdown) {
1819: throw StandardException
1820: .newException(SQLState.CLOUDSCAPE_SYSTEM_SHUTDOWN);
1821: }
1822:
1823: for (int i = 1; i < services.size(); i++) {
1824: TopService ts2 = (TopService) services.elementAt(i);
1825: if (ts2.isPotentialService(serviceKey)) {
1826: // if the service already exists then just return null
1827: return null;
1828: }
1829: }
1830:
1831: Locale serviceLocale = null;
1832: if (create) {
1833:
1834: // always wrap the property set in an outer set.
1835: // this ensures that any random attributes from
1836: // a JDBC URL are not written into the service.properties
1837: // file (e.g. like user and password :-)
1838: properties = new Properties(properties);
1839:
1840: serviceLocale = setLocale(properties);
1841:
1842: properties.put(Property.SERVICE_PROTOCOL,
1843: factoryInterface);
1844:
1845: serviceName = provider
1846: .createServiceRoot(
1847: serviceName,
1848: Boolean
1849: .valueOf(
1850: properties
1851: .getProperty(Property.DELETE_ON_CREATE))
1852: .booleanValue());
1853:
1854: serviceKey = ProtocolKey.create(factoryInterface,
1855: serviceName);
1856: } else if (properties != null) {
1857: String serverLocaleDescription = properties
1858: .getProperty(Property.SERVICE_LOCALE);
1859: if (serverLocaleDescription != null)
1860: serviceLocale = staticGetLocaleFromString(serverLocaleDescription);
1861: }
1862:
1863: ts = new TopService(this , serviceKey, provider,
1864: serviceLocale);
1865: services.addElement(ts);
1866: }
1867:
1868: if (SanityManager.DEBUG) {
1869: if (provider != null) {
1870: SanityManager
1871: .ASSERT(
1872: provider.getCanonicalServiceName(
1873: serviceName).equals(
1874: serviceName),
1875: "mismatched canonical names "
1876: + provider
1877: .getCanonicalServiceName(serviceName)
1878: + " != " + serviceName);
1879: SanityManager.ASSERT(serviceName.equals(serviceKey
1880: .getIdentifier()), "mismatched names "
1881: + serviceName + " != "
1882: + serviceKey.getIdentifier());
1883: }
1884: }
1885:
1886: if (properties != null) {
1887:
1888: // these properties must not be stored in the persistent properties,
1889: // otherwise moving databases from one directory to another
1890: // will not work. Thus they all have a fixed prefix
1891:
1892: // the root of the data
1893: properties.put(PersistentService.ROOT, serviceName);
1894:
1895: // the type of the service
1896: properties.put(PersistentService.TYPE, provider
1897: .getType());
1898: }
1899:
1900: if (SanityManager.DEBUG && reportOn) {
1901: dumpProperties("Service Properties: "
1902: + serviceKey.toString(), properties);
1903: }
1904:
1905: // push a new context manager
1906: if (previousCM == null) {
1907: cm = contextService.newContextManager();
1908:
1909: contextService.setCurrentContextManager(cm);
1910: }
1911: sb = new ServiceBootContext(cm);
1912:
1913: UpdateServiceProperties usProperties;
1914: Properties serviceProperties;
1915:
1916: //while doing restore from backup, we don't want service properties to be
1917: //updated until all the files are copied from backup.
1918: boolean inRestore = (properties != null ? properties
1919: .getProperty(Property.IN_RESTORE_FROM_BACKUP) != null
1920: : false);
1921:
1922: if ((provider != null) && (properties != null)) {
1923: // we need to track to see if the properties have
1924: // been updated or not. If the database is not created yet, we don't create the
1925: // services.properties file yet. We let the following if (create) statement do
1926: //that at the end of the database creation. After that, the changes in
1927: // services.properties file will be tracked by UpdateServiceProperties.
1928: usProperties = new UpdateServiceProperties(provider,
1929: serviceName, properties, !(create || inRestore));
1930: serviceProperties = usProperties;
1931: } else {
1932: usProperties = null;
1933: serviceProperties = properties;
1934: }
1935:
1936: instance = ts.bootModule(create, null, serviceKey,
1937: serviceProperties);
1938:
1939: if (create || inRestore) {
1940: // remove all the in-memory properties
1941: provider.saveServiceProperties(serviceName,
1942: usProperties.getStorageFactory(), BaseMonitor
1943: .removeRuntimeProperties(properties),
1944: false);
1945: usProperties.setServiceBooted();
1946: }
1947:
1948: if (cm != previousCM)
1949: cm.cleanupOnError(StandardException.closeException());
1950:
1951: } catch (Throwable t) {
1952:
1953: // ensure that the severity will shutdown the service
1954: if ((t instanceof StandardException)
1955: && (((StandardException) t).getSeverity() == ExceptionSeverity.DATABASE_SEVERITY))
1956: ;
1957: else
1958: t = Monitor.exceptionStartingModule(t);
1959:
1960: if (cm != previousCM) {
1961: cm.cleanupOnError(t);
1962: }
1963:
1964: if (ts != null) {
1965: ts.shutdown();
1966: synchronized (this ) {
1967: services.removeElement(ts);
1968: }
1969:
1970: // Service root will only have been created if
1971: // ts is non-null.
1972: boolean deleteOnError = (properties != null ? properties
1973: .getProperty(Property.DELETE_ROOT_ON_ERROR) != null
1974: : false);
1975: if (create || deleteOnError)
1976: provider.removeServiceRoot(serviceName);
1977: }
1978:
1979: Throwable nested = ((StandardException) t)
1980: .getNestedException();
1981:
1982: // never hide ThreadDeath
1983: if (nested instanceof ThreadDeath)
1984: throw (ThreadDeath) t;
1985:
1986: if (nested instanceof StandardException)
1987: throw (StandardException) t;
1988:
1989: throw (StandardException) t;
1990:
1991: } finally {
1992: if ((previousCM == cm) && (sb != null))
1993: sb.popMe();
1994:
1995: if (previousCM == null)
1996: contextService.resetCurrentContextManager(cm);
1997: }
1998:
1999: // from this point onwards the service is open for business
2000: ts.setTopModule(instance);
2001:
2002: //
2003: // The following yield allows our background threads to
2004: // execute their run methods. This is needed due to
2005: // bug 4081540 on Solaris. When the bug is fixed we can
2006: // remove this yield.
2007: Thread.yield();
2008:
2009: return instance;
2010: }
2011:
2012: /*
2013: ** Methods of com.ibm.db2j.system.System
2014: */
2015:
2016: /**
2017: Return the UUID factory for this system. Returns null
2018: if there isn't one.
2019: See com.ibm.db2j.system.System
2020: */
2021: public UUIDFactory getUUIDFactory() {
2022:
2023: return uuidFactory;
2024: }
2025:
2026: /**
2027: * Returns the Timer factory for this system.
2028: *
2029: * @return the system's Timer factory.
2030: */
2031: public TimerFactory getTimerFactory() {
2032: return timerFactory;
2033: }
2034:
2035: /*
2036: ** Methods to deal with storing error messages until an InfoStreams is available.
2037: */
2038:
2039: private PrintWriter tmpWriter;
2040: private AccessibleByteArrayOutputStream tmpArray;
2041: private boolean dumpedTempWriter;
2042:
2043: private PrintWriter getTempWriter() {
2044: if (tmpWriter == null && !dumpedTempWriter) {
2045: tmpArray = new AccessibleByteArrayOutputStream();
2046: tmpWriter = new PrintWriter(tmpArray);
2047: }
2048: return tmpWriter;
2049: }
2050:
2051: private void dumpTempWriter(boolean bothPlaces) {
2052:
2053: if (tmpWriter == null)
2054: return;
2055:
2056: tmpWriter.flush();
2057:
2058: BufferedReader lnr = new BufferedReader(new InputStreamReader(
2059: new ByteArrayInputStream(tmpArray
2060: .getInternalByteArray())));
2061: try {
2062: String s;
2063: while ((s = lnr.readLine()) != null) {
2064: if (systemStreams != null)
2065: systemStreams.stream().printlnWithHeader(s);
2066:
2067: if ((systemStreams == null) || bothPlaces)
2068: logging.println(s);
2069: }
2070: } catch (IOException ioe) {
2071: }
2072:
2073: if ((systemStreams == null) || bothPlaces)
2074: logging.flush();
2075:
2076: tmpWriter = null;
2077: tmpArray = null;
2078: dumpedTempWriter = true;
2079: logging = null;
2080: }
2081:
2082: /**
2083: If the module implements ModuleSupportable then call its
2084: canSupport() method to see if it can or should run in
2085: this setup. If it doesn't then it can always run.
2086: */
2087: static boolean canSupport(Object instance, Properties properties) {
2088: if (instance instanceof ModuleSupportable) {
2089: // see if the instance can support the properties
2090: if (!((ModuleSupportable) instance).canSupport(properties))
2091: return false;
2092: }
2093: return true;
2094: }
2095:
2096: /**
2097: Boot a module. If the module implements ModuleControl
2098: then its boot() method is called. Otherwise all the
2099: boot code is assumed to take place in its constructor.
2100: */
2101: static void boot(Object module, boolean create,
2102: Properties properties) throws StandardException {
2103:
2104: if (module instanceof ModuleControl)
2105: ((ModuleControl) module).boot(create, properties);
2106: }
2107:
2108: /*
2109: ** Locale handling
2110: */
2111: private static Locale staticGetLocaleFromString(
2112: String localeDescription) throws StandardException {
2113:
2114: // Check String is of expected format
2115: // even though country should not be optional
2116: // some jvm's support this, so go with the flow.
2117: // xx[_YY[_variant]]
2118:
2119: int len = localeDescription.length();
2120:
2121: boolean isOk = (len == 2) || (len == 5) || (len > 6);
2122:
2123: // must have underscores at position 2
2124: if (isOk && (len != 2))
2125: isOk = localeDescription.charAt(2) == '_';
2126:
2127: // must have underscores at position 2
2128: if (isOk && (len > 5))
2129: isOk = localeDescription.charAt(5) == '_';
2130:
2131: if (!isOk)
2132: throw StandardException.newException(
2133: SQLState.INVALID_LOCALE_DESCRIPTION,
2134: localeDescription);
2135:
2136: String language = localeDescription.substring(0, 2);
2137: String country = len == 2 ? "" : localeDescription.substring(3,
2138: 5);
2139:
2140: if (len < 6) {
2141: return new Locale(language, country);
2142: }
2143:
2144: String variant = (len > 6) ? localeDescription
2145: .substring(6, len) : null;
2146:
2147: return new Locale(language, country, variant);
2148: }
2149:
2150: private static Locale setLocale(Properties properties)
2151: throws StandardException {
2152:
2153: String userDefinedLocale = properties
2154: .getProperty(Attribute.TERRITORY);
2155: Locale locale;
2156: if (userDefinedLocale == null)
2157: locale = Locale.getDefault();
2158: else {
2159: // validate the passed in string
2160: locale = staticGetLocaleFromString(userDefinedLocale);
2161: }
2162:
2163: properties.put(Property.SERVICE_LOCALE, locale.toString());
2164: return locale;
2165: }
2166:
2167: /*
2168: ** BundleFinder
2169: */
2170:
2171: //private Hashtable localeBundles;
2172: /**
2173: Get the locale from the ContextManager and then find the bundle
2174: based upon that locale.
2175: */
2176: public ResourceBundle getBundle(String messageId) {
2177: ContextManager cm;
2178: try {
2179: cm = ContextService.getFactory().getCurrentContextManager();
2180: } catch (ShutdownException se) {
2181: cm = null;
2182: }
2183:
2184: if (cm != null) {
2185: return MessageService.getBundleForLocale(cm
2186: .getMessageLocale(), messageId);
2187: }
2188: return null;
2189: }
2190:
2191: public Thread getDaemonThread(Runnable task, String name,
2192: boolean setMinPriority) {
2193: Thread t = new Thread(daemonGroup, task, "derby.".concat(name));
2194: t.setDaemon(true);
2195: if (setMinPriority) {
2196: t.setPriority(Thread.MIN_PRIORITY);
2197: }
2198: return t;
2199:
2200: }
2201:
2202: public void setThreadPriority(int priority) {
2203:
2204: Thread t = Thread.currentThread();
2205:
2206: if (t.getThreadGroup() == daemonGroup) {
2207: t.setPriority(priority);
2208: }
2209: }
2210:
2211: /**
2212: Initialize the monitor wrt the current environemnt.
2213: Returns false if the monitor cannot be initialized, true otherwise.
2214: */
2215: abstract boolean initialize(boolean lite);
2216:
2217: class ProviderEnumeration implements Enumeration {
2218: private Enumeration serviceProvidersKeys = (serviceProviders == null) ? null
2219: : serviceProviders.keys();
2220: private Properties startParams;
2221: private Enumeration paramEnumeration;
2222: private boolean enumeratedDirectoryProvider;
2223: private PersistentService storageFactoryPersistentService;
2224:
2225: ProviderEnumeration(Properties startParams) {
2226: this .startParams = startParams;
2227: if (startParams != null)
2228: paramEnumeration = startParams.keys();
2229: }
2230:
2231: public Object nextElement() throws NoSuchElementException {
2232: if (serviceProvidersKeys != null
2233: && serviceProvidersKeys.hasMoreElements())
2234: return serviceProviders.get(serviceProvidersKeys
2235: .nextElement());
2236: getNextStorageFactory();
2237: Object ret = storageFactoryPersistentService;
2238: storageFactoryPersistentService = null;
2239: return ret;
2240: }
2241:
2242: private void getNextStorageFactory() {
2243: if (storageFactoryPersistentService != null)
2244: return;
2245: if (paramEnumeration != null) {
2246: while (paramEnumeration.hasMoreElements()) {
2247: String prop = (String) paramEnumeration
2248: .nextElement();
2249: if (prop
2250: .startsWith(Property.SUB_SUB_PROTOCOL_PREFIX)) {
2251: try {
2252: String storageFactoryClassName = (String) startParams
2253: .get(prop);
2254: if (storageFactoryClassName != null) {
2255: storageFactoryPersistentService = getPersistentService(
2256: (String) startParams.get(prop),
2257: prop
2258: .substring(Property.SUB_SUB_PROTOCOL_PREFIX
2259: .length()));
2260: if (storageFactoryPersistentService != null)
2261: return;
2262: }
2263: } catch (StandardException se) {
2264: }
2265: ;
2266: }
2267: }
2268: }
2269: if (!enumeratedDirectoryProvider) {
2270: try {
2271: storageFactoryPersistentService = getPersistentService(
2272: getStorageFactoryClassName(PersistentService.DIRECTORY),
2273: PersistentService.DIRECTORY);
2274: } catch (StandardException se) {
2275: storageFactoryPersistentService = null;
2276: }
2277: enumeratedDirectoryProvider = true;
2278: }
2279: } // end of getNextStorageFactory
2280:
2281: public boolean hasMoreElements() {
2282: if (serviceProvidersKeys != null
2283: && serviceProvidersKeys.hasMoreElements())
2284: return true;
2285: getNextStorageFactory();
2286: return storageFactoryPersistentService != null;
2287: }
2288: } // end of class ProviderEnumeration
2289: } // end of class BaseMonitor
2290:
2291: class AntiGC implements Runnable {
2292:
2293: boolean goAway;
2294: private Object keep1;
2295:
2296: AntiGC(Object a) {
2297: keep1 = a;
2298: }
2299:
2300: public void run() {
2301: while (true) {
2302: synchronized (this ) {
2303: if (goAway)
2304: return;
2305: try {
2306: wait();
2307: } catch (InterruptedException ie) {
2308: }
2309: }
2310: }
2311: }
2312: } // end of class AntiGC
|