18a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak/* 28a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * Licensed to the Apache Software Foundation (ASF) under one or more 38a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * contributor license agreements. See the NOTICE file distributed with 48a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * this work for additional information regarding copyright ownership. 58a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * The ASF licenses this file to You under the Apache License, Version 2.0 68a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * (the "License"); you may not use this file except in compliance with 78a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * the License. You may obtain a copy of the License at 88a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * 98a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * http://www.apache.org/licenses/LICENSE-2.0 108a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * 118a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * Unless required by applicable law or agreed to in writing, software 128a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * distributed under the License is distributed on an "AS IS" BASIS, 138a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 148a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * See the License for the specific language governing permissions and 158a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * limitations under the License. 168a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak */ 178a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak 188a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniakpackage android.util.jar; 198a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak 208a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniakimport java.io.IOException; 218a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniakimport java.io.InputStream; 228a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniakimport java.io.OutputStream; 238a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniakimport java.nio.ByteBuffer; 248a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniakimport java.nio.CharBuffer; 258a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniakimport java.nio.charset.CharsetEncoder; 268a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniakimport java.nio.charset.CoderResult; 278a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniakimport java.nio.charset.StandardCharsets; 288a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniakimport java.util.HashMap; 298a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniakimport java.util.Iterator; 308a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniakimport java.util.Map; 318a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniakimport java.util.jar.Attributes; 328a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniakimport libcore.io.Streams; 338a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak 348a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak/** 358a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * The {@code StrictJarManifest} class is used to obtain attribute information for a 368a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * {@code StrictJarFile} and its entries. 378a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * 388a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * @hide 398a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak */ 408a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniakpublic class StrictJarManifest implements Cloneable { 418a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak static final int LINE_LENGTH_LIMIT = 72; 428a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak 438a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak private static final byte[] LINE_SEPARATOR = new byte[] { '\r', '\n' }; 448a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak 458a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak private static final byte[] VALUE_SEPARATOR = new byte[] { ':', ' ' }; 468a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak 478a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak private final Attributes mainAttributes; 488a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak private final HashMap<String, Attributes> entries; 498a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak 508a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak static final class Chunk { 518a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak final int start; 528a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak final int end; 538a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak 548a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak Chunk(int start, int end) { 558a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak this.start = start; 568a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak this.end = end; 578a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak } 588a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak } 598a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak 608a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak private HashMap<String, Chunk> chunks; 618a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak 628a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak /** 638a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * The end of the main attributes section in the manifest is needed in 648a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * verification. 658a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak */ 668a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak private int mainEnd; 678a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak 688a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak /** 698a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * Creates a new {@code StrictJarManifest} instance. 708a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak */ 718a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak public StrictJarManifest() { 728a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak entries = new HashMap<String, Attributes>(); 738a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak mainAttributes = new Attributes(); 748a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak } 758a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak 768a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak /** 778a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * Creates a new {@code StrictJarManifest} instance using the attributes obtained 788a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * from the input stream. 798a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * 808a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * @param is 818a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * {@code InputStream} to parse for attributes. 828a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * @throws IOException 838a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * if an IO error occurs while creating this {@code StrictJarManifest} 848a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak */ 858a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak public StrictJarManifest(InputStream is) throws IOException { 868a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak this(); 878a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak read(Streams.readFully(is)); 888a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak } 898a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak 908a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak /** 918a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * Creates a new {@code StrictJarManifest} instance. The new instance will have the 928a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * same attributes as those found in the parameter {@code StrictJarManifest}. 938a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * 948a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * @param man 958a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * {@code StrictJarManifest} instance to obtain attributes from. 968a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak */ 978a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak @SuppressWarnings("unchecked") 988a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak public StrictJarManifest(StrictJarManifest man) { 998a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak mainAttributes = (Attributes) man.mainAttributes.clone(); 1008a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak entries = (HashMap<String, Attributes>) ((HashMap<String, Attributes>) man 1018a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak .getEntries()).clone(); 1028a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak } 1038a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak 1048a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak StrictJarManifest(byte[] manifestBytes, boolean readChunks) throws IOException { 1058a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak this(); 1068a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak if (readChunks) { 1078a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak chunks = new HashMap<String, Chunk>(); 1088a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak } 1098a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak read(manifestBytes); 1108a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak } 1118a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak 1128a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak /** 1138a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * Resets the both the main attributes as well as the entry attributes 1148a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * associated with this {@code StrictJarManifest}. 1158a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak */ 1168a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak public void clear() { 1178a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak entries.clear(); 1188a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak mainAttributes.clear(); 1198a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak } 1208a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak 1218a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak /** 1228a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * Returns the {@code Attributes} associated with the parameter entry 1238a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * {@code name}. 1248a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * 1258a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * @param name 1268a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * the name of the entry to obtain {@code Attributes} from. 1278a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * @return the Attributes for the entry or {@code null} if the entry does 1288a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * not exist. 1298a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak */ 1308a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak public Attributes getAttributes(String name) { 1318a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak return getEntries().get(name); 1328a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak } 1338a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak 1348a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak /** 1358a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * Returns a map containing the {@code Attributes} for each entry in the 1368a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * {@code StrictJarManifest}. 1378a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * 1388a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * @return the map of entry attributes. 1398a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak */ 1408a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak public Map<String, Attributes> getEntries() { 1418a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak return entries; 1428a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak } 1438a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak 1448a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak /** 1458a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * Returns the main {@code Attributes} of the {@code JarFile}. 1468a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * 1478a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * @return main {@code Attributes} associated with the source {@code 1488a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * JarFile}. 1498a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak */ 1508a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak public Attributes getMainAttributes() { 1518a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak return mainAttributes; 1528a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak } 1538a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak 1548a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak /** 1558a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * Creates a copy of this {@code StrictJarManifest}. The returned {@code StrictJarManifest} 1568a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * will equal the {@code StrictJarManifest} from which it was cloned. 1578a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * 1588a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * @return a copy of this instance. 1598a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak */ 1608a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak @Override 1618a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak public Object clone() { 1628a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak return new StrictJarManifest(this); 1638a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak } 1648a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak 1658a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak /** 1668a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * Writes this {@code StrictJarManifest}'s name/attributes pairs to the given {@code OutputStream}. 1678a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * The {@code MANIFEST_VERSION} or {@code SIGNATURE_VERSION} attribute must be set before 1688a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * calling this method, or no attributes will be written. 1698a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * 1708a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * @throws IOException 1718a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * If an error occurs writing the {@code StrictJarManifest}. 1728a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak */ 1738a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak public void write(OutputStream os) throws IOException { 1748a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak write(this, os); 1758a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak } 1768a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak 1778a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak /** 1788a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * Merges name/attribute pairs read from the input stream {@code is} into this manifest. 1798a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * 1808a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * @param is 1818a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * The {@code InputStream} to read from. 1828a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * @throws IOException 1838a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * If an error occurs reading the manifest. 1848a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak */ 1858a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak public void read(InputStream is) throws IOException { 1868a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak read(Streams.readFullyNoClose(is)); 1878a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak } 1888a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak 1898a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak private void read(byte[] buf) throws IOException { 1908a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak if (buf.length == 0) { 1918a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak return; 1928a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak } 1938a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak 1948a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak StrictJarManifestReader im = new StrictJarManifestReader(buf, mainAttributes); 1958a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak mainEnd = im.getEndOfMainSection(); 1968a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak im.readEntries(entries, chunks); 1978a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak } 1988a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak 1998a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak /** 2008a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * Returns the hash code for this instance. 2018a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * 2028a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * @return this {@code StrictJarManifest}'s hashCode. 2038a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak */ 2048a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak @Override 2058a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak public int hashCode() { 2068a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak return mainAttributes.hashCode() ^ getEntries().hashCode(); 2078a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak } 2088a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak 2098a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak /** 2108a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * Determines if the receiver is equal to the parameter object. Two {@code 2118a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * StrictJarManifest}s are equal if they have identical main attributes as well as 2128a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * identical entry attributes. 2138a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * 2148a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * @param o 2158a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * the object to compare against. 2168a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * @return {@code true} if the manifests are equal, {@code false} otherwise 2178a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak */ 2188a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak @Override 2198a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak public boolean equals(Object o) { 2208a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak if (o == null) { 2218a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak return false; 2228a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak } 2238a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak if (o.getClass() != this.getClass()) { 2248a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak return false; 2258a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak } 2268a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak if (!mainAttributes.equals(((StrictJarManifest) o).mainAttributes)) { 2278a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak return false; 2288a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak } 2298a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak return getEntries().equals(((StrictJarManifest) o).getEntries()); 2308a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak } 2318a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak 2328a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak Chunk getChunk(String name) { 2338a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak return chunks.get(name); 2348a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak } 2358a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak 2368a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak void removeChunks() { 2378a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak chunks = null; 2388a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak } 2398a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak 2408a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak int getMainAttributesEnd() { 2418a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak return mainEnd; 2428a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak } 2438a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak 2448a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak /** 2458a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * Writes out the attribute information of the specified manifest to the 2468a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * specified {@code OutputStream} 2478a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * 2488a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * @param manifest 2498a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * the manifest to write out. 2508a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * @param out 2518a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * The {@code OutputStream} to write to. 2528a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * @throws IOException 2538a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak * If an error occurs writing the {@code StrictJarManifest}. 2548a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak */ 2558a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak static void write(StrictJarManifest manifest, OutputStream out) throws IOException { 2568a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak CharsetEncoder encoder = StandardCharsets.UTF_8.newEncoder(); 2578a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak ByteBuffer buffer = ByteBuffer.allocate(LINE_LENGTH_LIMIT); 2588a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak 2598a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak Attributes.Name versionName = Attributes.Name.MANIFEST_VERSION; 2608a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak String version = manifest.mainAttributes.getValue(versionName); 2618a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak if (version == null) { 2628a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak versionName = Attributes.Name.SIGNATURE_VERSION; 2638a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak version = manifest.mainAttributes.getValue(versionName); 2648a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak } 2658a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak if (version != null) { 2668a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak writeEntry(out, versionName, version, encoder, buffer); 2678a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak Iterator<?> entries = manifest.mainAttributes.keySet().iterator(); 2688a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak while (entries.hasNext()) { 2698a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak Attributes.Name name = (Attributes.Name) entries.next(); 2708a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak if (!name.equals(versionName)) { 2718a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak writeEntry(out, name, manifest.mainAttributes.getValue(name), encoder, buffer); 2728a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak } 2738a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak } 2748a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak } 2758a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak out.write(LINE_SEPARATOR); 2768a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak Iterator<String> i = manifest.getEntries().keySet().iterator(); 2778a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak while (i.hasNext()) { 2788a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak String key = i.next(); 2798a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak writeEntry(out, Attributes.Name.NAME, key, encoder, buffer); 2808a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak Attributes attributes = manifest.entries.get(key); 2818a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak Iterator<?> entries = attributes.keySet().iterator(); 2828a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak while (entries.hasNext()) { 2838a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak Attributes.Name name = (Attributes.Name) entries.next(); 2848a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak writeEntry(out, name, attributes.getValue(name), encoder, buffer); 2858a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak } 2868a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak out.write(LINE_SEPARATOR); 2878a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak } 2888a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak } 2898a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak 2908a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak private static void writeEntry(OutputStream os, Attributes.Name name, 2918a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak String value, CharsetEncoder encoder, ByteBuffer bBuf) throws IOException { 2928a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak String nameString = name.toString(); 2938a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak os.write(nameString.getBytes(StandardCharsets.US_ASCII)); 2948a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak os.write(VALUE_SEPARATOR); 2958a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak 2968a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak encoder.reset(); 2978a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak bBuf.clear().limit(LINE_LENGTH_LIMIT - nameString.length() - 2); 2988a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak 2998a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak CharBuffer cBuf = CharBuffer.wrap(value); 3008a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak 3018a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak while (true) { 3028a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak CoderResult r = encoder.encode(cBuf, bBuf, true); 3038a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak if (CoderResult.UNDERFLOW == r) { 3048a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak r = encoder.flush(bBuf); 3058a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak } 3068a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak os.write(bBuf.array(), bBuf.arrayOffset(), bBuf.position()); 3078a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak os.write(LINE_SEPARATOR); 3088a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak if (CoderResult.UNDERFLOW == r) { 3098a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak break; 3108a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak } 3118a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak os.write(' '); 3128a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak bBuf.clear().limit(LINE_LENGTH_LIMIT - 1); 3138a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak } 3148a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak } 3158a7c1606d88873c5a1b5764c16cb046b6f2275b2Przemyslaw Szczepaniak} 316