001package ca.uhn.fhir.util.jar; 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 java.io.InputStream; 024import java.net.MalformedURLException; 025import java.net.URL; 026import java.util.jar.Attributes; 027import java.util.jar.Manifest; 028 029import ca.uhn.fhir.util.XmlUtil; 030 031public class DependencyLogImpl implements IDependencyLog { 032 private static final Attributes.Name BUNDLE_SYMBOLIC_NAME = new Attributes.Name("Bundle-SymbolicName"); 033 private static final Attributes.Name BUNDLE_VENDOR = new Attributes.Name("Bundle-Vendor"); 034 private static final Attributes.Name BUNDLE_VERSION = new Attributes.Name("Bundle-Version"); 035 private static final Attributes.Name IMPLEMENTATION_TITLE = new Attributes.Name("Implementation-Title"); 036 private static final Attributes.Name IMPLEMENTATION_VENDOR = new Attributes.Name("Implementation-Vendor"); 037 private static final Attributes.Name IMPLEMENTATION_VERSION = new Attributes.Name("Implementation-Version"); 038 private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(XmlUtil.class); 039 040 @Override 041 public void logStaxImplementation(Class<?> theClass) { 042 try { 043 URL rootUrl = getRootUrlForClass(theClass); 044 if (rootUrl == null) { 045 ourLog.info("Unable to determine location of StAX implementation containing class"); 046 } else { 047 Manifest manifest; 048 URL metaInfUrl = new URL(rootUrl, "META-INF/MANIFEST.MF"); 049 InputStream is = metaInfUrl.openStream(); 050 try { 051 manifest = new Manifest(is); 052 } finally { 053 is.close(); 054 } 055 Attributes attrs = manifest.getMainAttributes(); 056 String title = attrs.getValue(IMPLEMENTATION_TITLE); 057 String symbolicName = attrs.getValue(BUNDLE_SYMBOLIC_NAME); 058 if (symbolicName != null) { 059 int i = symbolicName.indexOf(';'); 060 if (i != -1) { 061 symbolicName = symbolicName.substring(0, i); 062 } 063 } 064 String vendor = attrs.getValue(IMPLEMENTATION_VENDOR); 065 if (vendor == null) { 066 vendor = attrs.getValue(BUNDLE_VENDOR); 067 } 068 String version = attrs.getValue(IMPLEMENTATION_VERSION); 069 if (version == null) { 070 version = attrs.getValue(BUNDLE_VERSION); 071 } 072 if (ourLog.isDebugEnabled()) { 073 ourLog.debug("FHIR XML procesing will use StAX implementation at {}\n Title: {}\n Symbolic name: {}\n Vendor: {}\n Version: {}", new Object[] { rootUrl, title, symbolicName, vendor, version } ); 074 } else { 075 ourLog.info("FHIR XML procesing will use StAX implementation '{}' version '{}'", title, version); 076 } 077 } 078 } catch (Throwable e) { 079 ourLog.info("Unable to determine StAX implementation: " + e.getMessage()); 080 } 081 } 082 083 private static URL getRootUrlForClass(Class<?> cls) { 084 ClassLoader classLoader = cls.getClassLoader(); 085 String resource = cls.getName().replace('.', '/') + ".class"; 086 if (classLoader == null) { 087 // A null class loader means the bootstrap class loader. In this case we use the 088 // system class loader. This is safe since we can assume that the system class 089 // loader uses parent first as delegation policy. 090 classLoader = ClassLoader.getSystemClassLoader(); 091 } 092 URL url = classLoader.getResource(resource); 093 if (url == null) { 094 return null; 095 } 096 String file = url.getFile(); 097 if (file.endsWith(resource)) { 098 try { 099 return new URL(url.getProtocol(), url.getHost(), url.getPort(), file.substring(0, file.length() - resource.length())); 100 } catch (MalformedURLException ex) { 101 return null; 102 } 103 } 104 return null; 105 } 106}