001/**
002 * Copyright 2015 DuraSpace, Inc.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.fcrepo.kernel.utils;
017
018import static com.google.common.base.Throwables.propagate;
019import static java.util.Collections.singletonMap;
020import static org.apache.commons.codec.binary.Hex.encodeHexString;
021import static org.slf4j.LoggerFactory.getLogger;
022
023import java.net.URI;
024import java.net.URISyntaxException;
025import java.util.Map;
026
027import org.slf4j.Logger;
028
029import com.google.common.collect.ImmutableMap;
030
031/**
032 * Digest helpers to convert digests (checksums) into URI strings
033 * (based loosely on Magnet URIs)
034 * @author Chris Beer
035 * @since Mar 6, 2013
036 */
037public abstract class ContentDigest {
038
039    private static final Logger LOGGER = getLogger(ContentDigest.class);
040
041    public static final Map<String, String> algorithmToScheme = ImmutableMap
042            .of("SHA-1", "urn:sha1", "SHA1", "urn:sha1");
043
044    public static final Map<String, String> schemeToAlgorithm =
045        singletonMap("urn:sha1", "SHA-1");
046    public static final String DEFAULT_ALGORITHM = "SHA-1";
047
048    /**
049     * Convert a MessageDigest algorithm and checksum value to a URN
050     * @param algorithm
051     * @param value
052     * @return URI
053     */
054    public static URI asURI(final String algorithm, final String value) {
055        try {
056            final String scheme = algorithmToScheme.get(algorithm);
057
058            return new URI(scheme, value, null);
059        } catch (final URISyntaxException unlikelyException) {
060            LOGGER.warn("Exception creating checksum URI: {}",
061                               unlikelyException);
062            throw propagate(unlikelyException);
063        }
064    }
065
066    /**
067     * Convert a MessageDigest algorithm and checksum byte-array data to a URN
068     * @param algorithm
069     * @param data
070     * @return URI
071     */
072    public static URI asURI(final String algorithm, final byte[] data) {
073        return asURI(algorithm, asString(data));
074    }
075
076    /**
077     * Given a digest URI, get the corresponding MessageDigest algorithm
078     * @param digestUri
079     * @return MessageDigest algorithm
080     */
081    public static String getAlgorithm(final URI digestUri) {
082        if (digestUri == null) {
083            return DEFAULT_ALGORITHM;
084        }
085        return schemeToAlgorithm
086        .get(digestUri.getScheme() + ":" +
087             digestUri.getSchemeSpecificPart().split(":", 2)[0]);
088    }
089
090    private static String asString(final byte[] data) {
091        return encodeHexString(data);
092    }
093
094    /**
095     * Placeholder checksum value.
096     * @return URI
097     */
098    public static URI missingChecksum() {
099        return asURI("SHA-1", "missing");
100    }
101}