001    /*
002     * Cumulus4j - Securing your data in the cloud - http://cumulus4j.org
003     * Copyright (C) 2011 NightLabs Consulting GmbH
004     *
005     * This program is free software: you can redistribute it and/or modify
006     * it under the terms of the GNU Affero General Public License as
007     * published by the Free Software Foundation, either version 3 of the
008     * License, or (at your option) any later version.
009     *
010     * This program is distributed in the hope that it will be useful,
011     * but WITHOUT ANY WARRANTY; without even the implied warranty of
012     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
013     * GNU Affero General Public License for more details.
014     *
015     * You should have received a copy of the GNU Affero General Public License
016     * along with this program.  If not, see <http://www.gnu.org/licenses/>.
017     */
018    package org.cumulus4j.keystore.prop;
019    
020    import java.io.ByteArrayInputStream;
021    import java.io.ByteArrayOutputStream;
022    import java.io.DataInputStream;
023    import java.io.DataOutputStream;
024    import java.io.IOException;
025    import java.util.Map;
026    import java.util.SortedMap;
027    import java.util.TreeMap;
028    
029    /**
030     * {@link Property} implementation for the value type {@link SortedMap}
031     * with both key and value being {@link Long}s.
032     * <p>
033     * Used for example by the date-dependent key-strategy to store it's key-is-valid-from-dates.
034     * </p>
035     *
036     * @author Marco หงุ่ยตระกูล-Schulze - marco at nightlabs dot de
037     */
038    public class Long2LongSortedMapProperty
039    extends Property<SortedMap<Long, Long>>
040    {
041    
042            @Override
043            public SortedMap<Long, Long> getValue()
044            {
045                    if (super.getValue() == null)
046                            setValue(new TreeMap<Long, Long>());
047    
048                    return super.getValue();
049            }
050    
051            @Override
052            public byte[] getValueEncoded()
053            {
054                    SortedMap<Long, Long> map = getValue();
055    
056                    if (map == null || map.isEmpty())
057                            return null;
058    
059                    ByteArrayOutputStream bout = new ByteArrayOutputStream();
060                    DataOutputStream out = new DataOutputStream(bout);
061                    try {
062                            out.writeInt(map.size());
063                            for (Map.Entry<Long, Long> me : map.entrySet()) {
064                                    out.writeLong(me.getKey());
065                                    out.writeLong(me.getValue());
066                            }
067                            out.close(); // Might be necessary for the flushing of the DataOutputStream even though the ByteArrayOutputStream doesn't need it.
068                    } catch (IOException e) {
069                            throw new RuntimeException(e);
070                    }
071    
072                    return bout.toByteArray();
073            }
074    
075            @Override
076            public void setValueEncoded(byte[] encodedValue)
077            throws IllegalArgumentException
078            {
079                    if (encodedValue == null) {
080                            setValue(null);
081                            return;
082                    }
083    
084                    DataInputStream in = new DataInputStream(new ByteArrayInputStream(encodedValue));
085                    try {
086                            int mapSize = in.readInt();
087                            SortedMap<Long, Long> map = new TreeMap<Long, Long>();
088                            for (int i = 0; i < mapSize; ++i) {
089                                    long key = in.readLong();
090                                    long value = in.readLong();
091                                    map.put(key, value);
092                            }
093                            setValue(map);
094                    } catch (IOException e) {
095                            throw new RuntimeException(e);
096                    }
097            }
098    
099    }