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
|
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.container.plugin.bundle
import java.io.File
import java.util.jar.{Manifest => JarManifest}
import com.yahoo.container.plugin.osgi.ExportPackageParser
import com.yahoo.container.plugin.osgi.ExportPackages.Export
import com.yahoo.container.plugin.util.JarFiles
/**
* @author tonytv
*/
object AnalyzeBundle {
case class PublicPackages(exports : List[Export], globals : List[String])
def publicPackagesAggregated(jarFiles : Iterable[File]) = aggregate(jarFiles map {publicPackages(_)})
def aggregate(publicPackagesList : Iterable[PublicPackages]) =
(PublicPackages(List(), List()) /: publicPackagesList) { (a,b) =>
PublicPackages(a.exports ++ b.exports, a.globals ++ b.globals)
}
def publicPackages(jarFile: File): PublicPackages = {
try {
(for {
manifest <- JarFiles.getManifest(jarFile)
if isOsgiManifest(manifest)
} yield PublicPackages(parseExports(manifest), parseGlobals(manifest))).
getOrElse(PublicPackages(List(), List()))
} catch {
case e : Exception => throw new RuntimeException("Invalid manifest in bundle '%s'".format(jarFile.getPath), e)
}
}
def bundleSymbolicName(jarFile: File): Option[String] = {
JarFiles.getManifest(jarFile).flatMap(getBundleSymbolicName)
}
private def parseExportsFromAttribute(manifest : JarManifest, attributeName : String) = {
(for (export <- getMainAttributeValue(manifest, attributeName)) yield
ExportPackageParser.parseAll(export) match {
case noSuccess: ExportPackageParser.NoSuccess => throw new RuntimeException(
"Failed parsing %s: %s".format(attributeName, noSuccess))
case success => success.get
}).
getOrElse(List())
}
private def parseExports = parseExportsFromAttribute(_ : JarManifest, "Export-Package")
private def parseGlobals(manifest : JarManifest) = {
//TODO: Use separate parser for global packages.
val globals = parseExportsFromAttribute(manifest, "Global-Package")
if (globals map {_.parameters} exists {!_.isEmpty}) {
throw new RuntimeException("Parameters not valid for Global-Package.")
}
globals flatMap {_.packageNames}
}
private def getMainAttributeValue(manifest: JarManifest, name: String): Option[String] =
Option(manifest.getMainAttributes.getValue(name))
private def isOsgiManifest = getBundleSymbolicName(_: JarManifest).isDefined
private def getBundleSymbolicName = getMainAttributeValue(_: JarManifest, "Bundle-SymbolicName")
}
|