github.com/westcoastroms/westcoastroms-build@v0.0.0-20190928114312-2350e5a73030/build/soong/jar/jar.go (about) 1 // Copyright 2017 Google Inc. All rights reserved. 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 package jar 16 17 import ( 18 "bytes" 19 "fmt" 20 "io/ioutil" 21 "os" 22 "strings" 23 "time" 24 25 "android/soong/third_party/zip" 26 ) 27 28 const ( 29 MetaDir = "META-INF/" 30 ManifestFile = MetaDir + "MANIFEST.MF" 31 ModuleInfoClass = "module-info.class" 32 ) 33 34 var DefaultTime = time.Date(2008, 1, 1, 0, 0, 0, 0, time.UTC) 35 36 var MetaDirExtra = [2]byte{0xca, 0xfe} 37 38 // EntryNamesLess tells whether <filepathA> should precede <filepathB> in 39 // the order of files with a .jar 40 func EntryNamesLess(filepathA string, filepathB string) (less bool) { 41 diff := index(filepathA) - index(filepathB) 42 if diff == 0 { 43 return filepathA < filepathB 44 } 45 return diff < 0 46 } 47 48 // Treats trailing * as a prefix match 49 func patternMatch(pattern, name string) bool { 50 if strings.HasSuffix(pattern, "*") { 51 return strings.HasPrefix(name, strings.TrimSuffix(pattern, "*")) 52 } else { 53 return name == pattern 54 } 55 } 56 57 var jarOrder = []string{ 58 MetaDir, 59 ManifestFile, 60 MetaDir + "*", 61 "*", 62 } 63 64 func index(name string) int { 65 for i, pattern := range jarOrder { 66 if patternMatch(pattern, name) { 67 return i 68 } 69 } 70 panic(fmt.Errorf("file %q did not match any pattern", name)) 71 } 72 73 func MetaDirFileHeader() *zip.FileHeader { 74 dirHeader := &zip.FileHeader{ 75 Name: MetaDir, 76 Extra: []byte{MetaDirExtra[1], MetaDirExtra[0], 0, 0}, 77 } 78 dirHeader.SetMode(0700 | os.ModeDir) 79 dirHeader.SetModTime(DefaultTime) 80 81 return dirHeader 82 } 83 84 // Convert manifest source path to zip header and contents. If path is empty uses a default 85 // manifest. 86 func ManifestFileContents(src string) (*zip.FileHeader, []byte, error) { 87 b, err := manifestContents(src) 88 if err != nil { 89 return nil, nil, err 90 } 91 92 fh := &zip.FileHeader{ 93 Name: ManifestFile, 94 Method: zip.Store, 95 UncompressedSize64: uint64(len(b)), 96 } 97 fh.SetMode(0700) 98 fh.SetModTime(DefaultTime) 99 100 return fh, b, nil 101 } 102 103 // Convert manifest source path to contents. If path is empty uses a default manifest. 104 func manifestContents(src string) ([]byte, error) { 105 var givenBytes []byte 106 var err error 107 108 if src != "" { 109 givenBytes, err = ioutil.ReadFile(src) 110 if err != nil { 111 return nil, err 112 } 113 } 114 115 manifestMarker := []byte("Manifest-Version:") 116 header := append(manifestMarker, []byte(" 1.0\nCreated-By: soong_zip\n")...) 117 118 var finalBytes []byte 119 if !bytes.Contains(givenBytes, manifestMarker) { 120 finalBytes = append(append(header, givenBytes...), byte('\n')) 121 } else { 122 finalBytes = givenBytes 123 } 124 125 return finalBytes, nil 126 }