PageRenderTime 41ms CodeModel.GetById 12ms RepoModel.GetById 1ms app.codeStats 0ms

/src/java/org/apache/hadoop/io/ObjectWritable.java

https://github.com/RS1999ent/hadoop-common
Java | 315 lines | 219 code | 47 blank | 49 comment | 98 complexity | cfc4b574ffcc58a8b351ca91f7775d3c MD5 | raw file
  1. /**
  2. * Licensed to the Apache Software Foundation (ASF) under one
  3. * or more contributor license agreements. See the NOTICE file
  4. * distributed with this work for additional information
  5. * regarding copyright ownership. The ASF licenses this file
  6. * to you under the Apache License, Version 2.0 (the
  7. * "License"); you may not use this file except in compliance
  8. * with the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. */
  18. package org.apache.hadoop.io;
  19. import java.lang.reflect.Array;
  20. import java.io.*;
  21. import java.util.*;
  22. import org.apache.hadoop.classification.InterfaceAudience;
  23. import org.apache.hadoop.classification.InterfaceStability;
  24. import org.apache.hadoop.conf.*;
  25. /** A polymorphic Writable that writes an instance with it's class name.
  26. * Handles arrays, strings and primitive types without a Writable wrapper.
  27. */
  28. @InterfaceAudience.Public
  29. @InterfaceStability.Stable
  30. public class ObjectWritable implements Writable, Configurable {
  31. private Class declaredClass;
  32. private Object instance;
  33. private Configuration conf;
  34. public ObjectWritable() {}
  35. public ObjectWritable(Object instance) {
  36. set(instance);
  37. }
  38. public ObjectWritable(Class declaredClass, Object instance) {
  39. this.declaredClass = declaredClass;
  40. this.instance = instance;
  41. }
  42. /** Return the instance, or null if none. */
  43. public Object get() { return instance; }
  44. /** Return the class this is meant to be. */
  45. public Class getDeclaredClass() { return declaredClass; }
  46. /** Reset the instance. */
  47. public void set(Object instance) {
  48. this.declaredClass = instance.getClass();
  49. this.instance = instance;
  50. }
  51. public String toString() {
  52. return "OW[class=" + declaredClass + ",value=" + instance + "]";
  53. }
  54. public void readFields(DataInput in) throws IOException {
  55. readObject(in, this, this.conf);
  56. }
  57. public void write(DataOutput out) throws IOException {
  58. writeObject(out, instance, declaredClass, conf);
  59. }
  60. private static final Map<String, Class<?>> PRIMITIVE_NAMES = new HashMap<String, Class<?>>();
  61. static {
  62. PRIMITIVE_NAMES.put("boolean", Boolean.TYPE);
  63. PRIMITIVE_NAMES.put("byte", Byte.TYPE);
  64. PRIMITIVE_NAMES.put("char", Character.TYPE);
  65. PRIMITIVE_NAMES.put("short", Short.TYPE);
  66. PRIMITIVE_NAMES.put("int", Integer.TYPE);
  67. PRIMITIVE_NAMES.put("long", Long.TYPE);
  68. PRIMITIVE_NAMES.put("float", Float.TYPE);
  69. PRIMITIVE_NAMES.put("double", Double.TYPE);
  70. PRIMITIVE_NAMES.put("void", Void.TYPE);
  71. }
  72. private static class NullInstance extends Configured implements Writable {
  73. private Class<?> declaredClass;
  74. public NullInstance() { super(null); }
  75. public NullInstance(Class declaredClass, Configuration conf) {
  76. super(conf);
  77. this.declaredClass = declaredClass;
  78. }
  79. public void readFields(DataInput in) throws IOException {
  80. String className = UTF8.readString(in);
  81. declaredClass = PRIMITIVE_NAMES.get(className);
  82. if (declaredClass == null) {
  83. try {
  84. declaredClass = getConf().getClassByName(className);
  85. } catch (ClassNotFoundException e) {
  86. throw new RuntimeException(e.toString());
  87. }
  88. }
  89. }
  90. public void write(DataOutput out) throws IOException {
  91. UTF8.writeString(out, declaredClass.getName());
  92. }
  93. }
  94. /** Write a {@link Writable}, {@link String}, primitive type, or an array of
  95. * the preceding. */
  96. public static void writeObject(DataOutput out, Object instance,
  97. Class declaredClass,
  98. Configuration conf) throws IOException {
  99. writeObject(out, instance, declaredClass, conf, false);
  100. }
  101. /**
  102. * Write a {@link Writable}, {@link String}, primitive type, or an array of
  103. * the preceding.
  104. *
  105. * @param allowCompactArrays - set true for RPC and internal or intra-cluster
  106. * usages. Set false for inter-cluster, File, and other persisted output
  107. * usages, to preserve the ability to interchange files with other clusters
  108. * that may not be running the same version of software. Sometime in ~2013
  109. * we can consider removing this parameter and always using the compact format.
  110. */
  111. public static void writeObject(DataOutput out, Object instance,
  112. Class declaredClass, Configuration conf, boolean allowCompactArrays)
  113. throws IOException {
  114. if (instance == null) { // null
  115. instance = new NullInstance(declaredClass, conf);
  116. declaredClass = Writable.class;
  117. }
  118. // Special case: must come before writing out the declaredClass.
  119. // If this is an eligible array of primitives,
  120. // wrap it in an ArrayPrimitiveWritable$Internal wrapper class.
  121. if (allowCompactArrays && declaredClass.isArray()
  122. && instance.getClass().getName().equals(declaredClass.getName())
  123. && instance.getClass().getComponentType().isPrimitive()) {
  124. instance = new ArrayPrimitiveWritable.Internal(instance);
  125. declaredClass = ArrayPrimitiveWritable.Internal.class;
  126. }
  127. UTF8.writeString(out, declaredClass.getName()); // always write declared
  128. if (declaredClass.isArray()) { // non-primitive or non-compact array
  129. int length = Array.getLength(instance);
  130. out.writeInt(length);
  131. for (int i = 0; i < length; i++) {
  132. writeObject(out, Array.get(instance, i),
  133. declaredClass.getComponentType(), conf, allowCompactArrays);
  134. }
  135. } else if (declaredClass == ArrayPrimitiveWritable.Internal.class) {
  136. ((ArrayPrimitiveWritable.Internal) instance).write(out);
  137. } else if (declaredClass == String.class) { // String
  138. UTF8.writeString(out, (String)instance);
  139. } else if (declaredClass.isPrimitive()) { // primitive type
  140. if (declaredClass == Boolean.TYPE) { // boolean
  141. out.writeBoolean(((Boolean)instance).booleanValue());
  142. } else if (declaredClass == Character.TYPE) { // char
  143. out.writeChar(((Character)instance).charValue());
  144. } else if (declaredClass == Byte.TYPE) { // byte
  145. out.writeByte(((Byte)instance).byteValue());
  146. } else if (declaredClass == Short.TYPE) { // short
  147. out.writeShort(((Short)instance).shortValue());
  148. } else if (declaredClass == Integer.TYPE) { // int
  149. out.writeInt(((Integer)instance).intValue());
  150. } else if (declaredClass == Long.TYPE) { // long
  151. out.writeLong(((Long)instance).longValue());
  152. } else if (declaredClass == Float.TYPE) { // float
  153. out.writeFloat(((Float)instance).floatValue());
  154. } else if (declaredClass == Double.TYPE) { // double
  155. out.writeDouble(((Double)instance).doubleValue());
  156. } else if (declaredClass == Void.TYPE) { // void
  157. } else {
  158. throw new IllegalArgumentException("Not a primitive: "+declaredClass);
  159. }
  160. } else if (declaredClass.isEnum()) { // enum
  161. UTF8.writeString(out, ((Enum)instance).name());
  162. } else if (Writable.class.isAssignableFrom(declaredClass)) { // Writable
  163. UTF8.writeString(out, instance.getClass().getName());
  164. ((Writable)instance).write(out);
  165. } else {
  166. throw new IOException("Can't write: "+instance+" as "+declaredClass);
  167. }
  168. }
  169. /** Read a {@link Writable}, {@link String}, primitive type, or an array of
  170. * the preceding. */
  171. public static Object readObject(DataInput in, Configuration conf)
  172. throws IOException {
  173. return readObject(in, null, conf);
  174. }
  175. /** Read a {@link Writable}, {@link String}, primitive type, or an array of
  176. * the preceding. */
  177. @SuppressWarnings("unchecked")
  178. public static Object readObject(DataInput in, ObjectWritable objectWritable, Configuration conf)
  179. throws IOException {
  180. String className = UTF8.readString(in);
  181. Class<?> declaredClass = PRIMITIVE_NAMES.get(className);
  182. if (declaredClass == null) {
  183. declaredClass = loadClass(conf, className);
  184. }
  185. Object instance;
  186. if (declaredClass.isPrimitive()) { // primitive types
  187. if (declaredClass == Boolean.TYPE) { // boolean
  188. instance = Boolean.valueOf(in.readBoolean());
  189. } else if (declaredClass == Character.TYPE) { // char
  190. instance = Character.valueOf(in.readChar());
  191. } else if (declaredClass == Byte.TYPE) { // byte
  192. instance = Byte.valueOf(in.readByte());
  193. } else if (declaredClass == Short.TYPE) { // short
  194. instance = Short.valueOf(in.readShort());
  195. } else if (declaredClass == Integer.TYPE) { // int
  196. instance = Integer.valueOf(in.readInt());
  197. } else if (declaredClass == Long.TYPE) { // long
  198. instance = Long.valueOf(in.readLong());
  199. } else if (declaredClass == Float.TYPE) { // float
  200. instance = Float.valueOf(in.readFloat());
  201. } else if (declaredClass == Double.TYPE) { // double
  202. instance = Double.valueOf(in.readDouble());
  203. } else if (declaredClass == Void.TYPE) { // void
  204. instance = null;
  205. } else {
  206. throw new IllegalArgumentException("Not a primitive: "+declaredClass);
  207. }
  208. } else if (declaredClass.isArray()) { // array
  209. int length = in.readInt();
  210. instance = Array.newInstance(declaredClass.getComponentType(), length);
  211. for (int i = 0; i < length; i++) {
  212. Array.set(instance, i, readObject(in, conf));
  213. }
  214. } else if (declaredClass == ArrayPrimitiveWritable.Internal.class) {
  215. // Read and unwrap ArrayPrimitiveWritable$Internal array.
  216. // Always allow the read, even if write is disabled by allowCompactArrays.
  217. ArrayPrimitiveWritable.Internal temp =
  218. new ArrayPrimitiveWritable.Internal();
  219. temp.readFields(in);
  220. instance = temp.get();
  221. declaredClass = instance.getClass();
  222. } else if (declaredClass == String.class) { // String
  223. instance = UTF8.readString(in);
  224. } else if (declaredClass.isEnum()) { // enum
  225. instance = Enum.valueOf((Class<? extends Enum>) declaredClass, UTF8.readString(in));
  226. } else { // Writable
  227. Class instanceClass = null;
  228. String str = UTF8.readString(in);
  229. instanceClass = loadClass(conf, str);
  230. Writable writable = WritableFactories.newInstance(instanceClass, conf);
  231. writable.readFields(in);
  232. instance = writable;
  233. if (instanceClass == NullInstance.class) { // null
  234. declaredClass = ((NullInstance)instance).declaredClass;
  235. instance = null;
  236. }
  237. }
  238. if (objectWritable != null) { // store values
  239. objectWritable.declaredClass = declaredClass;
  240. objectWritable.instance = instance;
  241. }
  242. return instance;
  243. }
  244. /**
  245. * Find and load the class with given name <tt>className</tt> by first finding
  246. * it in the specified <tt>conf</tt>. If the specified <tt>conf</tt> is null,
  247. * try load it directly.
  248. */
  249. public static Class<?> loadClass(Configuration conf, String className) {
  250. Class<?> declaredClass = null;
  251. try {
  252. if (conf != null)
  253. declaredClass = conf.getClassByName(className);
  254. else
  255. declaredClass = Class.forName(className);
  256. } catch (ClassNotFoundException e) {
  257. throw new RuntimeException("readObject can't find class " + className,
  258. e);
  259. }
  260. return declaredClass;
  261. }
  262. public void setConf(Configuration conf) {
  263. this.conf = conf;
  264. }
  265. public Configuration getConf() {
  266. return this.conf;
  267. }
  268. }