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