001// *************************************************************************************************************************** 002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * 003// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * 004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance * 005// * with the License. You may obtain a copy of the License at * 006// * * 007// * http://www.apache.org/licenses/LICENSE-2.0 * 008// * * 009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an * 010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * 011// * specific language governing permissions and limitations under the License. * 012// *************************************************************************************************************************** 013package org.apache.juneau.utils; 014 015import static org.apache.juneau.internal.ObjectUtils.*; 016 017import java.io.*; 018import java.util.*; 019import java.util.concurrent.*; 020 021import org.apache.juneau.internal.*; 022 023/** 024 * Class for retrieving and caching resource files from the classpath. 025 * 026 * @deprecated Use {@link org.apache.juneau.cp.ResourceManager}. 027 */ 028@Deprecated 029public final class ClasspathResourceManager { 030 031 // Maps resource names+locales to found resources. 032 private final ConcurrentHashMap<ResourceKey,byte[]> byteCache; 033 private final ConcurrentHashMap<ResourceKey,String> stringCache; 034 035 private final Class<?> baseClass; 036 private final ClasspathResourceFinder resourceFinder; 037 private final boolean useCache; 038 039 /** 040 * Constructor. 041 * 042 * @param baseClass The default class to use for retrieving resources from the classpath. 043 * @param resourceFinder The resource finder implementation. 044 * @param useCache If <jk>true</jk>, retrieved resources are stored in an in-memory cache for fast lookup. 045 */ 046 public ClasspathResourceManager(Class<?> baseClass, ClasspathResourceFinder resourceFinder, boolean useCache) { 047 this.baseClass = baseClass; 048 this.resourceFinder = resourceFinder; 049 this.useCache = useCache; 050 if (useCache) { 051 this.byteCache = new ConcurrentHashMap<>(); 052 this.stringCache = new ConcurrentHashMap<>(); 053 } else { 054 this.byteCache = null; 055 this.stringCache = null; 056 } 057 } 058 059 /** 060 * Constructor. 061 * 062 * <p> 063 * Uses default {@link ClasspathResourceFinderBasic} for finding resources. 064 * 065 * @param baseClass The default class to use for retrieving resources from the classpath. 066 */ 067 public ClasspathResourceManager(Class<?> baseClass) { 068 this(baseClass, new ClasspathResourceFinderBasic(), false); 069 } 070 071 /** 072 * Finds the resource with the given name. 073 * 074 * @param name Name of the desired resource. 075 * @return An input stream to the object, or <jk>null</jk> if the resource could not be found. 076 * @throws IOException Thrown by underlying stream. 077 */ 078 public InputStream getStream(String name) throws IOException { 079 return getStream(name, null); 080 } 081 082 /** 083 * Finds the resource with the given name for the specified locale and returns it as an input stream. 084 * 085 * @param name Name of the desired resource. 086 * @param locale The locale. Can be <jk>null</jk>. 087 * @return An input stream to the object, or <jk>null</jk> if the resource could not be found. 088 * @throws IOException Thrown by underlying stream. 089 */ 090 public InputStream getStream(String name, Locale locale) throws IOException { 091 return getStream(baseClass, name, locale); 092 } 093 094 /** 095 * Finds the resource with the given name for the specified locale and returns it as an input stream. 096 * 097 * @param baseClass 098 * Overrides the default class to use for retrieving the classpath resource. 099 * <br>If <jk>null</jk>, uses the base class passed in through the constructor of this class. 100 * @param name Name of the desired resource. 101 * @param locale The locale. Can be <jk>null</jk>. 102 * @return An input stream to the object, or <jk>null</jk> if the resource could not be found. 103 * @throws IOException Thrown by underlying stream. 104 */ 105 public InputStream getStream(Class<?> baseClass, String name, Locale locale) throws IOException { 106 107 if (baseClass == null) 108 baseClass = this.baseClass; 109 110 if (! useCache) 111 return resourceFinder.findResource(baseClass, name, locale); 112 113 ResourceKey key = new ResourceKey(name, locale); 114 115 byte[] r = byteCache.get(key); 116 if (r == null) { 117 try (InputStream is = resourceFinder.findResource(baseClass, name, locale)) { 118 if (is != null) 119 byteCache.putIfAbsent(key, IOUtils.readBytes(is, 1024)); 120 } 121 } 122 123 r = byteCache.get(key); 124 return r == null ? null : new ByteArrayInputStream(r); 125 } 126 127 /** 128 * Finds the resource with the given name and converts it to a simple string. 129 * 130 * @param name Name of the desired resource. 131 * @return The resource converted to a string, or <jk>null</jk> if the resource could not be found. 132 * @throws IOException Thrown by underlying stream. 133 */ 134 public String getString(String name) throws IOException { 135 return getString(baseClass, name, null); 136 } 137 138 /** 139 * Finds the resource with the given name and converts it to a simple string. 140 * 141 * @param baseClass 142 * Overrides the default class to use for retrieving the classpath resource. 143 * <br>If <jk>null</jk>, uses the base class passed in through the constructor of this class. 144 * @param name Name of the desired resource. 145 * @return The resource converted to a string, or <jk>null</jk> if the resource could not be found. 146 * @throws IOException Thrown by underlying stream. 147 */ 148 public String getString(Class<?> baseClass, String name) throws IOException { 149 return getString(baseClass, name, null); 150 } 151 152 /** 153 * Finds the resource with the given name and converts it to a simple string. 154 * 155 * @param name Name of the desired resource. 156 * @param locale The locale. Can be <jk>null</jk>. 157 * @return The resource converted to a string, or <jk>null</jk> if the resource could not be found. 158 * @throws IOException Thrown by underlying stream. 159 */ 160 public String getString(String name, Locale locale) throws IOException { 161 return getString(baseClass, name, locale); 162 } 163 164 /** 165 * Finds the resource with the given name and converts it to a simple string. 166 * 167 * @param baseClass 168 * Overrides the default class to use for retrieving the classpath resource. 169 * <br>If <jk>null</jk>, uses the base class passed in through the constructor of this class. 170 * @param name Name of the desired resource. 171 * @param locale The locale. Can be <jk>null</jk>. 172 * @return The resource converted to a string, or <jk>null</jk> if the resource could not be found. 173 * @throws IOException Thrown by underlying stream. 174 */ 175 public String getString(Class<?> baseClass, String name, Locale locale) throws IOException { 176 177 if (baseClass == null) 178 baseClass = this.baseClass; 179 180 if (! useCache) { 181 try (InputStream is = resourceFinder.findResource(baseClass, name, locale)) { 182 return IOUtils.read(is, IOUtils.UTF8); 183 } 184 } 185 186 ResourceKey key = new ResourceKey(name, locale); 187 188 String r = stringCache.get(key); 189 if (r == null) { 190 try (InputStream is = resourceFinder.findResource(baseClass, name, locale)) { 191 if (is != null) 192 stringCache.putIfAbsent(key, IOUtils.read(is, IOUtils.UTF8)); 193 } 194 } 195 196 return stringCache.get(key); 197 } 198 199 private class ResourceKey { 200 final String name; 201 final Locale locale; 202 203 ResourceKey(String name, Locale locale) { 204 this.name = name; 205 this.locale = locale; 206 } 207 208 @Override 209 public int hashCode() { 210 return name.hashCode() + (locale == null ? 0 : locale.hashCode()); 211 } 212 213 @Override 214 public boolean equals(Object o) { 215 return (o instanceof ResourceKey) && eq(this, (ResourceKey)o, (x,y)->eq(x.name, y.name) && eq(x.locale, y.locale)); 216 } 217 } 218}