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.juneau.rest.server.staticfile;
018
019import static org.apache.juneau.commons.utils.CollectionUtils.*;
020
021import java.nio.file.Path;
022import java.util.*;
023
024import org.apache.juneau.commons.inject.*;
025import org.apache.juneau.commons.io.*;
026import org.apache.juneau.http.*;
027import org.apache.juneau.marshall.cp.*;
028
029/**
030 * API for retrieving localized static files from either the classpath or file system.
031 *
032 * <h5 class='section'>See Also:</h5><ul>
033 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/StaticFiles">Static files</a>
034 * </ul>
035 */
036@SuppressWarnings({
037   "java:S9398" // Nested types are public API; moving them would break callers.
038})
039public interface StaticFiles extends FileFinder {
040
041   /**
042    * Builder class.
043    */
044   public static class Builder {
045
046      private final BeanStore beanStore;
047      List<HttpHeader> headers;
048      MimeTypeDetector mimeTypes;
049      FileFinder.Builder fileFinder;
050
051      /**
052       * Constructor.
053       *
054       * @param beanStore The bean store to use for creating beans.
055       */
056      protected Builder(BeanStore beanStore) {
057         this.beanStore = beanStore;
058         headers = list();
059         fileFinder = FileFinder.create(beanStore);
060         mimeTypes = MimeTypeDetector.DEFAULT;
061      }
062
063      /**
064       * Returns the bean store used by this builder.
065       *
066       * @return The bean store used by this builder.
067       */
068      public BeanStore beanStore() {
069         return beanStore;
070      }
071
072      /**
073       * Prepend the MIME type values to the MIME types registry.
074       *
075       * @param mimeTypes A .mime.types formatted string of entries.  See {@link org.apache.juneau.commons.io.MimeTypeDetector.Builder#addTypes(String...) MimeTypeDetector.Builder#addTypes(String...)}.
076       * @return This object.
077       */
078      public Builder addMimeTypes(String mimeTypes) {
079         this.mimeTypes = MimeTypeDetector.builder().addTypes(mimeTypes).build();
080         return this;
081      }
082
083      /**
084       * Enables in-memory caching of files for quicker retrieval.
085       *
086       * @param cachingLimit The maximum file size in bytes.
087       * @return This object.
088       */
089      public Builder caching(long cachingLimit) {
090         fileFinder.caching(cachingLimit);
091         return this;
092      }
093
094      /**
095       * Adds a class subpackage to the lookup paths.
096       *
097       * @param c The class whose package will be added to the lookup paths.  Must not be <jk>null</jk>.
098       * @param path The absolute or relative subpath.
099       * @param recursive If <jk>true</jk>, also recursively adds all the paths of the parent classes as well.
100       * @return This object.
101       */
102      public Builder cp(Class<?> c, String path, boolean recursive) {
103         fileFinder.cp(c, path, recursive);
104         return this;
105      }
106
107      /**
108       * Adds a file system directory to the lookup paths.
109       *
110       * @param path The path relative to the working directory.  Must not be <jk>null</jk>
111       * @return This object.
112       */
113      public Builder dir(String path) {
114         fileFinder.dir(path);
115         return this;
116      }
117
118      /**
119       * Specifies the regular expression file name pattern to use to exclude files from being retrieved from the file source.
120       *
121       * @param patterns
122       *    The regular expression exclude patterns.
123       *    <br>If none are specified, no files will be excluded.
124       * @return This object.
125       */
126      public Builder exclude(String...patterns) {
127         fileFinder.exclude(patterns);
128         return this;
129      }
130
131      /**
132       * Appends headers to add to HTTP responses.
133       *
134       * <p>
135       * Can be called multiple times to add multiple headers.
136       *
137       * @param headers The headers to add.
138       * @return This object.
139       */
140      public Builder headers(HttpHeader...headers) {
141         addAll(this.headers, headers);
142         return this;
143      }
144
145
146      /**
147       * Specifies the regular expression file name patterns to use to include files being retrieved from the file source.
148       *
149       * @param patterns
150       *    The regular expression include patterns.
151       *    <br>The default is <js>".*"</js>.
152       * @return This object.
153       */
154      public Builder include(String...patterns) {
155         fileFinder.include(patterns);
156         return this;
157      }
158
159      /**
160       * Replaces the MIME types registry used for determining content types.
161       *
162       * @param value The new MIME types registry.
163       * @return This object.
164       */
165      public Builder mimeTypes(MimeTypeDetector value) {
166         mimeTypes = value;
167         return this;
168      }
169
170      /**
171       * Adds a file system directory to the lookup paths.
172       *
173       * @param value The directory path.
174       * @return This object.
175       */
176      public Builder path(Path value) {
177         fileFinder.path(value);
178         return this;
179      }
180
181      /**
182       * Builds the static files.
183       *
184       * @return A new {@link BasicStaticFiles}.
185       */
186      public StaticFiles build() {
187         return new BasicStaticFiles(this);
188      }
189   }
190
191   /** Represents no static files */
192   @SuppressWarnings({
193      "java:S9398" // Public annotation-default marker; moving breaks API.
194   })
195   public abstract class Void implements StaticFiles {}
196
197   /**
198    * Static creator.
199    *
200    * @param beanStore The bean store to use for creating beans.
201    * @return A new builder for this object.
202    */
203   static Builder create(BeanStore beanStore) {
204      return new Builder(beanStore);
205   }
206
207   /**
208    * Resolve the specified path.
209    *
210    * @param path The path to resolve to a static file.
211    * @param locale Optional locale.
212    * @return The resource, or an empty {@link Optional} if not found.
213    */
214   Optional<HttpResource> resolve(String path, Locale locale);
215}