001: /*-
002: * See the file LICENSE for redistribution information.
003: *
004: * Copyright (c) 2002,2008 Oracle. All rights reserved.
005: *
006: * $Id: ProxiedFormat.java,v 1.19.2.5 2008/01/07 15:14:20 cwl Exp $
007: */
008:
009: package com.sleepycat.persist.impl;
010:
011: import java.lang.reflect.Array;
012: import java.util.IdentityHashMap;
013: import java.util.Map;
014: import java.util.Set;
015:
016: import com.sleepycat.persist.model.PersistentProxy;
017: import com.sleepycat.persist.raw.RawObject;
018:
019: /**
020: * Format for types proxied by a PersistentProxy.
021: *
022: * @author Mark Hayes
023: */
024: public class ProxiedFormat extends Format {
025:
026: private static final long serialVersionUID = -1000032651995478768L;
027:
028: private Format proxyFormat;
029: private transient String proxyClassName;
030:
031: ProxiedFormat(Class proxiedType, String proxyClassName) {
032: super (proxiedType);
033: this .proxyClassName = proxyClassName;
034: }
035:
036: /**
037: * Returns the proxy class name. The proxyClassName field is non-null for
038: * a constructed object and null for a de-serialized object. Whenever the
039: * proxyClassName field is null (for a de-serialized object), the
040: * proxyFormat will be non-null.
041: */
042: private String getProxyClassName() {
043: if (proxyClassName != null) {
044: return proxyClassName;
045: } else {
046: assert proxyFormat != null;
047: return proxyFormat.getClassName();
048: }
049: }
050:
051: /**
052: * In the future if we implement container proxies, which support nested
053: * references to the container, then we will return false if this is a
054: * container proxy. [#15815]
055: */
056: @Override
057: boolean areNestedRefsProhibited() {
058: return true;
059: }
060:
061: @Override
062: void collectRelatedFormats(Catalog catalog,
063: Map<String, Format> newFormats) {
064: /* Collect the proxy format. */
065: assert proxyClassName != null;
066: catalog.createFormat(proxyClassName, newFormats);
067: }
068:
069: @Override
070: void initialize(Catalog catalog, int initVersion) {
071: /* Set the proxy format for a new (never initialized) format. */
072: if (proxyFormat == null) {
073: assert proxyClassName != null;
074: proxyFormat = catalog.getFormat(proxyClassName);
075: }
076: /* Make the linkage from proxy format to proxied format. */
077: proxyFormat.setProxiedFormat(this );
078: }
079:
080: @Override
081: Object newArray(int len) {
082: return Array.newInstance(getType(), len);
083: }
084:
085: @Override
086: public Object newInstance(EntityInput input, boolean rawAccess) {
087: Reader reader = proxyFormat.getReader();
088: if (rawAccess) {
089: return reader.newInstance(null, true);
090: } else {
091: PersistentProxy proxy = (PersistentProxy) reader
092: .newInstance(null, false);
093: proxy = (PersistentProxy) reader.readObject(proxy, input,
094: false);
095: return proxy.convertProxy();
096: }
097: }
098:
099: @Override
100: public Object readObject(Object o, EntityInput input,
101: boolean rawAccess) {
102: if (rawAccess) {
103: o = proxyFormat.getReader().readObject(o, input, true);
104: }
105: /* Else, do nothing here -- newInstance reads the value. */
106: return o;
107: }
108:
109: @Override
110: void writeObject(Object o, EntityOutput output, boolean rawAccess) {
111: if (rawAccess) {
112: proxyFormat.writeObject(o, output, true);
113: } else {
114: PersistentProxy proxy = (PersistentProxy) proxyFormat
115: .newInstance(null, false);
116: proxy.initializeProxy(o);
117: proxyFormat.writeObject(proxy, output, false);
118: }
119: }
120:
121: @Override
122: Object convertRawObject(Catalog catalog, boolean rawAccess,
123: RawObject rawObject, IdentityHashMap converted) {
124: PersistentProxy proxy = (PersistentProxy) proxyFormat
125: .convertRawObject(catalog, rawAccess, rawObject,
126: converted);
127: Object o = proxy.convertProxy();
128: converted.put(rawObject, o);
129: return o;
130: }
131:
132: @Override
133: void skipContents(RecordInput input) {
134: proxyFormat.skipContents(input);
135: }
136:
137: @Override
138: void copySecMultiKey(RecordInput input, Format keyFormat,
139: Set results) {
140: CollectionProxy.copyElements(input, this , keyFormat, results);
141: }
142:
143: @Override
144: boolean evolve(Format newFormatParam, Evolver evolver) {
145: if (!(newFormatParam instanceof ProxiedFormat)) {
146: evolver
147: .addEvolveError(this , newFormatParam, null,
148: "A proxied class may not be changed to a different type");
149: return false;
150: }
151: ProxiedFormat newFormat = (ProxiedFormat) newFormatParam;
152: if (!evolver.evolveFormat(proxyFormat)) {
153: return false;
154: }
155: Format newProxyFormat = proxyFormat.getLatestVersion();
156: if (!newProxyFormat.getClassName().equals(
157: newFormat.getProxyClassName())) {
158: evolver.addEvolveError(this , newFormat, null,
159: "The proxy class for this type has been changed from: "
160: + newProxyFormat.getClassName() + " to: "
161: + newFormat.getProxyClassName());
162: return false;
163: }
164: if (newProxyFormat != proxyFormat) {
165: evolver.useEvolvedFormat(this , this , newFormat);
166: } else {
167: evolver.useOldFormat(this , newFormat);
168: }
169: return true;
170: }
171: }
|