001/**
002 * Copyright 2005-2014 The Kuali Foundation
003 *
004 * Licensed under the Educational Community 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.opensource.org/licenses/ecl2.php
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.kuali.rice.kew.batch;
017
018import org.apache.commons.io.FileUtils;
019import org.junit.Assert;
020import org.junit.Test;
021import org.kuali.rice.core.api.CoreApiServiceLocator;
022import org.kuali.rice.core.api.impex.xml.FileXmlDocCollection;
023import org.kuali.rice.core.api.impex.xml.XmlDocCollection;
024import org.kuali.rice.core.api.util.ClasspathOrFileResourceLoader;
025import org.kuali.rice.edl.impl.bo.EDocLiteAssociation;
026import org.kuali.rice.edl.impl.service.EdlServiceLocator;
027import org.kuali.rice.edl.impl.xml.export.EdlExportDataSet;
028import org.kuali.rice.kew.test.KEWTestCase;
029import org.springframework.core.io.Resource;
030import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
031import org.springframework.core.io.support.ResourcePatternResolver;
032import org.springframework.util.FileCopyUtils;
033
034import java.io.File;
035import java.io.IOException;
036import java.util.ArrayList;
037import java.util.Collection;
038import java.util.Iterator;
039import java.util.LinkedList;
040import java.util.List;
041import java.util.Map;
042import java.util.Properties;
043
044import static org.junit.Assert.assertFalse;
045import static org.junit.Assert.assertTrue;
046
047/**
048 * Tests XML "ingestion" pipeline
049 *
050 * @author Kuali Rice Team (rice.collab@kuali.org)
051 */
052public class XmlIngestionTest extends KEWTestCase {
053
054    private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(XmlIngestionTest.class);
055
056    private static final File TMP_DIR = new File(System.getProperty("java.io.tmpdir"), "XmlIngestionTest_dir");
057    private static final File PENDING_DIR = new File(TMP_DIR, "pending");
058    private static final File LOADED_DIR = new File(TMP_DIR, "loaded");
059    private static final File PROBLEM_DIR = new File(TMP_DIR, "problem");
060
061    public void setUp() throws Exception {
062        super.setUp();
063        deleteDirectories();
064        TMP_DIR.mkdirs();
065        PENDING_DIR.mkdirs();
066        LOADED_DIR.mkdirs();
067        PROBLEM_DIR.mkdirs();
068    }
069
070    private void deleteContentsOfDir(File dir, int depth) {
071        File[] files = dir.listFiles();
072        if (files == null) return;
073        for (File file : files) {
074            if (file.isDirectory() && depth > 0) {
075                // decrement depth
076                // to avoid the possibility of inadvertent
077                // recursive delete!
078                deleteContentsOfDir(file, depth - 1);
079            }
080            boolean success = file.delete();
081            LOG.info("deleting: " + file + "..." + (success ? "succeeded" : "failed"));
082        }
083    }
084
085    public void tearDown() throws Exception {
086        try {
087            deleteDirectories();
088        } finally {
089            super.tearDown();
090        }
091    }
092
093    protected void deleteDirectories() {
094        deleteContentsOfDir(PENDING_DIR, 0);
095        deleteContentsOfDir(LOADED_DIR, 2);
096        deleteContentsOfDir(PROBLEM_DIR, 2);
097        deleteContentsOfDir(TMP_DIR, 0);
098        TMP_DIR.delete();
099    }
100
101    protected boolean verifyFileExists(File dir, File file) throws IOException {
102        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
103        Resource[] resources = resolver.getResources(dir.toURL() + "/**/" + file.getName());
104        if (resources == null) {
105            return false;
106        }
107        for (int i = 0; i < resources.length; i++) {
108            if (resources[i].exists()) {
109                return true;
110            }
111        }
112        return false;
113    }
114    
115
116    public void testXmlReIngestion() throws Exception {
117
118        // Define the path for the test environment
119        String filePath = "org/kuali/rice/kew/batch/data/widgetsTest.xml";
120        File ingestedFile = new ClasspathOrFileResourceLoader().getResource(filePath).getFile();
121        List<XmlDocCollection> collections = new ArrayList<XmlDocCollection>();
122        XmlDocCollection fileDoc = new FileXmlDocCollection(ingestedFile);
123        collections.add(fileDoc);
124        // ingest the collection and save it to the database
125        Collection<XmlDocCollection> ingestedXmlFile = null;
126        try {
127            ingestedXmlFile = CoreApiServiceLocator.getXmlIngesterService().ingest(collections);
128        } catch (Exception e) {
129            LOG.error("Error ingesting data", e);
130            //throw new RuntimeException(e);
131        }
132
133        EdlExportDataSet dataSet = new EdlExportDataSet();
134
135        //Cast this for now
136        List<EDocLiteAssociation> edla = EdlServiceLocator.getEDocLiteService().getEDocLiteAssociations();     
137        String style = null;
138        for (EDocLiteAssociation edl : edla) {
139            if (edl != null) {
140                style = edl.getStyle();
141                if ("widgetsTest".equals(style)) {
142                    dataSet.getEdocLites().add(edl);
143                }
144            }
145        }
146        
147        byte[] xmlBytes = CoreApiServiceLocator.getXmlExporterService().export(dataSet.createExportDataSet());
148        // now export that xml into a file
149        File reingestFile = File.createTempFile("widgetsTestOutput", ".xml");           
150        FileUtils.writeByteArrayToFile(reingestFile, xmlBytes);
151        String ingestedString = FileUtils.readFileToString(ingestedFile);
152        String reingestedString = FileUtils.readFileToString(reingestFile);
153        //assertTrue(FileUtils.contentEquals(ingestedFile, reingestFile));
154    }
155
156
157    /**
158     * TODO: beef this up
159     * need a reliable way to test if the file arrived in the right date-stamped
160     * subdirectory (maybe just pick the last, or first directory?)
161     *
162     * @throws java.io.IOException
163     */
164    @Test
165    public void testXmlIngestion() throws IOException {
166        XmlPollerServiceImpl poller = new XmlPollerServiceImpl();
167        poller.setPollIntervalSecs(1);
168        poller.setXmlParentDirectory(TMP_DIR.toString());
169        poller.setXmlPendingLocation(PENDING_DIR.toString());
170        poller.setXmlCompletedLocation(LOADED_DIR.toString());
171        poller.setXmlProblemLocation(PROBLEM_DIR.toString());
172
173        Properties filesToIngest = new Properties();
174        filesToIngest.load(getClass().getResourceAsStream("XmlIngestionTest.txt"));
175        List<File> pendingFiles = new LinkedList<File>();
176        List<File> shouldPass = new LinkedList<File>();
177        List<File> shouldFail = new LinkedList<File>();
178        Iterator<Map.Entry<Object, Object>> entries = filesToIngest.entrySet().iterator();
179        int i = 0;
180        while (entries.hasNext()) {
181            Map.Entry<?, ?> entry = entries.next();
182            String filePath = entry.getKey().toString();
183            File testFile = new ClasspathOrFileResourceLoader().getResource(filePath).getFile();
184            File pendingDir = new File(PENDING_DIR + "/TestDoc-" + i);
185            Assert.assertTrue(pendingDir.mkdirs());
186            assertTrue(pendingDir.isDirectory());
187            File pending = new File(pendingDir, testFile.getName());
188            pendingFiles.add(pending);
189            if (Boolean.valueOf(entry.getValue().toString())) {
190                shouldPass.add(pending);
191            } else {
192                shouldFail.add(pending);
193            }
194            FileCopyUtils.copy(testFile, pending);
195            LOG.info("created: " + pending);
196            i++;
197        }
198
199        // poller should not throw exceptions
200        poller.run();
201
202        // check that all files have been processed
203        Iterator<File> it = pendingFiles.iterator();
204        while (it.hasNext()) {
205            File pending = it.next();
206            assertTrue(!pending.isFile());
207        }
208
209        // check that they landed in the appropriate location
210
211        // loaded files should be in the loaded dir...
212        it = shouldPass.iterator();
213        while (it.hasNext()) {
214            File file = it.next();
215            assertTrue("Loaded file " + file + " was not moved to loaded directory " + LOADED_DIR, verifyFileExists(LOADED_DIR, file));
216            assertFalse("Loaded file " + file + " was moved to problem directory " + PROBLEM_DIR, verifyFileExists(PROBLEM_DIR, file));
217        }
218        // and problem files should be in the problem dir...
219        it = shouldFail.iterator();
220        while (it.hasNext()) {
221            File file = it.next();
222            assertTrue("Problem file " + file + " was not moved to problem directory" + PROBLEM_DIR, verifyFileExists(PROBLEM_DIR, file));
223            assertFalse("Problem file " + file + " was moved to loaded directory" + LOADED_DIR, verifyFileExists(LOADED_DIR, file));
224        }
225    }
226}