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.io;
020
021import java.io.*;
022
023/**
024 * Serializer implementation that uses the default JVM serialization mechanism (Object Input/Output Streams).
025 *
026 * @since 0.9
027 */
028public class DefaultSerializer<T> implements Serializer<T> {
029
030    /**
031     * This implementation serializes the Object by using an {@link ObjectOutputStream} backed by a
032     * {@link ByteArrayOutputStream}.  The {@code ByteArrayOutputStream}'s backing byte array is returned.
033     *
034     * @param o the Object to convert into a byte[] array.
035     * @return the bytes representing the serialized object using standard JVM serialization.
036     * @throws SerializationException wrapping a {@link IOException} if something goes wrong with the streams.
037     */
038    public byte[] serialize(T o) throws SerializationException {
039        if (o == null) {
040            String msg = "argument cannot be null.";
041            throw new IllegalArgumentException(msg);
042        }
043        ByteArrayOutputStream baos = new ByteArrayOutputStream();
044        BufferedOutputStream bos = new BufferedOutputStream(baos);
045
046        try {
047            ObjectOutputStream oos = new ObjectOutputStream(bos);
048            oos.writeObject(o);
049            oos.close();
050            return baos.toByteArray();
051        } catch (IOException e) {
052            String msg = "Unable to serialize object [" + o + "].  " +
053                    "In order for the DefaultSerializer to serialize this object, the [" + o.getClass().getName() + "] " +
054                    "class must implement java.io.Serializable.";
055            throw new SerializationException(msg, e);
056        }
057    }
058
059    /**
060     * This implementation deserializes the byte array using a {@link ObjectInputStream} using a source
061     * {@link ByteArrayInputStream} constructed with the argument byte array.
062     *
063     * @param serialized the raw data resulting from a previous {@link #serialize(Object) serialize} call.
064     * @return the deserialized/reconstituted object based on the given byte array
065     * @throws SerializationException if anything goes wrong using the streams.
066     */
067    public T deserialize(byte[] serialized) throws SerializationException {
068        if (serialized == null) {
069            String msg = "argument cannot be null.";
070            throw new IllegalArgumentException(msg);
071        }
072        ByteArrayInputStream bais = new ByteArrayInputStream(serialized);
073        BufferedInputStream bis = new BufferedInputStream(bais);
074        try {
075            ObjectInputStream ois = new ClassResolvingObjectInputStream(bis);
076            @SuppressWarnings({"unchecked"})
077            T deserialized = (T) ois.readObject();
078            ois.close();
079            return deserialized;
080        } catch (Exception e) {
081            String msg = "Unable to deserialze argument byte array.";
082            throw new SerializationException(msg, e);
083        }
084    }
085}