private void writeState()

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);
            }
        }
    }