/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF 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 * * http://www.apache.org/licenses/LICENSE-2.0 * * 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.apache.jackrabbit.vfs.ext.ds; import java.io.File; import java.io.FileInputStream; import java.io.StringReader; import java.util.Properties; import javax.jcr.RepositoryException; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import org.apache.commons.io.FilenameUtils; import org.apache.commons.io.IOUtils; import org.apache.commons.vfs2.FileObject; import org.apache.commons.vfs2.FileSystemOptions; import org.apache.commons.vfs2.provider.sftp.SftpFileSystemConfigBuilder; import org.apache.jackrabbit.core.data.CachingDataStore; import org.apache.jackrabbit.core.data.TestCaseBase; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.xml.sax.InputSource; import junit.framework.Assert; /** * Test {@link CachingDataStore} with VFSBackend with a VFS file system (local file system) by default. * <P> * You can provide different properties to use other file system backend by passing vfs config file via system property. * For e.g. -Dconfig=/opt/repository/vfs-webdav.properties. * </P> * <P> * Sample VFS properties located at src/test/resources/vfs-*.properties * </P> */ public class TestVFSDataStore extends TestCaseBase { /** * Logger instance. */ private static final Logger LOG = LoggerFactory.getLogger(TestVFSDataStore.class); // Example when http provider or its variants (https or webdav) FSO is used. @SuppressWarnings("unused") private static final String HTTP_FILE_SYSTEM_OPTIONS_PARAM_XML = "<param " + "name=\"fileSystemOptionsPropertiesInString\" " + "value=\"fso.http.maxTotalConnections = 200 " + " fso.http.maxConnectionsPerHost = 100 " + " fso.http.preemptiveAuth = true\" />"; private static final String SFTP_FILE_SYSTEM_OPTIONS_PARAM_XML = "<param " + "name=\"fileSystemOptionsPropertiesInString\" " + "value=\"fso.sftp.identities = /home/tester/.ssh/id_rsa " + " fso.sftp.timeout = 30000\" />"; private String baseFolderUri; private VFSDataStore dataStore; private Properties configProps; @Override protected void setUp() throws Exception { super.setUp(); String configProp = System.getProperty("config"); if (configProp != null && !"".equals(configProp)) { Properties props = new Properties(); File configFile = new File(configProp); if (configFile.isFile()) { FileInputStream fis = null; try { fis = new FileInputStream(configFile); props.load(fis); } finally { IOUtils.closeQuietly(fis); } } else { props = loadProperties(configProp); } configProps = props; } } @Override protected CachingDataStore createDataStore() throws RepositoryException { dataStore = new VFSDataStore(); Properties props = getConfigProps(); baseFolderUri = props.getProperty(VFSDataStore.BASE_FOLDER_URI); dataStore.setBaseFolderUri(baseFolderUri); LOG.info("baseFolderUri [{}] set.", baseFolderUri); String value = props.getProperty(VFSDataStore.ASYNC_WRITE_POOL_SIZE); if (value != null) { dataStore.setAsyncWritePoolSize(Integer.parseInt(value)); LOG.info("asyncWritePoolSize [{}] set.", dataStore.getAsyncWritePoolSize()); } dataStore.setFileSystemOptionsProperties(props); dataStore.setSecret("123456"); dataStore.init(dataStoreDir); return dataStore; } @Override protected void tearDown() { LOG.info("cleaning vfsBaseFolderUri [{}]", baseFolderUri); VFSBackend backend = (VFSBackend) dataStore.getBackend(); FileObject vfsBaseFolder = backend.getBaseFolderObject(); try { // Let's wait for 5 minutes at max if there are still execution jobs in the async writing executor's queue. int seconds = 0; while (backend.getAsyncWriteExecutorActiveCount() > 0 && seconds++ < 300) { Thread.sleep(1000); } VFSTestUtils.deleteAllDescendantFiles(vfsBaseFolder); } catch (Exception e) { LOG.error("Failed to clean base folder at '{}'.", vfsBaseFolder.getName().getFriendlyURI(), e); } super.tearDown(); } /** * Test case to validate {@link VFSDataStore#setFileSystemOptionsPropertiesInString(String)}. */ public void testSetFileSystemOptionsPropertiesInString() throws Exception { try { long start = System.currentTimeMillis(); LOG.info("Testcase: " + this.getClass().getName() + "#setFileSystemOptionsPropertiesInString, testDir=" + dataStoreDir); doSetFileSystemOptionsPropertiesInString(); LOG.info("Testcase: " + this.getClass().getName() + "#setFileSystemOptionsPropertiesInString finished, time taken = [" + (System.currentTimeMillis() - start) + "]ms"); } catch (Exception e) { LOG.error("error:", e); fail(e.getMessage()); } } /** * Test {@link VFSDataStore#setFileSystemOptionsPropertiesInString(String)} and validate the internal properties. */ protected void doSetFileSystemOptionsPropertiesInString() throws Exception { dataStore = new VFSDataStore(); Properties props = getConfigProps(); baseFolderUri = props.getProperty(VFSDataStore.BASE_FOLDER_URI); dataStore.setBaseFolderUri(baseFolderUri); LOG.info("baseFolderUri [{}] set.", baseFolderUri); dataStore.setFileSystemOptionsProperties(props); dataStore.setSecret("123456"); DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); Document document = builder.parse(new InputSource(new StringReader(SFTP_FILE_SYSTEM_OPTIONS_PARAM_XML))); Element paramElem = document.getDocumentElement(); String propsInString = paramElem.getAttribute("value"); dataStore.setFileSystemOptionsPropertiesInString(propsInString); final Properties internalProps = dataStore.getFileSystemOptionsProperties(); Assert.assertEquals("/home/tester/.ssh/id_rsa", internalProps.getProperty("fso.sftp.identities")); Assert.assertEquals("30000", internalProps.getProperty("fso.sftp.timeout")); dataStore.init(dataStoreDir); final FileSystemOptions fso = dataStore.getFileSystemOptions(); final SftpFileSystemConfigBuilder configBuilder = SftpFileSystemConfigBuilder.getInstance(); File [] identities = configBuilder.getIdentities(fso); Assert.assertNotNull(identities); Assert.assertEquals(1, identities.length); Assert.assertEquals("/home/tester/.ssh/id_rsa", FilenameUtils.separatorsToUnix(identities[0].getPath())); Assert.assertEquals(Integer.valueOf(30000), configBuilder.getTimeout(fso)); dataStore.close(); } private Properties getConfigProps() { if (configProps == null) { Properties props = new Properties(); String baseFolderUri = new File(new File(dataStoreDir), "vfsds").toURI().toString(); props.setProperty(VFSDataStore.BASE_FOLDER_URI, baseFolderUri); // By default (when testing with local file system), disable asynchronous writing to the backend. props.setProperty(VFSDataStore.ASYNC_WRITE_POOL_SIZE, "0"); configProps = props; } return configProps; } }