All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jboss.marshalling.Marshalling Maven / Gradle / Ivy

/*
 * JBoss, Home of Professional Open Source.
 * Copyright 2014 Red Hat, Inc., and individual contributors
 * as indicated by the @author tags.
 *
 * Licensed 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.jboss.marshalling;

import static java.lang.System.getSecurityManager;
import static java.security.AccessController.doPrivileged;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.EOFException;
import java.io.OptionalDataException;
import java.io.StreamCorruptedException;
import java.io.Serializable;
import java.nio.ByteBuffer;
import java.security.PrivilegedAction;
import java.util.Arrays;
import java.util.ServiceLoader;

import sun.reflect.ReflectionFactory;

/**
 * Static utility methods for simplifying use of marshallers.
 * @apiviz.landmark
 */
public final class Marshalling {

    private Marshalling() {
    }

    /**
     * Get a marshaller factory, by name.  Uses the thread's current context classloader, if available, to locate
     * the factory.
     *
     * @param name the name of the protocol to acquire
     * @return the marshaller factory, or {@code null} if no matching factory was found
     *
     * @see ServiceLoader
     *
     * @deprecated It is recommended that you use {@link #getProvidedMarshallerFactory(String)} instead; using the context
     * class loader to find a marshalling implementation is risky at best as the user may have just about anything on their
     * class path.
     */
    @Deprecated
    public static MarshallerFactory getMarshallerFactory(final String name) {
        if (getSecurityManager() == null) {
            return loadMarshallerFactory(ServiceLoader.load(ProviderDescriptor.class), name);
        } else {
            return loadMarshallerFactory(doPrivileged(new PrivilegedAction>() {
                public ServiceLoader run() {
                    return ServiceLoader.load(ProviderDescriptor.class);
                }
            }), name);
        }
    }

    /**
     * Get a marshaller factory, by name.  Uses the given classloader to locate
     * the factory.
     *
     * @param name the name of the protocol to acquire
     * @param classLoader the class loader to use
     * @return the marshaller factory, or {@code null} if no matching factory was found
     *
     * @see ServiceLoader
     */
    public static MarshallerFactory getMarshallerFactory(final String name, final ClassLoader classLoader) {
        if (getSecurityManager() == null) {
            return loadMarshallerFactory(ServiceLoader.load(ProviderDescriptor.class, classLoader), name);
        } else {
            return loadMarshallerFactory(doPrivileged(new PrivilegedAction>() {
                public ServiceLoader run() {
                    return ServiceLoader.load(ProviderDescriptor.class, classLoader);
                }
            }), name);
        }
    }

    /**
     * Get a marshaller factory which is visible to this implementation, by name.  Uses the class loader of this API.
     *
     * @param name the name of the protocol to acquire
     * @return the marshaller factory, or {@code null} if no matching factory was found
     */
    public static MarshallerFactory getProvidedMarshallerFactory(final String name) {
        if (getSecurityManager() == null) {
            return loadMarshallerFactory(ServiceLoader.load(ProviderDescriptor.class, Marshalling.class.getClassLoader()), name);
        } else {
            return loadMarshallerFactory(doPrivileged(new PrivilegedAction>() {
                public ServiceLoader run() {
                    return ServiceLoader.load(ProviderDescriptor.class, Marshalling.class.getClassLoader());
                }
            }), name);
        }
    }

    private static MarshallerFactory loadMarshallerFactory(ServiceLoader loader, String name) {
        for (ProviderDescriptor descriptor : loader) {
            if (name.equals(descriptor.getName())) {
                return descriptor.getMarshallerFactory();
            }
        }
        return null;
    }

    private static final StreamHeader NULL_STREAM_HEADER = new StreamHeader() {
        public void readHeader(final ByteInput input) throws IOException {
        }

        public void writeHeader(final ByteOutput output) throws IOException {
        }

        public String toString() {
            return "Null StreamHeader";
        }
    };

    /**
     * Get the default stream header producer, which reads and writes no header at all.
     *
     * @return the default stream header producer
     */
    public static StreamHeader nullStreamHeader() {
        return NULL_STREAM_HEADER;
    }

    /**
     * Create a stream header that uses the given bytes.
     *
     * @param headerBytes the header bytes
     * @return the stream header object
     */
    public static StreamHeader streamHeader(final byte[] headerBytes) {
        return new StaticStreamHeader(headerBytes);
    }

    private static final class StaticStreamHeader implements StreamHeader, Serializable {
        private final byte[] headerBytes;

        private static final long serialVersionUID = 8465784729867667872L;

        public StaticStreamHeader(final byte[] bytes) {
            headerBytes = bytes;
        }

        public void readHeader(final ByteInput input) throws IOException {
            final byte[] buf = new byte[headerBytes.length];
            readFully(input, buf);
            if (! Arrays.equals(buf, headerBytes)) {
                throw new StreamCorruptedException("Header is incorrect (expected " + Arrays.toString(headerBytes) + ", got " + Arrays.toString(buf) + ")");
            }
        }

        public void writeHeader(final ByteOutput output) throws IOException {
            output.write(headerBytes);
        }

        public String toString() {
            return "static StreamHeader@" + Integer.toHexString(hashCode()) + " (" + headerBytes.length + " bytes)";
        }
    }

    /**
     * Read bytes from a {@code ByteInput}.  Fully fills in the array.
     *
     * @param input the input
     * @param dest the destination
     * @throws EOFException if the end of file is reached before the array is filled
     * @throws IOException if an I/O error occurs
     */
    public static void readFully(ByteInput input, byte[] dest) throws IOException {
        readFully(input, dest, 0, dest.length);
    }

