/* * ModeShape (http://www.modeshape.org) * * Licensed 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.modeshape.web.jcr.webdav; import javax.jcr.Node; import javax.jcr.NodeIterator; import javax.jcr.Session; import javax.servlet.ServletContext; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import javax.servlet.http.HttpServletRequest; import static org.hamcrest.core.Is.is; import static org.hamcrest.core.IsNull.notNullValue; import org.junit.After; import org.junit.AfterClass; import static org.junit.Assert.assertThat; import org.junit.Before; import org.junit.Test; import org.mockito.Mock; import static org.mockito.Mockito.when; import org.mockito.MockitoAnnotations; import org.modeshape.common.FixFor; import org.modeshape.common.util.IoUtil; import org.modeshape.jcr.api.RepositoryFactory; import org.modeshape.web.jcr.ModeShapeJcrDeployer; import org.modeshape.web.jcr.RepositoryManager; import org.modeshape.web.jcr.webdav.ModeShapeWebdavStore.JcrSessionTransaction; import org.modeshape.webdav.IWebdavStore; import org.modeshape.webdav.StoredObject; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.security.Principal; import java.util.Calendar; import java.util.LinkedList; import java.util.List; public class ModeShapeWebdavStoreTest { private static final String TEST_ROOT = "testRoot"; private static final String TEST_ROOT_PATH = "/" + TEST_ROOT; private static final String[] EMPTY_STRING_ARRAY = new String[0]; private static final String REPOSITORY_NAME = "repo"; private static final String WORKSPACE_NAME = "default"; private static ServletContextListener contextListener = new ModeShapeJcrDeployer(); @Mock private static ServletContextEvent event; private IWebdavStore store; private JcrSessionTransaction tx; private Session session; @Mock private Principal principal; @Mock private HttpServletRequest request; @Mock private ServletContext context; private Node testRoot; @Before public void beforeEach() throws Exception { MockitoAnnotations.initMocks(this); when(principal.getName()).thenReturn("testuser"); when(request.getUserPrincipal()).thenReturn(principal); when(request.isUserInRole("readwrite")).thenReturn(true); when(context.getInitParameter(RepositoryFactory.URL)).thenReturn("file:///repository-config.json"); when(context.getInitParameter(SingleRepositoryRequestResolver.INIT_REPOSITORY_NAME)).thenReturn(REPOSITORY_NAME); when(context.getInitParameter(SingleRepositoryRequestResolver.INIT_WORKSPACE_NAME)).thenReturn(WORKSPACE_NAME); when(event.getServletContext()).thenReturn(context); RequestResolver uriResolver = new SingleRepositoryRequestResolver(); uriResolver.initialize(context); ContentMapper contentMapper = new DefaultContentMapper(); contentMapper.initialize(context); store = new ModeShapeWebdavStore(uriResolver, contentMapper); contextListener.contextInitialized(event); ModeShapeWebdavStore.setRequest(request); session = RepositoryManager.getSession(request, REPOSITORY_NAME, WORKSPACE_NAME); testRoot = session.getRootNode().addNode(TEST_ROOT); session.save(); tx = (JcrSessionTransaction)store.begin(principal); assertThat(tx.owns(session), is(false)); } @After public void afterEach() throws Exception { ModeShapeWebdavStore.setRequest(null); testRoot.remove(); session.save(); session.logout(); } @AfterClass public static void afterClass() throws Exception { contextListener.contextDestroyed(event); } @Test public void shouldBeginTransaction() throws Exception { assertThat(tx, is(notNullValue())); } @Test public void shouldCommitTransaction() throws Exception { store.commit(tx); } @Test( expected = IllegalArgumentException.class ) public void shouldNotCommitNullTransaction() throws Exception { store.commit(null); } private void compareChildrenWithSession( String[] children, String path ) throws Exception { List<String> sessChildren = new LinkedList<>(); Node node = (Node)session.getItem(path); for (NodeIterator iter = node.getNodes(); iter.hasNext(); ) { sessChildren.add(iter.nextNode().getName()); } assertThat(children, is(sessChildren.toArray(EMPTY_STRING_ARRAY))); } @Test public void shouldListFilesAtRoot() throws Exception { String[] children = store.getChildrenNames(tx, "/"); compareChildrenWithSession(children, "/"); } @Test public void shouldAddFolderAtRoot() throws Exception { String[] children = store.getChildrenNames(tx, "/"); store.createFolder(tx, TEST_ROOT_PATH + "/newFolder"); // Make sure that the node isn't visible yet compareChildrenWithSession(children, "/"); store.commit(tx); session.refresh(false); // Make sure that the node is visible after the commit compareChildrenWithSession(store.getChildrenNames(tx, "/"), "/"); } @Test public void shouldAddFileAtRoot() throws Exception { String[] children = store.getChildrenNames(tx, "/"); store.createResource(tx, TEST_ROOT_PATH + "/newFile"); // Make sure that the node isn't visible yet compareChildrenWithSession(children, "/"); store.commit(tx); session.refresh(false); // Make sure that the node is visible after the commit compareChildrenWithSession(store.getChildrenNames(tx, "/"), "/"); } @Test public void shouldReadFileLengthAndContent() throws Exception { final String TEST_STRING = "This is my miraculous test string!"; Node fileNode = testRoot.addNode("newFile", "nt:file"); Node contentNode = fileNode.addNode("jcr:content", "mode:resource"); contentNode.setProperty("jcr:data", TEST_STRING); contentNode.setProperty("jcr:mimeType", "text/plain"); contentNode.setProperty("jcr:encoding", "UTF-8"); contentNode.setProperty("jcr:lastModified", Calendar.getInstance()); session.save(); when(request.getPathInfo()).thenReturn(TEST_ROOT_PATH + "/newFile"); assertThat((int)store.getResourceLength(tx, TEST_ROOT_PATH + "/newFile"), is(TEST_STRING.length())); InputStream is = store.getResourceContent(tx, TEST_ROOT_PATH + "/newFile"); String webdavContent = IoUtil.read(is); assertThat(webdavContent, is(TEST_STRING)); } @Test public void shouldRemoveFile() throws Exception { final String TEST_STRING = "This is my miraculous test string!"; Node fileNode = testRoot.addNode("newFile", "nt:file"); Node contentNode = fileNode.addNode("jcr:content", "mode:resource"); contentNode.setProperty("jcr:data", TEST_STRING); contentNode.setProperty("jcr:mimeType", "text/plain"); contentNode.setProperty("jcr:encoding", "UTF-8"); contentNode.setProperty("jcr:lastModified", Calendar.getInstance()); session.save(); when(request.getPathInfo()).thenReturn(TEST_ROOT_PATH + "/newFile"); store.removeObject(tx, TEST_ROOT_PATH + "/newFile"); store.commit(tx); session.refresh(false); assertThat(testRoot.hasNode("newFile"), is(false)); } @Test public void shouldSimulateAddingFileThroughWebdav() throws Exception { final String TEST_STRING = "This is my miraculous test string!"; final String TEST_URI = TEST_ROOT_PATH + "/TestFile.rtf"; when(request.getPathInfo()).thenReturn(""); store.getStoredObject(tx, ""); when(request.getPathInfo()).thenReturn(TEST_URI); store.getStoredObject(tx, TEST_URI); when(request.getPathInfo()).thenReturn("/"); // will ask for parent during resolution ... store.createResource(tx, TEST_URI); when(request.getPathInfo()).thenReturn(TEST_URI); long length = store.setResourceContent(tx, TEST_URI, new ByteArrayInputStream(TEST_STRING.getBytes()), "text/plain", "UTF-8"); assertThat((int)length, is(TEST_STRING.getBytes().length)); StoredObject ob = store.getStoredObject(tx, TEST_URI); assertThat(ob, is(notNullValue())); } @Test @FixFor( "MODE-2589" ) public void shouldSimulateAddingAndCopyingZeroLengthFileThroughWebdav() throws Exception { final String testString = ""; final String sourceUri = TEST_ROOT_PATH + "/TestFile.rtf"; final String destinationUri = TEST_ROOT_PATH + "/CopyOfTestFile.rtf"; when(request.getPathInfo()).thenReturn(""); store.getStoredObject(tx, ""); when(request.getPathInfo()).thenReturn(sourceUri); store.getStoredObject(tx, sourceUri); when(request.getPathInfo()).thenReturn("/"); // will ask for parent during resolution ... store.createResource(tx, sourceUri); when(request.getPathInfo()).thenReturn(sourceUri); long length = store.setResourceContent(tx, sourceUri, new ByteArrayInputStream(testString.getBytes()), "text/plain", "UTF-8"); assertThat((int)length, is(testString.getBytes().length)); StoredObject ob = store.getStoredObject(tx, sourceUri); assertThat(ob, is(notNullValue())); when(request.getPathInfo()).thenReturn("/"); // will ask for parent during resolution ... store.createResource(tx, destinationUri); when(request.getPathInfo()).thenReturn(destinationUri); length = store.setResourceContent(tx, destinationUri, store.getResourceContent(tx, sourceUri), "text/plain", "UTF-8"); assertThat((int)length, is(testString.getBytes().length)); ob = store.getStoredObject(tx, destinationUri); assertThat(ob, is(notNullValue())); } }