aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/tools/singlejar/combiners.h
blob: 98c2df47c5c6c09a125106365e3e66fa1d79e440 (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
134
135
136
// 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_COMBINERS_H_
#define SRC_TOOLS_SINGLEJAR_COMBINERS_H_ 1

#include <memory>
#include <string>

#include "src/tools/singlejar/transient_bytes.h"
#include "src/tools/singlejar/zip_headers.h"

// An interface for combining the files.
class Combiner {
 public:
  virtual ~Combiner();
  // Merges the contents of the given Zip entry to this instance.
  virtual bool Merge(const CDH *cdh, const LH *lh) = 0;
  // Returns a point to the buffer containing Local Header followed by the
  // payload. The caller is responsible of freeing the buffer. If `compress'
  // is not set, the payload is a copy of the bytes held by this combiner.
  // Otherwise the payload is compressed, provided that the compressed data
  // is smaller than the original.
  virtual void *OutputEntry(bool compress) = 0;
};

// An output jar entry consisting of a concatenation of the input jar
// entries. Byte sequences can be appended to it, too.
class Concatenator : public Combiner {
 public:
  Concatenator(const std::string &filename, bool insert_newlines = true)
      : filename_(filename), insert_newlines_(insert_newlines) {}

  ~Concatenator() override;

  bool Merge(const CDH *cdh, const LH *lh) override;

  void *OutputEntry(bool compress) override;

  void Append(const char *s, size_t n) {
    CreateBuffer();
    buffer_->Append(reinterpret_cast<const uint8_t *>(s), n);
  }

  void Append(const char *s) { Append(s, strlen(s)); }

  void Append(const std::string &str) { Append(str.c_str(), str.size()); }

  const std::string &filename() const { return filename_; }

 private:
  void CreateBuffer() {
    if (!buffer_.get()) {
      buffer_.reset(new TransientBytes());
    }
  }
  const std::string filename_;
  std::unique_ptr<TransientBytes> buffer_;
  std::unique_ptr<Inflater> inflater_;
  bool insert_newlines_;
};

// The combiner that does nothing. Useful to represent for instance directory
// entries: once a directory entry has been created and added to the output
// jar, the subsequent entries are ignored on input, and nothing is output.
class NullCombiner : public Combiner {
 public:
  ~NullCombiner() override;
  bool Merge(const CDH *cdh, const LH *lh) override;
  void *OutputEntry(bool compress) override;
};

// Combines the contents of the multiple input entries which are XML
// files into a single XML output entry with given top level XML tag.
class XmlCombiner : public Combiner {
 public:
  XmlCombiner(const std::string &filename, const std::string &xml_tag)
      : filename_(filename),
        start_tag_("<" + xml_tag + ">"),
        end_tag_("</" + xml_tag + ">") {}
  ~XmlCombiner() override;

  bool Merge(const CDH *cdh, const LH *lh) override;

  void *OutputEntry(bool compress) override;

  const std::string filename() const { return filename_; }

 private:
  const std::string filename_;
  const std::string start_tag_;
  const std::string end_tag_;
  std::unique_ptr<Concatenator> concatenator_;
  std::unique_ptr<Inflater> inflater_;
};

// A wrapper around Concatenator allowing to append
//   NAME=VALUE
// lines to the contents.
// NOTE that it does not allow merging existing entries.
class PropertyCombiner : public Concatenator {
 public:
  PropertyCombiner(const std::string &filename) : Concatenator(filename) {}
  ~PropertyCombiner();

  bool Merge(const CDH *cdh, const LH *lh) override;

  void AddProperty(const char *key, const char *value) {
    // TODO(asmundak): deduplicate properties.
    Append(key);
    Append("=", 1);
    Append(value);
    Append("\n", 1);
  }

  void AddProperty(const std::string &key, const std::string &value) {
    // TODO(asmundak): deduplicate properties.
    Append(key);
    Append("=", 1);
    Append(value);
    Append("\n", 1);
  }
};

#endif  //  SRC_TOOLS_SINGLEJAR_COMBINERS_H_