    /**
     * Read bytes from a {@code ByteInput}.  Fully fills in {@code len} bytes in the array.
     *
     * @param input the input
     * @param dest the destination
     * @param offs the offset into the array
     * @param len the number of bytes
     * @throws EOFException if the end of file is reached before the array is filled
     * @throws IOException if an I/O error occurs
     */
    public static void readFully(ByteInput input, byte[] dest, int offs, int len) throws IOException {
        while (len > 0) {
            final int r = input.read(dest, offs, len);
            if (r == -1) {
                throw new EOFException();
            }
            len -= r;
            offs += r;
        }
    }

    /**
     * Create a {@code ByteInput} wrapper for a {@code ByteBuffer}.
     *
     * @param buffer the byte buffer
     * @return the byte input wrapper
     */
    public static ByteInput createByteInput(final ByteBuffer buffer) {
        return new ByteBufferInput(buffer);
    }

    /**
     * Create a {@code ByteInput} wrapper for an {@code InputStream}.
     *
     * @param inputStream the input stream
     * @return the byte input wrapper
     */
    public static ByteInput createByteInput(final InputStream inputStream) {
        return inputStream instanceof ByteInput ? (ByteInput) inputStream : new InputStreamByteInput(inputStream);
    }

    /**
     * Create an {@code InputStream} wrapper for a {@code ByteInput}.
     *
     * @param byteInput the byte input
     * @return the input stream wrapper
     */
    public static InputStream createInputStream(final ByteInput byteInput) {
        return byteInput instanceof InputStream ? (InputStream) byteInput : new ByteInputStream(byteInput);
    }

    /**
     * Create a {@code ByteOutput} wrapper for a {@code ByteBuffer}.
     *
     * @param buffer the byte buffer
     * @return the byte output wrapper
     */
    public static ByteOutput createByteOutput(final ByteBuffer buffer) {
        return new ByteBufferOutput(buffer);
    }

    /**
     * Create a {@code ByteOutput} wrapper for an {@code OutputStream}.
     *
     * @param outputStream the output stream
     * @return the byte output wrapper
     */
    public static ByteOutput createByteOutput(final OutputStream outputStream) {
        return outputStream instanceof ByteOutput ? (ByteOutput) outputStream : new OutputStreamByteOutput(outputStream);
    }

    /**
     * Create a {@code OutputStream} wrapper for a {@code ByteOutput}.
     *
     * @param byteOutput the byte output
     * @return the output stream wrapper
     */
    public static OutputStream createOutputStream(final ByteOutput byteOutput) {
        return byteOutput instanceof OutputStream ? (OutputStream)byteOutput : new ByteOutputStream(byteOutput);
    }

    private static final ClassExternalizerFactory NULL_CLASS_EXTERNALIZER_FACTORY = new ClassExternalizerFactory() {
        public Externalizer getExternalizer(final Class type) {
            return null;
        }

        public String toString() {
            return "Null class externalizer factory";
        }
    };

    /**
     * Return the null class externalizer factory.  This instance does not externalize any classes.
     *
     * @return the null class externalizer factory
     */
    public static ClassExternalizerFactory nullClassExternalizerFactory() {
        return NULL_CLASS_EXTERNALIZER_FACTORY;
    }

    private static final ObjectResolver NULL_OBJECT_RESOLVER = new ObjectResolver() {
        public Object readResolve(final Object replacement) {
            return replacement;
        }

        public Object writeReplace(final Object original) {
            return original;
        }

        public String toString() {
            return "Null object resolver";
        }
    };

    /**
     * Return the null object resolver.  This instance does not translate objects in any way.
     *
     * @return the null object resolver
     */
    public static ObjectResolver nullObjectResolver() {
        return NULL_OBJECT_RESOLVER;
    }

    private static final ObjectTable NULL_OBJECT_TABLE = new ObjectTable() {
        public Writer getObjectWriter(final Object object) {
            return null;
        }

        public Object readObject(final Unmarshaller unmarshaller) throws IOException, ClassNotFoundException {
            return null;
        }

        public String toString() {
            return "Null object table";
        }
    };

    /**
     * Return the null object instance table.  This instance contains no predefined instances.
     *
     * @return the null instance table
     */
    public static ObjectTable nullObjectTable() {
        return NULL_OBJECT_TABLE;
    }

    private static final ClassTable NULL_CLASS_TABLE = new ClassTable() {
        public Writer getClassWriter(final Class clazz) {
            return null;
        }

        public Class readClass(final Unmarshaller unmarshaller) throws IOException, ClassNotFoundException {
            return null;
        }

        public String toString() {
            return "Null class table";
        }
    };

    /**
     * Return the null class table instance.  This instance contains no predefined classes.
     *
     * @return the null class table
     */
    public static ClassTable nullClassTable() {
        return NULL_CLASS_TABLE;
    }

    private static final ReflectionFactory reflectionFactory = doPrivileged((PrivilegedAction) ReflectionFactory::getReflectionFactory);

    /**
     * Construct a new {@link java.io.OptionalDataException}.  This method is necessary because there are no
     * public constructors in the API.
     *
     * @param eof {@code true} if there is no more data in the buffered part of the stream
     * @return a new OptionalDataException
     */
    public static OptionalDataException createOptionalDataException(boolean eof) {
        return reflectionFactory.newOptionalDataExceptionForSerialization(eof);
    }

    /**
     * Construct a new {@link java.io.OptionalDataException}.  This method is necessary because there are no
     * public constructors in the API.
     *
     * @param length the number of bytes of primitive data available to be read in the current buffer
     * @return a new OptionalDataException
     */
    public static OptionalDataException createOptionalDataException(int length) {
        final OptionalDataException optionalDataException = createOptionalDataException(false);
        optionalDataException.length = length;
        return optionalDataException;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy