001: /* Copyright (C) 2004 - 2007 db4objects Inc. http://www.db4o.com
002:
003: This file is part of the db4o open source object database.
004:
005: db4o is free software; you can redistribute it and/or modify it under
006: the terms of version 2 of the GNU General Public License as published
007: by the Free Software Foundation and as clarified by db4objects' GPL
008: interpretation policy, available at
009: http://www.db4o.com/about/company/legalpolicies/gplinterpretation/
010: Alternatively you can write to db4objects, Inc., 1900 S Norfolk Street,
011: Suite 350, San Mateo, CA 94403, USA.
012:
013: db4o is distributed in the hope that it will be useful, but WITHOUT ANY
014: WARRANTY; without even the implied warranty of MERCHANTABILITY or
015: FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
016: for more details.
017:
018: You should have received a copy of the GNU General Public License along
019: with this program; if not, write to the Free Software Foundation, Inc.,
020: 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
021: package com.db4o.internal;
022:
023: import java.net.*;
024: import java.util.Date;
025:
026: import com.db4o.*;
027: import com.db4o.config.*;
028: import com.db4o.foundation.*;
029: import com.db4o.internal.handlers.*;
030: import com.db4o.internal.query.processor.*;
031: import com.db4o.query.*;
032: import com.db4o.reflect.*;
033: import com.db4o.reflect.generic.*;
034: import com.db4o.types.*;
035:
036: /**
037: * @exclude
038: * @sharpen.ignore
039: */
040: public final class Platform4 {
041:
042: private static final String JDK_PACKAGE = "com.db4o.internal.";
043:
044: static private TernaryBool collectionCheck = TernaryBool.UNSPECIFIED;
045:
046: static private JDK jdkWrapper;
047: static private TernaryBool nioCheck = TernaryBool.UNSPECIFIED;
048:
049: static private TernaryBool setAccessibleCheck = TernaryBool.UNSPECIFIED;
050: static private TernaryBool shutDownHookCheck = TernaryBool.UNSPECIFIED;
051: static TernaryBool callConstructorCheck = TernaryBool.UNSPECIFIED;
052: static ShutDownRunnable shutDownRunnable;
053:
054: static Thread shutDownThread;
055:
056: static final String ACCESSIBLEOBJECT = "java.lang.reflect.AccessibleObject";
057: static final String GETCONSTRUCTOR = "newConstructorForSerialization";
058: static final String REFERENCEQUEUE = "java.lang.ref.ReferenceQueue";
059: static final String REFLECTIONFACTORY = "sun.reflect.ReflectionFactory";
060: static final String RUNFINALIZERSONEXIT = "runFinalizersOnExit";
061:
062: static final String UTIL = "java.util.";
063: static final String DB4O_PACKAGE = "com.db4o.";
064: static final String DB4O_CONFIG = DB4O_PACKAGE + "config.";
065: static final String DB4O_ASSEMBLY = ", db4o";
066:
067: // static private int cCreateNewFile;
068: static private TernaryBool weakReferenceCheck = TernaryBool.UNSPECIFIED;
069:
070: private static final Class[] SIMPLE_CLASSES = { Integer.class,
071: Long.class, Float.class, Boolean.class, Double.class,
072: Byte.class, Character.class, Short.class, String.class,
073: java.util.Date.class };
074:
075: synchronized static final void addShutDownHook(
076: PartialObjectContainer container) {
077: if (!hasShutDownHook()) {
078: return;
079: }
080:
081: if (shutDownThread == null) {
082: shutDownRunnable = new ShutDownRunnable();
083: shutDownThread = jdk().addShutdownHook(shutDownRunnable);
084: }
085: shutDownRunnable.ensure(container);
086: }
087:
088: public static final boolean canSetAccessible() {
089: if (setAccessibleCheck.unspecified()) {
090: if (jdk().ver() >= 2) {
091: setAccessibleCheck = TernaryBool.YES;
092: } else {
093: setAccessibleCheck = TernaryBool.NO;
094: if (((Config4Impl) Db4o.configure()).messageLevel() >= 0) {
095: Messages.logErr(Db4o.configure(), 47, null, null);
096: }
097: }
098: }
099: return setAccessibleCheck.definiteYes();
100: }
101:
102: /**
103: * use for system classes only, since not ClassLoader
104: * or Reflector-aware
105: */
106: static final boolean classIsAvailable(String className) {
107: return ReflectPlatform.forName(className) != null;
108: }
109:
110: static Db4oCollections collections(Transaction transaction) {
111: return jdk().collections(transaction);
112: }
113:
114: static final Reflector createReflector(Object classLoader) {
115: return jdk().createReflector(classLoader);
116: }
117:
118: static final Object createReferenceQueue() {
119: return jdk().createReferenceQueue();
120: }
121:
122: public static Object createWeakReference(Object obj) {
123: return jdk().createWeakReference(obj);
124: }
125:
126: static final Object createActiveObjectReference(Object a_queue,
127: Object a_yapObject, Object a_object) {
128: return jdk().createActivateObjectReference(a_queue,
129: (ObjectReference) a_yapObject, a_object);
130: }
131:
132: public static Object deserialize(byte[] bytes) {
133: return jdk().deserialize(bytes);
134: }
135:
136: public static final long doubleToLong(double a_double) {
137: return Double.doubleToLongBits(a_double);
138: }
139:
140: public static final QConEvaluation evaluationCreate(
141: Transaction a_trans, Object example) {
142: if (example instanceof Evaluation) {
143: return new QConEvaluation(a_trans, example);
144: }
145: return null;
146: }
147:
148: public static final void evaluationEvaluate(Object a_evaluation,
149: Candidate a_candidate) {
150: ((Evaluation) a_evaluation).evaluate(a_candidate);
151: }
152:
153: /** may be needed for YapConfig processID() at a later date */
154: /*
155: static boolean createNewFile(File file) throws IOException{
156: return file.createNewFile();
157: }
158: */
159:
160: public static Object[] collectionToArray(
161: ObjectContainerBase stream, Object obj) {
162: Collection4 col = flattenCollection(stream, obj);
163: Object[] ret = new Object[col.size()];
164: col.toArray(ret);
165: return ret;
166: }
167:
168: static final Collection4 flattenCollection(
169: ObjectContainerBase stream, Object obj) {
170: Collection4 col = new Collection4();
171: flattenCollection1(stream, obj, col);
172: return col;
173: }
174:
175: /**
176: * Should create additional configuration, for example through reflection
177: * on annotations.
178: *
179: * - If a valid configuration is passed as classConfig, any additional
180: * configuration, if available, should be applied to this object, and
181: * this object should be returned.
182: * - If classConfig is null and there is no additional configuration,
183: * null should be returned.
184: * - If classConfig is null and there is additional configuration, this code
185: * should create and register a new configuration via config.objectClass(),
186: * apply additional configuration there and return this new instance.
187: *
188: * The reason for this dispatch is to avoid creation of a configuration
189: * for a class that doesn't need configuration at all.
190: *
191: * @param clazz The class to be searched for additional configuration information
192: * @param config The global database configuration
193: * @param classConfig A class configuration, if one already exists
194: * @return classConfig, if not null, a newly created ObjectClass otherwise.
195: */
196: public static Config4Class extendConfiguration(ReflectClass clazz,
197: Configuration config, Config4Class classConfig) {
198: return jdk().extendConfiguration(clazz, config, classConfig);
199: }
200:
201: static final void flattenCollection1(ObjectContainerBase stream,
202: Object obj, Collection4 col) {
203: if (obj == null) {
204: col.add(null);
205: } else {
206: ReflectClass claxx = stream.reflector().forObject(obj);
207: if (claxx.isArray()) {
208: Object[] objects;
209: if (claxx.getComponentType().isArray()) {
210: objects = new MultidimensionalArrayHandler(stream,
211: null, false).allElements(obj);
212: } else {
213: objects = new ArrayHandler(stream, null, false)
214: .allElements(obj);
215: }
216: for (int i = 0; i < objects.length; i++) {
217: flattenCollection1(stream, objects[i], col);
218: }
219: } else {
220: flattenCollection2(stream, obj, col);
221: }
222: }
223: }
224:
225: static final void flattenCollection2(
226: final ObjectContainerBase a_stream, Object a_object,
227: final com.db4o.foundation.Collection4 col) {
228: Reflector reflector = a_stream.reflector();
229: if (reflector.forObject(a_object).isCollection()) {
230: forEachCollectionElement(a_object, new Visitor4() {
231: public void visit(Object obj) {
232: flattenCollection1(a_stream, obj, col);
233: }
234: });
235: } else {
236: col.add(a_object);
237: }
238: }
239:
240: static final void forEachCollectionElement(Object a_object,
241: Visitor4 a_visitor) {
242: jdk().forEachCollectionElement(a_object, a_visitor);
243: }
244:
245: public static final String format(Date date, boolean showTime) {
246: return jdk().format(date, showTime);
247: }
248:
249: public static Object getClassForType(Object obj) {
250: return obj;
251: }
252:
253: public static final void getDefaultConfiguration(Config4Impl config) {
254:
255: // Initialize all JDK stuff first, before doing ClassLoader stuff
256: jdk();
257: hasWeakReferences();
258: hasNio();
259: hasCollections();
260: hasShutDownHook();
261:
262: if (config.reflector() == null) {
263: config.reflectWith(jdk().createReflector(null));
264: }
265:
266: config.objectClass("java.lang.StringBuffer").compare(
267: new ObjectAttribute() {
268: public Object attribute(Object original) {
269: if (original instanceof StringBuffer) {
270: return ((StringBuffer) original).toString();
271: }
272: return original;
273: }
274: });
275:
276: translate(config.objectClass("java.lang.Class"), "TClass");
277: translateCollection(config, "Hashtable", "THashtable", true);
278: if (jdk().ver() >= 2) {
279: try {
280: translateCollection(config, "AbstractCollection",
281: "TCollection", false);
282: translateUtilNull(config, "AbstractList");
283: translateUtilNull(config, "AbstractSequentialList");
284: translateUtilNull(config, "LinkedList");
285: translateUtilNull(config, "ArrayList");
286: translateUtilNull(config, "Vector");
287: translateUtilNull(config, "Stack");
288: translateUtilNull(config, "AbstractSet");
289: translateUtilNull(config, "HashSet");
290: translate(config, UTIL + "TreeSet", "TTreeSet");
291: translateCollection(config, "AbstractMap", "TMap", true);
292: translateUtilNull(config, "HashMap");
293: translateUtilNull(config, "WeakHashMap");
294: translate(config, UTIL + "TreeMap", "TTreeMap");
295: } catch (Exception e) {
296: }
297: } else {
298: translateCollection(config, "Vector", "TVector", false);
299: }
300: netReadAsJava(config, "ext.Db4oDatabase");
301: netReadAsJava(config, "P1Object");
302: netReadAsJava(config, "P1Collection");
303: netReadAsJava(config, "P1HashElement");
304: netReadAsJava(config, "P1ListElement");
305: netReadAsJava(config, "P2HashMap");
306: netReadAsJava(config, "P2LinkedList");
307: netReadAsJava(config, "StaticClass");
308: netReadAsJava(config, "StaticField");
309: }
310:
311: public static Object getTypeForClass(Object obj) {
312: return obj;
313: }
314:
315: static final Object getYapRefObject(Object a_object) {
316: return jdk().getYapRefObject(a_object);
317: }
318:
319: static final synchronized boolean hasCollections() {
320: if (collectionCheck.unspecified()) {
321: if (classIsAvailable(UTIL + "Collection")) {
322: collectionCheck = TernaryBool.YES;
323: return true;
324: }
325: collectionCheck = TernaryBool.NO;
326: }
327: return collectionCheck.definiteYes();
328: }
329:
330: public static final boolean hasLockFileThread() {
331: return true;
332: }
333:
334: public static final boolean hasNio() {
335: if (!Debug.nio) {
336: return false;
337: }
338: if (nioCheck.unspecified()) {
339: if ((jdk().ver() >= 4) && (!noNIO())) {
340: nioCheck = TernaryBool.YES;
341: return true;
342: }
343: nioCheck = TernaryBool.NO;
344: }
345: return nioCheck.definiteYes();
346:
347: }
348:
349: static final boolean hasShutDownHook() {
350: if (shutDownHookCheck.unspecified()) {
351: if (jdk().ver() >= 3) {
352: shutDownHookCheck = TernaryBool.YES;
353: return true;
354: }
355: Reflection4.invoke(System.class, RUNFINALIZERSONEXIT,
356: new Class[] { boolean.class },
357: new Object[] { new Boolean(true) });
358: shutDownHookCheck = TernaryBool.NO;
359: }
360: return shutDownHookCheck.definiteYes();
361: }
362:
363: static final boolean hasWeakReferences() {
364: if (!Debug.weakReferences) {
365: return false;
366: }
367: if (weakReferenceCheck.unspecified()) {
368: if (classIsAvailable(ACCESSIBLEOBJECT)
369: && classIsAvailable(REFERENCEQUEUE)
370: && jdk().ver() >= 2) {
371: weakReferenceCheck = TernaryBool.YES;
372: return true;
373: }
374: weakReferenceCheck = TernaryBool.NO;
375: }
376: return weakReferenceCheck.definiteYes();
377: }
378:
379: /** @param obj */
380: static final boolean ignoreAsConstraint(Object obj) {
381: return false;
382: }
383:
384: static final boolean isCollectionTranslator(Config4Class a_config) {
385: return jdk().isCollectionTranslator(a_config);
386: }
387:
388: public static boolean isConnected(Socket socket) {
389: return jdk().isConnected(socket);
390: }
391:
392: /** @param claxx */
393: public static final boolean isValueType(ReflectClass claxx) {
394: return false;
395: }
396:
397: public static JDK jdk() {
398: if (jdkWrapper == null) {
399: createJdk();
400: }
401: return jdkWrapper;
402: }
403:
404: private static void createJdk() {
405:
406: if (classIsAvailable("java.lang.reflect.Method")) {
407: jdkWrapper = (JDK) ReflectPlatform
408: .createInstance(JDK_PACKAGE + "JDKReflect");
409: }
410:
411: if (classIsAvailable(Platform4.ACCESSIBLEOBJECT)) {
412: jdkWrapper = createJDKWrapper("1_2");
413: }
414:
415: if (jdk().methodIsAvailable("java.lang.Runtime",
416: "addShutdownHook", new Class[] { Thread.class })) {
417: jdkWrapper = createJDKWrapper("1_3");
418: }
419:
420: if (classIsAvailable("java.nio.channels.FileLock")) {
421: jdkWrapper = createJDKWrapper("1_4");
422: }
423:
424: if (classIsAvailable("java.lang.Enum")) {
425: jdkWrapper = createJDKWrapper("5");
426: }
427:
428: }
429:
430: private static JDK createJDKWrapper(String name) {
431: JDK newWrapper = (JDK) ReflectPlatform
432: .createInstance(JDK_PACKAGE + "JDK_" + name);
433: if (newWrapper != null) {
434: return newWrapper;
435: }
436: return jdkWrapper;
437: }
438:
439: public static boolean isSimple(Class a_class) {
440: for (int i = 0; i < SIMPLE_CLASSES.length; i++) {
441: if (a_class == SIMPLE_CLASSES[i]) {
442: return true;
443: }
444: }
445: return false;
446: }
447:
448: static final void killYapRef(Object a_object) {
449: jdk().killYapRef(a_object);
450: }
451:
452: public static void link() {
453: // link standard translators, so they won't get deleted
454: // by deployment
455:
456: new TClass();
457: new TVector();
458: new THashtable();
459: new TNull();
460: }
461:
462: // FIXME: functionality should really be in IoAdapter
463: public static final void lockFile(String path, Object file) {
464: if (!hasNio()) {
465: return;
466: }
467:
468: // FIXME: libgcj 3.x isn't able to properly lock the database file
469: String fullversion = System.getProperty("java.fullversion");
470: if (fullversion != null
471: && fullversion.indexOf("GNU libgcj") >= 0) {
472: System.err
473: .println("Warning: Running in libgcj 3.x--not locking database file!");
474: return;
475: }
476:
477: jdk().lockFile(path, file);
478: }
479:
480: public static final void unlockFile(String path, Object file) {
481: if (hasNio()) {
482: jdk().unlockFile(path, file);
483: }
484: }
485:
486: public static final double longToDouble(long a_long) {
487: return Double.longBitsToDouble(a_long);
488: }
489:
490: /** @param marker */
491: static void markTransient(String marker) {
492: // do nothing
493: }
494:
495: static boolean callConstructor() {
496: if (callConstructorCheck.unspecified()) {
497:
498: if (jdk()
499: .methodIsAvailable(
500: REFLECTIONFACTORY,
501: GETCONSTRUCTOR,
502: new Class[] { Class.class,
503: jdk().constructorClass() })) {
504:
505: callConstructorCheck = TernaryBool.NO;
506: return false;
507: }
508: callConstructorCheck = TernaryBool.YES;
509: }
510: return callConstructorCheck.definiteYes();
511: }
512:
513: private static final void netReadAsJava(Config4Impl config,
514: String className) {
515: Config4Class classConfig = (Config4Class) config
516: .objectClass(DB4O_PACKAGE + className + DB4O_ASSEMBLY);
517: if (classConfig == null) {
518: return;
519: }
520: classConfig.maintainMetaClass(false);
521: classConfig.readAs(DB4O_PACKAGE + className);
522: }
523:
524: private static final boolean noNIO() {
525: try {
526: if (propertyIs("java.vendor", "Sun")
527: && propertyIs("java.version", "1.4.0")
528: && (propertyIs("os.name", "Linux")
529: || propertyIs("os.name", "Windows 95") || propertyIs(
530: "os.name", "Windows 98"))) {
531: return true;
532: }
533: return false;
534: } catch (Exception e) {
535: return true;
536: }
537: }
538:
539: static final void pollReferenceQueue(Object a_stream,
540: Object a_referenceQueue) {
541: jdk().pollReferenceQueue((ObjectContainerBase) a_stream,
542: a_referenceQueue);
543: }
544:
545: /** @param oc */
546: public static void postOpen(ObjectContainer oc) {
547: // do nothing
548: }
549:
550: /** @param oc */
551: static void preClose(ObjectContainer oc) {
552: // do nothing
553: }
554:
555: private static final boolean propertyIs(String propertyName,
556: String propertyValue) {
557: String property = System.getProperty(propertyName);
558: return (property != null)
559: && (property.indexOf(propertyValue) == 0);
560: }
561:
562: public static void registerCollections(GenericReflector reflector) {
563: reflector.registerCollection(P1Collection.class);
564: jdk().registerCollections(reflector);
565: }
566:
567: synchronized static final void removeShutDownHook(
568: PartialObjectContainer container) {
569: if (!hasShutDownHook() || shutDownRunnable == null) {
570: return;
571: }
572:
573: shutDownRunnable.remove(container);
574: if (shutDownRunnable.size() == 0) {
575: if (!shutDownRunnable.dontRemove) {
576: try {
577: jdk().removeShutdownHook(shutDownThread);
578: } catch (Exception e) {
579: // this is safer than attempting perfect
580: // synchronisation
581: }
582: }
583: shutDownThread = null;
584: shutDownRunnable = null;
585: }
586: }
587:
588: public static final byte[] serialize(Object obj) throws Exception {
589: return jdk().serialize(obj);
590: }
591:
592: public static final void setAccessible(Object a_accessible) {
593: if (setAccessibleCheck == TernaryBool.UNSPECIFIED) {
594: canSetAccessible();
595: }
596: if (setAccessibleCheck == TernaryBool.YES) {
597: jdk().setAccessible(a_accessible);
598: }
599: }
600:
601: public static boolean storeStaticFieldValues(Reflector reflector,
602: ReflectClass claxx) {
603: return jdk().isEnum(reflector, claxx);
604: }
605:
606: private static final void translate(ObjectClass oc, String to) {
607: ((Config4Class) oc).translateOnDemand(DB4O_CONFIG + to);
608: }
609:
610: private static final void translate(Config4Impl config,
611: String from, String to) {
612: translate(config.objectClass(from), to);
613: }
614:
615: private static final void translateCollection(Config4Impl config,
616: String from, String to, boolean cascadeOnDelete) {
617: ObjectClass oc = config.objectClass(UTIL + from);
618: oc.updateDepth(3);
619: if (cascadeOnDelete) {
620: oc.cascadeOnDelete(true);
621: }
622: translate(oc, to);
623: }
624:
625: private static final void translateUtilNull(Config4Impl config,
626: String className) {
627: translate(config, UTIL + className, "TNull");
628: }
629:
630: static final NetTypeHandler[] types(ObjectContainerBase container) {
631: return jdk().types(container);
632: }
633:
634: public static byte[] updateClassName(byte[] bytes) {
635: // needed for .NET only: update assembly names if necessary
636: return bytes;
637: }
638:
639: public static Object weakReferenceTarget(Object weakRef) {
640: return jdk().weakReferenceTarget(weakRef);
641: }
642:
643: public static Object wrapEvaluation(Object evaluation) {
644: return evaluation;
645: }
646:
647: public static boolean isDb4oClass(String className) {
648: if (className.indexOf(".test.") > 0) {
649: return false;
650: }
651: if (className.indexOf(".db4ounit.") > 0) {
652: return false;
653: }
654: return className.indexOf("com.db4o") == 0;
655: }
656:
657: /** @param claxx */
658: public static boolean isTransient(ReflectClass claxx) {
659: return false;
660: }
661:
662: public static Reflector reflectorForType(Class clazz) {
663: return jdk().reflectorForType(clazz);
664: }
665: }
|