Search in sources :

Example 1 with InternalValue

use of org.apache.jackrabbit.core.value.InternalValue in project jackrabbit by apache.

the class BundleWriter method writeState.

/**
     * Serializes a property entry. The serialization begins with the
     * property name followed by a single byte that encodes the type and
     * multi-valuedness of the property:
     * <pre>
     * +-------------------------------+
     * |   mv count    |     type      |
     * +-------------------------------+
     * </pre>
     * <p>
     * The lower four bits encode the property type (0-12 in JCR 2.0) and
     * higher bits indicate whether this is a multi-valued property and how
     * many property values there are. A value of 0 is reserved for
     * single-valued properties (that are guaranteed to always have just a
     * single value), and all non-zero values indicate a multi-valued property.
     * <p>
     * In multi-valued properties the exact value of the "mv count" field is
     * the number of property values plus one and truncated at 15 (the highest
     * four-bit value). If there are 14 or more (14 + 1 == 15) property values,
     * then the number of additional values is serialized as a variable-length
     * integer (see {@link #writeVarInt(int)}) right after this byte.
     * <p>
     * The modification count of the property state is written next as a
     * variable-length integer, followed by the serializations of all the
     * values of this property.
     *
     * @param state the property entry to store
     * @throws IOException if an I/O error occurs.
     */
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 {
                                // 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
                        // value
                        writeString(blobId);
                    } 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);
        }
    }
}
Also used : IOExceptionWithCause(org.apache.commons.io.IOExceptionWithCause) DataInputStream(java.io.DataInputStream) InputStream(java.io.InputStream) RepositoryException(javax.jcr.RepositoryException) IOException(java.io.IOException) InternalValue(org.apache.jackrabbit.core.value.InternalValue) IOException(java.io.IOException) RepositoryException(javax.jcr.RepositoryException)

Example 2 with InternalValue

use of org.apache.jackrabbit.core.value.InternalValue in project jackrabbit by apache.

the class XMLPersistenceManager method store.

/**
     * {@inheritDoc}
     */
