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