2 * Copyright (C) 2006 Shawn Pearce <spearce@spearce.org>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License, version 2.1, as published by the Free Software Foundation.
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
17 package org
.spearce
.jgit
.lib
;
19 import java
.io
.FileInputStream
;
20 import java
.io
.IOException
;
21 import java
.util
.zip
.DataFormatException
;
22 import java
.util
.zip
.Inflater
;
24 import org
.spearce
.jgit
.errors
.CorruptObjectException
;
26 public class UnpackedObjectLoader
extends ObjectLoader
{
27 private final String objectType
;
29 private final int objectSize
;
31 private final byte[] bytes
;
33 public UnpackedObjectLoader(final Repository db
, final ObjectId id
)
35 final FileInputStream objStream
= new FileInputStream(db
.toFile(id
));
36 final byte[] compressed
;
38 compressed
= new byte[objStream
.available()];
40 while (off
< compressed
.length
)
41 off
+= objStream
.read(compressed
, off
, compressed
.length
- off
);
47 // Try to determine if this is a legacy format loose object or
48 // a new style loose object. The legacy format was completely
49 // compressed with zlib so the first byte must be 0x78 (15-bit
50 // window size, deflated) and the first 16 bit word must be
51 // evenly divisible by 31. Otherwise its a new style loose
54 final int fb
= compressed
[0] & 0xff;
55 if (fb
== 0x78 && (((fb
<< 8) | compressed
[1] & 0xff) % 31) == 0) {
56 final Inflater inflater
= new Inflater(false);
57 inflater
.setInput(compressed
);
58 final byte[] hdr
= new byte[64];
60 while (!inflater
.finished() && avail
< hdr
.length
)
62 avail
+= inflater
.inflate(hdr
, avail
, hdr
.length
- avail
);
63 } catch (DataFormatException dfe
) {
64 final CorruptObjectException coe
;
65 coe
= new CorruptObjectException(getId(), "bad stream");
71 throw new CorruptObjectException(id
, "no header");
76 if (hdr
[1] != 'l' || hdr
[2] != 'o' || hdr
[3] != 'b'
78 throw new CorruptObjectException(id
, "invalid type");
79 objectType
= Constants
.TYPE_BLOB
;
83 if (avail
< 7 || hdr
[1] != 'o' || hdr
[2] != 'm'
84 || hdr
[3] != 'm' || hdr
[4] != 'i' || hdr
[5] != 't'
86 throw new CorruptObjectException(id
, "invalid type");
87 objectType
= Constants
.TYPE_COMMIT
;
93 if (hdr
[2] != 'g' || hdr
[3] != ' ')
94 throw new CorruptObjectException(id
, "invalid type");
95 objectType
= Constants
.TYPE_TAG
;
99 if (hdr
[2] != 'e' || hdr
[3] != 'e' || hdr
[4] != ' ')
100 throw new CorruptObjectException(id
, "invalid type");
101 objectType
= Constants
.TYPE_TREE
;
105 throw new CorruptObjectException(id
, "invalid type");
109 throw new CorruptObjectException(id
, "invalid type");
113 while (pos
< avail
) {
114 final int c
= hdr
[pos
++];
117 else if (c
< '0' || c
> '9')
118 throw new CorruptObjectException(id
, "invalid length");
122 objectSize
= tempSize
;
123 bytes
= new byte[objectSize
];
125 System
.arraycopy(hdr
, pos
, bytes
, 0, avail
- pos
);
126 decompress(inflater
, avail
);
129 int c
= compressed
[p
++] & 0xff;
130 final int typeCode
= (c
>> 4) & 7;
133 while ((c
& 0x80) != 0) {
134 c
= compressed
[p
++] & 0xff;
135 size
+= (c
& 0x7f) << shift
;
140 case Constants
.OBJ_COMMIT
:
141 objectType
= Constants
.TYPE_COMMIT
;
143 case Constants
.OBJ_TREE
:
144 objectType
= Constants
.TYPE_TREE
;
146 case Constants
.OBJ_BLOB
:
147 objectType
= Constants
.TYPE_BLOB
;
149 case Constants
.OBJ_TAG
:
150 objectType
= Constants
.TYPE_TAG
;
153 throw new CorruptObjectException(id
, "invalid type");
157 bytes
= new byte[objectSize
];
158 final Inflater inflater
= new Inflater(false);
159 inflater
.setInput(compressed
, p
, compressed
.length
- p
);
160 decompress(inflater
, 0);
164 private void decompress(final Inflater inf
, int p
) throws IOException
{
166 while (!inf
.finished())
167 p
+= inf
.inflate(bytes
, p
, objectSize
- p
);
168 } catch (DataFormatException dfe
) {
169 final CorruptObjectException coe
;
170 coe
= new CorruptObjectException(getId(), "bad stream");
177 new CorruptObjectException(getId(), "incorrect length");
180 public String
getType() {
184 public long getSize() {
188 public byte[] getBytes() {