blob: e1ee50c2db0db1dae1a3bfccd7ad26eec52e167b [file] [edit]
// 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 <cstddef>
#include <cstdint>
#include <memory>
#include <string>
#include <string_view>
#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/log4j2_plugin_dat_combiner.h"
#include "src/tools/singlejar/options.h"
#include "absl/container/flat_hash_map.h"
#include "re2/re2.h"
/*
* Jar file we are writing.
*/
class OutputJar {
public:
// Constructor.
explicit OutputJar(Options* options);
// Do all that needs to be done. Can be called only once.
int Doit();
// 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(std::string_view entry_name) {
return known_members_.count(entry_name) == 0;
}
bool IncludeEntry(std::string_view file_name);
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(std::string_view 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.
// Be sure to call this: Some users of OutputJar avoid calling the destructor.
// (They do that as a performance optimization.)
bool Close();
// Set classpath resource with given resource name and path.
void ClasspathResource(const std::string& resource_name,
const std::string& resource_path);
// Append file starting at page boundary.
off64_t PageAlignedAppendFile(const std::string& file_path,
size_t* file_size);
void AppendPageAlignedFile(const std::string& file,
const std::string& offset_manifest_attr_name,
const std::string& size_manifest_attr_name,
const std::string& property_name);
// Append data from the file specified by file_path.
size_t AppendFile(Options* options, const char* file_path);
// Copy 'count' bytes starting at the beginning of the given file.
ssize_t CopyAppendData(int in_fd, size_t count);
// Write bytes to the output file, return true on success.
bool WriteBytes(const void* buffer, size_t count);
// Write to the output file without updating outpos_.
size_t WriteNoLock(const void* buffer, size_t count);
// Try to expand the file to be at least large enough for the upcoming write.
void EnsureCapacity(size_t to_write);
Options* options_;
bool done_;
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.
};
absl::flat_hash_map<std::string, struct EntryInfo> known_members_;
int fd_;
FILE* file_;
off64_t outpos_;
std::unique_ptr<char[]> buffer_;
int entries_;
int duplicate_entries_;
size_t fallocated_;
bool fallocate_failed_;
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_;
Log4J2PluginDatCombiner log4j2_plugin_dat_combiner_;
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_;
std::unique_ptr<RE2> exclude_pattern_;
};
#endif // SRC_TOOLS_SINGLEJAR_COMBINED_JAR_H_