1/*- 2 * See the file LICENSE for redistribution information. 3 * 4 * Copyright (c) 2002,2008 Oracle. All rights reserved. 5 * 6 * $Id: ProxiedFormat.java,v 1.1 2008/02/07 17:12:27 mark Exp $ 7 */ 8 9package com.sleepycat.persist.impl; 10 11import java.lang.reflect.Array; 12import java.util.IdentityHashMap; 13import java.util.Map; 14import java.util.Set; 15 16import com.sleepycat.persist.model.PersistentProxy; 17import com.sleepycat.persist.raw.RawObject; 18 19/** 20 * Format for types proxied by a PersistentProxy. 21 * 22 * @author Mark Hayes 23 */ 24public class ProxiedFormat extends Format { 25 26 private static final long serialVersionUID = -1000032651995478768L; 27 28 private Format proxyFormat; 29 private transient String proxyClassName; 30 31 ProxiedFormat(Class proxiedType, String proxyClassName) { 32 super(proxiedType); 33 this.proxyClassName = proxyClassName; 34 } 35 36 /** 37 * Returns the proxy class name. The proxyClassName field is non-null for 38 * a constructed object and null for a de-serialized object. Whenever the 39 * proxyClassName field is null (for a de-serialized object), the 40 * proxyFormat will be non-null. 41 */ 42 private String getProxyClassName() { 43 if (proxyClassName != null) { 44 return proxyClassName; 45 } else { 46 assert proxyFormat != null; 47 return proxyFormat.getClassName(); 48 } 49 } 50 51 /** 52 * In the future if we implement container proxies, which support nested 53 * references to the container, then we will return false if this is a 54 * container proxy. [#15815] 55 */ 56 @Override 57 boolean areNestedRefsProhibited() { 58 return true; 59 } 60 61 @Override 62 void collectRelatedFormats(Catalog catalog, 63 Map<String,Format> newFormats) { 64 /* Collect the proxy format. */ 65 assert proxyClassName != null; 66 catalog.createFormat(proxyClassName, newFormats); 67 } 68 69 @Override 70 void initialize(Catalog catalog, int initVersion) { 71 /* Set the proxy format for a new (never initialized) format. */ 72 if (proxyFormat == null) { 73 assert proxyClassName != null; 74 proxyFormat = catalog.getFormat(proxyClassName); 75 } 76 /* Make the linkage from proxy format to proxied format. */ 77 proxyFormat.setProxiedFormat(this); 78 } 79 80 @Override 81 Object newArray(int len) { 82 return Array.newInstance(getType(), len); 83 } 84 85 @Override 86 public Object newInstance(EntityInput input, boolean rawAccess) { 87 Reader reader = proxyFormat.getReader(); 88 if (rawAccess) { 89 return reader.newInstance(null, true); 90 } else { 91 PersistentProxy proxy = 92 (PersistentProxy) reader.newInstance(null, false); 93 proxy = (PersistentProxy) reader.readObject(proxy, input, false); 94 return proxy.convertProxy(); 95 } 96 } 97 98 @Override 99 public Object readObject(Object o, EntityInput input, boolean rawAccess) { 100 if (rawAccess) { 101 o = proxyFormat.getReader().readObject(o, input, true); 102 } 103 /* Else, do nothing here -- newInstance reads the value. */ 104 return o; 105 } 106 107 @Override 108 void writeObject(Object o, EntityOutput output, boolean rawAccess) { 109 if (rawAccess) { 110 proxyFormat.writeObject(o, output, true); 111 } else { 112 PersistentProxy proxy = 113 (PersistentProxy) proxyFormat.newInstance(null, false); 114 proxy.initializeProxy(o); 115 proxyFormat.writeObject(proxy, output, false); 116 } 117 } 118 119 @Override 120 Object convertRawObject(Catalog catalog, 121 boolean rawAccess, 122 RawObject rawObject, 123 IdentityHashMap converted) { 124 PersistentProxy proxy = (PersistentProxy) proxyFormat.convertRawObject 125 (catalog, rawAccess, rawObject, converted); 126 Object o = proxy.convertProxy(); 127 converted.put(rawObject, o); 128 return o; 129 } 130 131 @Override 132 void skipContents(RecordInput input) { 133 proxyFormat.skipContents(input); 134 } 135 136 @Override 137 void copySecMultiKey(RecordInput input, Format keyFormat, Set results) { 138 CollectionProxy.copyElements(input, this, keyFormat, results); 139 } 140 141 @Override 142 boolean evolve(Format newFormatParam, Evolver evolver) { 143 if (!(newFormatParam instanceof ProxiedFormat)) { 144 evolver.addEvolveError 145 (this, newFormatParam, null, 146 "A proxied class may not be changed to a different type"); 147 return false; 148 } 149 ProxiedFormat newFormat = (ProxiedFormat) newFormatParam; 150 if (!evolver.evolveFormat(proxyFormat)) { 151 return false; 152 } 153 Format newProxyFormat = proxyFormat.getLatestVersion(); 154 if (!newProxyFormat.getClassName().equals 155 (newFormat.getProxyClassName())) { 156 evolver.addEvolveError 157 (this, newFormat, null, 158 "The proxy class for this type has been changed from: " + 159 newProxyFormat.getClassName() + " to: " + 160 newFormat.getProxyClassName()); 161 return false; 162 } 163 if (newProxyFormat != proxyFormat) { 164 evolver.useEvolvedFormat(this, this, newFormat); 165 } else { 166 evolver.useOldFormat(this, newFormat); 167 } 168 return true; 169 } 170} 171