001package ca.uhn.fhir.util; 002 003/*- 004 * #%L 005 * HAPI FHIR - Core Library 006 * %% 007 * Copyright (C) 2014 - 2022 Smile CDR, Inc. 008 * %% 009 * Licensed under the Apache License, Version 2.0 (the "License"); 010 * you may not use this file except in compliance with the License. 011 * You may obtain a copy of the License at 012 * 013 * http://www.apache.org/licenses/LICENSE-2.0 014 * 015 * Unless required by applicable law or agreed to in writing, software 016 * distributed under the License is distributed on an "AS IS" BASIS, 017 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 018 * See the License for the specific language governing permissions and 019 * limitations under the License. 020 * #L% 021 */ 022 023import ca.uhn.fhir.context.FhirContext; 024import ca.uhn.fhir.i18n.Msg; 025import ca.uhn.fhir.rest.api.EncodingEnum; 026import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; 027import com.google.common.base.Charsets; 028import org.apache.commons.io.IOUtils; 029import org.apache.commons.io.input.BOMInputStream; 030import org.hl7.fhir.instance.model.api.IBaseResource; 031import org.slf4j.Logger; 032import org.slf4j.LoggerFactory; 033 034import javax.annotation.Nonnull; 035import java.io.IOException; 036import java.io.InputStream; 037import java.util.function.Function; 038import java.util.zip.GZIPInputStream; 039 040/** 041 * Use this API with caution, it may change! 042 */ 043public class ClasspathUtil { 044 045 private static final Logger ourLog = LoggerFactory.getLogger(ClasspathUtil.class); 046 047 /** 048 * Non instantiable 049 */ 050 private ClasspathUtil() { 051 // nothing 052 } 053 054 /** 055 * Load a classpath resource, throw an {@link InternalErrorException} if not found 056 * 057 * @throws InternalErrorException If the resource can't be found 058 */ 059 public static String loadResource(String theClasspath) throws InternalErrorException { 060 return loadResource(theClasspath, Function.identity()); 061 } 062 063 /** 064 * Load a classpath resource, throw an {@link InternalErrorException} if not found 065 * 066 * @throws InternalErrorException If the resource can't be found 067 */ 068 @Nonnull 069 public static InputStream loadResourceAsStream(String theClasspath) throws InternalErrorException { 070 String classpath = theClasspath; 071 if (classpath.startsWith("classpath:")) { 072 classpath = classpath.substring("classpath:".length()); 073 } 074 075 InputStream retVal = ClasspathUtil.class.getResourceAsStream(classpath); 076 if (retVal == null) { 077 if (classpath.startsWith("/")) { 078 retVal = ClasspathUtil.class.getResourceAsStream(classpath.substring(1)); 079 } else { 080 retVal = ClasspathUtil.class.getResourceAsStream("/" + classpath); 081 } 082 if (retVal == null) { 083 throw new InternalErrorException(Msg.code(1758) + "Unable to find classpath resource: " + classpath); 084 } 085 } 086 return retVal; 087 } 088 089 /** 090 * Load a classpath resource, throw an {@link InternalErrorException} if not found 091 */ 092 @Nonnull 093 public static String loadResource(String theClasspath, Function<InputStream, InputStream> theStreamTransform) { 094 try (InputStream stream = loadResourceAsStream(theClasspath)) { 095 InputStream newStream = theStreamTransform.apply(stream); 096 return IOUtils.toString(newStream, Charsets.UTF_8); 097 } catch (IOException e) { 098 throw new InternalErrorException(Msg.code(1759) + e); 099 } 100 } 101 102 @Nonnull 103 public static String loadCompressedResource(String theClasspath) { 104 Function<InputStream, InputStream> streamTransform = t -> { 105 try { 106 return new GZIPInputStream(t); 107 } catch (IOException e) { 108 throw new InternalErrorException(Msg.code(1760) + e); 109 } 110 }; 111 return loadResource(theClasspath, streamTransform); 112 } 113 114 @Nonnull 115 public static <T extends IBaseResource> T loadResource(FhirContext theCtx, Class<T> theType, String theClasspath) { 116 String raw = loadResource(theClasspath); 117 return EncodingEnum.detectEncodingNoDefault(raw).newParser(theCtx).parseResource(theType, raw); 118 } 119 120 public static void close(InputStream theInput) { 121 try { 122 if (theInput != null) { 123 theInput.close(); 124 } 125 } catch (IOException e) { 126 ourLog.debug("Closing InputStream threw exception", e); 127 } 128 } 129 130 public static Function<InputStream, InputStream> withBom() { 131 return t -> new BOMInputStream(t); 132 } 133 134 public static byte[] loadResourceAsByteArray(String theClasspath) { 135 InputStream stream = loadResourceAsStream(theClasspath); 136 try { 137 return IOUtils.toByteArray(stream); 138 } catch (IOException e) { 139 throw new InternalErrorException(Msg.code(1761) + e); 140 } finally { 141 close(stream); 142 } 143 } 144}