001: /*
002: * Copyright (c) 1998 - 2005 Versant Corporation
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * Versant Corporation - initial API and implementation
010: */
011: package com.versant.core.jdo.externalizer;
012:
013: import com.versant.core.common.BindingSupportImpl;
014: import com.versant.core.common.Utils;
015:
016: import javax.jdo.PersistenceManager;
017: import java.lang.reflect.Constructor;
018: import java.lang.reflect.Method;
019: import java.io.*;
020:
021: /**
022: * This externalizer can convert any type to/from byte[]. The type must have
023: * a constructor that accepts a byte[] and a method called toBytes that
024: * will provide a byte[].
025: *
026: * This class is Serializable. This is only a requirement if you are using
027: * remote PMs.
028: */
029: public class TypeAsBytesExternalizer implements Externalizer,
030: Externalizable {
031:
032: public static final String SHORT_NAME = "BYTES";
033:
034: private Class type;
035: private Constructor constructor;
036: private Method toBytes;
037:
038: public TypeAsBytesExternalizer(Class type) {
039: this .type = type;
040: init();
041: }
042:
043: public TypeAsBytesExternalizer() {
044: }
045:
046: private void init() {
047: try {
048: constructor = type
049: .getConstructor(new Class[] { byte[].class });
050: } catch (NoSuchMethodException e) {
051: throw BindingSupportImpl.getInstance().runtime(
052: type + " does not have a "
053: + "constructor that accepts a byte[]", e);
054: }
055: try {
056: toBytes = type.getMethod("toBytes", null);
057: } catch (NoSuchMethodException e) {
058: throw BindingSupportImpl.getInstance().runtime(
059: type + " does not have a "
060: + "public toBytes() method", e);
061: }
062: if (toBytes.getReturnType() != byte[].class) {
063: throw BindingSupportImpl.getInstance().runtime(
064: type + ".toBytes() does not " + "return byte[]");
065: }
066: }
067:
068: public Object toExternalForm(PersistenceManager pm, Object o) {
069: if (o == null)
070: return null;
071: try {
072: return toBytes.invoke(o, null);
073: } catch (Throwable x) {
074: throw BindingSupportImpl.getInstance().fatalDatastore(
075: "Unable to convert instance of " + type.getName()
076: + " '" + Utils.toString(o)
077: + "' to byte[]: " + x, x);
078: }
079: }
080:
081: public Object fromExternalForm(PersistenceManager pm, Object o) {
082: if (o == null)
083: return null;
084: if (!(o instanceof byte[])) {
085: throw BindingSupportImpl.getInstance().runtime(
086: "Expected byte[] to create instance of "
087: + type.getName() + ", got: "
088: + Utils.toString(o));
089: }
090: try {
091: return constructor.newInstance(new Object[] { o });
092: } catch (Throwable x) {
093: throw BindingSupportImpl.getInstance().runtime(
094: "Unable to create instance of " + type.getName()
095: + " from " + Utils.toString(o) + ": " + x,
096: x);
097: }
098: }
099:
100: public Class getExternalType() {
101: return byte[].class;
102: }
103:
104: public void writeExternal(ObjectOutput out) throws IOException {
105: out.writeObject(type);
106: }
107:
108: public void readExternal(ObjectInput in) throws IOException,
109: ClassNotFoundException {
110: type = (Class) in.readObject();
111: init();
112: }
113: }
|