View Javadoc
1   /*
2    * Copyright (C) 2009, The Android Open Source Project
3    * Copyright (C) 2009, Shawn O. Pearce <spearce@spearce.org>
4    * Copyright (C) 2018, David Pursehouse <david.pursehouse@gmail.com>
5    * and other copyright owners as documented in the project's IP log.
6    *
7    * This program and the accompanying materials are made available
8    * under the terms of the Eclipse Distribution License v1.0 which
9    * accompanies this distribution, is reproduced below, and is
10   * available at http://www.eclipse.org/org/documents/edl-v10.php
11   *
12   * All rights reserved.
13   *
14   * Redistribution and use in source and binary forms, with or
15   * without modification, are permitted provided that the following
16   * conditions are met:
17   *
18   * - Redistributions of source code must retain the above copyright
19   *   notice, this list of conditions and the following disclaimer.
20   *
21   * - Redistributions in binary form must reproduce the above
22   *   copyright notice, this list of conditions and the following
23   *   disclaimer in the documentation and/or other materials provided
24   *   with the distribution.
25   *
26   * - Neither the name of the Eclipse Foundation, Inc. nor the
27   *   names of its contributors may be used to endorse or promote
28   *   products derived from this software without specific prior
29   *   written permission.
30   *
31   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
32   * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
33   * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
34   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
35   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
36   * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
37   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
38   * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
39   * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
40   * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
41   * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
42   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
43   * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
44   */
45  
46  package org.eclipse.jgit.lib;
47  
48  import static org.eclipse.jgit.lib.Constants.OBJECT_ID_LENGTH;
49  
50  import java.io.IOException;
51  import java.io.InputStream;
52  import java.io.OutputStream;
53  
54  import org.eclipse.jgit.annotations.NonNull;
55  import org.eclipse.jgit.annotations.Nullable;
56  import org.eclipse.jgit.util.IO;
57  
58  /**
59   * Helper to serialize {@link ObjectId} instances. {@link ObjectId} is already
60   * serializable, but this class provides methods to handle null and non-null
61   * instances.
62   *
63   * @since 4.11
64   */
65  public class ObjectIdSerializer {
66  	/*
67  	 * Marker to indicate a null ObjectId instance.
68  	 */
69  	private static final byte NULL_MARKER = 0;
70  
71  	/*
72  	 * Marker to indicate a non-null ObjectId instance.
73  	 */
74  	private static final byte NON_NULL_MARKER = 1;
75  
76  	/**
77  	 * Write a possibly null {@link ObjectId} to the stream, using markers to
78  	 * differentiate null and non-null instances.
79  	 *
80  	 * <p>
81  	 * If the id is non-null, writes a {@link #NON_NULL_MARKER} followed by the
82  	 * id's words. If it is null, writes a {@link #NULL_MARKER} and nothing
83  	 * else.
84  	 *
85  	 * @param out
86  	 *            the output stream
87  	 * @param id
88  	 *            the object id to serialize; may be null
89  	 * @throws IOException
90  	 *             the stream writing failed
91  	 */
92  	public static void write(OutputStream out, @Nullable AnyObjectId id)
93  			throws IOException {
94  		if (id != null) {
95  			out.write(NON_NULL_MARKER);
96  			writeWithoutMarker(out, id);
97  		} else {
98  			out.write(NULL_MARKER);
99  		}
100 	}
101 
102 	/**
103 	 * Write a non-null {@link ObjectId} to the stream.
104 	 *
105 	 * @param out
106 	 *            the output stream
107 	 * @param id
108 	 *            the object id to serialize; never null
109 	 * @throws IOException
110 	 *             the stream writing failed
111 	 * @since 4.11
112 	 */
113 	public static void writeWithoutMarker(OutputStream out, @NonNull AnyObjectId id)
114 			throws IOException {
115 		id.copyRawTo(out);
116 	}
117 
118 	/**
119 	 * Read a possibly null {@link ObjectId} from the stream.
120 	 *
121 	 * Reads the first byte of the stream, which is expected to be either
122 	 * {@link #NON_NULL_MARKER} or {@link #NULL_MARKER}.
123 	 *
124 	 * @param in
125 	 *            the input stream
126 	 * @return the object id, or null
127 	 * @throws IOException
128 	 *             there was an error reading the stream
129 	 */
130 	@Nullable
131 	public static ObjectId read(InputStream in) throws IOException {
132 		byte marker = (byte) in.read();
133 		switch (marker) {
134 		case NULL_MARKER:
135 			return null;
136 		case NON_NULL_MARKER:
137 			return readWithoutMarker(in);
138 		default:
139 			throw new IOException("Invalid flag before ObjectId: " + marker); //$NON-NLS-1$
140 		}
141 	}
142 
143 	/**
144 	 * Read a non-null {@link ObjectId} from the stream.
145 	 *
146 	 * @param in
147 	 *            the input stream
148 	 * @return the object id; never null
149 	 * @throws IOException
150 	 *             there was an error reading the stream
151 	 * @since 4.11
152 	 */
153 	@NonNull
154 	public static ObjectId readWithoutMarker(InputStream in) throws IOException {
155 		final byte[] b = new byte[OBJECT_ID_LENGTH];
156 		IO.readFully(in, b, 0, OBJECT_ID_LENGTH);
157 		return ObjectId.fromRaw(b);
158 	}
159 
160 	private ObjectIdSerializer() {
161 	}
162 }