| // 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 <memory> | |
| #include <string> | |
| #include <unordered_map> | |
| #include <vector> | |
| #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 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. | |
| off_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, off_t local_header_offset, | |
| 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); | |
| // Copy 'count' bytes starting at 'offset' from the given file. | |
| ssize_t AppendFile(int in_fd, off_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_; | |
| off_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_; | |
| Concatenator 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_ |