squash_java 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE.txt ADDED
@@ -0,0 +1,202 @@
1
+
2
+ Apache License
3
+ Version 2.0, January 2004
4
+ http://www.apache.org/licenses/
5
+
6
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7
+
8
+ 1. Definitions.
9
+
10
+ "License" shall mean the terms and conditions for use, reproduction,
11
+ and distribution as defined by Sections 1 through 9 of this document.
12
+
13
+ "Licensor" shall mean the copyright owner or entity authorized by
14
+ the copyright owner that is granting the License.
15
+
16
+ "Legal Entity" shall mean the union of the acting entity and all
17
+ other entities that control, are controlled by, or are under common
18
+ control with that entity. For the purposes of this definition,
19
+ "control" means (i) the power, direct or indirect, to cause the
20
+ direction or management of such entity, whether by contract or
21
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
22
+ outstanding shares, or (iii) beneficial ownership of such entity.
23
+
24
+ "You" (or "Your") shall mean an individual or Legal Entity
25
+ exercising permissions granted by this License.
26
+
27
+ "Source" form shall mean the preferred form for making modifications,
28
+ including but not limited to software source code, documentation
29
+ source, and configuration files.
30
+
31
+ "Object" form shall mean any form resulting from mechanical
32
+ transformation or translation of a Source form, including but
33
+ not limited to compiled object code, generated documentation,
34
+ and conversions to other media types.
35
+
36
+ "Work" shall mean the work of authorship, whether in Source or
37
+ Object form, made available under the License, as indicated by a
38
+ copyright notice that is included in or attached to the work
39
+ (an example is provided in the Appendix below).
40
+
41
+ "Derivative Works" shall mean any work, whether in Source or Object
42
+ form, that is based on (or derived from) the Work and for which the
43
+ editorial revisions, annotations, elaborations, or other modifications
44
+ represent, as a whole, an original work of authorship. For the purposes
45
+ of this License, Derivative Works shall not include works that remain
46
+ separable from, or merely link (or bind by name) to the interfaces of,
47
+ the Work and Derivative Works thereof.
48
+
49
+ "Contribution" shall mean any work of authorship, including
50
+ the original version of the Work and any modifications or additions
51
+ to that Work or Derivative Works thereof, that is intentionally
52
+ submitted to Licensor for inclusion in the Work by the copyright owner
53
+ or by an individual or Legal Entity authorized to submit on behalf of
54
+ the copyright owner. For the purposes of this definition, "submitted"
55
+ means any form of electronic, verbal, or written communication sent
56
+ to the Licensor or its representatives, including but not limited to
57
+ communication on electronic mailing lists, source code control systems,
58
+ and issue tracking systems that are managed by, or on behalf of, the
59
+ Licensor for the purpose of discussing and improving the Work, but
60
+ excluding communication that is conspicuously marked or otherwise
61
+ designated in writing by the copyright owner as "Not a Contribution."
62
+
63
+ "Contributor" shall mean Licensor and any individual or Legal Entity
64
+ on behalf of whom a Contribution has been received by Licensor and
65
+ subsequently incorporated within the Work.
66
+
67
+ 2. Grant of Copyright License. Subject to the terms and conditions of
68
+ this License, each Contributor hereby grants to You a perpetual,
69
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70
+ copyright license to reproduce, prepare Derivative Works of,
71
+ publicly display, publicly perform, sublicense, and distribute the
72
+ Work and such Derivative Works in Source or Object form.
73
+
74
+ 3. Grant of Patent License. Subject to the terms and conditions of
75
+ this License, each Contributor hereby grants to You a perpetual,
76
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77
+ (except as stated in this section) patent license to make, have made,
78
+ use, offer to sell, sell, import, and otherwise transfer the Work,
79
+ where such license applies only to those patent claims licensable
80
+ by such Contributor that are necessarily infringed by their
81
+ Contribution(s) alone or by combination of their Contribution(s)
82
+ with the Work to which such Contribution(s) was submitted. If You
83
+ institute patent litigation against any entity (including a
84
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
85
+ or a Contribution incorporated within the Work constitutes direct
86
+ or contributory patent infringement, then any patent licenses
87
+ granted to You under this License for that Work shall terminate
88
+ as of the date such litigation is filed.
89
+
90
+ 4. Redistribution. You may reproduce and distribute copies of the
91
+ Work or Derivative Works thereof in any medium, with or without
92
+ modifications, and in Source or Object form, provided that You
93
+ meet the following conditions:
94
+
95
+ (a) You must give any other recipients of the Work or
96
+ Derivative Works a copy of this License; and
97
+
98
+ (b) You must cause any modified files to carry prominent notices
99
+ stating that You changed the files; and
100
+
101
+ (c) You must retain, in the Source form of any Derivative Works
102
+ that You distribute, all copyright, patent, trademark, and
103
+ attribution notices from the Source form of the Work,
104
+ excluding those notices that do not pertain to any part of
105
+ the Derivative Works; and
106
+
107
+ (d) If the Work includes a "NOTICE" text file as part of its
108
+ distribution, then any Derivative Works that You distribute must
109
+ include a readable copy of the attribution notices contained
110
+ within such NOTICE file, excluding those notices that do not
111
+ pertain to any part of the Derivative Works, in at least one
112
+ of the following places: within a NOTICE text file distributed
113
+ as part of the Derivative Works; within the Source form or
114
+ documentation, if provided along with the Derivative Works; or,
115
+ within a display generated by the Derivative Works, if and
116
+ wherever such third-party notices normally appear. The contents
117
+ of the NOTICE file are for informational purposes only and
118
+ do not modify the License. You may add Your own attribution
119
+ notices within Derivative Works that You distribute, alongside
120
+ or as an addendum to the NOTICE text from the Work, provided
121
+ that such additional attribution notices cannot be construed
122
+ as modifying the License.
123
+
124
+ You may add Your own copyright statement to Your modifications and
125
+ may provide additional or different license terms and conditions
126
+ for use, reproduction, or distribution of Your modifications, or
127
+ for any such Derivative Works as a whole, provided Your use,
128
+ reproduction, and distribution of the Work otherwise complies with
129
+ the conditions stated in this License.
130
+
131
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
132
+ any Contribution intentionally submitted for inclusion in the Work
133
+ by You to the Licensor shall be under the terms and conditions of
134
+ this License, without any additional terms or conditions.
135
+ Notwithstanding the above, nothing herein shall supersede or modify
136
+ the terms of any separate license agreement you may have executed
137
+ with Licensor regarding such Contributions.
138
+
139
+ 6. Trademarks. This License does not grant permission to use the trade
140
+ names, trademarks, service marks, or product names of the Licensor,
141
+ except as required for reasonable and customary use in describing the
142
+ origin of the Work and reproducing the content of the NOTICE file.
143
+
144
+ 7. Disclaimer of Warranty. Unless required by applicable law or
145
+ agreed to in writing, Licensor provides the Work (and each
146
+ Contributor provides its Contributions) on an "AS IS" BASIS,
147
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148
+ implied, including, without limitation, any warranties or conditions
149
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150
+ PARTICULAR PURPOSE. You are solely responsible for determining the
151
+ appropriateness of using or redistributing the Work and assume any
152
+ risks associated with Your exercise of permissions under this License.
153
+
154
+ 8. Limitation of Liability. In no event and under no legal theory,
155
+ whether in tort (including negligence), contract, or otherwise,
156
+ unless required by applicable law (such as deliberate and grossly
157
+ negligent acts) or agreed to in writing, shall any Contributor be
158
+ liable to You for damages, including any direct, indirect, special,
159
+ incidental, or consequential damages of any character arising as a
160
+ result of this License or out of the use or inability to use the
161
+ Work (including but not limited to damages for loss of goodwill,
162
+ work stoppage, computer failure or malfunction, or any and all
163
+ other commercial damages or losses), even if such Contributor
164
+ has been advised of the possibility of such damages.
165
+
166
+ 9. Accepting Warranty or Additional Liability. While redistributing
167
+ the Work or Derivative Works thereof, You may choose to offer,
168
+ and charge a fee for, acceptance of support, warranty, indemnity,
169
+ or other liability obligations and/or rights consistent with this
170
+ License. However, in accepting such obligations, You may act only
171
+ on Your own behalf and on Your sole responsibility, not on behalf
172
+ of any other Contributor, and only if You agree to indemnify,
173
+ defend, and hold each Contributor harmless for any liability
174
+ incurred by, or claims asserted against, such Contributor by reason
175
+ of your accepting any such warranty or additional liability.
176
+
177
+ END OF TERMS AND CONDITIONS
178
+
179
+ APPENDIX: How to apply the Apache License to your work.
180
+
181
+ To apply the Apache License to your work, attach the following
182
+ boilerplate notice, with the fields enclosed by brackets "[]"
183
+ replaced with your own identifying information. (Don't include
184
+ the brackets!) The text should be enclosed in the appropriate
185
+ comment syntax for the file format. We also recommend that a
186
+ file or class name and description of purpose be included on the
187
+ same "printed page" as the copyright notice for easier
188
+ identification within third-party archives.
189
+
190
+ Copyright [yyyy] [name of copyright owner]
191
+
192
+ Licensed under the Apache License, Version 2.0 (the "License");
193
+ you may not use this file except in compliance with the License.
194
+ You may obtain a copy of the License at
195
+
196
+ http://www.apache.org/licenses/LICENSE-2.0
197
+
198
+ Unless required by applicable law or agreed to in writing, software
199
+ distributed under the License is distributed on an "AS IS" BASIS,
200
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201
+ See the License for the specific language governing permissions and
202
+ limitations under the License.
data/README.md ADDED
@@ -0,0 +1,98 @@
1
+ Squash Java Deobfuscation Library
2
+ =================================
3
+
4
+ This gem serves three purposes:
5
+
6
+ * to upload yGuard obfuscation data to Squash,
7
+ * to map class names to their file paths, and upload that data to Squash, and
8
+ * to notify Squash of new releases of Java software (internally or externally).
9
+
10
+ This gem installs a `deobfuscate` binary that converts a renamelog.xml file into
11
+ a format usable for Squash, locates the files in which classes are defined, and
12
+ then uploads that data to the Squash host. It also installs a `squash_release`
13
+ binary that notifies Squash of the release.
14
+
15
+ Documentation
16
+ -------------
17
+
18
+ Comprehensive documentation is written in YARD- and Markdown-formatted comments
19
+ throughout the source. To view this documentation as an HTML site, run
20
+ `rake doc`.
21
+
22
+ For an overview of the various components of Squash, see the website
23
+ documentation at https://github.com/SquareSquash/web.
24
+
25
+ Compatibility
26
+ -------------
27
+
28
+ This library is compatible with Ruby 1.8.6 and later, including Ruby Enterprise
29
+ Edition.
30
+
31
+ Requirements
32
+ ------------
33
+
34
+ This gem requires the `json` gem (http://rubygems.org/gems/json). You can use
35
+ any JSON gem that conforms to the typical standard
36
+ (`require 'json'; object.to_json`).
37
+
38
+ Usage
39
+ -----
40
+
41
+ ### Uploading Obfuscation and Class Path Data
42
+
43
+ This gem installs a command-line binary named `deobfuscate`. It is called in the
44
+ following format:
45
+
46
+ ````
47
+ deobfuscate [options] <API key> <environment> <build number> <renamelog file>
48
+ ````
49
+
50
+ Example: `deobfuscate --no-ssl-verification a9232f94-6c2d-45ae-8f9e-9add5bd7ff35 production 103 /path/to/renamelog.xml`
51
+
52
+ This binary is intended to be used as part of your release process. It will
53
+ first parse the renamelog file and generate an internal representation of your
54
+ program's namespace, along with all obfuscated aliases. Then it will attempt to
55
+ map class names to the files in which the classes are defined. In order for this
56
+ to work, your classes should be organized in folder structures according to
57
+ their package names. For example, the source of the class `com.foo.bar.Baz`
58
+ should be found in a "com/foo/bar/Baz.java" file path somewhere in your project.
59
+
60
+ By default this program assumes it's being run from the project root, but you
61
+ can also specify the root with the `--project-dir` switch. For documentation on
62
+ `deobfuscate`'s command-line options, run `deobfuscate --help.`
63
+
64
+ ### Release Notification
65
+
66
+ This gem installs a command-line binary named `squash_release`. It is called in
67
+ the following format:
68
+
69
+ ````
70
+ squash_release [options] <API key> <environment> <build number>
71
+ ````
72
+
73
+ Example: `squash_release a9232f94-6c2d-45ae-8f9e-9add5bd7ff35 production 103 `
74
+
75
+ This binary is intended to be used as part of your release process, similar to
76
+ `deobfuscate` (see above). Like `deobfuscate`, sensible defaults are provided
77
+ for all command line switches.
78
+
79
+ For documentation on `squash_release`'s command-line options, run
80
+ `squash_release --help`.
81
+
82
+ Data Transmission
83
+ -----------------
84
+
85
+ Deobfuscation and release data is transmitted to Squash using JSON-over-HTTPS. A
86
+ default API endpoint is pre-configured, though you can always set your own (see
87
+ `deobfuscate --help` or `squash_release --help`).
88
+
89
+ By default, `Net::HTTP` is used to transmit errors to the API server. If you
90
+ would prefer to use your own HTTP library, see the `squash_uploader` gem.
91
+
92
+ Use as a Library
93
+ ----------------
94
+
95
+ In addition to using the rename map with Squash, you can also use the gem as
96
+ a library, to perform deobfuscation for your own purposes (even unrelated to
97
+ Squash). See the {Squash::Java::Namespace} class documentation for more
98
+ information.
data/bin/deobfuscate ADDED
@@ -0,0 +1,74 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Copyright 2012 Square Inc.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ require 'optparse'
18
+ require 'base64'
19
+ require 'zlib'
20
+ require 'yaml'
21
+
22
+ require 'rubygems'
23
+ require 'squash/uploader'
24
+ require 'squash/java'
25
+
26
+ def git_revision(dir)
27
+ head = File.read(File.join(dir, '.git', 'HEAD')).chomp
28
+ if head =~ /^ref: (.+)$/
29
+ File.read(File.join(dir, '.git', $1)).chomp
30
+ else
31
+ raise "Couldn't determine current revision from #{head.inspect}"
32
+ end
33
+ end
34
+
35
+ project_dir = Dir.getwd
36
+ revision = nil
37
+ options = {}
38
+
39
+ parser = OptionParser.new do |parser|
40
+ parser.banner = "Usage: deobfuscate [options] YOUR_SQUASH_HOST YOUR_API_KEY ENVIRONMENT_NAME BUILD_NUMBER /path/to/renamelog_or_mapping"
41
+ parser.on('-o', '--open-timeout N', Integer, "HTTP connection open timeout") { |ot| options[:open_timeout] = ot }
42
+ parser.on('-r', '--read-timeout N', Integer, "HTTP connection data received timeout") { |rt| options[:read_timeout] = rt }
43
+ parser.on('-k', '--[no-]skip-verification', "Do not perform SSL peer verification") { |sv| options[:skip_verification] = sv }
44
+
45
+ parser.on('-p', '--project-dir F', "Specify a custom project directory (default current directory)") { |pd| project_dir = pd }
46
+ parser.on('-r', '--revision R', "Specify a code revision that was deployed (default current revision)") { |r| revision = r }
47
+
48
+ parser.on('-h', '--help', "Show this message") { puts parser; exit }
49
+ parser.on('--version', "Display version number of this program") { puts "1.0.0"; exit }
50
+ end
51
+ parser.parse!(ARGV)
52
+
53
+ if ARGV.size != 5
54
+ puts parser
55
+ exit 1
56
+ end
57
+
58
+ host = ARGV.shift
59
+ api_key = ARGV.shift
60
+ environment = ARGV.shift
61
+ build = ARGV.shift
62
+ file = ARGV.shift
63
+ revision = revision || git_revision(project_dir)
64
+
65
+ namespace = Squash::Java::RenameLog.new(file).parse
66
+ namespace.find_files project_dir
67
+
68
+ Squash::Uploader.new(host, options).transmit '/api/1.0/deobfuscation.json',
69
+ {
70
+ 'api_key' => api_key,
71
+ 'environment' => environment,
72
+ 'build' => build,
73
+ 'namespace' => Base64.encode64(Zlib::Deflate.deflate(namespace.to_yaml))
74
+ }
@@ -0,0 +1,68 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Copyright 2012 Square Inc.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ require 'optparse'
18
+ require 'rubygems'
19
+ require 'squash/uploader'
20
+
21
+ def git_revision(dir)
22
+ head = File.read(File.join(dir, '.git', 'HEAD')).chomp
23
+ if head =~ /^ref: (.+)$/
24
+ File.read(File.join(dir, '.git', $1)).chomp
25
+ else
26
+ raise "Couldn't determine current revision from #{head.inspect}"
27
+ end
28
+ end
29
+
30
+ project_dir = Dir.getwd
31
+ revision = nil
32
+ options = {}
33
+
34
+ parser = OptionParser.new do |parser|
35
+ parser.banner = "Usage: squash_release [options] YOUR_SQUASH_HOST YOUR_API_KEY ENVIRONMENT BUILD_NUMBER"
36
+ parser.on('-o', '--open-timeout N', Integer, "HTTP connection open timeout") { |ot| options[:open_timeout] = ot }
37
+ parser.on('-r', '--read-timeout N', Integer, "HTTP connection data received timeout") { |rt| options[:read_timeout] = rt }
38
+ parser.on('-k', '--[no-]skip-verification', "Do not perform SSL peer verification") { |sv| options[:skip_verification] = sv }
39
+
40
+ parser.on('-p', '--project-dir F', "Specify a custom project directory (default current directory)") { |pd| project_dir = pd }
41
+ parser.on('-r', '--revision R', "Specify a code revision that was deployed (default current revision)") { |r| revision = r }
42
+
43
+ parser.on('-h', '--help', "Show this message") { puts parser; exit }
44
+ parser.on('--version', "Display version number of this program") { puts "1.0.0"; exit }
45
+ end
46
+ parser.parse!(ARGV)
47
+
48
+ if ARGV.size != 4
49
+ puts parser
50
+ exit 1
51
+ end
52
+
53
+ host = ARGV.shift
54
+ api_key = ARGV.shift
55
+ environment = ARGV.shift
56
+ build = ARGV.shift
57
+ revision = revision || git_revision(project_dir)
58
+
59
+ Squash::Uploader.new(host, options).transmit '/api/1.0/deploy.json',
60
+ {
61
+ 'project' => {'api_key' => api_key},
62
+ 'environment' => {'name' => environment},
63
+ 'deploy' => {
64
+ 'deployed_at' => Time.now,
65
+ 'revision' => revision,
66
+ 'build' => build
67
+ }
68
+ }
@@ -0,0 +1,553 @@
1
+ # Copyright 2012 Square Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require 'set'
16
+ require 'find'
17
+
18
+
19
+ # A Ruby representation of the packages, classes, methods, and fields of a
20
+ # Java project, with their full and obfuscated names. The {RenameLog} class
21
+ # loads a Namespace from a yGuard or ProGuard rename log file.
22
+ #
23
+ # **Note:** Some of the finder methods of this class and its enclosed classes
24
+ # are find-or-create-type methods. Read the method documentation for each
25
+ # method carefully.
26
+ #
27
+ # **Another note:** A distinction is made between _full_ and _partial_ names
28
+ # (e.g., "MyClass" vs. "com.mycompany.MyClass"), and _cleartext_ and
29
+ # _obfuscated_ names (e.g., "com.mycompany.MyClass" vs. "com.A.B"). Note that
30
+ # there are four possible combinations of these states. Method docs will state
31
+ # what naming format is expected for each parameter.
32
+
33
+ class Squash::Java::Namespace
34
+ # @private
35
+ METHOD_REGEX = /^([a-z0-9_.$\[\]]+) ([a-z0-9_$]+)\(([a-z$0-9_.\[\] ,]*)\)/i
36
+
37
+ # Creates a new empty Namespace.
38
+
39
+ def initialize
40
+ @package_roots = Set.new
41
+ end
42
+
43
+ # @overload find_files(root)
44
+ # Attempts to locate the paths to the {Squash::Java::Class Classes} defined
45
+ # in this Namespace. Classes must be defined in files named after the class,
46
+ # organized into folders structured after the classes' packages. For
47
+ # example, the source of the `com.foo.bar.Baz` class should be defined in a
48
+ # file located at "com/foo/bar/Baz.java", somewhere inside your project
49
+ # root. This is a "best guess" attempt and will not work every time.
50
+ #
51
+ # Once this method is complete, any Class objects under this namespace that
52
+ # were successfully matched will have their {Squash::Java::Class#path path}
53
+ # attributes set.
54
+ #
55
+ # @param [String] root The project root. All source directories must be
56
+ # under this root.
57
+
58
+ def find_files(root, package_or_class=nil)
59
+ case package_or_class
60
+ when nil
61
+ root.sub! /\/$/, ''
62
+ @package_roots.each { |pkg| find_files root, pkg }
63
+ when Squash::Java::Package
64
+ package_or_class.classes.each { |cl| find_files root, cl }
65
+ package_or_class.children.each { |pkg| find_files root, pkg }
66
+ when Squash::Java::Class
67
+ class_subpath = package_or_class.subpath
68
+ Find.find(root) do |project_path|
69
+ if project_path[0, root.length + 2] == root + '/.'
70
+ Find.prune
71
+ next
72
+ end
73
+ if project_path[-class_subpath.length, class_subpath.length] == class_subpath
74
+ package_or_class.path = project_path.sub(/^#{Regexp.escape root}\//, '')
75
+ end
76
+ end
77
+ end
78
+ end
79
+
80
+ # Returns the path to a {Squash::Java::Class Class}'s source .java file,
81
+ # relative to the project root, if a) the class exists in the namespace, and
82
+ # b) the class has a known path.
83
+ #
84
+ # @param [String] klass The full class name (parts of which can be
85
+ # obfuscated), e.g., "com.foo.A.Baz".
86
+ # @return [String, nil] The path to the class's source file, if known.
87
+ # @see #find_files
88
+
89
+ def path_for_class(klass)
90
+ cl = obfuscated_class(klass)
91
+ cl ? cl.path : nil
92
+ end
93
+
94
+ # Associates a full package name with an obfuscated name.
95
+ #
96
+ # @param [String] name The full package name (e.g., "com.foo.bar").
97
+ # @param [String] obfuscation The obfuscated name for just the last segment of
98
+ # the full name (e.g., "A").
99
+ # @return [Squash::Java::Package] The newly created package object.
100
+
101
+ def add_package_alias(name, obfuscation)
102
+ pkg = package(name)
103
+ pkg.obfuscation = obfuscation
104
+ return pkg
105
+ end
106
+
107
+ # Associates a full class name with an obfuscated name.
108
+ #
109
+ # @param [String] name The full class name (e.g., "com.foo.bar.Baz").
110
+ # @param [String] obfuscation The obfuscated name for just the last segment of
111
+ # the full name (e.g., "A").
112
+ # @return [Squash::Java::Class] The newly created class object.
113
+
114
+ def add_class_alias(name, obfuscation)
115
+ cl = klass(name)
116
+ cl.obfuscation = obfuscation
117
+ return cl
118
+ end
119
+
120
+ # Associates a method name with an obfuscated alias.
121
+ #
122
+ # @param [String, Squash::Java::Class] class_or_name A full class name (e.g.,
123
+ # "com.foo.bar.Baz"), or a class object.
124
+ # @param [String] method_name A method name, with return value and argument
125
+ # types (e.g., "com.foo.Type1 methodName(com.foo.Type2, int[])").
126
+ # @return [Squash::Java::Method] The newly created method object.
127
+
128
+ def add_method_alias(class_or_name, method_name, obfuscation)
129
+ cl = (class_or_name.kind_of?(Squash::Java::Class) ? class_or_name : klass(class_or_name))
130
+ meth = method(cl, method_name)
131
+ meth.obfuscation = obfuscation
132
+ return meth
133
+ end
134
+
135
+ # **Finds or creates** a package by its full name.
136
+ #
137
+ # @param [String] identifier A full package name (e.g., "com.foo.bar").
138
+ # @return [Squash::Java::Package] The package with that name.
139
+
140
+ def package(identifier)
141
+ parts = identifier.split('.')
142
+ root_name = parts.shift
143
+ root = @package_roots.detect { |pkg| pkg.name == root_name } || begin
144
+ pkg = Squash::Java::Package.new(root_name)
145
+ @package_roots << pkg
146
+ pkg
147
+ end
148
+ if parts.empty?
149
+ root
150
+ else
151
+ root.find_or_create(parts.join('.'))
152
+ end
153
+ end
154
+
155
+ alias klass package
156
+
157
+ # **Finds** a package by its obfuscated (or partially obfuscated) full name.
158
+ # (Technically it also works as a **find-only** variant of {#package} since
159
+ # all, some, or none of the name need be obfuscated.)
160
+ #
161
+ # @param [String] identifier An obfuscated full package name (e.g.,
162
+ # "com.foo.A").
163
+ # @return [Squash::Java::Package, nil] The package with that obfuscated name.
164
+
165
+ def obfuscated_package(identifier)
166
+ parts = identifier.split('.')
167
+ root_name = parts.shift
168
+ root = @package_roots.detect { |pkg| pkg.name == root_name }
169
+ if parts.empty?
170
+ root
171
+ else
172
+ root ? root.find_obfuscated(parts.join('.')) : nil
173
+ end
174
+ end
175
+
176
+ # **Finds** a class by its obfuscated (or partially obfuscated) full name.
177
+ # (Technically it also works as a **find-only** variant of {#klass} since all
178
+ # some, or none of the name need be obfuscated.)
179
+ #
180
+ # @param [String] identifier An obfuscated full class name (e.g.,
181
+ # "com.foo.A.B").
182
+ # @return [Squash::Java::Class, nil] The class with that obfuscated name.
183
+
184
+ def obfuscated_class(identifier)
185
+ parts = identifier.split('.')
186
+ class_name = parts.pop
187
+ pkg = obfuscated_package(parts.join('.'))
188
+ return nil unless pkg
189
+
190
+ pkg.classes.detect { |cl| cl.obfuscation == class_name || cl.name == class_name }
191
+ end
192
+
193
+ # **Finds or creates** a primitive or class type by its name.
194
+ #
195
+ # @param [String] name The type name (e.g., "int" or "FooClass").
196
+ # @return [Squash::Java::Type] The type object.
197
+
198
+ def type(name)
199
+ Squash::Java::PRIMITIVES.detect { |prim| prim.name == name } || klass(name)
200
+ end
201
+
202
+ # **Finds** a class or primitive type by its obfuscated name. Primitives are
203
+ # never obfuscated.
204
+ #
205
+ # @param [String] name The obfuscated full class name (e.g.,
206
+ # "com.squareup.A.B") or full primitive name
207
+ # @return [Squash::Java::Type, nil] The type of that name, if found.
208
+
209
+ def obfuscated_type(name)
210
+ Squash::Java::PRIMITIVES.detect { |prim| prim.name == name } || obfuscated_class(name)
211
+ end
212
+
213
+ # **Finds or creates** a method by its name and parent class. Polymorphism is
214
+ # supported: Two methods can share the same name so long as their argument
215
+ # count or types are different.
216
+ #
217
+ # @param [Squash::Java::Class] klass The class containing the method.
218
+ # @param [String] name The method name, with return type and arguments as
219
+ # full, unobfuscated types (e.g., "com.foo.Bar myMethod(com.foo.Baz, int[])".
220
+ # @return [Squash::Java::Method] The corresponding method.
221
+
222
+ def method(klass, name)
223
+ matches = name.match(METHOD_REGEX) or raise "Invalid method name #{name.inspect}"
224
+ return_type = type(matches[1])
225
+ method_name = matches[2]
226
+ args = matches[3].split(/,\s*/).map { |arg| argument(arg) }
227
+ args = [] if matches[3].empty?
228
+
229
+ klass.java_methods.detect { |meth| meth.name == method_name && meth.arguments == args } ||
230
+ Squash::Java::Method.new(klass, method_name, return_type, *args)
231
+ end
232
+
233
+ # **Finds** a method by its obfuscated name and parent class. Polymorphism is
234
+ # supported: Two methods can share the same name so long as their argument
235
+ # count or types are different.
236
+ #
237
+ # @param [Squash::Java::Class] klass The class containing the method.
238
+ # @param [String] name The obfuscated method name, with return type and
239
+ # arguments as full, obfuscated types (e.g., "com.foo.A myMethod(com.foo.B, int[])".
240
+ # @return [Squash::Java::Method, nil] The corresponding method.
241
+
242
+ def obfuscated_method(klass, name)
243
+ matches = name.match(METHOD_REGEX) or raise "Invalid method name #{name.inspect}"
244
+ return_type = obfuscated_type(matches[1])
245
+ method_name = matches[2]
246
+ args = matches[3].split(/,\s*/).map { |arg| obfuscated_argument(arg) }
247
+ args = [] if matches[3].empty?
248
+ klass.java_methods.detect { |m| m.obfuscation == method_name && m.arguments == args }
249
+ end
250
+
251
+ # Creates a new Argument for a given type descriptor. This can be a
252
+ # primitive (e.g., "float") or a full class name (e.g., "com.foo.Bar"), and
253
+ # can be a scalar or an array (e.g., "float[]" or "com.foo.Bar[]"). **Finds or
254
+ # creates** the {Squash::Java::Type Type}, and **always creates** a new
255
+ # Argument.
256
+ #
257
+ # @param [String] type_descriptor The type description.
258
+ # @return [Squash::Java::Argument] The argument object, unbound to any
259
+ # {Squash::Java::Method Method}.
260
+
261
+ def argument(type_descriptor)
262
+ array = type_descriptor[-2..-1] == '[]'
263
+ type_name = type_descriptor.sub(/\[\]$/, '')
264
+ Squash::Java::Argument.new type(type_name), array
265
+ end
266
+
267
+ # Creates a new Argument for a given type descriptor, which can be fully or
268
+ # partially obfuscated. This can be an unobfuscated primitive (e.g., "float")
269
+ # or a possibly-obfuscated full class name (e.g., "com.foo.A"), and can be a
270
+ # scalar or an array (e.g., "float[]" or "com.foo.A[]"). **Finds** the
271
+ # {Squash::Java::Type Type}, and **always creates** a new Argument. Returns
272
+ # `nil` for unknown types.
273
+ #
274
+ # @param [String] type_descriptor The type description.
275
+ # @return [Squash::Java::Argument, nil] The argument object, unbound to any
276
+ # {Squash::Java::Method Method}, or `nil` if the type is not recognized.
277
+
278
+ def obfuscated_argument(type_descriptor)
279
+ array = type_descriptor[-2..-1] == '[]'
280
+ type_name = type_descriptor.sub(/\[\]$/, '')
281
+ type = obfuscated_type(type_name)
282
+ return nil unless type
283
+ Squash::Java::Argument.new type, array
284
+ end
285
+ end
286
+
287
+ # Represents a Java package.
288
+
289
+ class Squash::Java::Package
290
+
291
+ # @return [String] The last part of the package name (e.g., "bar" for package
292
+ # "com.foo.bar").
293
+ attr_reader :name
294
+
295
+ # @return [String, nil] The obfuscated package name (e.g., "A" for
296
+ # "com.foo.A").
297
+ attr_reader :obfuscation
298
+
299
+ # Sets the method's obfuscation.
300
+ # @raise [ArgumentError] If the obfuscation is taken by another class or in
301
+ # package the same namespace.
302
+
303
+ def obfuscation=(name)
304
+ if (package = parent.children.detect { |p| p.obfuscation == name })
305
+ raise ArgumentError, "Tried to assign obfuscation #{name} to #{package.inspect} and #{inspect}"
306
+ end
307
+ @obfuscation = name
308
+ end
309
+
310
+ # @return [Squash::Java::Package] The parent package (e.g., package "com.foo"
311
+ # for "com.foo.bar").
312
+ attr_reader :parent
313
+
314
+ # @return [Array<Squash::Java::Package>] Packages nested underneath this
315
+ # package (see {#parent}).
316
+ attr_reader :children
317
+
318
+ # @return [Array<Squash::Java::Class>] Classes belonging to this package.
319
+ attr_reader :classes
320
+
321
+ # @private
322
+ def initialize(name, parent=nil)
323
+ @name = name
324
+ @parent = parent
325
+ @parent.children << self if @parent
326
+ @children = Set.new
327
+ @classes = Set.new
328
+ end
329
+
330
+ # **Finds** a package underneath this package.
331
+ #
332
+ # @param [String] identifier The package name relative to this package. If
333
+ # finding package "com.foo.bar", pass "foo.bar" to Package "com".
334
+ # @return [Squash::Java::Package, nil] The matching package, if found.
335
+
336
+ def find(identifier)
337
+ parts = identifier.split('.')
338
+ name = parts.shift
339
+ child = children.detect { |pkg| pkg.name == name }
340
+ if parts.empty?
341
+ child
342
+ else
343
+ child ? child.find(parts.join('.')) : nil
344
+ end
345
+ end
346
+
347
+ # **Finds** a package by obfuscated (or non-obfuscated) name relative to this
348
+ # package.
349
+ #
350
+ # @param [String] identifier The package name relative to this package (parts
351
+ # may be obfuscated). If finding package "com.A.B", pass "A.B" to package
352
+ # "com".
353
+ # @return [Squash::Java::Package, nil] The matching package, if found.
354
+
355
+ def find_obfuscated(identifier)
356
+ parts = identifier.split('.')
357
+ name = parts.shift
358
+ child = children.detect { |pkg| pkg.obfuscation == name || pkg.name == name }
359
+ if parts.empty?
360
+ child
361
+ else
362
+ child ? child.find_obfuscated(parts.join('.')) : nil
363
+ end
364
+ end
365
+
366
+ # **Finds or creates** A package underneath this package.
367
+ #
368
+ # @param [String] identifier The package name relative to this package. If
369
+ # finding package "com.foo.bar", pass "foo.bar" to Package "com".
370
+ # @return [Squash::Java::Package] The matching package, or the newly created
371
+ # package.
372
+
373
+ def find_or_create(identifier)
374
+ parts = identifier.split('.')
375
+ name = parts.shift
376
+
377
+ if ('A'..'Z').include? name[0, 1] # class
378
+ raise "Unexpected class midway through identifier" unless parts.empty?
379
+ classes.detect { |cl| cl.name == name } || Squash::Java::Class.new(self, name)
380
+ else # package
381
+ child = children.detect { |pkg| pkg.name == name } || Squash::Java::Package.new(name, self)
382
+ parts.empty? ? child : child.find_or_create(parts.join('.'))
383
+ end
384
+ end
385
+
386
+ # @return [String] The full name of this package (e.g., "com.foo.bar").
387
+ def full_name() parent ? "#{parent.full_name}.#{name}" : name end
388
+
389
+ # @private
390
+ def inspect() "#<#{self.class.to_s} #{full_name}>" end
391
+
392
+ # @private
393
+ def subpath() parent ? "#{parent.subpath}/#{name}" : name end
394
+ end
395
+
396
+ # Superclass describing both {Squash::Java::Primitive Primitive} types and
397
+ # {Squash::Java::Class Classes}.
398
+
399
+ class Squash::Java::Type
400
+ # @return [String] The type name.
401
+ attr_reader :name
402
+
403
+ # @return [String] The full type name. By default this is equal to {#name},
404
+ # but can be overridden.
405
+ def full_name() name end
406
+
407
+ # @private
408
+ def inspect() "#<#{self.class.to_s} #{full_name}>" end
409
+ end
410
+
411
+ # Represents a Java class or inner class.
412
+
413
+ class Squash::Java::Class < Squash::Java::Type
414
+ # @return [Squash::Java::Class, Squash::Java::Package] The parent package (or
415
+ # parent class for inner classes).
416
+ attr_reader :parent
417
+
418
+ # @return [String, nil] The obfuscated name of this class.
419
+ attr_accessor :obfuscation
420
+
421
+ # @return [Array<Squash::Java::Method>] The instance methods of this class.
422
+ attr_reader :java_methods
423
+
424
+ # @return [Array<Squash::Java::Class>] The inner classes of this class.
425
+ attr_reader :classes
426
+
427
+ # @return [String] The path to the .java file defining this class, relative to
428
+ # the project root.
429
+ # @see Squash::Java::Namespace#find_files
430
+ attr_accessor :path
431
+
432
+ # @private
433
+ def initialize(parent, name)
434
+ @parent = parent
435
+ @java_methods = Set.new
436
+ @classes = Array.new
437
+ @name = name
438
+
439
+ @parent.classes << self
440
+ end
441
+
442
+ # @return [String] The name of this class (with package and parent class
443
+ # names).
444
+
445
+ def full_name
446
+ "#{parent.full_name}.#{name}"
447
+ end
448
+
449
+ # @private
450
+ def subpath() parent.kind_of?(Squash::Java::Package) ? "#{parent.subpath}/#{name}.java" : parent.subpath end
451
+ end
452
+
453
+ # Represents a primitive Java type, like `int` or `float`.
454
+
455
+ class Squash::Java::Primitive < Squash::Java::Type
456
+
457
+ # @private
458
+ def initialize(name)
459
+ @name = name
460
+ end
461
+ end
462
+
463
+ # Represents a Java instance method. Polymorphism is handled by using separate
464
+ # Method instances with different {#arguments} values.
465
+
466
+ class Squash::Java::Method
467
+ # @return [Squash::Java::Class] The class owning this method.
468
+ attr_reader :klass
469
+
470
+ # @return [Squash::Java::Argument] The type of object returned.
471
+ attr_reader :return_type
472
+
473
+ # @return [String] The method name.
474
+ attr_reader :name
475
+
476
+ # @return [Array<Squash::Java::Argument>] The method arguments.
477
+ attr_reader :arguments
478
+
479
+ # @return [String, nil] The obfuscated method name.
480
+ attr_reader :obfuscation
481
+
482
+ # Sets the method's obfuscation.
483
+ # @raise [ArgumentError] If the obfuscation is taken by another method in
484
+ # the same class.
485
+
486
+ def obfuscation=(name)
487
+ if (meth = klass.java_methods.detect { |m| m.arguments == arguments && m.obfuscation == name })
488
+ raise ArgumentError, "Tried to assign obfuscation #{name} to #{meth.inspect} and #{inspect}"
489
+ end
490
+ @obfuscation = name
491
+ end
492
+
493
+ # @private
494
+ def initialize(klass, name, return_type, *arguments)
495
+ @klass = klass
496
+ @name = name
497
+ @return_type = return_type
498
+ @arguments = arguments
499
+ klass.java_methods << self
500
+ end
501
+
502
+ # @private
503
+ def add_argument(type)
504
+ @arguments << type
505
+ @arguments.size - 1
506
+ end
507
+
508
+ # @return [String] The full method name, along with return value and arguments
509
+ # as full type names.
510
+
511
+ def full_name
512
+ args = arguments.map { |type| type.to_s }.join(', ')
513
+ "#{return_type.full_name} #{name}(#{args})"
514
+ end
515
+
516
+ # @private
517
+ def inspect() "#<#{self.class.to_s} #{full_name}>" end
518
+ end
519
+
520
+ # A {Squash::Java::Method Method} argument. Includes the argument
521
+ # {Squash::Java::Type} and whether it is a scalar or an array.
522
+
523
+ class Squash::Java::Argument
524
+ # @return [Squash::Java::Type] The argument type.
525
+ attr_reader :type
526
+
527
+ # @return [true, false] `true` if the argument is an array, false if it is a
528
+ # scalar.
529
+ attr_reader :array
530
+ alias array? array
531
+
532
+ # @private
533
+ def initialize(type, array=false)
534
+ @type = type
535
+ @array = array
536
+ end
537
+
538
+ # @private
539
+ def ==(other)
540
+ other.kind_of?(Squash::Java::Argument) &&
541
+ type == other.type &&
542
+ array? == other.array?
543
+ end
544
+
545
+ # @return [String] The type's full name, with "[]" appended for arrays.
546
+ def to_s() "#{type.full_name}#{'[]' if array?}" end
547
+
548
+ # @private
549
+ def inspect() "#<#{self.class} #{to_s}>" end
550
+ end
551
+
552
+ # All known Java primitives.
553
+ Squash::Java::PRIMITIVES = %w(boolean byte char short int long float double void).map { |name| Squash::Java::Primitive.new name }
@@ -0,0 +1,119 @@
1
+ # Copyright 2012 Square Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require 'rexml/document'
16
+
17
+ # Parses a rename log file (generated from yGuard or ProGuard) and generates a
18
+ # {Squash::Java::Namespace} object from it.
19
+
20
+ class Squash::Java::RenameLog
21
+ # @private
22
+ JAVA_PACKAGE_COMPONENT = '[a-z][a-z0-9_]*'
23
+ # @private
24
+ JAVA_PACKAGE_NAME = "#{JAVA_PACKAGE_COMPONENT}(?:\\.#{JAVA_PACKAGE_COMPONENT})*"
25
+ # @private
26
+ JAVA_CLASS_NAME = JAVA_VARIABLE_NAME = JAVA_OBFUSCATED_NAME = JAVA_METHOD_NAME = "[A-Za-z0-9_$]+"
27
+ # @private
28
+ JAVA_CLASS_PATH = "(?:#{JAVA_PACKAGE_NAME}\\.)?#{JAVA_CLASS_NAME}"
29
+ # @private
30
+ JAVA_PRIMITIVE = '(?:boolean|byte|char|short|int|long|float|double|void)'
31
+ # @private
32
+ JAVA_TYPE = "(?:#{JAVA_PRIMITIVE}|#{JAVA_CLASS_PATH})(?:\\[\\])*"
33
+ # @private
34
+ JAVA_TYPE_LIST = "#{JAVA_TYPE}(?:,\\s?#{JAVA_TYPE})*"
35
+ # @private
36
+ JAVA_METHOD_SIGNATURE = "#{JAVA_TYPE} #{JAVA_METHOD_NAME}\\((?:#{JAVA_TYPE_LIST})?\\)"
37
+
38
+ # Creates a new parser for a given rename log file. The file is assumed to be
39
+ # in the yGuard format if it ends in ".xml", and in the ProGuard format if it
40
+ # ends in ".txt".
41
+ #
42
+ # @param [String] logfile The path to a rename log file.
43
+
44
+ def initialize(logfile)
45
+ @logfile = logfile
46
+ end
47
+
48
+ # @return [Squash::Java::Namespace] The name mapping in the file.
49
+
50
+ def parse
51
+ return parse_yguard if File.extname(@logfile) == '.xml'
52
+ return parse_proguard if File.extname(@logfile) == '.txt'
53
+ end
54
+
55
+ private
56
+
57
+ def parse_yguard
58
+ namespace = Squash::Java::Namespace.new
59
+
60
+ xml = REXML::Document.new(File.new(@logfile))
61
+ xml.elements.each("//yguard/map/*") do |element|
62
+ obfuscation = element.attributes['map']
63
+ name = element.attributes['name']
64
+ case element.name
65
+ when 'package'
66
+ namespace.add_package_alias name, obfuscation
67
+ when 'class'
68
+ # "com.hvilela.Wallpaperer$6" gets an obfuscation of "6" when it should be "Wallpaperer$6"
69
+ class_name = name.split('.').last
70
+ if class_name.include?('$')
71
+ base_class = namespace.klass(class_name.split('$').first)
72
+ new_obfuscation = [base_class.obfuscation || base_class.name]
73
+ new_obfuscation += class_name.split('$')[1..-2] << obfuscation
74
+ obfuscation = new_obfuscation.join('$')
75
+ end
76
+ namespace.add_class_alias name, obfuscation
77
+ when 'method'
78
+ namespace.add_method_alias element.attributes['class'], name, obfuscation
79
+ end
80
+ end
81
+
82
+ xml.elements.each("//yguard/expose/class") do |element|
83
+ name = element.attributes['name']
84
+ namespace.klass name
85
+ end
86
+
87
+ return namespace
88
+ end
89
+
90
+ def parse_proguard
91
+ namespace = Squash::Java::Namespace.new
92
+
93
+ File.open(@logfile) do |f|
94
+ current_class = nil
95
+ f.each_line do |line|
96
+ if line =~ /^(#{JAVA_CLASS_PATH}) -> (#{JAVA_CLASS_PATH}):$/ # class
97
+ current_class = namespace.add_class_alias($1, $2.split('.').last)
98
+ elsif line =~ /^ #{JAVA_TYPE} #{JAVA_VARIABLE_NAME} -> #{JAVA_OBFUSCATED_NAME}$/ # field, skip
99
+ raise "Unexpected field mapping outside of class" unless current_class
100
+ elsif line =~ /^ (?:\d+:\d+:)?(#{JAVA_METHOD_SIGNATURE}) -> (#{JAVA_OBFUSCATED_NAME})$/ # method
101
+ raise "Unexpected method mapping outside of class" unless current_class
102
+ begin
103
+ namespace.add_method_alias(current_class, $1, $2) if current_class.kind_of?(Squash::Java::Class)
104
+ rescue ArgumentError
105
+ # duplicate obfuscation -- this happens when the Java compiler
106
+ # generates multiple methods with the same signature to support
107
+ # generics. ignore the less specific variant (all later variants)
108
+ raise unless $!.to_s =~ /Tried to assign obfuscation/
109
+ end
110
+ elsif line.empty? # blank, skip
111
+ else
112
+ raise "Invalid mapping line: #{line}"
113
+ end
114
+ end
115
+ end
116
+
117
+ return namespace
118
+ end
119
+ end
@@ -0,0 +1,26 @@
1
+ # Copyright 2012 Square Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ # Container module for Squash-related code.
16
+
17
+ module Squash
18
+
19
+ # Container module for Squash Java-related code.
20
+
21
+ module Java
22
+ end
23
+ end
24
+
25
+ require 'squash/java/namespace'
26
+ require 'squash/java/rename_log'
metadata ADDED
@@ -0,0 +1,156 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: squash_java
3
+ version: !ruby/object:Gem::Version
4
+ hash: 23
5
+ prerelease:
6
+ segments:
7
+ - 1
8
+ - 0
9
+ - 0
10
+ version: 1.0.0
11
+ platform: ruby
12
+ authors:
13
+ - Tim Morgan
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2012-12-07 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ prerelease: false
22
+ requirement: &id001 !ruby/object:Gem::Requirement
23
+ none: false
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ hash: 3
28
+ segments:
29
+ - 0
30
+ version: "0"
31
+ type: :runtime
32
+ name: json
33
+ version_requirements: *id001
34
+ - !ruby/object:Gem::Dependency
35
+ prerelease: false
36
+ requirement: &id002 !ruby/object:Gem::Requirement
37
+ none: false
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ hash: 3
42
+ segments:
43
+ - 0
44
+ version: "0"
45
+ type: :runtime
46
+ name: squash_uploader
47
+ version_requirements: *id002
48
+ - !ruby/object:Gem::Dependency
49
+ prerelease: false
50
+ requirement: &id003 !ruby/object:Gem::Requirement
51
+ none: false
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ hash: 3
56
+ segments:
57
+ - 0
58
+ version: "0"
59
+ type: :development
60
+ name: rspec
61
+ version_requirements: *id003
62
+ - !ruby/object:Gem::Dependency
63
+ prerelease: false
64
+ requirement: &id004 !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ hash: 3
70
+ segments:
71
+ - 0
72
+ version: "0"
73
+ type: :development
74
+ name: yard
75
+ version_requirements: *id004
76
+ - !ruby/object:Gem::Dependency
77
+ prerelease: false
78
+ requirement: &id005 !ruby/object:Gem::Requirement
79
+ none: false
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ hash: 3
84
+ segments:
85
+ - 0
86
+ version: "0"
87
+ type: :development
88
+ name: redcarpet
89
+ version_requirements: *id005
90
+ - !ruby/object:Gem::Dependency
91
+ prerelease: false
92
+ requirement: &id006 !ruby/object:Gem::Requirement
93
+ none: false
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ hash: 3
98
+ segments:
99
+ - 0
100
+ version: "0"
101
+ type: :development
102
+ name: jeweler
103
+ version_requirements: *id006
104
+ description: This gem includes a library that imports yGuard or ProGuard rename logs, and a binary that uploads the data to Squash.
105
+ email: tim@squareup.com
106
+ executables:
107
+ - squash_release
108
+ - deobfuscate
109
+ extensions: []
110
+
111
+ extra_rdoc_files:
112
+ - LICENSE.txt
113
+ - README.md
114
+ files:
115
+ - LICENSE.txt
116
+ - README.md
117
+ - bin/deobfuscate
118
+ - bin/squash_release
119
+ - lib/squash/java.rb
120
+ - lib/squash/java/namespace.rb
121
+ - lib/squash/java/rename_log.rb
122
+ homepage: http://github.com/SquareSquash/java_deobfuscator
123
+ licenses:
124
+ - Apache 2.0
125
+ post_install_message:
126
+ rdoc_options: []
127
+
128
+ require_paths:
129
+ - lib
130
+ required_ruby_version: !ruby/object:Gem::Requirement
131
+ none: false
132
+ requirements:
133
+ - - ">="
134
+ - !ruby/object:Gem::Version
135
+ hash: 3
136
+ segments:
137
+ - 0
138
+ version: "0"
139
+ required_rubygems_version: !ruby/object:Gem::Requirement
140
+ none: false
141
+ requirements:
142
+ - - ">="
143
+ - !ruby/object:Gem::Version
144
+ hash: 3
145
+ segments:
146
+ - 0
147
+ version: "0"
148
+ requirements: []
149
+
150
+ rubyforge_project:
151
+ rubygems_version: 1.8.24
152
+ signing_key:
153
+ specification_version: 3
154
+ summary: Binary and library for deobfuscating your Java project and uploading the rename log to Squash.
155
+ test_files: []
156
+