You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wicket.apache.org by mo...@apache.org on 2015/11/08 18:15:41 UTC

[42/50] wicket git commit: WICKET-6025 Read resource files with Java's NIO API

WICKET-6025 Read resource files with Java's NIO API


Project: http://git-wip-us.apache.org/repos/asf/wicket/repo
Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/e0c2f1bb
Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/e0c2f1bb
Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/e0c2f1bb

Branch: refs/heads/lambdas
Commit: e0c2f1bbae576d26f2dc54996905e9acb63ccca0
Parents: 6355d71
Author: Tobias Soloschenko <ts...@apache.org>
Authored: Sun Nov 1 09:22:57 2015 +0100
Committer: Tobias Soloschenko <ts...@apache.org>
Committed: Fri Nov 6 22:41:38 2015 +0100

----------------------------------------------------------------------
 .../FileSystemResourceStreamReference.java      |  29 +++
 .../wicket/resource/FileSystemResource.java     | 130 +++++++++++
 .../resource/FileSystemResourceReference.java   | 170 +++++++++++++++
 .../services/java.nio.file.spi.FileTypeDetector |   1 +
 .../wicket/filetype/TestFileTypeDetector.java   |  42 ++++
 .../resource/FileSystemResourceReference.txt    |   1 +
 .../resource/FileSystemResourceReference.uke    |   1 +
 .../FileSystemResourceReferenceTest.java        | 218 +++++++++++++++++++
 .../FileSystemResourceReferenceTest.zip         | Bin 0 -> 986 bytes
 .../util/resource/FileSystemResourceStream.java | 169 ++++++++++++++
 10 files changed, 761 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/wicket/blob/e0c2f1bb/wicket-core/src/main/java/org/apache/wicket/core/util/resource/locator/caching/FileSystemResourceStreamReference.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/core/util/resource/locator/caching/FileSystemResourceStreamReference.java b/wicket-core/src/main/java/org/apache/wicket/core/util/resource/locator/caching/FileSystemResourceStreamReference.java
new file mode 100644
index 0000000..1feae37
--- /dev/null
+++ b/wicket-core/src/main/java/org/apache/wicket/core/util/resource/locator/caching/FileSystemResourceStreamReference.java
@@ -0,0 +1,29 @@
+package org.apache.wicket.core.util.resource.locator.caching;
+
+import java.nio.file.Paths;
+
+import org.apache.wicket.util.resource.FileSystemResourceStream;
+
+/**
+ * A reference which can be used to recreate {@link FileSystemResourceStream}
+ * 
+ * @author Tobias Soloschenko
+ */
+public class FileSystemResourceStreamReference extends AbstractResourceStreamReference
+{
+	private final String absolutePath;
+
+	FileSystemResourceStreamReference(final FileSystemResourceStream fileSystemResourceStream)
+	{
+		absolutePath = fileSystemResourceStream.getPath().toAbsolutePath().toString();
+		saveResourceStream(fileSystemResourceStream);
+	}
+
+	@Override
+	public FileSystemResourceStream getReference()
+	{
+		FileSystemResourceStream fileSystemResourceStream = new FileSystemResourceStream(Paths.get(absolutePath));
+		restoreResourceStream(fileSystemResourceStream);
+		return fileSystemResourceStream;
+	}
+}

