001// Generated by delombok at Sat Feb 25 17:58:34 UTC 2023 002package io.cui.tools.io; 003 004import static io.cui.tools.base.Preconditions.checkState; 005import static io.cui.tools.string.MoreStrings.isEmpty; 006import static io.cui.tools.string.MoreStrings.requireNotEmpty; 007import static java.util.Objects.requireNonNull; 008import java.io.IOException; 009import java.io.InputStream; 010import java.net.URL; 011import io.cui.tools.lang.SecuritySupport; 012import io.cui.tools.logging.CuiLogger; 013 014/** 015 * Variant of {@link FileLoader} that loads files from the classpath. 016 * 017 * @author Oliver Wolff 018 */ 019public class ClassPathLoader implements FileLoader { 020 private static final long serialVersionUID = 9140071059594577808L; 021 private static final CuiLogger log = new CuiLogger(ClassPathLoader.class); 022 private final String normalizedPathName; 023 private final String givenPathName; 024 private final StructuredFilename fileName; 025 private URL url; 026 027 /** 028 * @param pathName must not be null nor empty, may start with the prefix 029 * {@link FileTypePrefix#CLASSPATH} but not with 030 * {@link FileTypePrefix#FILE} and contain at least one character despite the prefix. 031 * On all other cases a {@link IllegalArgumentException} will be 032 * thrown. 033 */ 034 public ClassPathLoader(final String pathName) { 035 requireNonNull(pathName); 036 givenPathName = pathName; 037 normalizedPathName = checkClasspathName(pathName); 038 fileName = new StructuredFilename(FilenameUtils.getName(normalizedPathName)); 039 } 040 041 /** 042 * Checks and modifies a given pathName 043 * 044 * @param pathName must not be null nor empty, may start with the prefix 045 * {@link FileTypePrefix#CLASSPATH} but not with 046 * {@link FileTypePrefix#FILE} and contain at least one character despite 047 * the prefix. On all other cases a {@link IllegalArgumentException} will be 048 * thrown. 049 * @return the normalized pathname without prefix but with a leading '/' 050 */ 051 static String checkClasspathName(final String pathName) { 052 requireNotEmpty(pathName); 053 if (FileTypePrefix.FILE.is(pathName)) { 054 throw new IllegalArgumentException("Invalid path name, must start not start with " + FileTypePrefix.FILE + " but was: " + pathName); 055 } 056 var newPathName = pathName; 057 if (FileTypePrefix.CLASSPATH.is(pathName)) { 058 newPathName = FileTypePrefix.CLASSPATH.removePrefix(pathName); 059 } 060 if (isEmpty(newPathName)) { 061 throw new IllegalArgumentException("Filename " + pathName + " is invalid"); 062 } 063 if (newPathName.indexOf('/') != 0) { 064 newPathName = '/' + newPathName; 065 } 066 return newPathName; 067 } 068 069 @Override 070 public boolean isReadable() { 071 return null != getURL(); 072 } 073 074 @Override 075 public InputStream inputStream() { 076 checkState(isReadable(), "Resource \'{}\' is not readable", givenPathName); 077 try { 078 return getURL().openStream(); 079 } catch (IOException e) { 080 throw new IllegalStateException("Unable to load classpath file for " + givenPathName, e); 081 } 082 } 083 084 @Override 085 public boolean isFilesystemLoader() { 086 return false; 087 } 088 089 @Override 090 public URL getURL() { 091 if (null == url) { 092 url = resolveUrl(normalizedPathName); 093 } 094 return url; 095 } 096 097 private static URL resolveUrl(String path) { 098 log.debug("Resolving URL for \'{}\'", path); 099 var url = ClassPathLoader.class.getResource(path); 100 if (null != url) { 101 log.debug("Resolved \'{}\' from ClassPathLoader.class", path); 102 return url; 103 } 104 var loader = SecuritySupport.getContextClassLoader(); 105 if (loader.isPresent()) { 106 url = loader.get().getResource(path); 107 if (null != url) { 108 log.debug("Resolved \'{}\' from ContextClassLoader", path); 109 return url; 110 } 111 } 112 log.warn("Unable to resolve \'{}\' from classpath", path); 113 return null; 114 } 115 116 @java.lang.Override 117 @java.lang.SuppressWarnings("all") 118 @lombok.Generated 119 public boolean equals(final java.lang.Object o) { 120 if (o == this) return true; 121 if (!(o instanceof ClassPathLoader)) return false; 122 final ClassPathLoader other = (ClassPathLoader) o; 123 if (!other.canEqual((java.lang.Object) this)) return false; 124 final java.lang.Object this$normalizedPathName = this.normalizedPathName; 125 final java.lang.Object other$normalizedPathName = other.normalizedPathName; 126 if (this$normalizedPathName == null ? other$normalizedPathName != null : !this$normalizedPathName.equals(other$normalizedPathName)) return false; 127 return true; 128 } 129 130 @java.lang.SuppressWarnings("all") 131 @lombok.Generated 132 protected boolean canEqual(final java.lang.Object other) { 133 return other instanceof ClassPathLoader; 134 } 135 136 @java.lang.Override 137 @java.lang.SuppressWarnings("all") 138 @lombok.Generated 139 public int hashCode() { 140 final int PRIME = 59; 141 int result = 1; 142 final java.lang.Object $normalizedPathName = this.normalizedPathName; 143 result = result * PRIME + ($normalizedPathName == null ? 43 : $normalizedPathName.hashCode()); 144 return result; 145 } 146 147 @java.lang.Override 148 @java.lang.SuppressWarnings("all") 149 @lombok.Generated 150 public java.lang.String toString() { 151 return "ClassPathLoader(normalizedPathName=" + this.normalizedPathName + ", givenPathName=" + this.givenPathName + ", fileName=" + this.getFileName() + ", url=" + this.getURL() + ")"; 152 } 153 154 @java.lang.SuppressWarnings("all") 155 @lombok.Generated 156 public StructuredFilename getFileName() { 157 return this.fileName; 158 } 159}