protected void store(PropertyState state) throws ItemStateException {
    if (!initialized) {
        throw new IllegalStateException("not initialized");
    }
    String propFilePath = buildPropFilePath(state.getPropertyId());
    FileSystemResource propFile = new FileSystemResource(itemStateFS, propFilePath);
    try {
        propFile.makeParentDirs();
        OutputStream os = propFile.getOutputStream();
        // write property state to xml file
        Writer writer = null;
        try {
            String encoding = DEFAULT_ENCODING;
            try {
                writer = new BufferedWriter(new OutputStreamWriter(os, encoding));
            } catch (UnsupportedEncodingException e) {
                // should never get here!
                OutputStreamWriter osw = new OutputStreamWriter(os);
                encoding = osw.getEncoding();
                writer = new BufferedWriter(osw);
            }
            String typeName;
            int type = state.getType();
            try {
                typeName = PropertyType.nameFromValue(type);
            } catch (IllegalArgumentException iae) {
                // should never be getting here
                throw new ItemStateException("unexpected property-type ordinal: " + type, iae);
            }
            writer.write("<?xml version=\"1.0\" encoding=\"" + encoding + "\"?>\n");
            writer.write("<" + PROPERTY_ELEMENT + " " + NAME_ATTRIBUTE + "=\"" + Text.encodeIllegalXMLCharacters(state.getName().toString()) + "\" " + PARENTUUID_ATTRIBUTE + "=\"" + state.getParentId() + "\" " + MULTIVALUED_ATTRIBUTE + "=\"" + Boolean.toString(state.isMultiValued()) + "\" " + MODCOUNT_ATTRIBUTE + "=\"" + state.getModCount() + "\" " + TYPE_ATTRIBUTE + "=\"" + typeName + "\">\n");
            // values
            writer.write("\t<" + VALUES_ELEMENT + ">\n");
            InternalValue[] values = state.getValues();
            if (values != null) {
                for (int i = 0; i < values.length; i++) {
                    writer.write("\t\t<" + VALUE_ELEMENT + ">");
                    InternalValue val = values[i];
                    if (val != null) {
                        if (type == PropertyType.BINARY) {
                            // special handling required for binary value:
                            // put binary value in BLOB store
                            InputStream in = val.getStream();
                            String blobId = blobStore.createId(state.getPropertyId(), i);
                            try {
                                blobStore.put(blobId, in, val.getLength());
                            } finally {
                                IOUtils.closeQuietly(in);
                            }
                            // store id of BLOB as property value
                            writer.write(blobId);
                            // in BLOB store and discard old value instance (e.g. temp file)
                            if (blobStore instanceof ResourceBasedBLOBStore) {
                                // optimization: if the BLOB store is resource-based
                                // retrieve the resource directly rather than having
                                // to read the BLOB from an input stream
                                FileSystemResource fsRes = ((ResourceBasedBLOBStore) blobStore).getResource(blobId);
                                values[i] = InternalValue.create(fsRes);
                            } else {
                                in = blobStore.get(blobId);
                                try {
                                    values[i] = InternalValue.create(in);
                                } finally {
                                    try {
                                        in.close();
                                    } catch (IOException e) {
                                    // ignore
                                    }
                                }
                            }
                            val.discard();
                        } else {
                            writer.write(Text.encodeIllegalXMLCharacters(val.toString()));
                        }
                    }
                    writer.write("</" + VALUE_ELEMENT + ">\n");
                }
            }
            writer.write("\t</" + VALUES_ELEMENT + ">\n");
            writer.write("</" + PROPERTY_ELEMENT + ">\n");
        } finally {
            writer.close();
        }
    } catch (Exception e) {
        String msg = "failed to store property state: " + state.getParentId() + "/" + state.getName();
        log.debug(msg);
        throw new ItemStateException(msg, e);
    }
}
Also used : InputStream(java.io.InputStream) OutputStream(java.io.OutputStream) UnsupportedEncodingException(java.io.UnsupportedEncodingException) FileSystemResource(org.apache.jackrabbit.core.fs.FileSystemResource) IOException(java.io.IOException) InternalValue(org.apache.jackrabbit.core.value.InternalValue) NoSuchItemStateException(org.apache.jackrabbit.core.state.NoSuchItemStateException) IOException(java.io.IOException) ItemStateException(org.apache.jackrabbit.core.state.ItemStateException) FileSystemException(org.apache.jackrabbit.core.fs.FileSystemException) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) UnsupportedEncodingException(java.io.UnsupportedEncodingException) BufferedWriter(java.io.BufferedWriter) NoSuchItemStateException(org.apache.jackrabbit.core.state.NoSuchItemStateException) ItemStateException(org.apache.jackrabbit.core.state.ItemStateException) ResourceBasedBLOBStore(org.apache.jackrabbit.core.persistence.util.ResourceBasedBLOBStore) OutputStreamWriter(java.io.OutputStreamWriter) OutputStreamWriter(java.io.OutputStreamWriter) BufferedWriter(java.io.BufferedWriter) Writer(java.io.Writer)

Example 3 with InternalValue

use of org.apache.jackrabbit.core.value.InternalValue in project jackrabbit by apache.

the class Serializer method deserialize.

/**
     * Deserializes a <code>PropertyState</code> object from the given binary
     * <code>stream</code>. Binary values are retrieved from the specified
     * <code>BLOBStore</code>.
     *
     * @param state     <code>state</code> to deserialize
     * @param stream    the stream where the <code>state</code> should be
     *                  deserialized from
     * @param blobStore handler for BLOB data
     * @throws Exception if an error occurs during the deserialization
     * @see #serialize(PropertyState, OutputStream, BLOBStore)
     */
