001/* 002 * Copyright 2002-2018 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.core.io; 018 019import java.io.File; 020import java.io.IOException; 021import java.io.InputStream; 022import java.net.URI; 023import java.net.URL; 024import java.nio.channels.Channels; 025import java.nio.channels.ReadableByteChannel; 026 027import org.springframework.lang.Nullable; 028 029/** 030 * Interface for a resource descriptor that abstracts from the actual 031 * type of underlying resource, such as a file or class path resource. 032 * 033 * <p>An InputStream can be opened for every resource if it exists in 034 * physical form, but a URL or File handle can just be returned for 035 * certain resources. The actual behavior is implementation-specific. 036 * 037 * @author Juergen Hoeller 038 * @since 28.12.2003 039 * @see #getInputStream() 040 * @see #getURL() 041 * @see #getURI() 042 * @see #getFile() 043 * @see WritableResource 044 * @see ContextResource 045 * @see UrlResource 046 * @see FileUrlResource 047 * @see FileSystemResource 048 * @see ClassPathResource 049 * @see ByteArrayResource 050 * @see InputStreamResource 051 */ 052public interface Resource extends InputStreamSource { 053 054 /** 055 * Determine whether this resource actually exists in physical form. 056 * <p>This method performs a definitive existence check, whereas the 057 * existence of a {@code Resource} handle only guarantees a valid 058 * descriptor handle. 059 */ 060 boolean exists(); 061 062 /** 063 * Indicate whether non-empty contents of this resource can be read via 064 * {@link #getInputStream()}. 065 * <p>Will be {@code true} for typical resource descriptors that exist 066 * since it strictly implies {@link #exists()} semantics as of 5.1. 067 * Note that actual content reading may still fail when attempted. 068 * However, a value of {@code false} is a definitive indication 069 * that the resource content cannot be read. 070 * @see #getInputStream() 071 * @see #exists() 072 */ 073 default boolean isReadable() { 074 return exists(); 075 } 076 077 /** 078 * Indicate whether this resource represents a handle with an open stream. 079 * If {@code true}, the InputStream cannot be read multiple times, 080 * and must be read and closed to avoid resource leaks. 081 * <p>Will be {@code false} for typical resource descriptors. 082 */ 083 default boolean isOpen() { 084 return false; 085 } 086 087 /** 088 * Determine whether this resource represents a file in a file system. 089 * A value of {@code true} strongly suggests (but does not guarantee) 090 * that a {@link #getFile()} call will succeed. 091 * <p>This is conservatively {@code false} by default. 092 * @since 5.0 093 * @see #getFile() 094 */ 095 default boolean isFile() { 096 return false; 097 } 098 099 /** 100 * Return a URL handle for this resource. 101 * @throws IOException if the resource cannot be resolved as URL, 102 * i.e. if the resource is not available as descriptor 103 */ 104 URL getURL() throws IOException; 105 106 /** 107 * Return a URI handle for this resource. 108 * @throws IOException if the resource cannot be resolved as URI, 109 * i.e. if the resource is not available as descriptor 110 * @since 2.5 111 */ 112 URI getURI() throws IOException; 113 114 /** 115 * Return a File handle for this resource. 116 * @throws java.io.FileNotFoundException if the resource cannot be resolved as 117 * absolute file path, i.e. if the resource is not available in a file system 118 * @throws IOException in case of general resolution/reading failures 119 * @see #getInputStream() 120 */ 121 File getFile() throws IOException; 122 123 /** 124 * Return a {@link ReadableByteChannel}. 125 * <p>It is expected that each call creates a <i>fresh</i> channel. 126 * <p>The default implementation returns {@link Channels#newChannel(InputStream)} 127 * with the result of {@link #getInputStream()}. 128 * @return the byte channel for the underlying resource (must not be {@code null}) 129 * @throws java.io.FileNotFoundException if the underlying resource doesn't exist 130 * @throws IOException if the content channel could not be opened 131 * @since 5.0 132 * @see #getInputStream() 133 */ 134 default ReadableByteChannel readableChannel() throws IOException { 135 return Channels.newChannel(getInputStream()); 136 } 137 138 /** 139 * Determine the content length for this resource. 140 * @throws IOException if the resource cannot be resolved 141 * (in the file system or as some other known physical resource type) 142 */ 143 long contentLength() throws IOException; 144 145 /** 146 * Determine the last-modified timestamp for this resource. 147 * @throws IOException if the resource cannot be resolved 148 * (in the file system or as some other known physical resource type) 149 */ 150 long lastModified() throws IOException; 151 152 /** 153 * Create a resource relative to this resource. 154 * @param relativePath the relative path (relative to this resource) 155 * @return the resource handle for the relative resource 156 * @throws IOException if the relative resource cannot be determined 157 */ 158 Resource createRelative(String relativePath) throws IOException; 159 160 /** 161 * Determine a filename for this resource, i.e. typically the last 162 * part of the path: for example, "myfile.txt". 163 * <p>Returns {@code null} if this type of resource does not 164 * have a filename. 165 */ 166 @Nullable 167 String getFilename(); 168 169 /** 170 * Return a description for this resource, 171 * to be used for error output when working with the resource. 172 * <p>Implementations are also encouraged to return this value 173 * from their {@code toString} method. 174 * @see Object#toString() 175 */ 176 String getDescription(); 177 178}