001/**
002 * The contents of this file are subject to the license and copyright
003 * detailed in the LICENSE and NOTICE files at the root of the source
004 * tree.
005 *
006 */
007package org.fcrepo.migration.urlmappers;
008
009import org.fcrepo.migration.ExternalContentURLMapper;
010import org.fcrepo.migration.MigrationIDMapper;
011
012import java.util.ArrayList;
013import java.util.List;
014import java.util.regex.Matcher;
015import java.util.regex.Pattern;
016
017/**
018 * An ExternalContentURLMapper implementation that updates redirects that point to the
019 * fedora repository in which they originated to the destination of that pointed-to resource
020 * in the fedora 4 repository to which the content is being migrated.
021 *
022 * For example, if "http://localhost:8080/fedora/objects/object:1/datastreams/POLICY" was a
023 * redirect datastream in fedora 3 that redirected to
024 * "http://localhost:8080/fedora/objects/policy:1/datastreams/XACML/content", this class would
025 * supply the URL for the content of the migrated XACML datastream on the migrated policy:1
026 * object.
027 *
028 * @author Mike Durbin
029 */
030public class SelfReferencingURLMapper implements ExternalContentURLMapper {
031
032    private static final String OLD_DS_CONTENT_URL_PATTERN = "http://{local-fedora-server}/fedora/get/([^/]+)/(.+)";
033    private static final String NEW_DS_CONTENT_URL_PATTERN
034            = "http://{local-fedora-server}/fedora/objects/([^/]+)/datastreams/([^/]+)/content";
035
036    private List<Pattern> contentPatterns;
037
038    /**
039     * A pattern that is compared after the content patterns, and if it matches,
040     * an exception is thrown.  This is implemented to allow an error to be thrown
041     * if any unmatched URLs that reference the fedora 3 repository are found; a
042     * case that generally indicates a configuration error in the migration scenario.
043     */
044    private Pattern invalidPattern;
045
046    private MigrationIDMapper idMapper;
047
048    /**
049     * Basic constructor.
050     * @param localFedoraServer the domain and port for the server that hosted the fedora objects in the format
051     *                          "localhost:8080".
052     * @param idMapper the MigrationIDMapper used for the current migration scenario
053     */
054    public SelfReferencingURLMapper(final String localFedoraServer, final MigrationIDMapper idMapper) {
055        this.contentPatterns = new ArrayList<>();
056        this.contentPatterns.add(parsePattern(OLD_DS_CONTENT_URL_PATTERN, localFedoraServer));
057        this.contentPatterns.add(parsePattern(NEW_DS_CONTENT_URL_PATTERN, localFedoraServer));
058        this.idMapper = idMapper;
059
060        this.invalidPattern = parsePattern("http://{local-fedora-server}/fedora/.*", localFedoraServer);
061    }
062
063    private Pattern parsePattern(final String pattern, final String localFedoraServer) {
064        return Pattern.compile(pattern.replace("{local-fedora-server}", localFedoraServer));
065    }
066
067    @Override
068    public String mapURL(final String url) {
069        for (Pattern p : contentPatterns) {
070            final Matcher m = p.matcher(url);
071            if (m.matches()) {
072                return idMapper.getBaseURL() + idMapper.mapDatastreamPath(m.group(1), m.group(2));
073            }
074        }
075        if (invalidPattern.matcher(url).matches()) {
076            throw new IllegalArgumentException("Unhandled internal external fedora 3 URL. (" + url + ")");
077        }
078        return url;
079    }
080}