public static void deserialize(PropertyState state, InputStream stream, BLOBStore blobStore) throws Exception {
    DataInputStream in = new DataInputStream(stream);
    // type
    int type = in.readInt();
    state.setType(type);
    // multiValued
    boolean multiValued = in.readBoolean();
    state.setMultiValued(multiValued);
    // definitionId
    in.readUTF();
    // modCount
    short modCount = in.readShort();
    state.setModCount(modCount);
    // values
    // count
    int count = in.readInt();
    InternalValue[] values = new InternalValue[count];
    for (int i = 0; i < count; i++) {
        InternalValue val;
        if (type == PropertyType.BINARY) {
            // value (i.e. blobId)
            String s = in.readUTF();
            // in the BLOB store
            if (blobStore instanceof ResourceBasedBLOBStore) {
                // optimization: if the BLOB store is resource-based
                // retrieve the resource directly rather than having
                // to read the BLOB from an input stream
                FileSystemResource fsRes = ((ResourceBasedBLOBStore) blobStore).getResource(s);
                val = InternalValue.create(fsRes);
            } else {
                InputStream is = blobStore.get(s);
                try {
                    val = InternalValue.create(is);
                } finally {
                    try {
                        is.close();
                    } catch (IOException e) {
                    // ignore
                    }
                }
            }
        } else {
            /**
                 * because writeUTF(String) has a size limit of 65k,
                 * Strings are serialized as <length><byte[]>
                 */
            //s = in.readUTF();   // value
            // lenght of byte[]
            int len = in.readInt();
            byte[] bytes = new byte[len];
            // byte[]
            in.readFully(bytes);
            String s = new String(bytes, ENCODING);
            val = InternalValue.valueOf(s, type);
        }
        values[i] = val;
    }
    state.setValues(values);
}
Also used : DataInputStream(java.io.DataInputStream) InputStream(java.io.InputStream) FileSystemResource(org.apache.jackrabbit.core.fs.FileSystemResource) IOException(java.io.IOException) DataInputStream(java.io.DataInputStream) InternalValue(org.apache.jackrabbit.core.value.InternalValue)

Example 4 with InternalValue

use of org.apache.jackrabbit.core.value.InternalValue in project jackrabbit by apache.

the class VersionManagerImplRestore method internalRestoreFrozen.

/**
     * Restores the properties and child nodes from the frozen state.
     *
     * @param state state to restore
     * @param freeze the frozen node
     * @param vsel version selector
     * @param restored set of restored versions
     * @param removeExisting remove existing flag
     * @param copy if <code>true</code> a pure copy is performed
     * @throws RepositoryException if an error occurs
     * @throws ItemStateException if an error occurs
     */
