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.cp;
018
019import static org.apache.juneau.common.utils.IOUtils.*;
020
021import java.io.*;
022import java.nio.file.*;
023
024import org.apache.juneau.common.utils.*;
025
026/**
027 * Identifies a file located either on the classpath or file system.
028 *
029 * Used to encapsulate basic resolution and retrieval of files regardless of where they are located.
030 *
031 * <h5 class='section'>See Also:</h5><ul>
032 * </ul>
033 */
034public class LocalFile {
035
036   private final Class<?> clazz;
037   private final String clazzPath;
038   private final Path path;
039   private final String name;
040   private byte[] cache;
041
042   /**
043    * Constructor for classpath file.
044    *
045    * @param clazz The class used to retrieve resources.  Must not be <jk>null</jk>.
046    * @param clazzPath The path relative to the class.  Must be a non-null normalized relative path.
047    */
048   public LocalFile(Class<?> clazz, String clazzPath) {
049      this.clazz = Utils.assertArgNotNull("clazz", clazz);
050      this.clazzPath = Utils.assertArgNotNull("clazzPath", clazzPath);
051      this.path = null;
052      int i = clazzPath.lastIndexOf('/');
053      this.name = i == -1 ? clazzPath : clazzPath.substring(i+1);
054   }
055
056   /**
057    * Constructor for file system file.
058    *
059    * @param path Filesystem file location.  Must not be <jk>null</jk>.
060    */
061   public LocalFile(Path path) {
062      this.clazz = null;
063      this.clazzPath = null;
064      this.path = Utils.assertArgNotNull("path", path);
065      this.name = path.getFileName().toString();
066   }
067
068   /**
069    * Returns the contents of this file.
070    *
071    * @return An input stream of the contents of this file.
072    * @throws IOException If file could not be read.
073    */
074   public InputStream read() throws IOException {
075      synchronized(this) {
076         if (cache != null)
077            return new ByteArrayInputStream(cache);
078      }
079      if (clazz != null)
080         return clazz.getResourceAsStream(clazzPath);
081      return Files.newInputStream(path);
082   }
083
084   /**
085    * Returns the size of this file.
086    *
087    * @return The size of this file in bytes, or <c>-1</c> if not known.
088    * @throws IOException If file size could not be determined.
089    */
090   public long size() throws IOException {
091      return (path == null ? -1 : Files.size(path));
092   }
093
094   /**
095    * Caches the contents of this file into an internal byte array for quick future retrieval.
096    *
097    * @return This object.
098    * @throws IOException If file could not be read.
099    */
100   public LocalFile cache() throws IOException {
101      synchronized(this) {
102         this.cache = readBytes(read());
103      }
104      return this;
105   }
106
107   /**
108    * Returns the name of this file.
109    *
110    * @return The name of this file.
111    */
112   public String getName() {
113      return name;
114   }
115}