http://git-wip-us.apache.org/repos/asf/wicket/blob/e0c2f1bb/wicket-core/src/main/java/org/apache/wicket/resource/FileSystemResource.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/resource/FileSystemResource.java b/wicket-core/src/main/java/org/apache/wicket/resource/FileSystemResource.java
new file mode 100644
index 0000000..56e1b95
--- /dev/null
+++ b/wicket-core/src/main/java/org/apache/wicket/resource/FileSystemResource.java
@@ -0,0 +1,130 @@
+/*
+ * 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.wicket.resource;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.attribute.BasicFileAttributes;
+
+import org.apache.wicket.Application;
+import org.apache.wicket.WicketRuntimeException;
+import org.apache.wicket.request.cycle.RequestCycle;
+import org.apache.wicket.request.resource.AbstractResource;
+import org.apache.wicket.request.resource.PartWriterCallback;
+import org.apache.wicket.util.lang.Args;
+
+/**
+ * Used to provide resources based on the on Java NIO FileSystem API.<br>
+ * <br>
+ * For more information see {@link org.apache.wicket.markup.html.media.FileSystemResourceReference}
+ * 
+ * @author Tobias Soloschenko
+ *
+ */
+public class FileSystemResource extends AbstractResource
+{
+	private static final long serialVersionUID = 1L;
+
+	private final Path path;
+
+	/**
+	 * Creates a new file system resource based on the given path
+	 * 
+	 * @param path
+	 *            the path to be read for the resource
+	 */
+	public FileSystemResource(Path path)
+	{
+		Args.notNull(path, "path");
+		this.path = path;
+	}
+
+	/**
+	 * Creates a new resource response and reads the given path
+	 */
+	@Override
+	protected ResourceResponse newResourceResponse(Attributes attributes)
+	{
+		try
+		{
+			long size = getSize();
+			ResourceResponse resourceResponse = new ResourceResponse();
+			resourceResponse.setContentType(getMimeType());
+			resourceResponse.setAcceptRange(ContentRangeType.BYTES);
+			resourceResponse.setContentLength(size);
+			RequestCycle cycle = RequestCycle.get();
+			Long startbyte = cycle.getMetaData(CONTENT_RANGE_STARTBYTE);
+			Long endbyte = cycle.getMetaData(CONTENT_RANGE_ENDBYTE);
+			resourceResponse.setWriteCallback(new PartWriterCallback(getInputStream(), size,
+				startbyte, endbyte));
+			return resourceResponse;
+		}
+		catch (IOException e)
+		{
+			throw new WicketRuntimeException(
+				"An error occured while processing the media resource response", e);
+		}
+	}
+
+	/**
+	 * Gets the size of the resource
+	 * 
+	 * @return the size of the resource
+	 * @throws IOException
+	 *             if the size attribute can't be read
+	 */
+	protected long getSize() throws IOException
+	{
+		return Files.readAttributes(path, BasicFileAttributes.class).size();
+	}
+
+	/**
+	 * Gets the mime type to be used for the response it first uses the URL connection to get the
+	 * mime type and after this the FileTypeDetector SPI is used.
+	 * 
+	 * @return the mime type to be used for the response
+	 * @throws IOException
+	 *             if the mime type could'nt be resoulved
+	 */
+	protected String getMimeType() throws IOException
+	{
+		String mimeType = null;
+		if (Application.exists())
+		{
+			mimeType = Application.get().getMimeType(path.getFileName().toString());
+		}
+		if (mimeType == null)
+		{
+			mimeType = Files.probeContentType(path);
+		}
+		return mimeType;
+	}
+
+	/**
+	 * Gets the input stream of the given path
+	 * 
+	 * @return the input stream of the given path
+	 * @throws IOException
+	 *             if there is an exception while receiving the input stream
+	 */
+	protected InputStream getInputStream() throws IOException
+	{
+		return Files.newInputStream(path);
+	}
+}

