001: /*
002:
003: Derby - Class org.apache.derby.iapi.services.monitor.Monitor
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.iapi.services.monitor;
023:
024: import org.apache.derby.iapi.error.StandardException;
025: import org.apache.derby.iapi.services.i18n.MessageService;
026: import org.apache.derby.iapi.services.sanity.SanityManager;
027: import org.apache.derby.iapi.services.stream.HeaderPrintWriter;
028: import org.apache.derby.iapi.services.info.ProductGenusNames;
029: import org.apache.derby.iapi.services.info.ProductVersionHolder;
030: import org.apache.derby.iapi.reference.EngineType;
031: import org.apache.derby.iapi.reference.Attribute;
032: import org.apache.derby.iapi.services.property.PropertyUtil;
033:
034: import org.apache.derby.iapi.services.loader.InstanceGetter;
035:
036: import org.apache.derby.iapi.reference.SQLState;
037: import org.apache.derby.iapi.reference.Property;
038:
039: import java.util.Properties;
040: import java.util.Locale;
041: import java.io.PrintStream;
042:
043: /**
044: <P><B>Services</B><BR>
045:
046: A service is a collection of modules that combine to provide
047: the full functionality defined by the service. A service is defined
048: by three pieces of information:
049: <OL>
050: <LI>A fully qualified java class name that identifies the functionality or API
051: that the service must provide. Typically this class represents a java interface.
052: This class name is termed the <EM>factory interface</EM>.
053: <LI>The <EM>identifier</EM> of the service. Services are identified by a String, this may
054: be hard-coded, come from a UUID or any other source.
055: <LI>An optional java.util.Properties set.
056: </OL>
057: <BR>
058: The running functionality of the service is provided by a module
059: that implements the factory interface. The identifier of the this module
060: is not (need not be) the same as the identifier of the service. The identifier
061: of the service is held by the monitor in its service tables.
062: <BR>
063: Each module in a service is keyed by at least one factory interface, identifier}
064: pair. This pair is guaranteed to be unique within the service.
065: <BR>
066: The lifetime of a module in a service is no longer than the lifetime of the service.
067: Thus shutting down a service shuts down all the modules within a service.
068: <B>Optionally - </B> an individual module within a service may be shutdown, this will
069: in turn shutdown any modules it started if those module are not in use by other
070: modules within the service. This would be handled by the monitor, not the module itself.
071: <BR>
072: A service may be persistent, it goes through a boot in create mode, and subsequently boot
073: in non-create mode, or a non-peristent service, it always boots in non-create mode.
074: Persistent services can store their re-start parameters in their properties set, the monitor
075: provides the persistent storage of the properties set.
076: Non-persistent services do not have a properties set.
077:
078: <P><B>Booting Services</B><BR>
079: Services can be booted a number of ways
080: <UL>
081: <LI>A non-persistent service can be booted by having a property in the application properties
082: or the system (JVM) set.
083: <PRE>
084: derby.service.<EM>service name</EM>=<EM>class name</EM>
085: e.g.
086: # Added to the properties automatically by the class org.apache.derby.jdbc.EmbeddedDriver
087: derby.service.jdbc=java.sql.Driver
088: </PRE>
089: <LI>A persistent service can be booted by having a property in the application properties
090: or the system (JVM) set.
091: <PRE>
092: derby.service.<EM>service name</EM>=<EM>persistent storage type</EM>
093: e.g.
094: derby.service.mydatabase=serviceDirectory
095: </PRE>
096: serviceDirectory is a type understood by the monitor which means that there is a directory
097: named mydatabase within the system directory and within it is a properties file service.properties. This properties
098: set is the set for the service and must contain a property
099: <PRE>
100: derby.protocol=<EM>class name</EM>
101: </PRE>
102: This is then the factory interface for the service. Other storage types could be added in
103: the future.
104: <LI>
105: The monitor at start time looks for all persistent services that it can find and starts them.
106: E.g. all directories in the system directory that have a file service.properties are started
107: as services.
108: <LI>Services are started on demand, e.g. a findService attempts to boot a service if it
109: cannot be found.
110: </UL>
111: <B>Any or all of these three latter methods can be implemented. A first release may
112: just implement the look for all services and boot them.</B>
113: .
114: <P><B>System Service</B><BR>
115: A special service exists, the System Service. This service has no factory interface,
116: no identifier and no Properties set. It allows modules to be started that are required
117: by another service (or the monitor itself) but are not fundamentally part of the service.
118: Modules within this service are unidentified.
119: Typically these modules are system wide types of functionality like streams, uuid creation etc.
120: <BR>
121: The lifetime of a system module is the lifetime of the monitor.
122: <B>Optionally - </B> this could be changed to reference count on individual modules, requires
123: some minor api changes.
124:
125: <P><B>Modules</B><BR>
126:
127: A module is found or booted using four pieces of information:
128: <OL>
129: <LI>The service the module lives in or will live in.
130: <LI>A fully qualified java class name that identifies the functionality or API
131: that the module must provide. Typically this class represents a java interface.
132: This class name is termed the <EM>factory interface</EM>.
133: <LI>The <EM>identifier</EM> of the module. Modules are identified by a String, this may
134: be null, be hard-coded, come from a UUID or any other source. If the identifier
135: is null then the module is described as <EM>unidentified</EM>.
136: <LI>Boot time only - A java.util.Properties set. This Properties set is service wide
137: and typically contains parameters used to determine module implementation or runtime
138: behaviour.
139: </OL>
140: <BR>
141: The service is identified by explicitly identifiying the System Service or
142: by providing a reference to a module that already exists with the required service.
143: <BR>
144: The factory interface is provided by a String constant of the form class.MODULE
145: from the required interface.
146: <BR>
147: The module identifier is provided in a fashion determined by the code, in most
148: cases a unidentified module will suffice.
149: <BR>
150: The Properties set is also determined in a fashion determined by the code at
151: create or add service time.
152:
153: <P><B>Module Implementations</B><BR>
154:
155: When creating an instance of a module, an implementation is found through lists of
156: potential implementations.
157: <BR>
158: A list of potential implementations is obtained from a Properties set. Any property
159: within this set that is of the form
160: <PRE>
161: derby.module.<EM>tag</EM>=<EM>java class name</EM>
162: </PRE>
163: is seen by the monitor as a possible implementation. <EM>tag</EM> has no meaning within
164: the monitor, it is only there to provide uniqueness within the properties file. Typically
165: the tag is to provide some description for human readers of the properties file, e.g.
166: derby.module.lockManager for an implementation of a lock manager.
167: <BR>
168: The monitor looks through four properties sets for lists of potential implementations in this
169: order.
170: <OL>
171: <LI>The properties set of the service (i.e. that passed into Monitor.createPersistentService()
172: or Monitor.startService()).
173: <LI>The System (JVM) properties set (i.e. java.lang.System.getProperties()).
174: <LI>The application properties set (i.e. obtained from the cloudscape.properties file).
175: <LI>The default implementation properties set (i.e. obtained from the
176: /org/apache/derby/modules.properties resource).
177: </OL>
178: Any one of the properties can be missing or not have any implementations listed within it.
179: <BR>
180: Every request to create an instance of a module searches the four implementation
181: lists in the order above. Which list the current running code or the passed in service
182: module came from is not relevant.
183: <BR>
184: Within each list of potential implementations the search is conducted as follows:
185: <OL>
186: <LI>Attempt to load the class, if the class cannot be loaded skip to the next potential
187: implementation.
188: <LI>See if the factory interface is assignable from the class (isAssignableFrom() method
189: of java.lang.Class), if not skip to the next potential implementation.
190: <LI>See if an instance of the class can be created without any exceptions (newInstance() method
191: of java.lang.Class), if not skip to the next potential implementation.
192: <LI>[boot time only] See if the canSupport() method of ModuleControl returns true when called with the
193: Properties set of the service, if not skip to the next potential implementation.
194: </OL>
195: If all these checks pass then the instance is a valid implementation and its boot() method
196: of ModuleControl is called to activate it. Note that the search order within
197: the list obtained from a Properties set is not guaranteed.
198:
199: <P><B>Module Searching</B><BR>
200:
201: When searching for a module the search space is always restricted to a single service.
202: This service is usually the system service or the service of the module making the
203: search request. It would be very rare (wrong?) to search for a module in a service that
204: was not the current service and not the system service.
205: <BR>
206: Within the list of modules in the service the search is conducted as follows:
207: <OL>
208: <LI>See if the instance of the module an instance of the factory interface (isInstance() method
209: of java.lang.Class), if not skip to the next module.
210: <LI>See if the identifier of the module matches the required identifier, if not skip to the next module.
211: <LI>See if the canSupport() method of ModuleControl returns true when called with the
212: Properties set of the service, if not skip to the next module.
213: </OL>
214: Note that no search order of the modules is guaranteed.
215: <BR>
216: Also note that a module may be found by a different factory interface to the one
217: it was created under. Thus a class may implement multiple factory interfaces, its boot
218: method has no knowledge of which factory interface it was requested by.
219:
220: <P><B>Service Properties</B><BR>
221:
222: Within the service's Properties a module may search for its parameters. It identifies
223: its parameters using a unqiue parameter name and its identifier.
224: <BR>
225: Unique parameter names are made unique through the 'dot' convention of Properties
226: files. A module protocol picks some unique key portion to start, e.g. RawStore for the RawStoreFactory
227: and then extends that for specific parameters, e.g. RawStore.PageSize. Thus
228: parameters that are typically understood by all implementations of that protocol would
229: start with that key portion. Parameters for specific implementations add another key portion
230: onto the protocol key portion, e.g. RawStore.FileSystem for an file system implementation
231: of the raw store, with a specific parameter being RawStore.FileSystem.SectorSize.
232:
233: <BR>These are general guidelines, UUID's could be used as the properties keys but
234: would make the parameters hard to read.
235: <BR>
236: When a module is unidentified it should look for a parameter using just
237: the property key for that parameter, e.g. getProperty("RawStore.PageSize").
238: <BR>
239: When a module has an identifier is should look for a property using the
240: key with a dot and the identifier appended, e.g. getProperty("RawStore.PageSize" + "." + identifier).
241: <BR>
242: In addition to searching for parameters in the service properties set, the system and
243: application set may be searched using the getProperty() method of ModuleFactory.
244: <BR><B>Should any order be defined for this, should it be automatic?</B>
245: */
246: public class Monitor {
247:
248: public static final String SERVICE_TYPE_DIRECTORY = "serviceDirectory";
249:
250: public static final Object syncMe = new Object();
251:
252: /**
253: Global debug flag to turn on tracing of reads calls newInstanceFromIdentifier()
254: */
255: public final static String NEW_INSTANCE_FROM_ID_TRACE_DEBUG_FLAG = SanityManager.DEBUG ? "MonitorNewInstanceFromId"
256: : null;
257:
258: public static final String DEBUG_TRUE = SanityManager.DEBUG ? "derby.debug.true"
259: : null;
260: public static final String DEBUG_FALSE = SanityManager.DEBUG ? "derby.debug.false"
261: : null;
262:
263: private static ModuleFactory monitor;
264: private static boolean active;
265:
266: public Monitor() {
267: }
268:
269: /**
270: Start a Monitor based software system.
271:
272: This method will execute the following steps.
273:
274: <OL>
275: <LI> Create an instance of a module (monitor) of the required implementation.
276: <LI> Start the monitor which will in turn start any requested services
277: <LI> Execute the run() method of startCode (if startCode was not null).
278: <LI> Return.
279: </OL>
280: <P> If MonitorBoot.start() is called more then once then subsequent calls
281: have no effect.
282:
283: @param bootProperties The application properties
284: @param logging Where to place initial error output. This location will be used
285: until an InfoStreams module is successfully started.
286: */
287:
288: public static void startMonitor(Properties bootProperties,
289: PrintStream logging) {
290:
291: new org.apache.derby.impl.services.monitor.FileMonitor(
292: bootProperties, logging);
293: }
294:
295: /**
296: Initialise this class, must only be called by an implementation
297: of the monitor (ModuleFactory).
298: */
299: public static boolean setMonitor(ModuleFactory theMonitor) {
300:
301: synchronized (syncMe) {
302: if (active)
303: return false;
304:
305: monitor = theMonitor;
306: active = true;
307: return true;
308: }
309: }
310:
311: public static void clearMonitor() {
312: // the monitor reference needs to remain valid
313: // as there are some accesses to getMonitor()
314: // after the system has been shutdown.
315: synchronized (syncMe) {
316: active = false;
317: }
318: }
319:
320: /**
321: Get the monitor.
322: */
323: public static ModuleFactory getMonitor() {
324: return monitor;
325: }
326:
327: public static ModuleFactory getMonitorLite() {
328: synchronized (syncMe) {
329: if (active && monitor != null)
330: return monitor;
331: }
332:
333: // initialize a monitor just to get system properties
334: // with the right secuirty checks and the correct sematics
335: // for lookup of derby.system.home.
336: // This instance will be discarded once it is used. ;
337:
338: return new org.apache.derby.impl.services.monitor.FileMonitor();
339: }
340:
341: public static HeaderPrintWriter getStream() {
342: return monitor.getSystemStreams().stream();
343: }
344:
345: /**
346: Return the name of the service that the passed in module lives in.
347: */
348: public static String getServiceName(Object serviceModule) {
349: return monitor.getServiceName(serviceModule);
350: }
351:
352: /**
353: Start or find a module in the system service. This call allows modules
354: to explictly start services they require.
355: If no module matching the criteria is found (see this class's prologue for details)
356: then an instance will be created (see prologue) and booted as follows.
357: <PRE>
358: ((ModuleControl) instance).boot(false, (String) null, (Properties) null);
359: </PRE>
360:
361: @return a reference to a module.
362:
363: @exception StandardException An attempt to start the module failed.
364:
365: @see ModuleControl#boot
366: */
367: public static Object startSystemModule(String factoryInterface)
368: throws StandardException {
369:
370: Object module = monitor.startModule(false, (Object) null,
371: factoryInterface, (String) null, (Properties) null);
372:
373: if (SanityManager.DEBUG) {
374: SanityManager.ASSERT(module != null, "module is null - "
375: + factoryInterface);
376: }
377:
378: return module;
379: }
380:
381: /**
382: Find a module in the system service.
383:
384: @return a reference to a module or null if one cannot be found.
385: */
386: public static Object findSystemModule(String factoryInterface)
387: throws StandardException {
388: Object module = getMonitor().findModule((Object) null,
389: factoryInterface, (String) null);
390: if (module == null)
391: throw Monitor.missingImplementation(factoryInterface);
392:
393: return module;
394: }
395:
396: public static Object getSystemModule(String factoryInterface) {
397: Object module = getMonitor().findModule((Object) null,
398: factoryInterface, (String) null);
399: return module;
400: }
401:
402: /**
403: Boot or find a unidentified module within a service. This call allows modules
404: to start or create any modules they explicitly require to exist within
405: their service. If no module matching the criteria is found (see this class's prologue for details)
406: then an instance will be created (see prologue) and booted as follows.
407: <PRE>
408: ((ModuleControl) instance).boot(create, (String) null, properties);
409: </PRE>
410: <BR>
411: The service is defined by the service that the module serviceModule lives in,
412: typically this call is made from the boot method of a module and thus
413: 'this' is passed in for serviceModule.
414:
415: @return a reference to a module.
416:
417: @exception StandardException An attempt to start the module failed.
418:
419: */
420: public static Object bootServiceModule(boolean create,
421: Object serviceModule, String factoryInterface,
422: Properties properties) throws StandardException {
423:
424: Object module = monitor.startModule(create, serviceModule,
425: factoryInterface, (String) null, properties);
426:
427: if (SanityManager.DEBUG) {
428: SanityManager.ASSERT(module != null, "module is null - "
429: + factoryInterface);
430: }
431:
432: return module;
433: }
434:
435: /**
436: Boot or find a identified module within a service. This call allows modules
437: to start or create any modules they explicitly require to exist within
438: their service. If no module matching the criteria is found (see this class's prologue for details)
439: then an instance will be created (see prologue) and booted as follows.
440: <PRE>
441: ((ModuleControl) instance).boot(create, identifer, properties);
442: </PRE>
443: <BR>
444: The service is defined by the service that the module serviceModule lives in,
445: typically this call is made from the boot method of a module and thus
446: 'this' is passed in for serviceModule.
447:
448: @return a reference to a module.
449:
450: @exception StandardException An attempt to start the module failed.
451:
452: */
453: public static Object bootServiceModule(boolean create,
454: Object serviceModule, String factoryInterface,
455: String identifier, Properties properties)
456: throws StandardException {
457:
458: Object module = monitor.startModule(create, serviceModule,
459: factoryInterface, identifier, properties);
460:
461: if (SanityManager.DEBUG) {
462: SanityManager.ASSERT(module != null, "module is null - "
463: + factoryInterface);
464: }
465:
466: return module;
467: }
468:
469: /**
470: Find an unidentified module within a service.
471: <BR>
472: The service is defined by the service that the module serviceModule lives in.
473:
474: @return a reference to a module or null if one cannot be found.
475:
476: */
477: public static Object findServiceModule(Object serviceModule,
478: String factoryInterface) throws StandardException {
479: Object module = getMonitor().findModule(serviceModule,
480: factoryInterface, (String) null);
481: if (module == null)
482: throw Monitor.missingImplementation(factoryInterface);
483: return module;
484: }
485:
486: public static Object getServiceModule(Object serviceModule,
487: String factoryInterface) {
488: Object module = getMonitor().findModule(serviceModule,
489: factoryInterface, (String) null);
490: return module;
491: }
492:
493: /**
494: Find an identified module within a service.
495: <BR>
496: The service is defined by the service that the module serviceModule lives in.
497:
498: @return a reference to a module or null if one cannot be found.
499:
500: */
501: //public static Object findServiceModule(Object serviceModule, String factoryInterface, String identifier) {
502: // return monitor.findModule(serviceModule, factoryInterface, identifier);
503: //}
504:
505: /**
506: Find a service.
507:
508: @return a refrence to a module represeting the service or null if the service does not exist.
509:
510: */
511: public static Object findService(String factoryInterface,
512: String serviceName) {
513: return monitor.findService(factoryInterface, serviceName);
514: }
515:
516: /**
517: Start a persistent service. The name of the service can include a
518: service type, in the form 'type:serviceName'.
519: <BR>
520: Note that the return type only indicates
521: if the service can be handled by the monitor. It does not indicate
522: the service was started successfully. The cases are
523: <OL>
524: <LI> Service type not handled - false returned.
525: <LI> Service type handled, service does not exist, true returned.
526: <LI> Service type handled, service exists and booted OK, true returned.
527: <LI> Service type handled, service exists and failed to boot, exception thrown.
528: </OL>
529:
530: If true is returned then findService should be used to see if the service
531: exists or not.
532:
533: <P> The poperty set passed in is for boot options for the modules
534: required to start the service. It does not support defining different
535: or new modules implementations.
536:
537: @param serviceName Name of the service to be started
538: @param properties Property set made available to all modules booted
539: for this service, through their ModuleControl.boot method.
540:
541: @return true if the service type is handled by the monitor, false if it isn't
542:
543: @exception StandardException An attempt to start the service failed.
544: */
545:
546: public static boolean startPersistentService(String serviceName,
547: Properties properties) throws StandardException {
548:
549: if (SanityManager.DEBUG) {
550: SanityManager.ASSERT(serviceName != null,
551: "serviceName is null");
552: }
553:
554: return monitor.startPersistentService(serviceName, properties);
555: }
556:
557: /**
558: Start a non-persistent service.
559: <P><B>Context</B><BR>
560: A context manager will be created and installed at the start of this method and destroyed
561: just before this method returns.
562:
563: @return The module from the service if it was started successfully.
564:
565: @exception StandardException An exception was thrown trying to start the service.
566: */
567: public static Object startNonPersistentService(
568: String factoryInterface, String serviceName,
569: Properties properties) throws StandardException {
570:
571: if (SanityManager.DEBUG) {
572: SanityManager.ASSERT(factoryInterface != null,
573: "serviceName is null");
574: SanityManager.ASSERT(serviceName != null,
575: "serviceName is null");
576: }
577:
578: return monitor.startNonPersistentService(factoryInterface,
579: serviceName, properties);
580: }
581:
582: /**
583: Create a named service that implements the java interface (or class) fully qualified by factoryInterface.
584: The Properties object specifies create time parameters to be used by the modules within the
585: service. Any module created by this service may add or remove parameters within the
586: properties object in their ModuleControl.boot() method. The properties set will be saved
587: by the Monitor for later use when the monitor is started.
588: <P><B>Context</B><BR>
589: A context manager will be created and installed at the start of this method and destroyed
590: just before this method returns.
591:
592: @return The module from the service if it was created successfully, null if a service already existed.
593:
594: @exception StandardException An exception was thrown trying to create the service.
595: */
596: public static Object createPersistentService(
597: String factoryInterface, String serviceName,
598: Properties properties) throws StandardException {
599:
600: if (SanityManager.DEBUG) {
601: SanityManager.ASSERT(factoryInterface != null,
602: "serviceName is null");
603: SanityManager.ASSERT(serviceName != null,
604: "serviceName is null");
605: }
606:
607: return monitor.createPersistentService(factoryInterface,
608: serviceName, properties);
609: }
610:
611: public static void removePersistentService(String name)
612: throws StandardException {
613: monitor.removePersistentService(name);
614: }
615:
616: /**
617: Obtain the class object for a class that supports the given identifier.
618:
619: If no class has been registered for the identifier then a StandardException
620: is thrown with no attached java.lang exception (nextException).
621: If a problem loading or accessing the class is obtained then a StandardException
622: is thrown with the real java.lang exception attached.
623:
624: @return a valid class object
625:
626: @exception StandardException See text above.
627: */
628: public static InstanceGetter classFromIdentifier(int identifier)
629: throws StandardException {
630: return monitor.classFromIdentifier(identifier);
631: }
632:
633: /**
634: Obtain an new instance of a class that supports the given identifier.
635:
636: If no class has been registered for the identifier then a StandardException
637: is thrown with no attached java.lang exception (getNestedException).
638: If a problem loading or accessing the class or creating the object is obtained
639: then a StandardException is thrown with the real java.lang exception attached.
640:
641: @return a reference to a newly created object
642:
643: @exception StandardException See text above.
644: */
645: public static Object newInstanceFromIdentifier(int identifier)
646: throws StandardException {
647: return monitor.newInstanceFromIdentifier(identifier);
648: }
649:
650: /*
651: ** Static methods for startup type exceptions.
652: */
653: /**
654: return a StandardException to indicate that a module failed to
655: start because it could not obtain the version of a required product.
656:
657: @param productGenusName The genus name of the product.
658: @return The exception.
659: */
660: public static StandardException missingProductVersion(
661: String productGenusName) {
662: return StandardException.newException(
663: SQLState.MISSING_PRODUCT_VERSION, productGenusName);
664: }
665:
666: /**
667: return a StandardException to indicate a missing
668: implementation.
669:
670: @param implementation the module name of the missing implementation.
671:
672: @return The exception.
673: */
674: public static StandardException missingImplementation(
675: String implementation) {
676: return StandardException
677: .newException(SQLState.SERVICE_MISSING_IMPLEMENTATION,
678: implementation);
679: }
680:
681: /**
682: return a StandardException to indicate that an exception caused
683: starting the module to fail.
684:
685: @param t the exception which caused starting the module to fail.
686:
687: @return The exception.
688: */
689: public static StandardException exceptionStartingModule(Throwable t) {
690: return StandardException.newException(
691: SQLState.SERVICE_STARTUP_EXCEPTION, t);
692: }
693:
694: public static void logMessage(String messageText) {
695: getStream().println(messageText);
696: }
697:
698: public static void logTextMessage(String messageID) {
699: getStream().println(MessageService.getTextMessage(messageID));
700: }
701:
702: public static void logTextMessage(String messageID, Object a1) {
703: getStream().println(
704: MessageService.getTextMessage(messageID, a1));
705: }
706:
707: public static void logTextMessage(String messageID, Object a1,
708: Object a2) {
709: getStream().println(
710: MessageService.getTextMessage(messageID, a1, a2));
711: }
712:
713: public static void logTextMessage(String messageID, Object a1,
714: Object a2, Object a3) {
715: getStream().println(
716: MessageService.getTextMessage(messageID, a1, a2, a3));
717: }
718:
719: public static void logTextMessage(String messageID, Object a1,
720: Object a2, Object a3, Object a4) {
721: getStream().println(
722: MessageService
723: .getTextMessage(messageID, a1, a2, a3, a4));
724: }
725:
726: /**
727: * Translate a localeDescription of the form ll[_CC[_variant]] to
728: * a Locale object.
729: */
730: public static Locale getLocaleFromString(String localeDescription)
731: throws StandardException {
732: return monitor.getLocaleFromString(localeDescription);
733: }
734:
735: /**
736: Single point for checking if an upgrade is allowed.
737: @return true a full upgrade has been requested, false soft upgrade mode is active.
738: */
739: public static boolean isFullUpgrade(Properties startParams,
740: String oldVersionInfo) throws StandardException {
741:
742: boolean fullUpgrade = Boolean
743: .valueOf(
744: startParams
745: .getProperty(org.apache.derby.iapi.reference.Attribute.UPGRADE_ATTR))
746: .booleanValue();
747:
748: ProductVersionHolder engineVersion = Monitor.getMonitor()
749: .getEngineVersion();
750:
751: if (engineVersion.isBeta() || engineVersion.isAlpha()) {
752:
753: if (!PropertyUtil
754: .getSystemBoolean(Property.ALPHA_BETA_ALLOW_UPGRADE)) {
755: // upgrade not supported for alpha/beta.
756: throw StandardException.newException(
757: SQLState.UPGRADE_UNSUPPORTED, oldVersionInfo,
758: engineVersion.getSimpleVersionString());
759: }
760: }
761:
762: return fullUpgrade;
763: }
764:
765: /**
766: *
767: * @param startParams startup parameters
768: * @param desiredProperty property we're interested in
769: *
770: * @return true type is as desired.
771: * false otherwise
772: *
773: */
774: public static boolean isDesiredType(Properties startParams,
775: int desiredProperty) {
776: boolean retval = false;
777: int engineType = EngineType.NONE;
778:
779: if (startParams != null) {
780: engineType = Monitor.getEngineType(startParams);
781: }
782:
783: return (engineType & desiredProperty) != 0;
784: }
785:
786: public static boolean isDesiredType(int engineType,
787: int desiredProperty) {
788: return (engineType & desiredProperty) != 0;
789: }
790:
791: /**
792: * @param startParams startup parameters
793: *
794: * @return type of engine
795: *
796: */
797:
798: static public int getEngineType(Properties startParams) {
799: if (startParams != null) {
800: String etp = startParams.getProperty(EngineType.PROPERTY);
801:
802: int engineType = etp == null ? EngineType.STANDALONE_DB
803: : Integer.parseInt(etp.trim());
804:
805: return engineType;
806: }
807:
808: return EngineType.STANDALONE_DB;
809: }
810:
811: /**
812: Return true if the properties set provided contains
813: database creation attributes for a database
814: of the correct type
815: */
816: public static boolean isDesiredCreateType(Properties p, int type) {
817: boolean plainCreate = Boolean.valueOf(
818: p.getProperty(Attribute.CREATE_ATTR)).booleanValue();
819:
820: if (plainCreate) {
821: return (type & EngineType.NONE) != 0;
822: }
823:
824: // database must already exist
825: return isDesiredType(p, type);
826: }
827: }
|