protected void internalRestoreFrozen(NodeStateEx state, InternalFrozenNode freeze, VersionSelector vsel, Set<InternalVersion> restored, boolean removeExisting, boolean copy) throws RepositoryException, ItemStateException {
    // check uuid
    if (state.getEffectiveNodeType().includesNodeType(NameConstants.MIX_REFERENCEABLE)) {
        if (!state.getNodeId().equals(freeze.getFrozenId())) {
            String msg = "Unable to restore version of " + safeGetJCRPath(state) + ". UUID changed.";
            log.error(msg);
            throw new ItemExistsException(msg);
        }
    }
    // check primary type
    if (!freeze.getFrozenPrimaryType().equals(state.getState().getNodeTypeName())) {
        // todo: implement
        String msg = "Unable to restore version of " + safeGetJCRPath(state) + ". PrimaryType change not supported yet.";
        log.error(msg);
        throw new UnsupportedRepositoryOperationException(msg);
    }
    // adjust mixins
    state.setMixins(freeze.getFrozenMixinTypes());
    // For each property P present on F (other than jcr:frozenPrimaryType,
    // jcr:frozenMixinTypes and jcr:frozenUuid): 
    // - If P has an OPV of COPY or VERSION then F/P is copied to N/P,
    //   replacing any existing N/P.
    // - F will never have a property with an OPV of IGNORE, INITIALIZE, COMPUTE
    //   or ABORT (see 15.2 Check-In: Creating a Version).
    Set<Name> propNames = new HashSet<Name>();
    PropertyState[] props = freeze.getFrozenProperties();
    for (PropertyState prop : props) {
        // don't restore jcr:activity
        Name name = prop.getName();
        if (!name.equals(NameConstants.JCR_ACTIVITY)) {
            state.copyFrom(prop);
            propNames.add(name);
        }
    }
    // remove properties that do not exist in the frozen representation
    for (PropertyState prop : state.getProperties()) {
        Name propName = prop.getName();
        if (!propNames.contains(propName)) {
            int opv = state.getDefinition(prop).getOnParentVersion();
            if (opv == OnParentVersionAction.COPY || opv == OnParentVersionAction.VERSION || opv == OnParentVersionAction.ABORT) {
                state.removeProperty(propName);
            } else if (opv == OnParentVersionAction.INITIALIZE) {
                InternalValue[] values = computeAutoValues(state, state.getDefinition(prop), true);
                if (values != null) {
                    state.setPropertyValues(propName, prop.getType(), values, prop.isMultiValued());
                }
            } else if (opv == OnParentVersionAction.COMPUTE) {
                InternalValue[] values = computeAutoValues(state, state.getDefinition(prop), false);
                if (values != null) {
                    state.setPropertyValues(propName, prop.getType(), values, prop.isMultiValued());
                }
            }
        }
    }
    // add 'auto-create' properties that do not exist yet
    for (QPropertyDefinition def : state.getEffectiveNodeType().getAutoCreatePropDefs()) {
        if (!state.hasProperty(def.getName())) {
            InternalValue[] values = computeAutoValues(state, def, true);
            if (values != null) {
                state.setPropertyValues(def.getName(), def.getRequiredType(), values, def.isMultiple());
            }
        }
    }
    // For each child node C present on N but not on F:
    // - If C has an OPV of COPY, VERSION or ABORT then N/C is removed.
    //   Note that while a node with a child item of OPV ABORT cannot be
    //   versioned, it is legal for a previously versioned node to have such
    //   a child item added to it and then for it to be restored to the state
    //   that it had before that item was added, as this step indicates.
    // - If C has an OPV of IGNORE then no change is made to N/C.
    // - If C has an OPV of INITIALIZE then N/C is re-initialized as if it
    //   were newly created, as defined in its node type.
    // - If C has an OPV of COMPUTE then N/C may be re-initialized according
    //   to an implementation-specific mechanism.
    LinkedList<ChildNodeEntry> toDelete = new LinkedList<ChildNodeEntry>();
    for (ChildNodeEntry entry : state.getState().getChildNodeEntries()) {
        if (!freeze.hasFrozenChildNode(entry.getName(), entry.getIndex())) {
            NodeStateEx child = state.getNode(entry.getName(), entry.getIndex());
            int opv = child.getDefinition().getOnParentVersion();
            if (copy || opv == OnParentVersionAction.COPY || opv == OnParentVersionAction.VERSION || opv == OnParentVersionAction.ABORT) {
                toDelete.addFirst(entry);
            } else if (opv == OnParentVersionAction.INITIALIZE) {
                log.warn("OPV.INITIALIZE not supported yet on restore of existing child nodes: " + safeGetJCRPath(child));
            } else if (opv == OnParentVersionAction.COMPUTE) {
                log.warn("OPV.COMPUTE not supported yet on restore of existing child nodes: " + safeGetJCRPath(child));
            }
        }
    }
    for (ChildNodeEntry entry : toDelete) {
        state.removeNode(entry.getName(), entry.getIndex());
    }
    // need to sync with state manager
    state.store();
    // create a map that contains a int->NodeStateEx mapping for each child name
    Map<Name, Map<Integer, NodeStateEx>> entryToNodeStateExMapping = new HashMap<Name, Map<Integer, NodeStateEx>>();
    for (ChildNodeEntry entry : state.getState().getChildNodeEntries()) {
        Map<Integer, NodeStateEx> id2stateMap = entryToNodeStateExMapping.get(entry.getName());
        if (id2stateMap == null) {
            id2stateMap = new HashMap<Integer, NodeStateEx>();
        }
        id2stateMap.put(entry.getIndex(), state.getNode(entry.getName(), entry.getIndex()));
        entryToNodeStateExMapping.put(entry.getName(), id2stateMap);
    }
    //   COMPUTE or ABORT (see 15.2 Check-In: Creating a Version).
    for (ChildNodeEntry entry : freeze.getFrozenChildNodes()) {
        InternalFreeze child = freeze.getFrozenChildNode(entry.getName(), entry.getIndex());
        NodeStateEx restoredChild = null;
        if (child instanceof InternalFrozenNode) {
            // - If C has an OPV of COPY or VERSION:
            //   - B is true, then F/C and its subgraph is copied to N/C, replacing
            //     any existing N/C and its subgraph and any node in the workspace
            //     with the same identifier as C or a node in the subgraph of C is
            //     removed.
            //   - B is false, then F/C and its subgraph is copied to N/C, replacing
            //     any existing N/C and its subgraph unless there exists a node in the
            //     workspace with the same identifier as C, or a node in the subgraph
            //     of C, in which case an ItemExistsException is thrown , all
            //     changes made by the restore are rolled back leaving N unchanged.
            InternalFrozenNode f = (InternalFrozenNode) child;
            // if node is present, remove it
            Map<Integer, NodeStateEx> id2stateMap = entryToNodeStateExMapping.get(entry.getName());
            if (id2stateMap != null && id2stateMap.containsKey(entry.getIndex())) {
                state.removeNode(id2stateMap.get(entry.getIndex()));
            }
            // check for existing
            if (f.getFrozenId() != null) {
                if (stateMgr.hasItemState(f.getFrozenId())) {
                    NodeStateEx existing = state.getNode(f.getFrozenId());
                    if (removeExisting) {
                        NodeStateEx parent = existing.getParent();
                        parent.removeNode(existing);
                        parent.store();
                    } else if (existing.getState().isShareable()) {
                        // if existing node is shareable, then clone it
                        restoredChild = state.moveFrom(existing, existing.getName(), true);
                    } else if (!existing.hasAncestor(state.getNodeId())) {
                        String msg = "Unable to restore node, item already exists " + "outside of restored tree: " + safeGetJCRPath(existing);
                        log.error(msg);
                        throw new ItemExistsException(msg);
                    }
                }
            }
            if (restoredChild == null) {
                restoredChild = state.addNode(f.getName(), f.getFrozenPrimaryType(), f.getFrozenId());
                restoredChild.setMixins(f.getFrozenMixinTypes());
            }
            internalRestoreFrozen(restoredChild, f, vsel, restored, removeExisting, true);
        } else if (child instanceof InternalFrozenVersionHistory) {
            //   Each child node C of N where C has an OPV of VERSION and C is
            //   mix:versionable, is represented in F not as a copy of N/C but as
            //   special node containing a reference to the version history of
            //   C. On restore, the following occurs:
            //   - If the workspace currently has an already existing node corresponding
            //     to C's version history and the removeExisting flag of the restore is
            //     set to true, then that instance of C becomes the child of the restored N.
            //   - If the workspace currently has an already existing node corresponding
            //     to C's version history and the removeExisting flag of the restore is
            //     set to false then an ItemExistsException is thrown.
            //   - If the workspace does not have an instance of C then one is restored from
            //     C's version history:
            //     - If the restore was initiated through a restoreByLabel where L is
            //       the specified label and there is a version of C with the label L then
            //       that version is restored.
            //     - If the version history of C does not contain a version with the label
            //       L or the restore was initiated by a method call that does not specify
            //       a label then the workspace in which the restore is being performed
            //       will determine which particular version of C will be restored. This
            //       determination depends on the configuration of the workspace and
            //       is outside the scope of this specification.
            InternalFrozenVersionHistory fh = (InternalFrozenVersionHistory) child;
            InternalVersionHistory vh = vMgr.getVersionHistory(fh.getVersionHistoryId());
            // get desired version from version selector
            InternalVersion v = vsel.select(vh);
            Name oldVersion = null;
            // check if representing versionable already exists somewhere
            NodeId nodeId = vh.getVersionableId();
            if (stateMgr.hasItemState(nodeId)) {
                restoredChild = state.getNode(nodeId);
                if (restoredChild.getParentId().equals(state.getNodeId())) {
                // if same parent, ignore
                } else if (removeExisting) {
                    NodeStateEx parent = restoredChild.getNode(restoredChild.getParentId());
                    state.moveFrom(restoredChild, fh.getName(), false);
                    parent.store();
                    // get old version name
                    oldVersion = getBaseVersion(restoredChild).getName();
                } else {
                    // since we delete the OPV=Copy children beforehand, all
                    // found nodes must be outside of this tree
                    String msg = "Unable to restore node, item already exists " + "outside of restored tree: " + safeGetJCRPath(restoredChild);
                    log.error(msg);
                    throw new ItemExistsException(msg);
                }
            }
            // check existing version of item exists
            if (restoredChild == null) {
                if (v == null) {
                    // if version selector was unable to select version,
                    // choose the initial one
                    List<InternalVersion> vs = vh.getRootVersion().getSuccessors();
                    if (vs.isEmpty()) {
                        String msg = "Unable to select appropriate version for " + child.getName() + " using " + vsel;
                        log.error(msg);
                        throw new VersionException(msg);
                    }
                    v = vs.get(0);
                }
                InternalFrozenNode f = v.getFrozenNode();
                restoredChild = state.addNode(fh.getName(), f.getFrozenPrimaryType(), f.getFrozenId());
                restoredChild.setMixins(f.getFrozenMixinTypes());
            } else {
                if (v == null || oldVersion == null || v.getName().equals(oldVersion)) {
                    v = null;
                }
            }
            if (v != null) {
                try {
                    internalRestore(restoredChild, v, vsel, removeExisting);
                } catch (RepositoryException e) {
                    log.error("Error while restoring node: " + e);
                    log.error("  child path: " + restoredChild);
                    log.error("  selected version: " + v.getName());
                    StringBuilder avail = new StringBuilder();
                    for (Name name : vh.getVersionNames()) {
                        avail.append(name);
                        avail.append(", ");
                    }
                    log.error("  available versions: " + avail);
                    log.error("  versionselector: " + vsel);
                    throw e;
                }
                // add this version to set
                restored.add(v);
            }
        }
        if (restoredChild != null && state.getEffectiveNodeType().hasOrderableChildNodes()) {
            //   In a repository that supports orderable child nodes, the relative
            //   ordering of the set of child nodes C that are copied from F is
            //   preserved.
            // order at end
            ArrayList<ChildNodeEntry> list = new ArrayList<ChildNodeEntry>(state.getState().getChildNodeEntries());
            ChildNodeEntry toReorder = null;
            boolean isLast = true;
            for (ChildNodeEntry e : list) {
                if (e.getId().equals(restoredChild.getNodeId())) {
                    toReorder = e;
                } else if (toReorder != null) {
                    isLast = false;
                }
            }
            if (toReorder != null && !isLast) {
                list.remove(toReorder);
                list.add(toReorder);
                state.getState().setChildNodeEntries(list);
            }
        }
    }
}
Also used : UnsupportedRepositoryOperationException(javax.jcr.UnsupportedRepositoryOperationException) Name(org.apache.jackrabbit.spi.Name) QPropertyDefinition(org.apache.jackrabbit.spi.QPropertyDefinition) ChildNodeEntry(org.apache.jackrabbit.core.state.ChildNodeEntry) RepositoryException(javax.jcr.RepositoryException) InternalValue(org.apache.jackrabbit.core.value.InternalValue) PropertyState(org.apache.jackrabbit.core.state.PropertyState) ItemExistsException(javax.jcr.ItemExistsException) NodeId(org.apache.jackrabbit.core.id.NodeId) VersionException(javax.jcr.version.VersionException)

