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 */
016
017package org.fcrepo.migration;
018
019import org.apache.commons.codec.digest.DigestUtils;
020import org.apache.commons.io.FileUtils;
021import org.fcrepo.storage.ocfl.OcflObjectSessionFactory;
022import org.junit.After;
023import org.junit.Test;
024import org.springframework.context.ConfigurableApplicationContext;
025import org.springframework.context.support.ClassPathXmlApplicationContext;
026
027import java.io.IOException;
028import java.io.UncheckedIOException;
029import java.nio.file.Files;
030import java.nio.file.Paths;
031import java.util.Map;
032import java.io.BufferedReader;
033import java.io.InputStreamReader;
034import java.nio.charset.StandardCharsets;
035import java.util.stream.Collectors;
036import static org.junit.Assert.assertEquals;
037import static org.junit.Assert.assertTrue;
038import static org.junit.Assert.fail;
039
040/**
041 * @author pwinckles
042 */
043public class InlineXmlIT {
044
045    private static final String OBJECT_ID = "info:fedora/1711.dl:CModelAudioStream";
046    private static final String AUDIT_ID = OBJECT_ID + "/AUDIT";
047    private static final String DC_ID = OBJECT_ID + "/DC";
048    private static final String DS_COMPOSITE_MODEL_ID = OBJECT_ID + "/DS-COMPOSITE-MODEL";
049    private static final String RELS_EXT_ID = OBJECT_ID + "/RELS-EXT";
050
051    private static final Map<String, String> EXPECTED_DIGESTS = Map.of(
052            AUDIT_ID, "c5aa5d74afc74aaf769b685e08d32cbc",
053            DC_ID, "9b3cb6287c11be2eddd3ff0a66805103",
054            DS_COMPOSITE_MODEL_ID, "84184d2d8ee6eae9dbcc5f02eaff681c",
055            RELS_EXT_ID, "c30c3df0877b8f113f8f4f844bdfe3e6"
056    );
057
058    private ConfigurableApplicationContext context;
059    private Migrator migrator;
060    private OcflObjectSessionFactory sessionFactory;
061
062    @After
063    public void tearDown() {
064        if (context != null) {
065            context.close();
066        }
067    }
068
069    private void setup(final String name) throws Exception {
070        // Create directories expected in this test (based on `spring/ocfl-user-it-setup.xml`)
071        final var storage = Paths.get(String.format("target/test/ocfl/%s/storage", name));
072        final var staging = Paths.get(String.format("target/test/ocfl/%s/staging", name));
073
074        if (Files.exists(storage)) {
075            FileUtils.forceDelete(storage.toFile());
076        }
077        if (Files.exists(staging)) {
078            FileUtils.forceDelete(staging.toFile());
079        }
080
081        Files.createDirectories(storage);
082        Files.createDirectories(staging);
083
084        context = new ClassPathXmlApplicationContext(String.format("spring/%s-setup.xml", name));
085        migrator = (Migrator) context.getBean("migrator");
086        sessionFactory = (OcflObjectSessionFactory) context.getBean("ocflSessionFactory");
087    }
088
089    @Test
090    public void testDcProperties() throws Exception {
091        setup("inline-it");
092        migrator.run();
093        final var session = sessionFactory.newSession("info:fedora/fedora-system:ContentModel-3.0");
094        final var content = session.readContent("info:fedora/fedora-system:ContentModel-3.0");
095        final String contentText = new BufferedReader(
096            new InputStreamReader(content.getContentStream().get(), StandardCharsets.UTF_8))
097                .lines()
098                .collect(Collectors.joining("\n"));
099        assertTrue(contentText.contains("<info:fedora/fedora-system:ContentModel-3.0> " +
100                    "<http://purl.org/dc/elements/1.1/identifier> \"fedora-system:ContentModel-3.0\""));
101    }
102
103    @Test
104    public void testMigrateObjectWithInlineXml() throws Exception {
105        setup("inline-it");
106
107        migrator.run();
108
109        final var session = sessionFactory.newSession(OBJECT_ID);
110
111        EXPECTED_DIGESTS.forEach((id, expected) -> {
112            final var content = session.readContent(id);
113            try {
114                final var actual = DigestUtils.md5Hex(content.getContentStream().get());
115                assertEquals(id, expected, actual);
116            } catch (IOException e) {
117                throw new UncheckedIOException(e);
118            }
119        });
120    }
121
122    @Test
123    public void failMigrationWhenInlineXmlDoesNotMatchDigest() throws Exception {
124        setup("inline-invalid-it");
125
126        try {
127            migrator.run();
128            fail("Expected migrator to fail");
129        } catch (RuntimeException e) {
130            assertTrue(e.getMessage()
131                    .contains("DC failed checksum validation. Expected MD5: 4e2a6140aa1369de6dd9736dfa8ab946"));
132        }
133    }
134
135
136}