001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.wicket.resource; 018 019import java.io.IOException; 020import java.net.URI; 021import java.net.URISyntaxException; 022import java.nio.file.Path; 023import java.nio.file.Paths; 024import java.util.Iterator; 025import java.util.Map; 026import java.util.ServiceLoader; 027 028import org.apache.wicket.WicketRuntimeException; 029import org.apache.wicket.request.resource.IResource; 030import org.apache.wicket.request.resource.ResourceReference; 031 032/** 033 * This resource reference is used to provide a reference to a resource based on Java NIO FileSystem 034 * API.<br> 035 * <br> 036 * To implement a mime type detection refer to the documentation of 037 * {@link java.nio.file.Files#probeContentType(Path)} and provide an implementation for 038 * java.nio.file.spi.FileTypeDetector in the META-INF/services folder for jars or in the 039 * /WEB-INF/classes/META-INF/services folder for webapps<br> 040 * <br> 041 * You can optionally override {@link #getFileSystemResource()} to provide an inline mime type 042 * detection, which is preferred to the default detection.<br> 043 * <br> 044 * Example: 045 * 046 * <pre> 047 * <code> 048 * Path path = FileSystemResourceReference.getPath(URI.create("jar:file:///folder/file.zip!/folderInZip/video.mp4")); 049 * add(new Video("video", new FileSystemResourceReference(path))); 050 * </code> 051 * </pre> 052 * 053 * Example 2: 054 * 055 * <pre> 056 * <code> 057 * mountResource("/filecontent/${name}", new FileSystemResourceReference("filesystem") 058 * { 059 * private static final long serialVersionUID = 1L; 060 * 061 * {@literal @}Override 062 * public IResource getResource() 063 * { 064 * return new FileSystemResource() 065 * { 066 * private static final long serialVersionUID = 1L; 067 * 068 * protected ResourceResponse newResourceResponse(Attributes attributes) 069 * { 070 * try 071 * { 072 * String name = attributes.getParameters().get("name").toString(""); 073 * URI uri = URI.create( 074 * "jar:file:////folder/example.zip!/zipfolder/" + name); 075 * return createResourceResponse(attributes, 076 * FileSystemResourceReference.getPath(uri)); 077 * } 078 * catch (IOException | URISyntaxException e) 079 * { 080 * throw new WicketRuntimeException("Error while reading the file.", e); 081 * } 082 * }; 083 * }; 084 * } 085 * }); 086 * </code> 087 * </pre> 088 * 089 * @author Tobias Soloschenko 090 */ 091public class FileSystemResourceReference extends ResourceReference 092{ 093 private static final long serialVersionUID = 1L; 094 095 private Path path; 096 097 /** 098 * Creates a file system resource reference based on the given path 099 * 100 * @param name 101 * the name of the resource reference to expose data 102 * @param path 103 * the path to create the resource reference 104 */ 105 public FileSystemResourceReference(String name, Path path) 106 { 107 super(name); 108 this.path = path; 109 } 110 111 /** 112 * Creates a file system resource reference based on the given name 113 * 114 * @param name 115 * the name of the resource reference 116 * 117 */ 118 public FileSystemResourceReference(String name) 119 { 120 super(name); 121 } 122 123 /** 124 * Creates a file system resource reference based on the given scope and name 125 * 126 * @param scope 127 * the scope as class 128 * @param name 129 * the name of the resource reference 130 * 131 */ 132 public FileSystemResourceReference(Class<?> scope, String name) 133 { 134 super(scope, name); 135 } 136 137 /** 138 * Creates a new {@link FileSystemResource} and applies the 139 * path to it. 140 */ 141 @Override 142 public IResource getResource() 143 { 144 return getFileSystemResource(); 145 } 146 147 /** 148 * Gets the file system resource to be used for the resource reference 149 * 150 * @return the file system resource to be used for the resource reference 151 */ 152 protected FileSystemResource getFileSystemResource() 153 { 154 if (path == null) 155 { 156 throw new WicketRuntimeException( 157 "Please override #getResource() and provide a path if using a constructor which doesn't take one as argument."); 158 } 159 return new FileSystemResource(path); 160 } 161 162 /** 163 * Creates a path and a file system (if required) based on the given URI 164 * 165 * @param uri 166 * the URI to create the file system and the path of 167 * @param env 168 * the environment parameter to create the file system with 169 * @return the path of the file in the file system 170 */ 171 public static Path getPath(URI uri, Map<String, String> env) 172 { 173 Iterator<FileSystemPathService> pathServiceIterator = ServiceLoader 174 .load(FileSystemPathService.class).iterator(); 175 while (pathServiceIterator.hasNext()) 176 { 177 FileSystemPathService pathService = pathServiceIterator.next(); 178 if (pathService.isResponsible(uri)) 179 { 180 Path fileSystemPath = pathService.getPath(uri, env); 181 if (fileSystemPath != null) 182 { 183 return fileSystemPath; 184 } 185 } 186 } 187 // fall back to just get the path from the URI 188 return Paths.get(uri); 189 } 190 191 /** 192 * Creates a path and a file system (if required) based on the given URI 193 * 194 * @param uri 195 * the URI to create the file system and the path of 196 * @return the path of the file in the file system 197 * @throws IOException 198 * if the file system could'nt be created 199 * @throws URISyntaxException 200 * if the URI has no valid syntax 201 */ 202 public static Path getPath(URI uri) throws IOException, URISyntaxException 203 { 204 return getPath(uri, null); 205 } 206}