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     */
019    package org.apache.wiki.util;
020    
021    import java.io.ByteArrayInputStream;
022    import java.io.ByteArrayOutputStream;
023    import java.io.IOException;
024    import java.io.InputStream;
025    import java.io.ObjectInputStream;
026    import java.io.ObjectOutputStream;
027    import java.io.Serializable;
028    import java.util.HashMap;
029    import java.util.Map;
030    
031    import org.apache.commons.codec.binary.Base64;
032    
033    /**
034     *  Provides static helper functions for serializing different objects.
035     *  
036     *  @since 2.8
037     */
038    public final class Serializer
039    {
040        /**
041         * Prefix used to indicated that a serialized item was encoded with Base64.
042         */
043        protected static final String BASE64_PREFIX = "base64 ";
044    
045        /**
046         *  Prevent instantiation.
047         */
048        private Serializer()
049        {}
050        
051        /**
052         * Deserializes a Base64-encoded String into a HashMap. Both the keys and values
053         * must implement {@link java.io.Serializable}.
054         * @param rawString the String contents containing the map to be deserialized
055         * @return the attributes, parsed into a Map
056         * @throws IOException if the contents cannot be parsed for any reason
057         */
058        @SuppressWarnings("unchecked")
059        public static Map<String,? extends Serializable> deserializeFromBase64( String rawString ) throws IOException
060        {
061            // Decode from Base64-encoded String to byte array
062            byte[] decodedBytes = Base64.decodeBase64( rawString.getBytes("UTF-8") );
063            
064            // Deserialize from the input stream to the Map
065            InputStream bytesIn = new ByteArrayInputStream( decodedBytes );
066            ObjectInputStream in = new ObjectInputStream( bytesIn );
067            HashMap<String,Serializable> attributes;
068            try
069            {
070                attributes = (HashMap<String,Serializable>)in.readObject();
071            }
072            catch ( ClassNotFoundException e )
073            {
074                throw new IOException( "Could not deserialiaze user profile attributes. Reason: " + e.getMessage() );
075            }
076            finally
077            {
078                in.close();
079            }
080            return attributes;
081        }
082    
083        /**
084         * Serializes a Map and formats it into a Base64-encoded String. For ease of serialization, the Map contents
085         * are first copied into a HashMap, then serialized into a byte array that is encoded as a Base64 String.
086         * @param map the Map to serialize
087         * @return a String representing the serialized form of the Map
088         * @throws IOException If serialization cannot be done
089         */
090        public static String serializeToBase64( Map<String,Serializable> map ) throws IOException
091        {
092            // Load the Map contents into a defensive HashMap
093            HashMap<String,Serializable> serialMap = new HashMap<String,Serializable>();
094            serialMap.putAll( map );
095            
096            // Serialize the Map to an output stream
097            ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
098            ObjectOutputStream out = new ObjectOutputStream( bytesOut );
099            out.writeObject( serialMap );
100            out.close();
101            
102            // Transform to Base64-encoded String
103            byte[] result = Base64.encodeBase64( bytesOut.toByteArray() );
104            return new String( result ) ;
105        }
106    
107    }