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.util.resource; 018 019import java.io.IOException; 020import java.io.InputStream; 021import java.net.URLConnection; 022import java.nio.file.Files; 023import java.nio.file.Path; 024import java.nio.file.attribute.BasicFileAttributes; 025import java.nio.file.attribute.FileTime; 026import java.time.Instant; 027import org.apache.wicket.util.file.File; 028import org.apache.wicket.util.lang.Args; 029import org.apache.wicket.util.lang.Bytes; 030 031/** 032 * A FileSystemResourceStream is an IResourceStream implementation for Java NIO paths. 033 * 034 * @see org.apache.wicket.util.resource.IResourceStream 035 * @see org.apache.wicket.util.watch.IModifiable 036 * @author Tobias Soloschenko 037 */ 038public class FileSystemResourceStream extends AbstractResourceStream 039 implements 040 IFixedLocationResourceStream 041{ 042 private static final long serialVersionUID = 1L; 043 044 /** Any associated path */ 045 private final Path path; 046 047 /** Resource stream */ 048 private transient InputStream inputStream; 049 050 /** 051 * Constructor. 052 * 053 * @param path 054 * {@link Path} containing resource 055 */ 056 public FileSystemResourceStream(final Path path) 057 { 058 Args.notNull(path, "path"); 059 this.path = path; 060 } 061 062 /** 063 * Constructor. 064 * 065 * @param file 066 * {@link java.io.File} containing resource 067 */ 068 public FileSystemResourceStream(final java.io.File file) 069 { 070 Args.notNull(file, "file"); 071 this.path = file.toPath(); 072 } 073 074 /** 075 * Constructor. 076 * 077 * @param file 078 * {@link File} containing resource 079 */ 080 public FileSystemResourceStream(final File file) 081 { 082 Args.notNull(file, "file"); 083 this.path = file.toPath(); 084 } 085 086 @Override 087 public InputStream getInputStream() throws ResourceStreamNotFoundException 088 { 089 if (inputStream == null) 090 { 091 try 092 { 093 inputStream = Files.newInputStream(path); 094 } 095 catch (IOException e) 096 { 097 throw new ResourceStreamNotFoundException("Input stream of path " + path + 098 " could not be acquired", e); 099 } 100 } 101 return inputStream; 102 } 103 104 @Override 105 public void close() throws IOException 106 { 107 if (inputStream != null) 108 { 109 inputStream.close(); 110 inputStream = null; 111 } 112 } 113 114 @Override 115 public String getContentType() 116 { 117 try 118 { 119 String contentType = Files.probeContentType(path); 120 if (contentType == null) 121 { 122 contentType = URLConnection.getFileNameMap().getContentTypeFor( 123 path.getFileName().toString()); 124 } 125 return contentType; 126 } 127 catch (IOException e) 128 { 129 throw new RuntimeException("Content type of path " + path + " could not be acquired", e); 130 } 131 } 132 133 /** 134 * @return The path this resource resides in, if any. 135 */ 136 public final Path getPath() 137 { 138 return path; 139 } 140 141 @Override 142 public Instant lastModifiedTime() 143 { 144 try 145 { 146 BasicFileAttributes attributes = Files.readAttributes(path, BasicFileAttributes.class); 147 FileTime lastModifiedTime = attributes.lastModifiedTime(); 148 long millis = lastModifiedTime.toMillis(); 149 return Instant.ofEpochMilli(millis); 150 } 151 catch (IOException e) 152 { 153 throw new RuntimeException("Modification time of path " + path + 154 " could not be acquired", e); 155 } 156 } 157 158 @Override 159 public Bytes length() 160 { 161 try 162 { 163 BasicFileAttributes attributes = Files.readAttributes(path, BasicFileAttributes.class); 164 long size = attributes.size(); 165 return Bytes.bytes(size); 166 } 167 catch (IOException e) 168 { 169 throw new RuntimeException("Length of path " + path + " could not be acquired", e); 170 } 171 } 172 173 @Override 174 public String locationAsString() 175 { 176 return path.toString(); 177 } 178 179 @Override 180 public String toString() 181 { 182 return locationAsString(); 183 } 184}