out.writeInt(values.length); // count
for (int i = 0; i < values.length; i++) {
InternalValue val = values[i];
switch (state.getType()) {
case PropertyType.BINARY:
BLOBFileValue blobVal = val.getBLOBFileValue();
if (InternalValue.USE_DATA_STORE && dataStore != null) {
if (blobVal.isSmall()) {
writeSmallBinary(out, blobVal, state, i);
} else {
out.writeInt(BINARY_IN_DATA_STORE);
try {
val.store(dataStore);
} catch (RepositoryException e) {
String msg = "Error while storing blob. id="
+ state.getId() + " idx=" + i + " size=" + val.getBLOBFileValue().getLength();
log.error(msg, e);
throw new IOException(msg);
}
out.writeUTF(val.toString());
}
break;
}
// special handling required for binary value:
// spool binary value to file in blob store
long size = blobVal.getLength();
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]);
blobVal.discard();
} else if (size > minBlobSize) {
out.writeInt(BINARY_IN_BLOB_STORE);
String blobId = state.getBlobId(i);
if (blobId == null) {
try {
InputStream in = blobVal.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 IOException(msg);
}
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]);
}
blobVal.discard();
}
// store id of blob as property value
out.writeUTF(blobId); // value
} else {
// delete evt. blob
byte[] data = writeSmallBinary(out, blobVal, state, i);
// replace value instance with value
// backed by resource in blob store and delete temp file
values[i] = InternalValue.create(data);
blobVal.discard();
}
break;
case PropertyType.DOUBLE:
try {
out.writeDouble(val.getDouble());