blob: 322aca3efeebcb7976da8ec198310ff9f72fda82 [file] [log] [blame]
// 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 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_;
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_