Package org.apache.jackrabbit.core.state

Source Code of org.apache.jackrabbit.core.state.PropertyState

/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements.  See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License.  You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.jackrabbit.core.state;

import org.apache.jackrabbit.core.PropertyId;
import org.apache.jackrabbit.core.NodeId;
import org.apache.jackrabbit.core.ItemId;
import org.apache.jackrabbit.core.nodetype.PropDefId;
import org.apache.jackrabbit.core.value.BLOBFileValue;
import org.apache.jackrabbit.core.value.InternalValue;
import org.apache.jackrabbit.spi.Name;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

/**
* <code>PropertyState</code> represents the state of a <code>Property</code>.
*/
public class PropertyState extends ItemState {
   
    /** Logger instance */
    private static Logger log = LoggerFactory.getLogger(PropertyState.class);

    /**
     * Serialization UID of this class.
     */
    static final long serialVersionUID = 90076676913237139L;

    /**
     * the id of this property state
     */
    private PropertyId id;

    /**
     * the internal values
     */
    private InternalValue[] values;

    /**
     * the type of this property state
     */
    private int type;

    /**
     * flag indicating if this is a multivalue property
     */
    private boolean multiValued;

    /**
     * the property definition id
     */
    private PropDefId defId;

    /**
     * Constructs a new property state that is initially connected to an
     * overlayed state.
     *
     * @param overlayedState the backing property state being overlayed
     * @param initialStatus  the initial status of the property state object
     * @param isTransient    flag indicating whether this state is transient or not
     */
    public PropertyState(PropertyState overlayedState, int initialStatus,
                         boolean isTransient) {
        super(overlayedState, initialStatus, isTransient);
        pull();
    }

    /**
     * Create a new <code>PropertyState</code>
     *
     * @param id            id of the property
     * @param initialStatus the initial status of the property state object
     * @param isTransient   flag indicating whether this state is transient or not
     */
    public PropertyState(PropertyId id, int initialStatus, boolean isTransient) {
        super(initialStatus, isTransient);
        this.id = id;
        type = PropertyType.UNDEFINED;
        values = InternalValue.EMPTY_ARRAY;
        multiValued = false;
    }

    /**
     * {@inheritDoc}
     */
    protected synchronized void copy(ItemState state, boolean syncModCount) {
        synchronized (state) {
            PropertyState propState = (PropertyState) state;
            id = propState.id;
            type = propState.type;
            defId = propState.defId;
            values = propState.values;
            multiValued = propState.multiValued;
            if (syncModCount) {
                setModCount(state.getModCount());
            }
        }
    }

    //-------------------------------------------------------< public methods >
    /**
     * Determines if this item state represents a node.
     *
     * @return always false
     * @see ItemState#isNode
     */
    public boolean isNode() {
        return false;
    }

    /**
     * {@inheritDoc}
     */
    public ItemId getId() {
        return id;
    }

    /**
     * Returns the identifier of this property.
     *
     * @return the id of this property.
     */
    public PropertyId getPropertyId() {
        return id;
    }

    /**
     * {@inheritDoc}
     */
    public NodeId getParentId() {
        return id.getParentId();
    }

    /**
     * Returns the name of this property.
     *
     * @return the name of this property.
     */
    public Name getName() {
        return id.getName();
    }

    /**
     * Sets the type of this property.
     *
     * @param type the type to be set
     * @see PropertyType
     */
    public void setType(int type) {
        this.type = type;
    }

    /**
     * Sets the flag indicating whether this property is multi-valued.
     *
     * @param multiValued flag indicating whether this property is multi-valued
     */
    public void setMultiValued(boolean multiValued) {
        this.multiValued = multiValued;
    }

    /**
     * Returns the type of this property.
     *
     * @return the type of this property.
     * @see PropertyType
     */
    public int getType() {
        return type;
    }

    /**
     * Returns true if this property is multi-valued, otherwise false.
     *
     * @return true if this property is multi-valued, otherwise false.
     */
    public boolean isMultiValued() {
        return multiValued;
    }

    /**
     * Returns the id of the definition applicable to this property state.
     *
     * @return the id of the definition
     */
    public PropDefId getDefinitionId() {
        return defId;
    }

    /**
     * Sets the id of the definition applicable to this property state.
     *
     * @param defId the id of the definition
     */
    public void setDefinitionId(PropDefId defId) {
        this.defId = defId;
    }

    /**
     * Sets the value(s) of this property.
     *
     * @param values the new values
     */
    public void setValues(InternalValue[] values) {
        this.values = values;
    }

    /**
     * Returns the value(s) of this property.
     *
     * @return the value(s) of this property.
     */
    public InternalValue[] getValues() {
        return values;
    }

    /**
     * {@inheritDoc}
     */
    public long calculateMemoryFootprint() {
        /*
        private PropertyId id;
        private InternalValue[] values;
        private int type;
        private boolean multiValued;
        private PropDefId defId;

        we assume an average Name localname of 30 chars.
        PropertyId = 8 + nodeId(36) * name(250) + hash(4) ~ 300;
        NodeDefId = 8 + id(4) = 12
        InternalValue = 8 + n * (values) ~ 8 + n*100;
        value=approx 100 bytes.
        */
        return 350 + values.length * 100;
    }
   
    //-------------------------------------------------< Serializable support >
    private void writeObject(ObjectOutputStream out) throws IOException {
        // important: fields must be written in same order as they are
        // read in readObject(ObjectInputStream)
        out.writeUTF(id.toString());
        out.writeUTF(defId.toString());
        out.writeInt(type);
        out.writeBoolean(multiValued);
        if (values == null) {
            out.writeShort(-1);
        } else {
            out.writeShort(values.length);
            for (int i = 0; i < values.length; i++) {
                InternalValue val = values[i];
                try {
                    if (type == PropertyType.BINARY) {
                        // special handling required for binary value
                        BLOBFileValue blob = val.getBLOBFileValue();
                        InputStream in = blob.getStream();
                        out.writeLong(blob.getLength());
                        byte[] buf = new byte[0x2000];
                        try {
                            int read;
                            while ((read = in.read(buf)) > 0) {
                                out.write(buf, 0, read);
                            }
                        } finally {
                            in.close();
                        }
                    } else {
                        out.writeUTF(val.toString());
                    }
                } catch (IllegalStateException ise) {
                    throw new IOException(ise.getMessage());
                } catch (RepositoryException re) {
                    throw new IOException(re.getMessage());
                }
            }
        }
    }

    private void readObject(ObjectInputStream in) throws IOException {
        // important: fields must be read in same order as they are
        // written in writeObject(ObjectOutputStream)
        id = PropertyId.valueOf(in.readUTF());
        defId = PropDefId.valueOf(in.readUTF());
        type = in.readInt();
        multiValued = in.readBoolean();
        short count = in.readShort(); // # of values
        if (count < 0) {
            values = null;
        } else {
            values = new InternalValue[count];
            for (int i = 0; i < values.length; i++) {
                if (type == PropertyType.BINARY) {
                    // special handling required for binary value
                    final long length = in.readLong();
                    final InputStream stream = in;
                    // create InputStream wrapper of size 'length'
                    try {
                        values[i] = createInternalValueFromInputStream(stream, length);
                    } catch (RepositoryException e) {
                        String msg = "Failed to create internal value: " + e.getMessage();
                        log.error(msg, e);
                        throw new IOException(msg);
                    }
                   
                } else {
                    values[i] = InternalValue.valueOf(in.readUTF(), type);
                }
            }
        }
    }
   
    private InternalValue createInternalValueFromInputStream(final InputStream stream, final long length) throws RepositoryException {
        return InternalValue.create(new InputStream() {
           
            private long consumed = 0;

            public int read() throws IOException {
                if (consumed >= length) {
                    return -1// eof
                }
                int b = stream.read();
                consumed++;
                return b;
            }

            public int read(byte[] b, int off, int len) throws IOException {
                if (consumed >= length) {
                    return -1// eof
                }
                if ((consumed + len) > length) {
                    len = (int) (length - consumed);
                }
                int read = stream.read(b, off, len);
                consumed += read;
                return read;
            }

            public long skip(long n) throws IOException {
                if (consumed >= length && n > 0) {
                    return -1// eof
                }
                if ((consumed + n) > length) {
                    n = length - consumed;
                }
                long skipped = stream.skip(n);
                consumed += skipped;
                return skipped;
            }

            public void close() {
                // nop
            }
        });
    }
}
TOP

Related Classes of org.apache.jackrabbit.core.state.PropertyState

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.