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.common.internal.IOUtils.*; 016 017import java.io.*; 018import java.net.*; 019import java.util.jar.*; 020 021import org.apache.juneau.collections.*; 022import org.apache.juneau.common.internal.*; 023 024/** 025 * Utility class for working with Jar manifest files. 026 * 027 * <p> 028 * Copies the contents of a {@link Manifest} into an {@link JsonMap} so that the various convenience methods on that 029 * class can be used to retrieve values. 030 * 031 * <h5 class='section'>See Also:</h5><ul> 032 033 * </ul> 034 * 035 * @serial exclude 036 */ 037public class ManifestFile extends JsonMap { 038 039 private static final long serialVersionUID = 1L; 040 041 /** 042 * Create an instance of this class from a manifest file on the file system. 043 * 044 * @param f The manifest file. 045 * @throws IOException If a problem occurred while trying to read the manifest file. 046 */ 047 public ManifestFile(File f) throws IOException { 048 Manifest mf = new Manifest(); 049 try (FileInputStream fis = new FileInputStream(f)) { 050 mf.read(fis); 051 load(mf); 052 } catch (IOException e) { 053 throw new IOException("Problem detected in MANIFEST.MF. Contents below:\n"+read(f), e); 054 } 055 } 056 057 /** 058 * Create an instance of this class from a {@link Manifest} object. 059 * 060 * @param f The manifest to read from. 061 */ 062 public ManifestFile(Manifest f) { 063 load(f); 064 } 065 066 /** 067 * Finds and loads the manifest file of the jar file that the specified class is contained within. 068 * 069 * @param c The class to get the manifest file of. 070 * @throws IOException If a problem occurred while trying to read the manifest file. 071 */ 072 public ManifestFile(Class<?> c) throws IOException { 073 String className = c.getSimpleName() + ".class"; 074 String classPath = c.getResource(className).toString(); 075 if (! classPath.startsWith("jar")) { 076 return; 077 } 078 String manifestPath = classPath.substring(0, classPath.lastIndexOf("!") + 1) + "/META-INF/MANIFEST.MF"; 079 try { 080 Manifest mf = new Manifest(new URL(manifestPath).openStream()); 081 load(mf); 082 } catch (MalformedURLException e) { 083 throw ThrowableUtils.cast(IOException.class, e); 084 } catch (IOException e) { 085 e.printStackTrace(); 086 } 087 } 088 089 /** 090 * Create an instance of this class loaded from the contents of a reader. 091 * 092 * <p> 093 * Note that the input must end in a newline to pick up the last line! 094 * 095 * @param r The manifest file contents. 096 * @throws IOException If a problem occurred while trying to read the manifest file. 097 */ 098 public ManifestFile(Reader r) throws IOException { 099 load(new Manifest(new ByteArrayInputStream(read(r).getBytes(UTF8)))); 100 } 101 102 /** 103 * Create an instance of this class loaded from the contents of an input stream. 104 * 105 * <p> 106 * Note that the input must end in a newline to pick up the last line! 107 * 108 * @param is The manifest file contents. 109 * @throws IOException If a problem occurred while trying to read the manifest file. 110 */ 111 public ManifestFile(InputStream is) throws IOException { 112 load(new Manifest(is)); 113 } 114 115 private void load(Manifest mf) { 116 mf.getMainAttributes().forEach((k,v) -> put(k.toString(), v.toString())); 117 } 118 119 @Override /* Object */ 120 public String toString() { 121 StringBuilder sb = new StringBuilder(); 122 forEach((k,v) -> sb.append(k).append(": ").append(v)); 123 return sb.toString(); 124 } 125}