http://git-wip-us.apache.org/repos/asf/wicket/blob/e0c2f1bb/wicket-core/src/main/java/org/apache/wicket/resource/FileSystemResourceReference.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/resource/FileSystemResourceReference.java b/wicket-core/src/main/java/org/apache/wicket/resource/FileSystemResourceReference.java
new file mode 100644
index 0000000..e10fe54
--- /dev/null
+++ b/wicket-core/src/main/java/org/apache/wicket/resource/FileSystemResourceReference.java
@@ -0,0 +1,170 @@
+/*
+ * 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.wicket.resource;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.wicket.Application;
+import org.apache.wicket.MetaDataKey;
+import org.apache.wicket.request.resource.IResource;
+import org.apache.wicket.request.resource.ResourceReference;
+import org.apache.wicket.util.lang.Args;
+
+/**
+ * This resource reference is used to provide a reference to a resource based on Java NIO FileSystem
+ * API.<br>
+ * <br>
+ * To implement a mime type detection refer to the documentation of
+ * {@link java.nio.file.Files#probeContentType(Path)} and provide an implementation for
+ * java.nio.file.spi.FileTypeDetector in the META-INF/services folder for jars or in the
+ * /WEB-INF/classes/META-INF/services folder for webapps<br>
+ * <br>
+ * You can optionally override {@link #getFileSystemResource()} to provide an inline mime type detection,
+ * which is preferred to the default detection.<br>
+ * <br>
+ * Example:
+ * 
+ * <pre>
+ * <code>
+ * Path path = FileSystemResourceReference.getPath(URI.create("jar:file:///folder/file.zip!/folderInZip/video.mp4"));
+ * add(new Video("video", new FileSystemResourceReference(path)));
+ * </code>
+ * </pre>
+ * 
+ * @author Tobias Soloschenko
+ */
+public class FileSystemResourceReference extends ResourceReference
+{
+	private static final long serialVersionUID = 1L;
+
+	private final Path path;
+
+	/** The key for the file system meta data **/
+	public static final MetaDataKey<Map<URI, FileSystem>> FILE_SYSTEM_META_DATA_KEY = new MetaDataKey<Map<URI, FileSystem>>()
+	{
+		private static final long serialVersionUID = 1L;
+	};
+
+	/**
+	 * Creates a file system resource reference based on the given path
+	 * 
+	 * @param name
+	 *            the name of the resource reference to expose data
+	 * @param path
+	 *            the path to create the resource reference
+	 */
+	public FileSystemResourceReference(String name, Path path)
+	{
+		super(name);
+		Args.notNull(path, "path");
+		this.path = path;
+	}
+
+	/**
+	 * Creates a new {@link org.apache.wicket.markup.html.media.FileSystemResource} and applies the
+	 * path to it.
+	 */
+	@Override
+	public IResource getResource()
+	{
+		return getFileSystemResource();
+	}
+
+	/**
+	 * Gets the file system resource to be used for the resource reference
+	 * 
+	 * @return the file system resource to be used for the resource reference
+	 */
+	protected FileSystemResource getFileSystemResource()
+	{
+		return new FileSystemResource(path);
+	}
+
+	/**
+	 * Creates a path and a file system (if required) based on the given URI
+	 * 
+	 * @param uri
+	 *            the URI to create the file system and the path of
+	 * @param env
+	 *            the environment parameter to create the file system with
+	 * @return the path of the file in the file system
+	 * @throws IOException
+	 *             if the file system could'nt be created
+	 * @throws URISyntaxException
+	 *             if the URI has no valid syntax
+	 */
+	public static Path getPath(URI uri, Map<String, String> env) throws IOException,
+		URISyntaxException
+	{
+		String uriString = uri.toString();
+		int indexOfExclamationMark = uriString.indexOf('!');
+		if (indexOfExclamationMark == -1)
+		{
+			return Paths.get(uri);
+		}
+		String zipFile = uriString.substring(0, indexOfExclamationMark);
+		FileSystem fileSystem = null;
+
+		synchronized (FILE_SYSTEM_META_DATA_KEY)
+		{
+			Map<URI, FileSystem> metaData = Application.get()
+				.getMetaData(FILE_SYSTEM_META_DATA_KEY);
+			if (metaData == null)
+			{
+				metaData = new HashMap<URI, FileSystem>();
+				Application.get().setMetaData(FILE_SYSTEM_META_DATA_KEY, metaData);
+			}
+			if (fileSystem == null)
+			{
+				if (env == null)
+				{
+					env = new HashMap<>();
+					env.put("create", "true");
+					env.put("encoding", "UTF-8");
+				}
+				fileSystem = FileSystems.newFileSystem(new URI(zipFile), env);
+				metaData.put(uri, fileSystem);
+			}
+		}
+		String fileName = uriString.substring(uriString.indexOf('!') + 1);
+		return fileSystem.getPath(fileName);
+	}
+
+	/**
+	 * Creates a path and a file system (if required) based on the given URI
+	 * 
+	 * @param uri
+	 *            the URI to create the file system and the path of
+	 * @return the path of the file in the file system
+	 * @throws IOException
+	 *             if the file system could'nt be created
+	 * @throws URISyntaxException
+	 *             if the URI has no valid syntax
+	 */
+	public static Path getPath(URI uri) throws IOException, URISyntaxException
+	{
+		return getPath(uri, null);
+	}
+}

