aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/tools/singlejar/output_jar.h
blob: c3b0ec5a53be477e6eb672c7be9821950c319f0a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
// 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 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);
  // Copy 'count' bytes starting at 'offset' from the given file.
  ssize_t AppendFile(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_