001/* 002 * #%L 003 * HAPI FHIR - Core Library 004 * %% 005 * Copyright (C) 2014 - 2024 Smile CDR, Inc. 006 * %% 007 * Licensed under the Apache License, Version 2.0 (the "License"); 008 * you may not use this file except in compliance with the License. 009 * You may obtain a copy of the License at 010 * 011 * http://www.apache.org/licenses/LICENSE-2.0 012 * 013 * Unless required by applicable law or agreed to in writing, software 014 * distributed under the License is distributed on an "AS IS" BASIS, 015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 016 * See the License for the specific language governing permissions and 017 * limitations under the License. 018 * #L% 019 */ 020package ca.uhn.fhir.util.jar; 021 022import ca.uhn.fhir.util.XmlUtil; 023 024import java.io.InputStream; 025import java.net.MalformedURLException; 026import java.net.URL; 027import java.util.jar.Attributes; 028import java.util.jar.Manifest; 029 030public class DependencyLogImpl implements IDependencyLog { 031 private static final Attributes.Name BUNDLE_SYMBOLIC_NAME = new Attributes.Name("Bundle-SymbolicName"); 032 private static final Attributes.Name BUNDLE_VENDOR = new Attributes.Name("Bundle-Vendor"); 033 private static final Attributes.Name BUNDLE_VERSION = new Attributes.Name("Bundle-Version"); 034 private static final Attributes.Name IMPLEMENTATION_TITLE = new Attributes.Name("Implementation-Title"); 035 private static final Attributes.Name IMPLEMENTATION_VENDOR = new Attributes.Name("Implementation-Vendor"); 036 private static final Attributes.Name IMPLEMENTATION_VERSION = new Attributes.Name("Implementation-Version"); 037 private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(XmlUtil.class); 038 039 @Override 040 public void logStaxImplementation(Class<?> theClass) { 041 try { 042 URL rootUrl = getRootUrlForClass(theClass); 043 if (rootUrl == null) { 044 ourLog.info("Unable to determine location of StAX implementation containing class"); 045 } else { 046 Manifest manifest; 047 URL metaInfUrl = new URL(rootUrl, "META-INF/MANIFEST.MF"); 048 InputStream is = metaInfUrl.openStream(); 049 try { 050 manifest = new Manifest(is); 051 } finally { 052 is.close(); 053 } 054 Attributes attrs = manifest.getMainAttributes(); 055 String title = attrs.getValue(IMPLEMENTATION_TITLE); 056 String symbolicName = attrs.getValue(BUNDLE_SYMBOLIC_NAME); 057 if (symbolicName != null) { 058 int i = symbolicName.indexOf(';'); 059 if (i != -1) { 060 symbolicName = symbolicName.substring(0, i); 061 } 062 } 063 String vendor = attrs.getValue(IMPLEMENTATION_VENDOR); 064 if (vendor == null) { 065 vendor = attrs.getValue(BUNDLE_VENDOR); 066 } 067 String version = attrs.getValue(IMPLEMENTATION_VERSION); 068 if (version == null) { 069 version = attrs.getValue(BUNDLE_VERSION); 070 } 071 if (ourLog.isDebugEnabled()) { 072 ourLog.debug( 073 "FHIR XML procesing will use StAX implementation at {}\n Title: {}\n Symbolic name: {}\n Vendor: {}\n Version: {}", 074 new Object[] {rootUrl, title, symbolicName, vendor, version}); 075 } else { 076 ourLog.info("FHIR XML procesing will use StAX implementation '{}' version '{}'", title, version); 077 } 078 } 079 } catch (Throwable e) { 080 ourLog.info("Unable to determine StAX implementation: " + e.getMessage()); 081 } 082 } 083 084 private static URL getRootUrlForClass(Class<?> cls) { 085 ClassLoader classLoader = cls.getClassLoader(); 086 String resource = cls.getName().replace('.', '/') + ".class"; 087 if (classLoader == null) { 088 // A null class loader means the bootstrap class loader. In this case we use the 089 // system class loader. This is safe since we can assume that the system class 090 // loader uses parent first as delegation policy. 091 classLoader = ClassLoader.getSystemClassLoader(); 092 } 093 URL url = classLoader.getResource(resource); 094 if (url == null) { 095 return null; 096 } 097 String file = url.getFile(); 098 if (file.endsWith(resource)) { 099 try { 100 return new URL( 101 url.getProtocol(), 102 url.getHost(), 103 url.getPort(), 104 file.substring(0, file.length() - resource.length())); 105 } catch (MalformedURLException ex) { 106 return null; 107 } 108 } 109 return null; 110 } 111}