Open
Description
Hello,
the method LocalReference.createFileReference(rootDirectory) does not return a valid root path for a Directory restlet with version 2.2.3, contrary to version 2.2.2. There is a workaround by tweaking the URI manually (use file:///C:/ rather than file:///C%3A/) and passing this string to the Directory constructor.
Test 2.2.2
Testsuite: org.restlet.test.TestRestletDirectory
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0,191 sec
------------- Standard Output ---------------
-- TestRestletDirectory.testDirectory : restletVersion [2.2.2]
-- TestRestletDirectory.testDirectory : rootDirectory [C:\Users\oparent\AppData\Local\Temp\restlet-test]
test result httpStatus rootDirUri mime uri
upper case plain OK 200 file:///C:/Users/oparent/AppData/Local/Temp/restlet-test text/html http://localhost:28092/hello.html
upper case plain OK 200 file:///C:/Users/oparent/AppData/Local/Temp/restlet-test application/x-javascript http://localhost:28092/test.js
upper case plain KO 404 file:///C:/Users/oparent/AppData/Local/Temp/restlet-test - http://localhost:28092/test-1.2.js
lower case plain OK 200 file:///c:/Users/oparent/AppData/Local/Temp/restlet-test text/html http://localhost:28092/hello.html
lower case plain OK 200 file:///c:/Users/oparent/AppData/Local/Temp/restlet-test application/x-javascript http://localhost:28092/test.js
lower case plain KO 404 file:///c:/Users/oparent/AppData/Local/Temp/restlet-test - http://localhost:28092/test-1.2.js
lower case uri encoded OK 200 file:///c%3A/Users/oparent/AppData/Local/Temp/restlet-test text/html http://localhost:28092/hello.html
lower case uri encoded OK 200 file:///c%3A/Users/oparent/AppData/Local/Temp/restlet-test application/x-javascript http://localhost:28092/test.js
lower case uri encoded KO 404 file:///c%3A/Users/oparent/AppData/Local/Temp/restlet-test - http://localhost:28092/test-1.2.js
upper case uri encoded OK 200 file:///C%3A/Users/oparent/AppData/Local/Temp/restlet-test text/html http://localhost:28092/hello.html
upper case uri encoded OK 200 file:///C%3A/Users/oparent/AppData/Local/Temp/restlet-test application/x-javascript http://localhost:28092/test.js
upper case uri encoded KO 404 file:///C%3A/Users/oparent/AppData/Local/Temp/restlet-test - http://localhost:28092/test-1.2.js
no drive letter OK 200 file:///Users/oparent/AppData/Local/Temp/restlet-test text/html http://localhost:28092/hello.html
no drive letter OK 200 file:///Users/oparent/AppData/Local/Temp/restlet-test application/x-javascript http://localhost:28092/test.js
no drive letter KO 404 file:///Users/oparent/AppData/Local/Temp/restlet-test - http://localhost:28092/test-1.2.js
localref.createref OK 200 file:///C%3A/Users/oparent/AppData/Local/Temp/restlet-test text/html http://localhost:28092/hello.html
localref.createref OK 200 file:///C%3A/Users/oparent/AppData/Local/Temp/restlet-test application/x-javascript http://localhost:28092/test.js
localref.createref KO 404 file:///C%3A/Users/oparent/AppData/Local/Temp/restlet-test - http://localhost:28092/test-1.2.js
------------- ---------------- ---------------
Testcase: testDirectoryWithDriveLetter took 0,189 sec
Test 2.2.3
Testsuite: org.restlet.test.TestRestletDirectory
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0,141 sec
------------- Standard Output ---------------
-- TestRestletDirectory.testDirectory : restletVersion [2.2.3]
-- TestRestletDirectory.testDirectory : rootDirectory [C:\Users\oparent\AppData\Local\Temp\restlet-test]
test result httpStatus rootDirUri mime uri
upper case plain OK 200 file:///C:/Users/oparent/AppData/Local/Temp/restlet-test text/html http://localhost:28092/hello.html
upper case plain OK 200 file:///C:/Users/oparent/AppData/Local/Temp/restlet-test application/x-javascript http://localhost:28092/test.js
upper case plain KO 404 file:///C:/Users/oparent/AppData/Local/Temp/restlet-test - http://localhost:28092/test-1.2.js
lower case plain OK 200 file:///c:/Users/oparent/AppData/Local/Temp/restlet-test text/html http://localhost:28092/hello.html
lower case plain OK 200 file:///c:/Users/oparent/AppData/Local/Temp/restlet-test application/x-javascript http://localhost:28092/test.js
lower case plain KO 404 file:///c:/Users/oparent/AppData/Local/Temp/restlet-test - http://localhost:28092/test-1.2.js
lower case uri encoded KO 403 file:///c%3A/Users/oparent/AppData/Local/Temp/restlet-test - http://localhost:28092/hello.html
lower case uri encoded KO 403 file:///c%3A/Users/oparent/AppData/Local/Temp/restlet-test - http://localhost:28092/test.js
lower case uri encoded KO 403 file:///c%3A/Users/oparent/AppData/Local/Temp/restlet-test - http://localhost:28092/test-1.2.js
upper case uri encoded KO 403 file:///C%3A/Users/oparent/AppData/Local/Temp/restlet-test - http://localhost:28092/hello.html
upper case uri encoded KO 403 file:///C%3A/Users/oparent/AppData/Local/Temp/restlet-test - http://localhost:28092/test.js
upper case uri encoded KO 403 file:///C%3A/Users/oparent/AppData/Local/Temp/restlet-test - http://localhost:28092/test-1.2.js
no drive letter OK 200 file:///Users/oparent/AppData/Local/Temp/restlet-test text/html http://localhost:28092/hello.html
no drive letter OK 200 file:///Users/oparent/AppData/Local/Temp/restlet-test application/x-javascript http://localhost:28092/test.js
no drive letter KO 404 file:///Users/oparent/AppData/Local/Temp/restlet-test - http://localhost:28092/test-1.2.js
localref.createref KO 403 file:///C%3A/Users/oparent/AppData/Local/Temp/restlet-test - http://localhost:28092/hello.html
localref.createref KO 403 file:///C%3A/Users/oparent/AppData/Local/Temp/restlet-test - http://localhost:28092/test.js
localref.createref KO 403 file:///C%3A/Users/oparent/AppData/Local/Temp/restlet-test - http://localhost:28092/test-1.2.js
------------- ---------------- ---------------
Testcase: testDirectoryWithDriveLetter took 0,14 sec
Junit Test Case
|package org.restlet.test;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.StringTokenizer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import junit.framework.TestCase;
import org.restlet.Application;
import org.restlet.Client;
import org.restlet.Component;
import org.restlet.Request;
import org.restlet.Response;
import org.restlet.Restlet;
import org.restlet.data.CharacterSet;
import org.restlet.data.LocalReference;
import org.restlet.data.Method;
import org.restlet.data.Protocol;
import org.restlet.data.Reference;
import org.restlet.data.Status;
import org.restlet.engine.Engine;
import org.restlet.representation.Representation;
import org.restlet.resource.Directory;
import org.restlet.routing.Router;
/**
* Tests Restlet {@link Directory} with different root URIs, issue on Windows with drive letter for 2.2.3.
*
*
* <!-- creation 2014-11-28 -->
* @author Olivier Parent
*/
public class TestRestletDirectory extends TestCase {
/** DEBUG constant. */
private static final boolean DEBUG = false;
static final Charset CHARSET = Charset.forName("utf-8");
static final Protocol PROTOCOL = Protocol.HTTP;
/**
* Tests {@link Directory} with a directory starting with a drive letter (Windows).
* @throws Exception
*/
public void testDirectoryWithDriveLetter() throws Exception {
final String restletVersion = getRestletVersion();
System.out.println("-- TestRestletDirectory.testDirectory : restletVersion [" + restletVersion + "]");
final String host = "localhost";
final int port = 28092;
// Creates the root directory in tmp folder
// ex C:\Users\{user}\AppData\Local\Temp\restlet-test
final File rootDirectory;
{
rootDirectory = new File(System.getProperty("java.io.tmpdir") + "restlet-test").getCanonicalFile();
if(!rootDirectory.exists()) {
if(!rootDirectory.mkdirs()) {
fail("cannot create the root directory [" + rootDirectory + "]");
}
}
}
final String rootPath = rootDirectory.getAbsolutePath();
System.out.println("-- TestRestletDirectory.testDirectory : rootDirectory [" + rootDirectory.getAbsolutePath() + "]");
// Creates same root directory URIs, with drive part modifications
final String[][] rootDirUris = createRootPaths(rootDirectory, CHARSET);
if(rootDirUris.length == 0) {
System.out.println("-- TestRestletDirectory.testDirectory : no drive letter [" + rootPath + "] -> skip test");
return;
}
// Some test files to be retrieved
final List<FileNameContent> fileNameContents;
{
final List<FileNameContent> list = new ArrayList<FileNameContent>();
list.add(new FileNameContent(rootDirectory, "hello.html" , "<!DOCTYPE html><html><head><meta charset=\"" + CHARSET.name() + "\"></head><body><h1>Hello World!</h1></body></html>"));
list.add(new FileNameContent(rootDirectory, "test.js" , "function test() {return 'test';}"));
// could not be retrieved with restlet-jse-2.2.2 ( 1.2 issue with tunneling maybe ?)
// ok with restlet-jse-2.2.3
list.add(new FileNameContent(rootDirectory, "test-1.2.js" , "function test1_2() {return 'test-1.2';}"));
fileNameContents = Collections.unmodifiableList(list);
}
// create local resources
{
for(FileNameContent f: fileNameContents) {
f.ensurePresent();
}
}
final Client client = new Client(PROTOCOL);
final Reference baseRef = new Reference(PROTOCOL.getSchemeName()+ "://" + host + ":" + port);
if(DEBUG) System.out.println("-- TestRestletDirectory.testDirectory : base ref [" + baseRef + "]");
final List<List<String>> results = new ArrayList<List<String>>();
final Component component = createComponent(host, port);
component.start();
for (int i = 0; i < rootDirUris.length;) {
final String testName = rootDirUris[i ][0];
final String rootDirUri = rootDirUris[i++][1];
if(DEBUG) {
System.out.println("-- TestRestletDirectory.testDirectory : test [" + testName + "]");
System.out.println(" [" + rootDirUri + "]");
}
final Application application = createApplication(rootDirUri);
component.getDefaultHost().attach(application);
for(FileNameContent f: fileNameContents) {
final Reference ref = new Reference(baseRef, f.getFileName());
if(DEBUG) System.out.println("-- TestRestletDirectory.testDirectory : ref [" + ref.getTargetRef() + "]");
final Request request = new Request(Method.GET, ref);
final Response response = client.handle(request);
if(DEBUG) System.out.println("-- TestRestletDirectory.testDirectory : response status [" + response + "]");
final String contentType;
if(response.getStatus().getCode() == Status.SUCCESS_OK.getCode()) {
final Representation rep = response.getEntity();
if(DEBUG) System.out.println("-- TestRestletDirectory.testDirectory : rep [" + rep + "]");
contentType = rep.getMediaType().getName();
}
else {
contentType = "-";
}
final List<String> result = new ArrayList<String>();
result.add(testName);
result.add(response.getStatus().getCode() == Status.SUCCESS_OK.getCode() ? "OK" : "KO" );
result.add(String.valueOf(response.getStatus().getCode()));
result.add(rootDirUri);
result.add(contentType);
result.add(ref.getTargetRef().toString());
results.add(result);
}
component.getDefaultHost().detach(application);
}
component.stop();
final char separator = '\t';
final List<String> headers = Arrays.asList(
"test", "result", "httpStatus", "rootDirUri", "mime", "uri"
);
System.out.println(join(headers, separator));
for(List<String> result: results) {
System.out.println(join(result, separator));
}
}
private static final String join(Collection<?> values, char separator) {
final StringBuilder sb = new StringBuilder();
boolean isFirst = true;
for(Object value: values) {
if(isFirst) {
isFirst = false;
}
else {
sb.append(separator);
}
sb.append(String.valueOf(value));
}
return sb.toString();
}
/**
* @return the restlet version
*/
private static final String getRestletVersion() throws Exception {
// {
// final ClassLoader classLoader = Restlet.class.getClassLoader();
// //final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
// final URL url = classLoader.getResource(Restlet.class.getName().replace('.', '/') + ".class");
// if(DEBUG) System.out.println("-- TestRestletDirectory.getRestletVersion : url [" + url + "]");
//
// final Pattern pattern = Pattern.compile("/(restlet[^/]+)");
// final Matcher matcher = pattern.matcher(url.toString());
// if(matcher.find()) {
// restletVersion = matcher.group(1);
// }
// else {
// restletVersion = (String) Engine.class.getField("VERSION").get(null);
// }
//
return (String) Engine.class.getField("VERSION").get(null);
// return Engine.VERSION;
}
/**
* @param rootDirectory
* @param uriCharset
* @return test paths
* @throws UnsupportedEncodingException
*/
private static final String[][] createRootPaths(File rootDirectory, Charset uriCharset) throws UnsupportedEncodingException {
final Pattern pattern = Pattern.compile("^((?i)[A-Z]):(.+)$");
final Matcher matcher = pattern.matcher(rootDirectory.getAbsolutePath());
if(matcher.matches()) {
final String driveLetter = matcher.group(1);
final String pathUri = toUri(matcher.group(2), uriCharset);
// format(test name, path)+
return new String[][] {
{"lower case plain" , "file:///" + driveLetter.toLowerCase(Locale.ENGLISH) + ":" + pathUri},
{"upper case plain" , "file:///" + driveLetter.toUpperCase(Locale.ENGLISH) + ":" + pathUri},
{"lower case uri encoded" , "file:///" + driveLetter.toLowerCase(Locale.ENGLISH) + toUri(":", uriCharset) + pathUri},
{"upper case uri encoded" , "file:///" + driveLetter.toUpperCase(Locale.ENGLISH) + toUri(":", uriCharset) + pathUri},
{"no drive letter" , "file://" + pathUri},
{"localref.createref" , LocalReference.createFileReference(rootDirectory).toString()}
};
}
return new String[0][0];
}
/**
* @param value
* @throws UnsupportedEncodingException
*/
private static final String toUri(String value, Charset charset) throws UnsupportedEncodingException {
final String delim = "/";
value = value.replace('\\', delim.charAt(0));
final StringBuilder sb = new StringBuilder();
//sb.append();
final StringTokenizer tokenizer = new StringTokenizer(value, delim, true);
while(tokenizer.hasMoreElements()) {
String token = tokenizer.nextToken();
if(!token.equals(delim)) {
token = URLEncoder.encode(token, charset.name());
}
sb.append(token);
}
return sb.toString();
}
private static final Component createComponent(final String host, final int port) {
final Component component = new Component();
component.getClients().add(Protocol.FILE);
component.getClients().add(Protocol.CLAP);
component.getClients().add(Protocol.HTTP);
component.getServers().add(PROTOCOL, host, port);
return component;
}
/**
* Creates a component with a server and and application with a router built with a single directory.
* @param rootDirUri
* @param host
* @param port
* @return a test component
*/
private static final Application createApplication(final String rootDirUri) {
final Application application = new Application() {
public Restlet createInboundRoot() {
final Router router = new Router(getContext());
final Directory directory = new Directory(getContext(), rootDirUri);
directory.setListingAllowed(true);
router.attachDefault(directory);
return router;
}
};
application.getMetadataService().setDefaultCharacterSet(new CharacterSet(CHARSET));
return application;
}
/**
* File name and content
*/
private static final class FileNameContent {
private final File directory;
private final String fileName;
private final String content;
public FileNameContent(File directory, String fileName, String content) {
this.directory = directory;
this.fileName = fileName;
this.content = content;
}
/**
*
*/
public void ensurePresent() throws IOException {
final File file = new File(directory, fileName);
if(file.exists()) {
return;
}
if(DEBUG) System.out.println("-- FileNameContent.ensurePresent : create [" + file + "]");
writeTextIfNotPresent(file, content);
}
public final String getFileName() {
return fileName;
}
// public final String getContent() {
// return content;
// }
private static final void writeTextIfNotPresent(File file, String text) throws IOException {
OutputStream output = null;
Writer writer = null;
try {
output = new FileOutputStream(file);
writer = new OutputStreamWriter(output, CHARSET);
writer.write(text);
writer.close();
}
finally {
if(writer != null) {
try { writer.close(); } catch (IOException e) { }
}
if(output != null) {
try { output.close(); } catch (IOException e) { }
}
}
}
}
}