http://git-wip-us.apache.org/repos/asf/wicket/blob/e0c2f1bb/wicket-core/src/test/java/META-INF/services/java.nio.file.spi.FileTypeDetector
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/java/META-INF/services/java.nio.file.spi.FileTypeDetector b/wicket-core/src/test/java/META-INF/services/java.nio.file.spi.FileTypeDetector
new file mode 100644
index 0000000..475e050
--- /dev/null
+++ b/wicket-core/src/test/java/META-INF/services/java.nio.file.spi.FileTypeDetector
@@ -0,0 +1 @@
+org.apache.wicket.filetype.TestFileTypeDetector
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/wicket/blob/e0c2f1bb/wicket-core/src/test/java/org/apache/wicket/filetype/TestFileTypeDetector.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/java/org/apache/wicket/filetype/TestFileTypeDetector.java b/wicket-core/src/test/java/org/apache/wicket/filetype/TestFileTypeDetector.java
new file mode 100644
index 0000000..115bebe
--- /dev/null
+++ b/wicket-core/src/test/java/org/apache/wicket/filetype/TestFileTypeDetector.java
@@ -0,0 +1,42 @@
+/*
+ * 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.wicket.filetype;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.nio.file.spi.FileTypeDetector;
+
+/**
+ * File type detector for unit tests of file system resource reference
+ * 
+ * @author Tobias Soloschenko
+ *
+ */
+public class TestFileTypeDetector extends FileTypeDetector
+{
+
+	@Override
+	public String probeContentType(Path path) throws IOException
+	{
+		if(path.getFileName().toString().contains("FileSystemResourceReference")){			
+			return "text/plain_provided_by_detector";
+		}else{
+			return null;
+		}
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/wicket/blob/e0c2f1bb/wicket-core/src/test/java/org/apache/wicket/resource/FileSystemResourceReference.txt
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/java/org/apache/wicket/resource/FileSystemResourceReference.txt b/wicket-core/src/test/java/org/apache/wicket/resource/FileSystemResourceReference.txt
new file mode 100644
index 0000000..3fa4830
--- /dev/null
+++ b/wicket-core/src/test/java/org/apache/wicket/resource/FileSystemResourceReference.txt
@@ -0,0 +1 @@
+FileSystemResourceReference.zip content in normal file
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/wicket/blob/e0c2f1bb/wicket-core/src/test/java/org/apache/wicket/resource/FileSystemResourceReference.uke
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/java/org/apache/wicket/resource/FileSystemResourceReference.uke b/wicket-core/src/test/java/org/apache/wicket/resource/FileSystemResourceReference.uke
new file mode 100644
index 0000000..3fa4830
--- /dev/null
+++ b/wicket-core/src/test/java/org/apache/wicket/resource/FileSystemResourceReference.uke
@@ -0,0 +1 @@
+FileSystemResourceReference.zip content in normal file
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/wicket/blob/e0c2f1bb/wicket-core/src/test/java/org/apache/wicket/resource/FileSystemResourceReferenceTest.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/java/org/apache/wicket/resource/FileSystemResourceReferenceTest.java b/wicket-core/src/test/java/org/apache/wicket/resource/FileSystemResourceReferenceTest.java
new file mode 100644
index 0000000..acbb986
--- /dev/null
+++ b/wicket-core/src/test/java/org/apache/wicket/resource/FileSystemResourceReferenceTest.java
@@ -0,0 +1,218 @@
+/*
+ * 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.wicket.resource;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.nio.file.Path;
+
+import org.apache.wicket.util.io.ByteArrayOutputStream;
+import org.apache.wicket.util.io.IOUtils;
+import org.apache.wicket.util.tester.WicketTestCase;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * Test for FileSystemResourceReference
+ * 
+ * @author Tobias Soloschenko
+ *
+ */
+public class FileSystemResourceReferenceTest extends WicketTestCase
+{
+
+	/**
+	 * Test ZIP files
+	 * 
+	 * @throws IOException
+	 *             if the ZIP file or the file content can't be read
+	 * @throws URISyntaxException
+	 *             if the URI is not readable
+	 */
+	@Test
+	public void testFileSystemResourceReferenceWithZip() throws IOException, URISyntaxException
+	{
+		InputStream inputStream = null;
+		try
+		{
+			URL resource = FileSystemResourceReferenceTest.class.getResource("FileSystemResourceReferenceTest.zip");
+			Path path = FileSystemResourceReference.getPath(URI.create("jar:" + resource.toURI() +
+				"!/folderInZip/FileSystemResourceReference.txt"));
+			final FileSystemResource fileSystemResource = new FileSystemResource(path);
+			FileSystemResourceReference fileSystemResourceReference = new FileSystemResourceReference(
+				"test", path)
+			{
+				private static final long serialVersionUID = 1L;
+
+				@Override
+				protected FileSystemResource getFileSystemResource()
+				{
+					return fileSystemResource;
+				}
+			};
+			// Size
+			Assert.assertEquals(fileSystemResource.getSize(), 39);
+
+			// Content
+			inputStream = fileSystemResource.getInputStream();
+			ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+			IOUtils.copy(inputStream, outputStream);
+			Assert.assertEquals("FileSystemResourceReference.zip content", outputStream.toString());
+		}
+		finally
+		{
+			IOUtils.closeQuietly(inputStream);
+		}
+	}
+
+	/**
+	 * Test normal files
+	 * 
+	 * @throws IOException
+	 *             if the file can't be read
+	 * @throws URISyntaxException
+	 *             if the URI is not readable
+	 */
+	@Test
+	public void testFileSystemResourceReferenceWithNormalFile() throws IOException,
+		URISyntaxException
+	{
+		InputStream inputStream = null;
+		try
+		{
+			URL resource = FileSystemResourceReferenceTest.class.getResource("FileSystemResourceReference.txt");
+			Path path = FileSystemResourceReference.getPath(resource.toURI());
+			final FileSystemResource fileSystemResource = new FileSystemResource(path);
+			FileSystemResourceReference fileSystemResourceReference = new FileSystemResourceReference(
+				"test", path)
+			{
+				private static final long serialVersionUID = 1L;
+
+				@Override
+				protected FileSystemResource getFileSystemResource()
+				{
+					return fileSystemResource;
+				}
+			};
+			// Size
+			Assert.assertEquals(fileSystemResource.getSize(), 54);
+
+			// Content
+			inputStream = fileSystemResource.getInputStream();
+			ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+			IOUtils.copy(inputStream, outputStream);
+			Assert.assertEquals("FileSystemResourceReference.zip content in normal file",
+				outputStream.toString());
+		}
+		finally
+		{
+			IOUtils.closeQuietly(inputStream);
+		}
+	}
+
+	/**
+	 * Test mime types
+	 * 
+	 * @throws IOException
+	 *             if the file or the mime type can't be read
+	 * @throws URISyntaxException
+	 *             if the URI is not readable
+	 */
+	@Test
+	public void testMimeTypeEqual() throws IOException, URISyntaxException
+	{
+		URL resource = FileSystemResourceReferenceTest.class.getResource("FileSystemResourceReference.txt");
+		Path path = FileSystemResourceReference.getPath(resource.toURI());
+		final FileSystemResource fileSystemResource = new FileSystemResource(path)
+		{
+
+			private static final long serialVersionUID = 1L;
+
+			protected String getMimeType() throws IOException
+			{
+				return "test/mime1";
+			}
+		};
+		FileSystemResourceReference fileSystemResourceReference = new FileSystemResourceReference(
+			"test", path)
+		{
+			private static final long serialVersionUID = 1L;
+
+			@Override
+			protected FileSystemResource getFileSystemResource()
+			{
+				return fileSystemResource;
+			}
+		};
+		Assert.assertEquals("test/mime1", fileSystemResource.getMimeType());
+	}
+
+	/**
+	 * Test mime type detection with java.nio.file.spi.FileTypeDetector
+	 * 
+	 * @throws IOException
+	 *             if the file can't be read
+	 * @throws URISyntaxException
+	 *             if the
+	 */
+	@Test
+	public void testMimeTypeDetection() throws IOException, URISyntaxException
+	{
+		// uke > unknown extension :-)
+		URL resource = FileSystemResourceReferenceTest.class.getResource("FileSystemResourceReference.uke");
+		Path path = FileSystemResourceReference.getPath(resource.toURI());
+
+		final FileSystemResource fileSystemResource = new FileSystemResource(path);
+		FileSystemResourceReference fileSystemResourceReference = new FileSystemResourceReference(
+			"test", path)
+		{
+			private static final long serialVersionUID = 1L;
+
+			protected FileSystemResource getFileSystemResource()
+			{
+				return fileSystemResource;
+
+			}
+		};
+		Assert.assertEquals("text/plain_provided_by_detector", fileSystemResource.getMimeType());
+
+		final FileSystemResource fileSystemResourceMime = new FileSystemResource(path)
+		{
+			private static final long serialVersionUID = 1L;
+
+			protected String getMimeType() throws IOException
+			{
+				return "text/plain";
+			}
+		};
+		FileSystemResourceReference fileSystemResourceReferenceOverriddenMime = new FileSystemResourceReference(
+			"test", path)
+		{
+			private static final long serialVersionUID = 1L;
+
+			@Override
+			protected FileSystemResource getFileSystemResource()
+			{
+				return fileSystemResourceMime;
+			}
+		};
+		Assert.assertEquals("text/plain", fileSystemResourceMime.getMimeType());
+	}
+}

http://git-wip-us.apache.org/repos/asf/wicket/blob/e0c2f1bb/wicket-core/src/test/java/org/apache/wicket/resource/FileSystemResourceReferenceTest.zip
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/java/org/apache/wicket/resource/FileSystemResourceReferenceTest.zip b/wicket-core/src/test/java/org/apache/wicket/resource/FileSystemResourceReferenceTest.zip
new file mode 100644
index 0000000..7b77d43
Binary files /dev/null and b/wicket-core/src/test/java/org/apache/wicket/resource/FileSystemResourceReferenceTest.zip differ

http://git-wip-us.apache.org/repos/asf/wicket/blob/e0c2f1bb/wicket-util/src/main/java/org/apache/wicket/util/resource/FileSystemResourceStream.java
----------------------------------------------------------------------
diff --git a/wicket-util/src/main/java/org/apache/wicket/util/resource/FileSystemResourceStream.java b/wicket-util/src/main/java/org/apache/wicket/util/resource/FileSystemResourceStream.java
new file mode 100644
index 0000000..61bd226
--- /dev/null
+++ b/wicket-util/src/main/java/org/apache/wicket/util/resource/FileSystemResourceStream.java
@@ -0,0 +1,169 @@
+package org.apache.wicket.util.resource;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URLConnection;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.nio.file.attribute.FileTime;
+
+import org.apache.wicket.util.file.File;
+import org.apache.wicket.util.lang.Args;
+import org.apache.wicket.util.lang.Bytes;
+import org.apache.wicket.util.time.Time;
+
+/**
+ * A FileSystemResourceStream is an IResourceStream implementation for Java NIO paths.
+ * 
+ * @see org.apache.wicket.util.resource.IResourceStream
+ * @see org.apache.wicket.util.watch.IModifiable
+ * @author Tobias Soloschenko
+ */
+public class FileSystemResourceStream extends AbstractResourceStream
+	implements
+		IFixedLocationResourceStream
+{
+	private static final long serialVersionUID = 1L;
+
+	/** Any associated path */
+	private final Path path;
+
+	/** Resource stream */
+	private transient InputStream inputStream;
+
+	/**
+	 * Constructor.
+	 * 
+	 * @param path
+	 *            {@link Path} containing resource
+	 */
+	public FileSystemResourceStream(final Path path)
+	{
+		Args.notNull(path, "path");
+		this.path = path;
+	}
+
+	/**
+	 * Constructor.
+	 * 
+	 * @param file
+	 *            {@link java.io.File} containing resource
+	 */
+	public FileSystemResourceStream(final java.io.File file)
+	{
+		Args.notNull(file, "file");
+		this.path = file.toPath();
+	}
+
+	/**
+	 * Constructor.
+	 * 
+	 * @param file
+	 *            {@link File} containing resource
+	 */
+	public FileSystemResourceStream(final File file)
+	{
+		Args.notNull(file, "file");
+		this.path = file.toPath();
+	}
+
+	@Override
+	public InputStream getInputStream() throws ResourceStreamNotFoundException
+	{
+		if (inputStream == null)
+		{
+			try
+			{
+				inputStream = Files.newInputStream(path);
+			}
+			catch (IOException e)
+			{
+				throw new ResourceStreamNotFoundException("Input stream of path " + path +
+					" could not be acquired", e);
+			}
+		}
+		return inputStream;
+	}
+
+	@Override
+	public void close() throws IOException
+	{
+		if (inputStream != null)
+		{
+			inputStream.close();
+			inputStream = null;
+		}
+	}
+
+	@Override
+	public String getContentType()
+	{
+		try
+		{
+			String contentType = Files.probeContentType(path);
+			if (contentType == null)
+			{
+				contentType = URLConnection.getFileNameMap().getContentTypeFor(
+					path.getFileName().toString());
+			}
+			return contentType;
+		}
+		catch (IOException e)
+		{
+			throw new RuntimeException("Content type of path " + path + " could not be acquired", e);
+		}
+	}
+
+	/**
+	 * @return The path this resource resides in, if any.
+	 */
+	public final Path getPath()
+	{
+		return path;
+	}
+
+	@Override
+	public Time lastModifiedTime()
+	{
+		try
+		{
+			BasicFileAttributes attributes = Files.readAttributes(path, BasicFileAttributes.class);
+			FileTime lastModifiedTime = attributes.lastModifiedTime();
+			long millis = lastModifiedTime.toMillis();
+			return Time.millis(millis);
+		}
+		catch (IOException e)
+		{
+			throw new RuntimeException("Modification time of path " + path +
+				" could not be acquired", e);
+		}
+	}
+
+	@Override
+	public Bytes length()
+	{
+		try
+		{
+			BasicFileAttributes attributes = Files.readAttributes(path, BasicFileAttributes.class);
+			long size = attributes.size();
+			return Bytes.bytes(size);
+		}
+		catch (IOException e)
+		{
+			throw new RuntimeException("Length of path " + path + " could not be acquired", e);
+		}
+	}
+
+	@Override
+	public String locationAsString()
+	{
+		return path.toString();
+	}
+
+	@Override
+	public String toString()
+	{
+		return locationAsString();
+	}
+}