| // Copyright 2016 The Bazel Authors. All rights reserved. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #ifndef SRC_TOOLS_SINGLEJAR_COMBINED_JAR_H_ |
| #define SRC_TOOLS_SINGLEJAR_COMBINED_JAR_H_ |
| |
| #include <stdio.h> |
| |
| #include <cinttypes> |
| #include <cstddef> |
| #include <memory> |
| #include <string> |
| #include <unordered_map> |
| #include <vector> |
| |
| // Must be included before <io.h> (on Windows) and <fcntl.h>. |
| #include "src/tools/singlejar/port.h" |
| // Need newline so clang-format won't alpha-sort with other headers. |
| |
| #include "src/tools/singlejar/combiners.h" |
| #include "src/tools/singlejar/options.h" |
| |
| /* |
| * Jar file we are writing. |
| */ |
| class OutputJar { |
| public: |
| // Constructor. |
| OutputJar(); |
| // Do all that needs to be done. Can be called only once. |
| int Doit(Options *options); |
| // Destructor. |
| virtual ~OutputJar(); |
| // Add a combiner to handle the entries with given name. OutputJar will |
| // own the instance of the combiner and will delete it on self destruction. |
| void ExtraCombiner(const std::string& entry_name, Combiner *combiner); |
| // Additional file handler to be redefined by a subclass. |
| virtual void ExtraHandler(const std::string &input_jar_path, const CDH *entry, |
| const std::string *input_jar_aux_label); |
| // Return jar path. |
| const char *path() const { return options_->output_jar.c_str(); } |
| // True if an entry with given name have not been added to this archive. |
| bool NewEntry(const std::string& entry_name) { |
| return known_members_.count(entry_name) == 0; |
| } |
| |
| protected: |
| // The purpose of these two tiny utility methods is to avoid creating a |
| // std::string instance (which always involves allocating an object on the |
| // heap) when we just need to check that a sequence of bytes in memory has |
| // given prefix or suffix. |
| static bool begins_with(const char *str, size_t n, const char *head) { |
| const size_t n_head = strlen(head); |
| return n >= n_head && !strncmp(str, head, n_head); |
| } |
| static bool ends_with(const char *str, size_t n, const char *tail) { |
| const size_t n_tail = strlen(tail); |
| return n >= n_tail && !strncmp(str + n - n_tail, tail, n_tail); |
| } |
| |
| private: |
| // Open output jar. |
| bool Open(); |
| // Add the contents of the given input jar. |
| bool AddJar(int jar_path_index); |
| // Returns the current output position. |
| off64_t Position(); |
| // Write Jar entry. |
| void WriteEntry(void *local_header_and_payload); |
| // Write META_INF/ entry (the first entry on output). |
| void WriteMetaInf(); |
| // Write a directory entry. |
| void WriteDirEntry(const std::string &name, const uint8_t *extra_fields, |
| const uint16_t n_extra_fields); |
| // Create output Central Directory Header for the given input entry and |
| // append it to CEN (Central Directory) buffer. |
| void AppendToDirectoryBuffer(const CDH *cdh, off64_t lh_pos, |
| uint16_t normalized_time, bool fix_timestamp); |
| // Reserve space in CEN buffer. |
| uint8_t *ReserveCdr(size_t chunk_size); |
| // Reserve space for the Central Directory Header in CEN buffer. |
| uint8_t *ReserveCdh(size_t size); |
| // Close output. |
| bool Close(); |
| // Set classpath resource with given resource name and path. |
| void ClasspathResource(const std::string& resource_name, |
| const std::string& resource_path); |
| // Append CDS archive file. |
| void AppendCDSArchive(const std::string &cds_archive); |
| // Append file starting at page boundary. |
| off64_t PageAlignedAppendFile(const std::string &file_path); |
| // Append data from the file specified by file_path. |
| void AppendFile(Options *options, const char *const file_path); |
| // Copy 'count' bytes starting at 'offset' from the given file. |
| ssize_t CopyAppendData(int in_fd, off64_t offset, size_t count); |
| // Write bytes to the output file, return true on success. |
| bool WriteBytes(const void *buffer, size_t count); |
| |
| |
| Options *options_; |
| struct EntryInfo { |
| EntryInfo(Combiner *combiner, int index = -1) |
| : combiner_(combiner), input_jar_index_(index) {} |
| Combiner *combiner_; |
| int input_jar_index_; // Input jar index for the plain entry or -1. |
| }; |
| |
| std::unordered_map<std::string, struct EntryInfo> known_members_; |
| FILE *file_; |
| off64_t outpos_; |
| std::unique_ptr<char[]> buffer_; |
| int entries_; |
| int duplicate_entries_; |
| uint8_t *cen_; |
| size_t cen_size_; |
| size_t cen_capacity_; |
| Concatenator spring_handlers_; |
| Concatenator spring_schemas_; |
| Concatenator protobuf_meta_handler_; |
| ManifestCombiner manifest_; |
| PropertyCombiner build_properties_; |
| NullCombiner null_combiner_; |
| std::vector<std::unique_ptr<Concatenator> > service_handlers_; |
| std::vector<std::unique_ptr<Concatenator> > classpath_resources_; |
| std::vector<std::unique_ptr<Combiner> > extra_combiners_; |
| }; |
| |
| #endif // SRC_TOOLS_SINGLEJAR_COMBINED_JAR_H_ |