Example 5 with InternalValue

use of org.apache.jackrabbit.core.value.InternalValue in project jackrabbit by apache.

the class InternalVersionHistoryImpl method checkin.

/**
     * Checks in a node. It creates a new version with the given name and freezes
     * the state of the given node.
     *
     * @param name new version name
     * @param src source node to version
     * @param created optional created date
     * @return the newly created version
     * @throws RepositoryException if an error occurs
     */
synchronized InternalVersionImpl checkin(Name name, NodeStateEx src, Calendar created) throws RepositoryException {
    // copy predecessors from src node
    InternalValue[] predecessors;
    if (src.hasProperty(NameConstants.JCR_PREDECESSORS)) {
        predecessors = src.getPropertyValues(NameConstants.JCR_PREDECESSORS);
        // check all predecessors
        for (InternalValue pred : predecessors) {
            NodeId predId = pred.getNodeId();
            // check if version exist
            if (!nameCache.containsValue(predId)) {
                throw new RepositoryException("Invalid predecessor in source node: " + predId);
            }
        }
    } else {
        // with simple versioning, the node does not contain a predecessors
        // property and we just use the 'head' version as predecessor
        Iterator<NodeId> iter = nameCache.values().iterator();
        NodeId last = null;
        while (iter.hasNext()) {
            last = iter.next();
        }
        if (last == null) {
            // should never happen
            last = rootVersion.getId();
        }
        predecessors = new InternalValue[] { InternalValue.create(last) };
    }
    NodeId versionId = vMgr.getNodeIdFactory().newNodeId();
    NodeStateEx vNode = node.addNode(name, NameConstants.NT_VERSION, versionId, true);
    // check for jcr:activity
    if (src.hasProperty(NameConstants.JCR_ACTIVITY)) {
        InternalValue act = src.getPropertyValue(NameConstants.JCR_ACTIVITY);
        vNode.setPropertyValue(NameConstants.JCR_ACTIVITY, act);
    }
    // initialize 'created', 'predecessors' and 'successors'
    if (created == null) {
        created = getCurrentTime();
    }
    vNode.setPropertyValue(NameConstants.JCR_CREATED, InternalValue.create(created));
    vNode.setPropertyValues(NameConstants.JCR_PREDECESSORS, PropertyType.REFERENCE, predecessors);
    vNode.setPropertyValues(NameConstants.JCR_SUCCESSORS, PropertyType.REFERENCE, InternalValue.EMPTY_ARRAY);
    // checkin source node
    InternalFrozenNodeImpl.checkin(vNode, NameConstants.JCR_FROZENNODE, src);
    // update version graph
    boolean isConfiguration = src.getEffectiveNodeType().includesNodeType(NameConstants.NT_CONFIGURATION);
    InternalVersionImpl version = isConfiguration ? new InternalBaselineImpl(this, vNode, name) : new InternalVersionImpl(this, vNode, name);
    version.internalAttach();
    // and store
    node.store();
    vMgr.versionCreated(version);
    // update cache
    versionCache.put(version.getId(), version);
    nameCache.put(version.getName(), version.getId());
    return version;
}
Also used : NodeId(org.apache.jackrabbit.core.id.NodeId) RepositoryException(javax.jcr.RepositoryException) InternalValue(org.apache.jackrabbit.core.value.InternalValue)

