/*
* Copyright (C) 2009 eXo Platform SAS.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.exoplatform.services.jcr.webdav.command;
import org.exoplatform.common.http.HTTPStatus;
import org.exoplatform.services.jcr.access.PermissionType;
import org.exoplatform.services.jcr.core.CredentialsImpl;
import org.exoplatform.services.jcr.core.ExtendedNode;
import org.exoplatform.services.jcr.core.nodetype.ExtendedNodeTypeManager;
import org.exoplatform.services.jcr.core.nodetype.NodeTypeDataManager;
import org.exoplatform.services.jcr.impl.core.version.VersionImpl;
import org.exoplatform.services.jcr.webdav.BaseStandaloneTest;
import org.exoplatform.services.jcr.webdav.WebDavConst;
import org.exoplatform.services.jcr.webdav.WebDavConstants.WebDAVMethods;
import org.exoplatform.services.jcr.webdav.util.TextUtil;
import org.exoplatform.services.jcr.webdav.utils.TestUtils;
import org.exoplatform.services.rest.ExtHttpHeaders;
import org.exoplatform.services.rest.ext.provider.XSLTStreamingOutput;
import org.exoplatform.services.rest.impl.ContainerResponse;
import org.exoplatform.services.rest.impl.MultivaluedMapImpl;
import org.exoplatform.services.security.IdentityConstants;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringWriter;
import java.net.URLDecoder;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Locale;
import javax.jcr.Node;
import javax.jcr.Session;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MultivaluedMap;
/**
* Created by The eXo Platform SAS Author : Dmytro Katayev
* work.visor.ck@gmail.com Aug 13, 2008
*/
public class TestGet extends BaseStandaloneTest
{
private String path = TestUtils.getFileName();
private String fileContent = TestUtils.getFileContent();
@Override
public void setUp() throws Exception
{
super.setUp();
session.getRootNode().addNode(TextUtil.relativizePath(path));
InputStream inputStream = new ByteArrayInputStream(fileContent.getBytes());
TestUtils.addContent(session, path, inputStream, defaultFileNodeType, "");
path = path + "[2]";
}
public void testSimpleGet() throws Exception
{
testSimpleGet(getPathWS());
}
public void testSimpleGetWithFakePathWS() throws Exception
{
testSimpleGet(getFakePathWS());
}
private void testSimpleGet(String pathWs) throws Exception
{
ContainerResponse response = serviceWithEscape(WebDAVMethods.GET, pathWs + path, "", null, null);
assertEquals(HTTPStatus.OK, response.getStatus());
FileInputStream content = (FileInputStream)response.getEntity();
Reader r = new InputStreamReader(content);
StringWriter sw = new StringWriter();
char[] buffer = new char[1024];
for (int n; (n = r.read(buffer)) != -1;)
{
sw.write(buffer, 0, n);
}
String str = sw.toString();
assertEquals(fileContent, str);
}
public void testNotFoundGet() throws Exception
{
ContainerResponse response = serviceWithEscape(WebDAVMethods.GET, getPathWS() + "/not-found" + path, "", null, null);
assertEquals(HTTPStatus.NOT_FOUND, response.getStatus());
}
/**
* Details can be found here: https://jira.jboss.org/browse/EXOJCR-956
* @throws Exception
*/
public void testMissingJcrLastModifiedProperty() throws Exception
{
File file = new File("src/test/resources/rh_nodetype.xml");
assertTrue("src/test/resources/rh_nodetype.xml not found", file.exists());
FileInputStream fis = new FileInputStream(file);
session.getWorkspace().getNamespaceRegistry().registerNamespace("rh", "www.vn.vnn");
session.getWorkspace().getNodeTypesHolder().registerNodeTypes(fis, ExtendedNodeTypeManager.IGNORE_IF_EXISTS,
NodeTypeDataManager.TEXT_XML);
Node podcast = session.getRootNode().addNode("podcast", "rh:podcast");
Node nodeToAdd = podcast.addNode("rh:podcastFile", "nt:file");
Node contentNodeOfNodeToAdd = nodeToAdd.addNode("jcr:content", "nt:resource");
contentNodeOfNodeToAdd.setProperty("jcr:data", new FileInputStream("src/test/resources/test.txt"));
contentNodeOfNodeToAdd.setProperty("jcr:mimeType", "text/plain");
contentNodeOfNodeToAdd.setProperty("jcr:lastModified", Calendar.getInstance());
session.save();
podcast.addMixin("mix:versionable");
session.save();
VersionImpl v = (VersionImpl)podcast.checkin();
session.save();
podcast.checkout();
session.save();
String path =
getPathWS() + "/jcr:system/jcr:versionStorage/" + v.getContainingHistory().getIdentifier()
+ "/1/jcr:frozenNode/rh:podcastFile";
ContainerResponse response = serviceWithEscape(WebDAVMethods.GET, path, "", null, null);
assertEquals("Successful result expected (200), but actual is: " + response.getStatus(), 200, response
.getStatus());
}
/**
* Tests if date passed through header If-modified-since of GET method parsed correctly.
* Details can be found here: http://jira.exoplatform.org/browse/JCR-1470
* @throws Exception
*/
public void testIfModifiedSinceDateParsing() throws Exception
{
session.getRootNode().addNode("node");
Node fileNode = session.getRootNode().addNode("node", "nt:file");
fileNode.addMixin("mix:versionable");
Node contentNode = fileNode.addNode("jcr:content", "nt:resource");
contentNode.setProperty("jcr:mimeType", "text/plain");
Calendar creationDate = Calendar.getInstance();
Calendar IfModifiedSince = Calendar.getInstance();
IfModifiedSince.add(Calendar.HOUR, -2);
creationDate.add(Calendar.HOUR, -1);
contentNode.setProperty("jcr:data", creationDate);
contentNode.setProperty("jcr:lastModified", creationDate);
session.save();
fileNode.checkin();
fileNode.checkout();
String path =
getPathWS() + "/" + fileNode.getName() + "[2]?time=" + IfModifiedSince.getTimeInMillis() + "&version=1";
SimpleDateFormat dateFormat = new SimpleDateFormat(WebDavConst.DateFormat.IF_MODIFIED_SINCE_PATTERN, Locale.US);
String ifModifiedSinceDate = dateFormat.format(IfModifiedSince.getTime());
MultivaluedMap<String, String> headers = new MultivaluedMapImpl();
headers.add(ExtHttpHeaders.IF_MODIFIED_SINCE, ifModifiedSinceDate);
ContainerResponse response = serviceWithEscape(WebDAVMethods.GET, path, "", headers, null);
assertEquals(HTTPStatus.OK, response.getStatus());
headers.clear();
IfModifiedSince.add(Calendar.HOUR, +4);
ifModifiedSinceDate = dateFormat.format(IfModifiedSince.getTime());
headers.add(ExtHttpHeaders.IF_MODIFIED_SINCE, ifModifiedSinceDate);
response = serviceWithEscape(WebDAVMethods.GET, path, "", headers, null);
assertEquals(HTTPStatus.NOT_MODIFIED, response.getStatus());
}
public void testXSLTParamsPassing() throws Exception
{
String strToTest = "/absolute/path/to/file";
String folderName = TestUtils.getFolderName();
TestUtils.addFolder(session, folderName, defaultFolderNodeType, "");
ContainerResponse response = serviceWithEscape(WebDAVMethods.GET, getPathWS() + folderName, "", null, null);
assertEquals(HTTPStatus.OK, response.getStatus());
XSLTStreamingOutput XSLTout = (XSLTStreamingOutput)response.getEntity();
ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
XSLTout.write(byteOut);
assertTrue(byteOut.toString().contains(strToTest));
}
/**
* We test for parent href to be contained in response.
* We GET a collection and receive an html. Html should contain
* a href to parent collection of requested collection.
* @throws Exception
*/
public void testParentHrefForGetColRequest() throws Exception
{
String folderOne = TestUtils.getFolderName();
String folderTwo = folderOne + TestUtils.getFolderName();
// add collections
TestUtils.addFolder(session, folderOne, defaultFolderNodeType, "");
TestUtils.addFolder(session, folderTwo, defaultFolderNodeType, "");
// get a sub-collection
ContainerResponse response = serviceWithEscape(WebDAVMethods.GET, getPathWS() + folderTwo, "", null, null);
assertEquals(HTTPStatus.OK, response.getStatus());
// serialize response entity to string
XSLTStreamingOutput XSLTout = (XSLTStreamingOutput)response.getEntity();
ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
XSLTout.write(byteOut);
assertTrue("Response should contain parent collection href", byteOut.toString().contains(folderOne));
}
/**
* We test for parent href to be contained in response. We GET a collection,
* which has non latin letters in its name, and receive an html like response.
* Response should contain href to parent collection of requested collection.
* Details can be found here: https://issues.jboss.org/browse/EXOJCR-1379
* @throws Exception
*/
public void testParentHrefForGetColWithNonLatinNameRequest() throws Exception
{
// "%40" corresponds to '@' symbol
String folderOne = TestUtils.getFolderName() + "%40";
String folderTwo = folderOne + TestUtils.getFolderName() + "%40";
ContainerResponse response;
//add collections
TestUtils.addFolder(session, URLDecoder.decode(folderOne, "UTF-8"), defaultFolderNodeType, "");
TestUtils.addFolder(session, URLDecoder.decode(folderTwo, "UTF-8"), defaultFolderNodeType, "");
//get a sub-collection
response = service(WebDAVMethods.GET, getPathWS() + folderTwo, "", null, null);
assertEquals(HTTPStatus.OK, response.getStatus());
// serialize response entity to string
XSLTStreamingOutput XSLTout = (XSLTStreamingOutput)response.getEntity();
ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
XSLTout.write(byteOut);
assertTrue("Response should contain parent collection href", byteOut.toString().contains(folderOne));
}
@Override
protected String getRepositoryName()
{
return null;
}
/**
* Unit test for https://jira.exoplatform.org/browse/JCR-1832
*/
public void testGetFileFromFolder() throws Exception
{
ExtendedNode folderA = (ExtendedNode)session.getRootNode().addNode("folderA", "nt:folder");
folderA.addMixin("exo:privilegeable");
folderA.setPermission("john", PermissionType.ALL);
folderA.removePermission(IdentityConstants.ANY);
session.save();
assertEquals(4, folderA.getACL().getPermissionEntries().size());
assertEquals("john read", folderA.getACL().getPermissionEntries().get(0).getAsString());
assertEquals("john add_node", folderA.getACL().getPermissionEntries().get(1).getAsString());
assertEquals("john set_property", folderA.getACL().getPermissionEntries().get(2).getAsString());
assertEquals("john remove", folderA.getACL().getPermissionEntries().get(3).getAsString());
Session sessJohn = repository.login(new CredentialsImpl("john", "exo".toCharArray()), "ws");
ExtendedNode folderB = (ExtendedNode)sessJohn.getRootNode().getNode("folderA").addNode("folderB", "nt:folder");
folderB.addMixin("exo:privilegeable");
folderB.setPermission("any", new String[]{"read"});
sessJohn.save();
assertEquals(5, folderB.getACL().getPermissionEntries().size());
assertEquals("john read", folderB.getACL().getPermissionEntries().get(0).getAsString());
assertEquals("john add_node", folderB.getACL().getPermissionEntries().get(1).getAsString());
assertEquals("john set_property", folderB.getACL().getPermissionEntries().get(2).getAsString());
assertEquals("john remove", folderB.getACL().getPermissionEntries().get(3).getAsString());
assertEquals("any read", folderB.getACL().getPermissionEntries().get(4).getAsString());
// Login as anonim.
// Tthis session use on server side, thank SessionProvider.
repository.login(new CredentialsImpl(IdentityConstants.ANONIM, "exo".toCharArray()), "ws");
String path = getPathWS() + "/folderA/folderB";
ContainerResponse response = serviceWithEscape(WebDAVMethods.GET, path, "", null, null);
assertEquals("Successful result expected (200), but actual is: " + response.getStatus(), 200, response.getStatus());
XSLTStreamingOutput XSLTout = (XSLTStreamingOutput)response.getEntity();
ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
XSLTout.write(byteOut);
assertTrue("Response should contain parent collection href", byteOut.toString().contains("folderA"));
}
public void testGetContentTypeWithEncoding() throws Exception
{
Node fileNode = session.getRootNode().addNode("node", "nt:file");
Node contentNode = fileNode.addNode("jcr:content", "nt:resource");
contentNode.setProperty("jcr:mimeType", "text/plain");
contentNode.setProperty("jcr:encoding", "test-encoding");
contentNode.setProperty("jcr:data", "There is no ignorance, there is knowledge.");
contentNode.setProperty("jcr:lastModified", Calendar.getInstance());
session.save();
ContainerResponse response = service(WebDAVMethods.GET, getPathWS() + "/" + fileNode.getName(), "", null, null);
assertEquals("text/plain; charset=test-encoding", response.getHttpHeaders().getFirst(HttpHeaders.CONTENT_TYPE)
.toString());
}
public void testGetContentTypeWithNoEncoding() throws Exception
{
Node fileNode = session.getRootNode().addNode("node", "nt:file");
Node contentNode = fileNode.addNode("jcr:content", "nt:resource");
contentNode.setProperty("jcr:mimeType", "text/plain");
contentNode.setProperty("jcr:encoding", "");
contentNode.setProperty("jcr:data", "There is no passion, there is serenity.");
contentNode.setProperty("jcr:lastModified", Calendar.getInstance());
session.save();
ContainerResponse response = service(WebDAVMethods.GET, getPathWS() + "/" + fileNode.getName(), "", null, null);
assertEquals("text/plain", response.getHttpHeaders().getFirst(HttpHeaders.CONTENT_TYPE)
.toString());
fileNode = session.getRootNode().addNode("node2", "nt:file");
contentNode = fileNode.addNode("jcr:content", "nt:resource");
contentNode.setProperty("jcr:mimeType", "text/plain");
contentNode.setProperty("jcr:data", "There is no passion, there is serenity.");
contentNode.setProperty("jcr:lastModified", Calendar.getInstance());
session.save();
response = service(WebDAVMethods.GET, getPathWS() + "/" + fileNode.getName(), "", null, null);
assertEquals("text/plain", response.getHttpHeaders().getFirst(HttpHeaders.CONTENT_TYPE).toString());
}
public void testETag() throws Exception
{
Node fileNodeI = session.getRootNode().addNode("node1", "nt:file");
Node contentNode = fileNodeI.addNode("jcr:content", "nt:resource");
contentNode.setProperty("jcr:mimeType", "text/plain");
contentNode.setProperty("jcr:encoding", "");
contentNode.setProperty("jcr:data", "test1");
contentNode.setProperty("jcr:lastModified", Calendar.getInstance());
session.save();
Node fileNodeII = session.getRootNode().addNode("node2", "nt:file");
contentNode = fileNodeII.addNode("jcr:content", "nt:resource");
contentNode.setProperty("jcr:mimeType", "text/plain");
contentNode.setProperty("jcr:encoding", "");
contentNode.setProperty("jcr:data", "test2");
contentNode.setProperty("jcr:lastModified", Calendar.getInstance());
session.save();
ContainerResponse response = service(WebDAVMethods.GET, getPathWS() + "/node1", "", null, null);
assertEquals(HTTPStatus.OK, response.getStatus());
String eTag = (String)response.getHttpHeaders().getFirst(HttpHeaders.ETAG);
assertNotNull(eTag);
MultivaluedMap<String, String> headers = new MultivaluedMapImpl();
headers.add(ExtHttpHeaders.IF_NONE_MATCH, eTag);
response = service(WebDAVMethods.GET, getPathWS() + "/node1", "", headers, null);
assertEquals(HTTPStatus.NOT_MODIFIED, response.getStatus());
String destAbsPath = fileNodeI.getPath();
fileNodeI.remove();
session.save();
session.move(fileNodeII.getPath(), destAbsPath);
session.save();
response = service(WebDAVMethods.GET, getPathWS() + "/node1", "", headers, null);
assertEquals(HTTPStatus.OK, response.getStatus());
eTag = (String)response.getHttpHeaders().getFirst(HttpHeaders.ETAG);
headers.clear();
headers.add(ExtHttpHeaders.IF_NONE_MATCH, eTag);
session.move(destAbsPath, destAbsPath + "_");
session.save();
response = service(WebDAVMethods.GET, getPathWS() + "/node1_", "", headers, null);
assertEquals(HTTPStatus.NOT_MODIFIED, response.getStatus());
}
}