001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied.  See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019package org.apache.shiro.lang.io;
020
021import java.io.BufferedInputStream;
022import java.io.BufferedOutputStream;
023import java.io.ByteArrayInputStream;
024import java.io.ByteArrayOutputStream;
025import java.io.IOException;
026import java.io.ObjectInputStream;
027import java.io.ObjectOutputStream;
028
029/**
030 * Serializer implementation that uses the default JVM serialization mechanism (Object Input/Output Streams).
031 *
032 * @param <T> the type of target.
033 * @since 0.9
034 */
035public class DefaultSerializer<T> implements Serializer<T> {
036
037    /**
038     * This implementation serializes the Object by using an {@link ObjectOutputStream} backed by a
039     * {@link ByteArrayOutputStream}.  The {@code ByteArrayOutputStream}'s backing byte array is returned.
040     *
041     * @param o the Object to convert into a byte[] array.
042     * @return the bytes representing the serialized object using standard JVM serialization.
043     * @throws SerializationException wrapping a {@link IOException} if something goes wrong with the streams.
044     */
045    public byte[] serialize(T o) throws SerializationException {
046        if (o == null) {
047            String msg = "argument cannot be null.";
048            throw new IllegalArgumentException(msg);
049        }
050        ByteArrayOutputStream baos = new ByteArrayOutputStream();
051        BufferedOutputStream bos = new BufferedOutputStream(baos);
052
053        try {
054            ObjectOutputStream oos = new ObjectOutputStream(bos);
055            oos.writeObject(o);
056            oos.close();
057            baos.flush();
058            return baos.toByteArray();
059        } catch (IOException e) {
060            String msg = "Unable to serialize object [" + o + "].  "
061                    + "In order for the DefaultSerializer to serialize this object, "
062                    + " the [" + o.getClass().getName() + "] class must implement java.io.Serializable.";
063            throw new SerializationException(msg, e);
064        }
065    }
066
067    /**
068     * This implementation deserializes the byte array using a {@link ObjectInputStream} using a source
069     * {@link ByteArrayInputStream} constructed with the argument byte array.
070     *
071     * @param serialized the raw data resulting from a previous {@link #serialize(Object) serialize} call.
072     * @return the deserialized/reconstituted object based on the given byte array
073     * @throws SerializationException if anything goes wrong using the streams.
074     */
075    public T deserialize(byte[] serialized) throws SerializationException {
076        if (serialized == null) {
077            String msg = "argument cannot be null.";
078            throw new IllegalArgumentException(msg);
079        }
080        ByteArrayInputStream bais = new ByteArrayInputStream(serialized);
081        BufferedInputStream bis = new BufferedInputStream(bais);
082        try {
083            ObjectInputStream ois = new ClassResolvingObjectInputStream(bis);
084            @SuppressWarnings({"unchecked"})
085            T deserialized = (T) ois.readObject();
086            ois.close();
087            return deserialized;
088        } catch (Exception e) {
089            String msg = "Unable to deserialize argument byte array.";
090            throw new SerializationException(msg, e);
091        }
092    }
093}