DurboOutput.java 8.97 KB
/*
 * Decompiled with CFR 0_118.
 * 
 * Could not load the following classes:
 *  javax.jcr.NamespaceException
 *  javax.jcr.Property
 *  javax.jcr.RepositoryException
 *  javax.jcr.Value
 *  javax.jcr.nodetype.PropertyDefinition
 *  org.apache.commons.io.IOUtils
 */
package com.day.durbo;

import com.day.durbo.*;
import com.day.durbo.impl.DurboOutputStream;
import org.apache.commons.io.IOUtils;

import javax.jcr.NamespaceException;
import javax.jcr.Property;
import javax.jcr.RepositoryException;
import javax.jcr.Value;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;

public class DurboOutput
implements DurboConstants {
    private static final int PROPERTY_TYPE_BINARY_V1 = 16;
    private static final int PROPERTY_TYPE_STRING_V1 = 17;
    private final DurboOutputStream out;
    private final DurboNamespaceResolver resolver;
    private final Map<String, String> namespaces = new HashMap<String, String>();
    private final double version;

    public DurboOutput(OutputStream out) throws IOException {
        this(out, new IdentityNamespaceResolver(), null, false, 1.0);
    }

    public DurboOutput(OutputStream out, double version) throws IOException {
        this(out, new IdentityNamespaceResolver(), null, false, version);
    }

    public DurboOutput(OutputStream out, DurboNamespaceResolver resolver) throws IOException {
        this(out, resolver, null, false);
    }

    public DurboOutput(OutputStream out, DurboNamespaceResolver resolver, double version) throws IOException {
        this(out, resolver, null, false, version);
    }

    public DurboOutput(OutputStream out, DurboNamespaceResolver resolver, String contentType, boolean compressed) throws IOException {
        this(out, resolver, contentType, compressed, 2.1);
    }

    public DurboOutput(OutputStream out, DurboNamespaceResolver resolver, String contentType, boolean compressed, double version) throws IOException {
        this.resolver = resolver;
        this.version = version;
        this.out = new DurboOutputStream(out);
        if (compressed && version < 2.0) {
            throw new UnsupportedOperationException("Compression is not supported in protocol version " + version);
        }
        if (contentType != null && version < 2.0) {
            throw new UnsupportedOperationException("ContentType is not supported in protocol version " + version);
        }
        this.writeProperty("DurboSer", String.valueOf(version));
        if (version >= 2.0) {
            this.writeProperty("ContentType", contentType == null ? "durboser/unstructured" : contentType);
            this.writeProperty("Encoding", compressed ? "zip" : "");
        }
        if (compressed) {
            this.out.enableCompression();
        }
    }

    public void close() throws IOException {
        this.out.close();
    }

    public void defineNamespace(String prefix, String uri) throws IOException {
        if (this.version < 2.0) {
            throw new UnsupportedOperationException("Namespaces are not supported in protocol version " + this.version);
        }
        if (this.namespaces.containsKey(prefix)) {
            if (!uri.equals(this.namespaces.get(prefix))) {
                throw new UnsupportedOperationException("Namespace remapping not implemented.");
            }
        } else {
            this.out.writeByte(33);
            this.out.write(prefix);
            this.out.write(uri);
            this.namespaces.put(prefix, uri);
        }
    }

    public void writeProperty(String name, byte[] data) throws IOException {
        this.writeHeader(18, name);
        this.out.write(data);
    }

    public void writeProperty(String name, String data) throws IOException {
        this.writeHeader(17, name);
        this.out.write(data);
    }

    public void writeProperty(Property prop) throws IOException, RepositoryException {
        Value[] arrvalue;
        if (prop.getDefinition().isMultiple()) {
            arrvalue = prop.getValues();
        } else {
            Value[] arrvalue2 = new Value[1];
            arrvalue = arrvalue2;
            arrvalue2[0] = prop.getValue();
        }
        Value[] values = arrvalue;
        if (this.version >= 2.0) {
            if (prop.getType() == 7) {
                for (Value value : values) {
                    this.checkNamespace(value.getString());
                }
            } else if (prop.getType() == 8) {
                for (Value value : values) {
                    this.checkNamespacesInPath(value.getString());
                }
            }
        }
        if (prop.getDefinition().isMultiple()) {
            if (this.version < 2.0) {
                throw new UnsupportedOperationException("Multivalue properties are not supported in protocol version " + this.version);
            }
            this.writeHeader(80 | prop.getType(), prop.getName());
            this.out.writeInt(values.length);
            for (Value value : values) {
                this.out.write(value);
            }
        } else {
            this.writeHeader(16 | prop.getType(), prop.getName());
            this.out.write(values[0]);
        }
    }

    public void writeProperty(DurboInput.Property prop) throws IOException {
        DurboValue[] values = prop.getValues();
        if (prop.isMultiple()) {
            if (this.version < 2.0) {
                throw new UnsupportedOperationException("Multivalue properties are not supported in protocol version " + this.version);
            }
            this.writeHeader(80 | prop.getType(), prop.name());
            this.out.writeInt(prop.getValues().length);
            for (DurboValue value : values) {
                this.out.write(value);
            }
        } else {
            this.writeHeader(16 | prop.getType(), prop.name());
            this.out.write(values[0]);
        }
    }

    public void writeProperty(String name, int type, String[] values) throws IOException {
        this.writeProperty(name, type, values, true);
    }

    public void writeProperty(String name, int type, String value) throws IOException {
        this.writeProperty(name, type, new String[]{value}, false);
    }

    private void writeProperty(String name, int type, String[] values, boolean isMultiple) throws IOException {
        if (this.version >= 2.0) {
            if (type == 7) {
                for (String value : values) {
                    this.checkNamespace(value);
                }
            } else if (type == 8) {
                for (String value : values) {
                    this.checkNamespacesInPath(value);
                }
            }
        }
        if (isMultiple) {
            if (this.version < 2.0) {
                throw new UnsupportedOperationException("Multivalue properties are not supported in protocol version " + this.version);
            }
            this.writeHeader(80 | type, name);
            this.out.writeInt(values.length);
            for (String value : values) {
                this.out.write(value);
            }
        } else {
            this.writeHeader(16 | type, name);
            this.out.write(values[0]);
        }
    }

    private void checkNamespacesInPath(String path) throws IOException {
        int pos;
        int lastpos = 0;
        while ((pos = path.indexOf(47, lastpos)) >= 0) {
            if (pos - lastpos > 0) {
                this.checkNamespace(path.substring(lastpos, pos));
            }
            lastpos = pos + 1;
        }
        if (lastpos < path.length()) {
            this.checkNamespace(path.substring(lastpos));
        }
    }

    public void writeProperty(String name, InputStream in) throws IOException {
        ByteArrayOutputStream tmp = new ByteArrayOutputStream();
        IOUtils.copy((InputStream)in, (OutputStream)tmp);
        in.close();
        this.writeProperty(name, tmp.toByteArray());
    }

    public void writeProperty(String name, InputStream in, int size) throws IOException {
        this.writeHeader(18, name);
        if (size < 0) {
            this.out.write(in);
        } else {
            this.out.write(in, size);
        }
    }

    public void openNode(String name) throws IOException {
        this.writeHeader(32, name);
    }

    public void closeNode() throws IOException {
        this.out.writeByte(47);
    }

    private void writeHeader(int type, String name) throws IOException {
        if (this.version >= 2.0) {
            this.checkNamespace(name);
        } else if ((type & 16) > 0) {
            type = (type & 15) == 2 ? 16 : 17;
        }
        this.out.writeByte(type);
        this.out.write(name);
    }

    private void checkNamespace(String name) throws IOException {
        int pos = name.indexOf(58);
        if (pos > 0) {
            String prefix = name.substring(0, pos);
            try {
                this.defineNamespace(prefix, this.resolver.getURI(prefix));
            }
            catch (NamespaceException e) {
                throw new IllegalArgumentException(e.toString());
            }
        }
    }
}