/** * Licensed to Apereo under one or more contributor license agreements. See the NOTICE file * distributed with this work for additional information regarding copyright ownership. Apereo * licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use * this file except in compliance with the License. You may obtain a copy of the License at the * following location: * * <p>http://www.apache.org/licenses/LICENSE-2.0 * * <p>Unless required by applicable law or agreed to in writing, software distributed under the * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either * express or implied. See the License for the specific language governing permissions and * limitations under the License. */ package org.apereo.portal.io.xml; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.mockito.Matchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList.Builder; import com.google.common.collect.ImmutableSet; import java.io.IOException; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.ThreadPoolExecutor; import javax.xml.transform.Source; import javax.xml.transform.Templates; import javax.xml.transform.TransformerConfigurationException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.stream.StreamSource; import org.apereo.portal.io.xml.user.ExternalUser; import org.apereo.portal.io.xml.user.UserPortalDataType; import org.apereo.portal.xml.XmlUtilities; import org.apereo.portal.xml.XmlUtilitiesImpl; import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; import org.springframework.core.io.ResourceLoader; import org.springframework.oxm.Unmarshaller; import org.springframework.oxm.jaxb.Jaxb2Marshaller; import org.springframework.scheduling.concurrent.ThreadPoolExecutorFactoryBean; /** */ @RunWith(MockitoJUnitRunner.class) public class JaxbPortalDataHandlerServiceTest { @InjectMocks private JaxbPortalDataHandlerService dataImportExportService = new JaxbPortalDataHandlerService(); private XmlUtilities xmlUtilities; @Mock private ResourceLoader resourceLoader; private ExecutorService threadPoolExecutor; @Rule public TemporaryFolder tempFolder = new TemporaryFolder(); @Before public void setup() throws Exception { xmlUtilities = new XmlUtilitiesImpl() { @Override public Templates getTemplates(Resource stylesheet) throws TransformerConfigurationException, IOException { final TransformerFactory transformerFactory = TransformerFactory.newInstance(); return transformerFactory.newTemplates( new StreamSource(stylesheet.getInputStream())); } }; dataImportExportService.setXmlUtilities(xmlUtilities); final ThreadPoolExecutorFactoryBean threadPoolExecutorFactoryBean = new ThreadPoolExecutorFactoryBean(); threadPoolExecutorFactoryBean.setCorePoolSize(0); threadPoolExecutorFactoryBean.setMaxPoolSize(20); threadPoolExecutorFactoryBean.setQueueCapacity(20); threadPoolExecutorFactoryBean.setThreadGroupName("uPortal-ImportExportThreadGroup"); threadPoolExecutorFactoryBean.setThreadNamePrefix("uPortal-ImportExport-"); threadPoolExecutorFactoryBean.setThreadPriority(5); threadPoolExecutorFactoryBean.setKeepAliveSeconds(30); threadPoolExecutorFactoryBean.setDaemon(true); threadPoolExecutorFactoryBean.setAllowCoreThreadTimeOut(true); threadPoolExecutorFactoryBean.setRejectedExecutionHandler( new ThreadPoolExecutor.CallerRunsPolicy()); threadPoolExecutorFactoryBean.afterPropertiesSet(); threadPoolExecutor = threadPoolExecutorFactoryBean.getObject(); this.dataImportExportService.setImportExportThreadPool(threadPoolExecutor); dataImportExportService.setDataFileIncludes( ImmutableSet.of( "**/*.xml", "**/*.entity-type", "**/*.template-user", "**/*.user", "**/*.group", "**/*.group_membership", "**/*.membership", "**/*.portlet-type", "**/*.channel-type", "**/*.portlet", "**/*.channel", "**/*.permission", "**/*.permission_set", "**/*.permission_owner", "**/*.profile", "**/*.fragment-layout", "**/*.layout", "**/*.fragment-definition")); dataImportExportService.setDataTypeImportOrder(getPortalDataTypes()); } protected List<IPortalDataType> getPortalDataTypes() { return ImmutableList.<IPortalDataType>of( new org.apereo.portal.io.xml.entitytype.EntityTypePortalDataType(), new org.apereo.portal.io.xml.ssd.StylesheetDescriptorPortalDataType(), new org.apereo.portal.io.xml.user.UserPortalDataType(), new org.apereo.portal.io.xml.group.GroupPortalDataType(), new org.apereo.portal.io.xml.group.GroupMembershipPortalDataType(), new org.apereo.portal.io.xml.group.MembershipPortalDataType(), new org.apereo.portal.io.xml.portlettype.PortletTypePortalDataType(), new org.apereo.portal.io.xml.portlet.PortletPortalDataType(), new org.apereo.portal.io.xml.permission.PermissionPortalDataType(), new org.apereo.portal.io.xml.permission.PermissionSetPortalDataType(), new org.apereo.portal.io.xml.permission.PermissionOwnerPortalDataType(), new org.apereo.portal.io.xml.layout.ProfilePortalDataType(), new org.apereo.portal.io.xml.layout.LayoutPortalDataType(), new org.apereo.portal.io.xml.dlm.FragmentDefinitionPortalDataType()); } private interface MockDataImporterSetup { void setup(IPortalDataType dataType, IDataImporter<? extends Object> dataImporter); } protected List<IDataImporter<? extends Object>> setupAllImporters( MockDataImporterSetup setupCallback) { final Builder<IDataImporter<? extends Object>> importersBuilder = ImmutableList.<IDataImporter<? extends Object>>builder(); for (final IPortalDataType portalDataType : getPortalDataTypes()) { final IDataImporter importer = mock(IDataImporter.class); when(importer.getImportDataKeys()) .thenReturn(new HashSet<PortalDataKey>(portalDataType.getDataKeyImportOrder())); if (setupCallback != null) { setupCallback.setup(portalDataType, importer); } importersBuilder.add(importer); } return importersBuilder.build(); } @After public void teardown() { threadPoolExecutor.shutdown(); } @Test public void testUpgradeThenImport() throws Exception { final ClassPathResource importDataResource = new ClassPathResource("/org/apereo/portal/io/xml/user/test_3-2.user.xml"); when(resourceLoader.getResource( "classpath:/org/apereo/portal/io/xml/user/test_3-2.user.xml")) .thenReturn(importDataResource); final ClassPathResource xslResource = new ClassPathResource("/org/apereo/portal/io/xml/user/upgrade-user_3-2.xsl"); final IDataUpgrader xsltDataUpgrader = createXsltDataUpgrader(xslResource, UserPortalDataType.IMPORT_32_DATA_KEY); dataImportExportService.setDataUpgraders(Arrays.asList(xsltDataUpgrader)); final Jaxb2Marshaller userJaxb2Marshaller = new Jaxb2Marshaller(); userJaxb2Marshaller.setContextPath("org.apereo.portal.io.xml.user"); userJaxb2Marshaller.afterPropertiesSet(); final IDataImporter<ExternalUser> userDataImporter = mock(IDataImporter.class); when(userDataImporter.getImportDataKeys()) .thenReturn(Collections.singleton(UserPortalDataType.IMPORT_40_DATA_KEY)); when(userDataImporter.getUnmarshaller()).thenReturn(userJaxb2Marshaller); Collection<IDataImporter<?>> dataImporters = new LinkedList<IDataImporter<?>>(); dataImporters.add(userDataImporter); dataImportExportService.setDataImporters(dataImporters); final Resource resource = resourceLoader.getResource( "classpath:/org/apereo/portal/io/xml/user/test_3-2.user.xml"); dataImportExportService.importData(resource); final ArgumentCaptor<ExternalUser> userArgumentCaptor = ArgumentCaptor.forClass(ExternalUser.class); verify(userDataImporter).importData(userArgumentCaptor.capture()); final ExternalUser externalUser = userArgumentCaptor.getValue(); assertNotNull(externalUser); assertEquals("student", externalUser.getUsername()); assertEquals("defaultTemplateUser", externalUser.getDefaultUser()); assertEquals("(MD5)mhmjKvf2F3gPizS9DrA+CsFmqj74oTSb", externalUser.getPassword()); assertNull(externalUser.getLastPasswordChange()); } @Test public void testImportJarArchive() throws Exception { final Unmarshaller unmarshaller = mock(Unmarshaller.class); final List<IDataImporter<? extends Object>> importers = setupAllImporters( new MockDataImporterSetup() { @Override public void setup( IPortalDataType dataType, IDataImporter<? extends Object> dataImporter) { when(dataImporter.getUnmarshaller()).thenReturn(unmarshaller); } }); this.dataImportExportService.setDataImporters(importers); final Resource archiveResource = new ClassPathResource("/org/apereo/portal/io/xml/import_archive.jar"); final IPortalDataHandlerService.BatchImportOptions options = new IPortalDataHandlerService.BatchImportOptions(); options.setLogDirectoryParent(tempFolder.newFolder("jarArchiveImport")); this.dataImportExportService.importDataArchive(archiveResource, options); verify(unmarshaller, times(16)).unmarshal(any(Source.class)); } @Test public void testImportZipArchive() throws Exception { final Unmarshaller unmarshaller = mock(Unmarshaller.class); final List<IDataImporter<? extends Object>> importers = setupAllImporters( new MockDataImporterSetup() { @Override public void setup( IPortalDataType dataType, IDataImporter<? extends Object> dataImporter) { when(dataImporter.getUnmarshaller()).thenReturn(unmarshaller); } }); this.dataImportExportService.setDataImporters(importers); final Resource archiveResource = new ClassPathResource("/org/apereo/portal/io/xml/import_archive.zip"); final IPortalDataHandlerService.BatchImportOptions options = new IPortalDataHandlerService.BatchImportOptions(); options.setLogDirectoryParent(tempFolder.newFolder("zipArchiveImport")); this.dataImportExportService.importDataArchive(archiveResource, options); verify(unmarshaller, times(16)).unmarshal(any(Source.class)); } @Test public void testImportTarGzipArchive() throws Exception { final Unmarshaller unmarshaller = mock(Unmarshaller.class); final List<IDataImporter<? extends Object>> importers = setupAllImporters( new MockDataImporterSetup() { @Override public void setup( IPortalDataType dataType, IDataImporter<? extends Object> dataImporter) { when(dataImporter.getUnmarshaller()).thenReturn(unmarshaller); } }); this.dataImportExportService.setDataImporters(importers); final Resource archiveResource = new ClassPathResource("/org/apereo/portal/io/xml/import_archive.tar.gz"); final IPortalDataHandlerService.BatchImportOptions options = new IPortalDataHandlerService.BatchImportOptions(); options.setLogDirectoryParent(tempFolder.newFolder("targzipArchiveImport")); this.dataImportExportService.importDataArchive(archiveResource, options); verify(unmarshaller, times(16)).unmarshal(any(Source.class)); } @Test public void testImportTGZArchive() throws Exception { final Unmarshaller unmarshaller = mock(Unmarshaller.class); final List<IDataImporter<? extends Object>> importers = setupAllImporters( new MockDataImporterSetup() { @Override public void setup( IPortalDataType dataType, IDataImporter<? extends Object> dataImporter) { when(dataImporter.getUnmarshaller()).thenReturn(unmarshaller); } }); this.dataImportExportService.setDataImporters(importers); final Resource archiveResource = new ClassPathResource("/org/apereo/portal/io/xml/import_archive.tgz"); final IPortalDataHandlerService.BatchImportOptions options = new IPortalDataHandlerService.BatchImportOptions(); options.setLogDirectoryParent(tempFolder.newFolder("tgzArchiveImport")); this.dataImportExportService.importDataArchive(archiveResource, options); verify(unmarshaller, times(16)).unmarshal(any(Source.class)); } protected IDataUpgrader createXsltDataUpgrader( final ClassPathResource xslResource, final PortalDataKey dataKey) throws Exception { final XsltDataUpgrader xsltDataUpgrader = new XsltDataUpgrader(); xsltDataUpgrader.setPortalDataKey(dataKey); xsltDataUpgrader.setXslResource(xslResource); xsltDataUpgrader.setXmlUtilities(xmlUtilities); xsltDataUpgrader.afterPropertiesSet(); return xsltDataUpgrader; } }