in jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/util/BundleWriter.java [182:338]
private void writeState(NodePropBundle.PropertyEntry state)
throws IOException {
writeName(state.getName());
InternalValue[] values = state.getValues();
int type = state.getType();
if (type < 0 || type > 0xf) {
throw new IOException("Illegal property type " + type);
}
if (state.isMultiValued()) {
int len = values.length + 1;
if (len < 0x0f) {
out.writeByte(len << 4 | type);
} else {
out.writeByte(0xf0 | type);
writeVarInt(len - 0x0f);
}
} else {
if (values.length != 1) {
throw new IOException(
"Single values property with " + values.length + " values: " +
state.getName());
}
out.writeByte(type);
}
writeVarInt(state.getModCount());
// values
for (int i = 0; i < values.length; i++) {
InternalValue val = values[i];
switch (type) {
case PropertyType.BINARY:
try {
long size = val.getLength();
if (val.isInDataStore()) {
out.writeInt(BundleBinding.BINARY_IN_DATA_STORE);
writeString(val.toString());
} else if (binding.dataStore != null) {
writeSmallBinary(val, state, i);
} else if (size < 0) {
log.warn("Blob has negative size. Potential loss of data. "
+ "id={} idx={}", state.getId(), String.valueOf(i));
out.writeInt(0);
values[i] = InternalValue.create(new byte[0]);
val.discard();
} else if (size > binding.getMinBlobSize()) {
// special handling required for binary value:
// spool binary value to file in blob store
out.writeInt(BundleBinding.BINARY_IN_BLOB_STORE);
String blobId = state.getBlobId(i);
if (blobId == null) {
BLOBStore blobStore = binding.getBlobStore();
try {
InputStream in = val.getStream();
try {
blobId = blobStore.createId(state.getId(), i);
blobStore.put(blobId, in, size);
state.setBlobId(blobId, i);
} finally {
IOUtils.closeQuietly(in);
}
} catch (Exception e) {
String msg = "Error while storing blob. id="
+ state.getId() + " idx=" + i + " size=" + size;
log.error(msg, e);
throw new IOExceptionWithCause(msg, e);
}
try {
// replace value instance with value
// backed by resource in blob store and delete temp file
if (blobStore instanceof ResourceBasedBLOBStore) {
values[i] = InternalValue.create(((ResourceBasedBLOBStore) blobStore).getResource(blobId));
} else {
values[i] = InternalValue.create(blobStore.get(blobId));
}
} catch (Exception e) {
log.error("Error while reloading blob. truncating. id="
+ state.getId() + " idx=" + i + " size=" + size, e);
values[i] = InternalValue.create(new byte[0]);
}
val.discard();
}
// store id of blob as property value
writeString(blobId); // value
} else {
// delete evt. blob
byte[] data = writeSmallBinary(val, state, i);
// replace value instance with value
// backed by resource in blob store and delete temp file
values[i] = InternalValue.create(data);
val.discard();
}
} catch (RepositoryException e) {
String msg = "Error while storing blob. id="
+ state.getId() + " idx=" + i + " value=" + val;
log.error(msg, e);
throw new IOExceptionWithCause(msg, e);
}
break;
case PropertyType.DOUBLE:
try {
out.writeDouble(val.getDouble());
} catch (RepositoryException e) {
throw convertToIOException(type, e);
}
break;
case PropertyType.DECIMAL:
try {
writeDecimal(val.getDecimal());
} catch (RepositoryException e) {
throw convertToIOException(type, e);
}
break;
case PropertyType.LONG:
try {
writeVarLong(val.getLong());
} catch (RepositoryException e) {
throw convertToIOException(type, e);
}
break;
case PropertyType.BOOLEAN:
try {
out.writeBoolean(val.getBoolean());
} catch (RepositoryException e) {
throw convertToIOException(type, e);
}
break;
case PropertyType.NAME:
try {
writeName(val.getName());
} catch (RepositoryException e) {
throw convertToIOException(type, e);
}
break;
case PropertyType.WEAKREFERENCE:
case PropertyType.REFERENCE:
writeNodeId(val.getNodeId());
break;
case PropertyType.DATE:
try {
writeDate(val.getCalendar());
} catch (RepositoryException e) {
throw convertToIOException(type, e);
}
break;
case PropertyType.STRING:
case PropertyType.PATH:
case PropertyType.URI:
writeString(val.toString());
break;
default:
throw new IOException("Inknown property type: " + type);
}
}
}