001package ca.uhn.fhir.util; 002 003/*- 004 * #%L 005 * HAPI FHIR - Core Library 006 * %% 007 * Copyright (C) 2014 - 2021 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.rest.api.EncodingEnum; 025import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; 026import com.google.common.base.Charsets; 027import org.apache.commons.io.IOUtils; 028import org.apache.commons.io.input.BOMInputStream; 029import org.hl7.fhir.instance.model.api.IBaseResource; 030import org.slf4j.Logger; 031import org.slf4j.LoggerFactory; 032 033import javax.annotation.Nonnull; 034import java.io.IOException; 035import java.io.InputStream; 036import java.util.function.Function; 037import java.util.zip.GZIPInputStream; 038 039/** 040 * Use this API with caution, it may change! 041 */ 042public class ClasspathUtil { 043 044 private static final Logger ourLog = LoggerFactory.getLogger(ClasspathUtil.class); 045 046 /** 047 * Non instantiable 048 */ 049 private ClasspathUtil() { 050 // nothing 051 } 052 053 public static String loadResource(String theClasspath) { 054 return loadResource(theClasspath, Function.identity()); 055 } 056 057 /** 058 * Load a classpath resource, throw an {@link InternalErrorException} if not found 059 * 060 * @throws InternalErrorException If the resource can't be found 061 */ 062 @Nonnull 063 public static InputStream loadResourceAsStream(String theClasspath) { 064 String classpath = theClasspath; 065 if (classpath.startsWith("classpath:")) { 066 classpath = classpath.substring("classpath:".length()); 067 } 068 069 InputStream retVal = ClasspathUtil.class.getResourceAsStream(classpath); 070 if (retVal == null) { 071 if (classpath.startsWith("/")) { 072 retVal = ClasspathUtil.class.getResourceAsStream(classpath.substring(1)); 073 } else { 074 retVal = ClasspathUtil.class.getResourceAsStream("/" + classpath); 075 } 076 if (retVal == null) { 077 throw new InternalErrorException("Unable to find classpath resource: " + classpath); 078 } 079 } 080 return retVal; 081 } 082 083 /** 084 * Load a classpath resource, throw an {@link InternalErrorException} if not found 085 */ 086 @Nonnull 087 public static String loadResource(String theClasspath, Function<InputStream, InputStream> theStreamTransform) { 088 try (InputStream stream = loadResourceAsStream(theClasspath)) { 089 InputStream newStream = theStreamTransform.apply(stream); 090 return IOUtils.toString(newStream, Charsets.UTF_8); 091 } catch (IOException e) { 092 throw new InternalErrorException(e); 093 } 094 } 095 096 @Nonnull 097 public static String loadCompressedResource(String theClasspath) { 098 Function<InputStream, InputStream> streamTransform = t -> { 099 try { 100 return new GZIPInputStream(t); 101 } catch (IOException e) { 102 throw new InternalErrorException(e); 103 } 104 }; 105 return loadResource(theClasspath, streamTransform); 106 } 107 108 @Nonnull 109 public static <T extends IBaseResource> T loadResource(FhirContext theCtx, Class<T> theType, String theClasspath) { 110 String raw = loadResource(theClasspath); 111 return EncodingEnum.detectEncodingNoDefault(raw).newParser(theCtx).parseResource(theType, raw); 112 } 113 114 public static void close(InputStream theInput) { 115 try { 116 if (theInput != null) { 117 theInput.close(); 118 } 119 } catch (IOException e) { 120 ourLog.debug("Closing InputStream threw exception", e); 121 } 122 } 123 124 public static Function<InputStream, InputStream> withBom() { 125 return t -> new BOMInputStream(t); 126 } 127 128 public static byte[] loadResourceAsByteArray(String theClasspath) { 129 InputStream stream = loadResourceAsStream(theClasspath); 130 try { 131 return IOUtils.toByteArray(stream); 132 } catch (IOException e) { 133 throw new InternalErrorException(e); 134 } finally { 135 close(stream); 136 } 137 } 138}