Aggregations

InternalValue (org.apache.jackrabbit.core.value.InternalValue)62 Name (org.apache.jackrabbit.spi.Name)21 NodeId (org.apache.jackrabbit.core.id.NodeId)20 PropertyState (org.apache.jackrabbit.core.state.PropertyState)17 RepositoryException (javax.jcr.RepositoryException)16 ItemStateException (org.apache.jackrabbit.core.state.ItemStateException)13 PropertyId (org.apache.jackrabbit.core.id.PropertyId)12 NoSuchItemStateException (org.apache.jackrabbit.core.state.NoSuchItemStateException)11 QPropertyDefinition (org.apache.jackrabbit.spi.QPropertyDefinition)11 NodeState (org.apache.jackrabbit.core.state.NodeState)10 Value (javax.jcr.Value)9 IOException (java.io.IOException)7 InputStream (java.io.InputStream)6 HashMap (java.util.HashMap)6 ConstraintViolationException (javax.jcr.nodetype.ConstraintViolationException)6 FileSystemResource (org.apache.jackrabbit.core.fs.FileSystemResource)6 ArrayList (java.util.ArrayList)5 PropertyDefinition (javax.jcr.nodetype.PropertyDefinition)4 EffectiveNodeType (org.apache.jackrabbit.core.nodetype.EffectiveNodeType)4 Path (org.apache.jackrabbit.spi.Path)4