diff options
Diffstat (limited to 'bundle-plugin/src/main/scala/com')
28 files changed, 0 insertions, 1470 deletions
diff --git a/bundle-plugin/src/main/scala/com/yahoo/container/plugin/bundle/AnalyzeBundle.scala b/bundle-plugin/src/main/scala/com/yahoo/container/plugin/bundle/AnalyzeBundle.scala deleted file mode 100644 index 1b3979476bd..00000000000 --- a/bundle-plugin/src/main/scala/com/yahoo/container/plugin/bundle/AnalyzeBundle.scala +++ /dev/null @@ -1,72 +0,0 @@ -// 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") -} diff --git a/bundle-plugin/src/main/scala/com/yahoo/container/plugin/bundle/TransformExportPackages.scala b/bundle-plugin/src/main/scala/com/yahoo/container/plugin/bundle/TransformExportPackages.scala deleted file mode 100644 index f924b12c539..00000000000 --- a/bundle-plugin/src/main/scala/com/yahoo/container/plugin/bundle/TransformExportPackages.scala +++ /dev/null @@ -1,54 +0,0 @@ -// 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 com.yahoo.container.plugin.osgi.ExportPackages.{Export, Parameter} -import com.yahoo.container.plugin.osgi.ExportPackages.Export - -/** - * @author tonytv - */ -object TransformExportPackages extends App { - def replaceVersions(exports: List[Export], newVersion: String): List[Export] = { - mapParameters(exports) { parameters => - parameters map replaceVersion(newVersion) - } - } - - def removeUses(exports: List[Export]): List[Export] = { - mapParameters(exports) { parameters => - parameters filter {_.name != "uses"} - } - } - - def mapParameters(exports: List[Export])(f: List[Parameter] => List[Parameter]): List[Export] = { - exports map { case Export(packageNames: List[String], parameters: List[Parameter]) => - Export(packageNames, f(parameters)) - } - } - - private def replaceVersion(newVersion: String)(parameter: Parameter) = { - parameter match { - case Parameter("version", _) => Parameter("version", newVersion) - case other => other - } - } - - def toExportPackageProperty(exports: List[Export]): String = { - val exportPackages = - exports map { case Export(packageNames: List[String], parameters: List[Parameter]) => - val parameterString = nameEqualsValue(parameters) - (packageNames ++ parameterString) mkString ";" - } - - exportPackages mkString "," - } - - private def nameEqualsValue(parameters: List[Parameter]) = { - parameters map { case Parameter(name, value) => - s"$name=${quote(value)}" - } - } - - def quote(s: String) = '"' + s + '"' -} diff --git a/bundle-plugin/src/main/scala/com/yahoo/container/plugin/classanalysis/Analyze.scala b/bundle-plugin/src/main/scala/com/yahoo/container/plugin/classanalysis/Analyze.scala deleted file mode 100644 index 2f2d034679d..00000000000 --- a/bundle-plugin/src/main/scala/com/yahoo/container/plugin/classanalysis/Analyze.scala +++ /dev/null @@ -1,28 +0,0 @@ -// 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.classanalysis - -import org.objectweb.asm._ -import java.io.{InputStream, File} -import com.yahoo.container.plugin.util.IO.withFileInputStream - -/** - * Main entry point for class analysis - * @author tonytv - */ -object Analyze { - def analyzeClass(classFile : File) : ClassFileMetaData = { - try { - withFileInputStream(classFile) { fileInputStream => - analyzeClass(fileInputStream) - } - } catch { - case e : RuntimeException => throw new RuntimeException("An error occurred when analyzing " + classFile.getPath, e) - } - } - - def analyzeClass(inputStream : InputStream) : ClassFileMetaData = { - val visitor = new AnalyzeClassVisitor() - new ClassReader(inputStream).accept(visitor, ClassReader.SKIP_DEBUG) - visitor.result - } -} diff --git a/bundle-plugin/src/main/scala/com/yahoo/container/plugin/classanalysis/AnalyzeClassVisitor.scala b/bundle-plugin/src/main/scala/com/yahoo/container/plugin/classanalysis/AnalyzeClassVisitor.scala deleted file mode 100644 index 539684f2024..00000000000 --- a/bundle-plugin/src/main/scala/com/yahoo/container/plugin/classanalysis/AnalyzeClassVisitor.scala +++ /dev/null @@ -1,102 +0,0 @@ -// 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.classanalysis - -import org.objectweb.asm._ -import com.yahoo.osgi.annotation.{ExportPackage, Version} -import collection.mutable - -/** - * Picks up classes used in class files. - * @author tonytv - */ -private class AnalyzeClassVisitor extends ClassVisitor(Opcodes.ASM6) with AnnotationVisitorTrait with AttributeVisitorTrait { - private var name : String = null - protected val imports : ImportsSet = mutable.Set() - protected var exportPackageAnnotation: Option[ExportPackageAnnotation] = None - - - override def visitAttribute(attribute: Attribute): Unit = super.visitAttribute(attribute) - - override def visitMethod(access: Int, name: String, desc: String, signature: String, - exceptions: Array[String]): MethodVisitor = { - - imports ++= (Type.getReturnType(desc) +: Type.getArgumentTypes(desc)).flatMap(getClassName) - - imports ++= Option(exceptions) getOrElse(Array()) flatMap internalNameToClassName - - AnalyzeSignatureVisitor.analyzeMethod(signature, this) - new AnalyzeMethodVisitor(this) - } - - override def visitField(access: Int, name: String, desc: String, signature: String, value: AnyRef): FieldVisitor = { - imports ++= getClassName(Type.getType(desc)).toList - - AnalyzeSignatureVisitor.analyzeField(signature, this) - new FieldVisitor(Opcodes.ASM6) with SubVisitorTrait with AttributeVisitorTrait with AnnotationVisitorTrait { - val analyzeClassVisitor = AnalyzeClassVisitor.this - - override def visitAnnotation(desc: String, visible: Boolean): AnnotationVisitor = super.visitAnnotation(desc, visible) - override def visitAttribute(attribute: Attribute): Unit = super.visitAttribute(attribute) - override def visitEnd(): Unit = super.visitEnd() - } - } - - override def visit(version: Int, access: Int, name: String, signature: String, superName: String, interfaces: Array[String]) { - this.name = internalNameToClassName(name).get - - imports ++= (superName +: interfaces) flatMap internalNameToClassName - AnalyzeSignatureVisitor.analyzeClass(signature, this) - } - - override def visitInnerClass(name: String, outerName: String, innerName: String, access: Int) {} - override def visitOuterClass(owner: String, name: String, desc: String) {} - override def visitSource(source: String, debug: String) {} - override def visitEnd() {} - - def addImports(imports: TraversableOnce[String]) { - this.imports ++= imports - } - - override def visitAnnotation(desc: String, visible: Boolean): AnnotationVisitor = { - if (Type.getType(desc).getClassName == classOf[ExportPackage].getName) { - visitExportPackage() - } else { - super.visitAnnotation(desc, visible) - } - } - - def visitExportPackage(): AnnotationVisitor = { - def defaultVersionValue[T](name: String) = classOf[Version].getMethod(name).getDefaultValue().asInstanceOf[T] - - new AnnotationVisitor(Opcodes.ASM6) { - var major: Int = defaultVersionValue("major") - var minor: Int = defaultVersionValue("minor") - var micro: Int = defaultVersionValue("micro") - var qualifier: String = defaultVersionValue("qualifier") - - override def visit(name: String, value: AnyRef) { - def valueAsInt = value.asInstanceOf[Int] - - name match { - case "major" => major = valueAsInt - case "minor" => minor = valueAsInt - case "micro" => micro = valueAsInt - case "qualifier" => qualifier = value.asInstanceOf[String] - } - } - - override def visitEnd() { - exportPackageAnnotation = Some(ExportPackageAnnotation(major, minor, micro, qualifier)) - } - - override def visitEnum(name: String, desc: String, value: String) {} - override def visitArray(name: String): AnnotationVisitor = this - override def visitAnnotation(name: String, desc: String): AnnotationVisitor = this - } - } - - def result = { - assert(!imports.contains("int")) - new ClassFileMetaData(name, imports.toSet, exportPackageAnnotation) - } -} diff --git a/bundle-plugin/src/main/scala/com/yahoo/container/plugin/classanalysis/AnalyzeMethodVisitor.scala b/bundle-plugin/src/main/scala/com/yahoo/container/plugin/classanalysis/AnalyzeMethodVisitor.scala deleted file mode 100644 index a8032b6a912..00000000000 --- a/bundle-plugin/src/main/scala/com/yahoo/container/plugin/classanalysis/AnalyzeMethodVisitor.scala +++ /dev/null @@ -1,88 +0,0 @@ -// 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.classanalysis - -import org.objectweb.asm._ - -/** - * Picks up classes used in method bodies. - * @author tonytv - */ -private class AnalyzeMethodVisitor(val analyzeClassVisitor : AnalyzeClassVisitor) - extends MethodVisitor(Opcodes.ASM6) with AnnotationVisitorTrait with AttributeVisitorTrait with SubVisitorTrait { - - - override def visitParameterAnnotation(parameter: Int, desc: String, visible: Boolean): AnnotationVisitor = super.visitParameterAnnotation(parameter, desc, visible) - override def visitAnnotationDefault(): AnnotationVisitor = super.visitAnnotationDefault() - override def visitAttribute(attribute: Attribute): Unit = super.visitAttribute(attribute) - override def visitAnnotation(desc: String, visible: Boolean): AnnotationVisitor = super.visitAnnotation(desc, visible) - override def visitEnd(): Unit = super.visitEnd() - - override def visitMultiANewArrayInsn(desc: String, dims: Int) { - imports ++= getClassName(Type.getType(desc)).toList - } - - - override def visitMethodInsn(opcode: Int, owner: String, name: String, desc: String, itf: Boolean) { - imports ++= internalNameToClassName(owner) - imports ++= Type.getArgumentTypes(desc).flatMap(getClassName) - imports ++= getClassName(Type.getReturnType(desc)) - } - - override def visitFieldInsn(opcode: Int, owner: String, name: String, desc: String) { - imports ++= internalNameToClassName(owner) ++ getClassName(Type.getType(desc)).toList - - } - - override def visitTypeInsn(opcode: Int, `type` : String) { - imports ++= internalNameToClassName(`type`) - } - - override def visitTryCatchBlock(start: Label, end: Label, handler: Label, `type` : String) { - if (`type` != null) //null means finally block - imports ++= internalNameToClassName(`type`) - } - - override def visitLocalVariable(name: String, desc: String, signature: String, start: Label, end: Label, index: Int) { - imports += Type.getType(desc).getClassName - } - - override def visitLdcInsn(constant: AnyRef) { - constant match { - case typeConstant: Type => imports ++= getClassName(typeConstant) - case _ => - } - } - - override def visitInvokeDynamicInsn(name: String, desc: String, bootstrapMethod: Handle, bootstrapMethodArgs: AnyRef*) { - bootstrapMethodArgs.foreach { - case typeConstant: Type => - imports ++= getClassName(typeConstant) - case handle: Handle => - imports ++= internalNameToClassName(handle.getOwner) - imports ++= Type.getArgumentTypes(desc).flatMap(getClassName) - case _ : Number => - case _ : String => - case other => throw new AssertionError(s"Unexpected type ${other.getClass} with value '$other'") - } - } - - override def visitMaxs(maxStack: Int, maxLocals: Int) {} - override def visitLineNumber(line: Int, start: Label) {} - //only for debugging - override def visitLookupSwitchInsn(dflt: Label, keys: Array[Int], labels: Array[Label]) {} - - - override def visitTableSwitchInsn(min: Int, max: Int, dflt: Label, labels: Label*): Unit = super.visitTableSwitchInsn(min, max, dflt, labels: _*) - override def visitIincInsn(`var` : Int, increment: Int) {} - override def visitLabel(label: Label) {} - override def visitJumpInsn(opcode: Int, label: Label) {} - override def visitVarInsn(opcode: Int, `var` : Int) {} - override def visitIntInsn(opcode: Int, operand: Int) {} - override def visitInsn(opcode: Int) {} - override def visitFrame(`type` : Int, nLocal: Int, local: Array[AnyRef], nStack: Int, stack: Array[AnyRef]) {} - override def visitCode() {} -} - - - - diff --git a/bundle-plugin/src/main/scala/com/yahoo/container/plugin/classanalysis/AnalyzeSignatureVisitor.scala b/bundle-plugin/src/main/scala/com/yahoo/container/plugin/classanalysis/AnalyzeSignatureVisitor.scala deleted file mode 100644 index 5bb8304cf1e..00000000000 --- a/bundle-plugin/src/main/scala/com/yahoo/container/plugin/classanalysis/AnalyzeSignatureVisitor.scala +++ /dev/null @@ -1,68 +0,0 @@ -// 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.classanalysis - -import org.objectweb.asm.Opcodes -import org.objectweb.asm.signature.{SignatureReader, SignatureVisitor} - - -/** - * @author tonytv - */ - -private class AnalyzeSignatureVisitor(val analyzeClassVisitor: AnalyzeClassVisitor) - extends SignatureVisitor(Opcodes.ASM6) - with SubVisitorTrait { - - - override def visitEnd(): Unit = super.visitEnd() - - override def visitClassType(className: String) { - imports ++= internalNameToClassName(className) - } - - override def visitFormalTypeParameter(name: String) {} - - override def visitClassBound() = this - - override def visitInterfaceBound() = this - - override def visitSuperclass() = this - - override def visitInterface() = this - - override def visitParameterType() = this - - override def visitReturnType() = this - - override def visitExceptionType() = this - - override def visitBaseType(descriptor: Char) {} - - override def visitTypeVariable(name: String) {} - - override def visitArrayType() = this - - override def visitInnerClassType(name: String) {} - - override def visitTypeArgument() {} - - override def visitTypeArgument(wildcard: Char) = this -} - - -object AnalyzeSignatureVisitor { - def analyzeClass(signature: String, analyzeClassVisitor: AnalyzeClassVisitor) { - if (signature != null) { - new SignatureReader(signature).accept(new AnalyzeSignatureVisitor(analyzeClassVisitor)) - } - } - - def analyzeMethod(signature: String, analyzeClassVisitor: AnalyzeClassVisitor) { - analyzeClass(signature, analyzeClassVisitor) - } - - def analyzeField(signature: String, analyzeClassVisitor: AnalyzeClassVisitor) { - if (signature != null) - new SignatureReader(signature).acceptType(new AnalyzeSignatureVisitor(analyzeClassVisitor)) - } -} diff --git a/bundle-plugin/src/main/scala/com/yahoo/container/plugin/classanalysis/AnnotationVisitorTrait.scala b/bundle-plugin/src/main/scala/com/yahoo/container/plugin/classanalysis/AnnotationVisitorTrait.scala deleted file mode 100644 index 0bf6ee4a6b4..00000000000 --- a/bundle-plugin/src/main/scala/com/yahoo/container/plugin/classanalysis/AnnotationVisitorTrait.scala +++ /dev/null @@ -1,39 +0,0 @@ -// 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.classanalysis - -import org.objectweb.asm.{Opcodes, AnnotationVisitor, Type} - -/** - * Picks up classes used in annotations. - * @author tonytv - */ -private trait AnnotationVisitorTrait { - protected val imports: ImportsSet - - def visitAnnotation(desc: String, visible: Boolean): AnnotationVisitor = { - imports ++= getClassName(Type.getType(desc)).toList - - visitAnnotationDefault() - } - - def visitAnnotationDefault(): AnnotationVisitor = - new AnnotationVisitor(Opcodes.ASM6) { - override def visit(name: String, value: AnyRef) {} - - override def visitEnum(name: String, desc: String, value: String) { - imports ++= getClassName(Type.getType(desc)).toList - } - - override def visitArray(name: String): AnnotationVisitor = this - - override def visitAnnotation(name: String, desc: String): AnnotationVisitor = { - imports ++= getClassName(Type.getType(desc)).toList - this - } - - override def visitEnd() {} - } - - def visitParameterAnnotation(parameter: Int, desc: String, visible: Boolean): AnnotationVisitor = - visitAnnotation(desc, visible) -} diff --git a/bundle-plugin/src/main/scala/com/yahoo/container/plugin/classanalysis/AttributeVisitorTrait.scala b/bundle-plugin/src/main/scala/com/yahoo/container/plugin/classanalysis/AttributeVisitorTrait.scala deleted file mode 100644 index 454bea99f29..00000000000 --- a/bundle-plugin/src/main/scala/com/yahoo/container/plugin/classanalysis/AttributeVisitorTrait.scala +++ /dev/null @@ -1,15 +0,0 @@ -// 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.classanalysis - -import org.objectweb.asm.{Type, Attribute} - -/** - * @author tonytv - */ -private trait AttributeVisitorTrait { - protected val imports: ImportsSet - - def visitAttribute(attribute: Attribute) { - imports ++= getClassName(Type.getObjectType(attribute.`type`)).toList - } -} diff --git a/bundle-plugin/src/main/scala/com/yahoo/container/plugin/classanalysis/ClassFileMetaData.scala b/bundle-plugin/src/main/scala/com/yahoo/container/plugin/classanalysis/ClassFileMetaData.scala deleted file mode 100644 index fb395749895..00000000000 --- a/bundle-plugin/src/main/scala/com/yahoo/container/plugin/classanalysis/ClassFileMetaData.scala +++ /dev/null @@ -1,10 +0,0 @@ -// 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.classanalysis - -/** - * The result of analyzing a .class file. - * @author tonytv - */ -sealed case class ClassFileMetaData(name:String, - referencedClasses : Set[String], - exportPackage : Option[ExportPackageAnnotation]) diff --git a/bundle-plugin/src/main/scala/com/yahoo/container/plugin/classanalysis/ExportPackageAnnotation.scala b/bundle-plugin/src/main/scala/com/yahoo/container/plugin/classanalysis/ExportPackageAnnotation.scala deleted file mode 100644 index f9dc459fcc7..00000000000 --- a/bundle-plugin/src/main/scala/com/yahoo/container/plugin/classanalysis/ExportPackageAnnotation.scala +++ /dev/null @@ -1,24 +0,0 @@ -// 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.classanalysis - -import com.yahoo.container.plugin.util.Strings - -/** - * @author tonytv - */ -case class ExportPackageAnnotation(major: Int, minor: Int, micro: Int, qualifier: String) { - requireNonNegative(major, "major") - requireNonNegative(minor, "minor") - requireNonNegative(micro, "micro") - require(qualifier.matches("""(\p{Alpha}|\p{Digit}|_|-)*"""), - exportPackageError("qualifier must follow the format (alpha|digit|'_'|'-')* but was '%s'.".format(qualifier))) - - - private def requireNonNegative(i: Int, fieldName: String) { - require(i >= 0, exportPackageError("%s must be non-negative but was %d.".format(fieldName, i))) - } - - private def exportPackageError(s: String) = "ExportPackage anntotation: " + s - - def osgiVersion : String = (List(major, minor, micro) ++ Strings.noneIfEmpty(qualifier)).mkString(".") -} diff --git a/bundle-plugin/src/main/scala/com/yahoo/container/plugin/classanalysis/PackageTally.scala b/bundle-plugin/src/main/scala/com/yahoo/container/plugin/classanalysis/PackageTally.scala deleted file mode 100644 index 2d2460cc9fd..00000000000 --- a/bundle-plugin/src/main/scala/com/yahoo/container/plugin/classanalysis/PackageTally.scala +++ /dev/null @@ -1,46 +0,0 @@ -// 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.classanalysis - -import com.yahoo.container.plugin.util.Maps - -/** - * - * @author tonytv - */ -final class PackageTally (private val definedPackagesMap : Map[String, Option[ExportPackageAnnotation]], - referencedPackagesUnfiltered : Set[String]) { - - val referencedPackages = referencedPackagesUnfiltered diff definedPackages - - def definedPackages = definedPackagesMap.keySet - - def exportedPackages = definedPackagesMap collect { case (name, Some(export)) => (name, export) } - - /** - * Represents the classes for two package tallies that are deployed as a single unit. - * - * ExportPackageAnnotations from this has precedence over the other. - */ - def combine(other: PackageTally): PackageTally = { - new PackageTally( - Maps.combine(definedPackagesMap, other.definedPackagesMap)(_ orElse _), - referencedPackages ++ other.referencedPackages) - } -} - - -object PackageTally { - def fromAnalyzedClassFiles(analyzedClassFiles : Seq[ClassFileMetaData]) : PackageTally = { - combine( - for (metaData <- analyzedClassFiles) - yield { - new PackageTally( - Map(Packages.packageName(metaData.name) -> metaData.exportPackage), - metaData.referencedClasses.map(Packages.packageName)) - }) - } - - def combine(packageTallies : Iterable[PackageTally]) : PackageTally = (empty /: packageTallies)(_.combine(_)) - - val empty : PackageTally = new PackageTally(Map(), Set()) -} diff --git a/bundle-plugin/src/main/scala/com/yahoo/container/plugin/classanalysis/Packages.scala b/bundle-plugin/src/main/scala/com/yahoo/container/plugin/classanalysis/Packages.scala deleted file mode 100644 index 517ef2626f9..00000000000 --- a/bundle-plugin/src/main/scala/com/yahoo/container/plugin/classanalysis/Packages.scala +++ /dev/null @@ -1,27 +0,0 @@ -// 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.classanalysis - -/** - * Utility methods related to packages. - * @author tonytv - */ -object Packages { - case class PackageMetaData(definedPackages: Set[String], referencedExternalPackages: Set[String]) - - def packageName(fullClassName: String) = { - def nullIfNotFound(index : Int) = if (index == -1) 0 else index - - fullClassName.substring(0, nullIfNotFound(fullClassName.lastIndexOf("."))) - } - - - - def analyzePackages(allClasses: Seq[ClassFileMetaData]): PackageMetaData = { - val (definedPackages, referencedClasses) = - (for (classMetaData <- allClasses) - yield (packageName(classMetaData.name), classMetaData.referencedClasses.map(packageName))). - unzip - - PackageMetaData(definedPackages.toSet, referencedClasses.flatten.toSet diff definedPackages.toSet) - } -} diff --git a/bundle-plugin/src/main/scala/com/yahoo/container/plugin/classanalysis/SubVisitorTrait.scala b/bundle-plugin/src/main/scala/com/yahoo/container/plugin/classanalysis/SubVisitorTrait.scala deleted file mode 100644 index 06ccfa7b88c..00000000000 --- a/bundle-plugin/src/main/scala/com/yahoo/container/plugin/classanalysis/SubVisitorTrait.scala +++ /dev/null @@ -1,19 +0,0 @@ -// 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.classanalysis - -import collection.mutable - -/** - * A visitor that's run for sub construct of a class - * and forwards all its imports the the owning ClassVisitor at the end. - * @author tonytv - */ -private trait SubVisitorTrait { - val analyzeClassVisitor : AnalyzeClassVisitor - - val imports : ImportsSet = mutable.Set() - - def visitEnd() { - analyzeClassVisitor.addImports(imports) - } -} diff --git a/bundle-plugin/src/main/scala/com/yahoo/container/plugin/classanalysis/package.scala b/bundle-plugin/src/main/scala/com/yahoo/container/plugin/classanalysis/package.scala deleted file mode 100644 index 631884c58e3..00000000000 --- a/bundle-plugin/src/main/scala/com/yahoo/container/plugin/classanalysis/package.scala +++ /dev/null @@ -1,27 +0,0 @@ -// 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 - -import org.objectweb.asm.Type -import collection.mutable - -package object classanalysis { - type ImportsSet = mutable.Set[String] - - def internalNameToClassName(internalClassName: String) : Option[String] = { - internalClassName match { - case null => None - case _ => getClassName(Type.getObjectType(internalClassName)) - } - } - - def getClassName(aType: Type): Option[String] = { - import Type._ - - aType.getSort match { - case ARRAY => getClassName(aType.getElementType) - case OBJECT => Some(aType.getClassName) - case _ => None - } - } -} - diff --git a/bundle-plugin/src/main/scala/com/yahoo/container/plugin/mojo/Artifacts.scala b/bundle-plugin/src/main/scala/com/yahoo/container/plugin/mojo/Artifacts.scala deleted file mode 100644 index 8370f8c615e..00000000000 --- a/bundle-plugin/src/main/scala/com/yahoo/container/plugin/mojo/Artifacts.scala +++ /dev/null @@ -1,29 +0,0 @@ -// 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.mojo - -import org.apache.maven.artifact.Artifact -import org.apache.maven.project.MavenProject - -import scala.collection.JavaConverters._ - -/** - * @author tonytv - */ -object Artifacts { - def getArtifacts(project : MavenProject) = { - type artifactSet = java.util.Set[Artifact] - val artifacts = project.getArtifacts.asInstanceOf[artifactSet].asScala.groupBy(_.getScope) - - def isTypeJar(artifact : Artifact) = artifact.getType == "jar" - def getByScope(scope: String) = - artifacts.getOrElse(scope, Iterable.empty).partition(isTypeJar) - - - val (jarArtifactsToInclude, nonJarArtifactsToInclude) = getByScope(Artifact.SCOPE_COMPILE) - val (jarArtifactsProvided, nonJarArtifactsProvided) = getByScope(Artifact.SCOPE_PROVIDED) - - (jarArtifactsToInclude, jarArtifactsProvided, nonJarArtifactsToInclude ++ nonJarArtifactsProvided) - } - - def getArtifactsToInclude(project: MavenProject) = getArtifacts(project)._1 -} diff --git a/bundle-plugin/src/main/scala/com/yahoo/container/plugin/mojo/AssembleContainerPluginMojo.scala b/bundle-plugin/src/main/scala/com/yahoo/container/plugin/mojo/AssembleContainerPluginMojo.scala deleted file mode 100644 index 4104e349208..00000000000 --- a/bundle-plugin/src/main/scala/com/yahoo/container/plugin/mojo/AssembleContainerPluginMojo.scala +++ /dev/null @@ -1,116 +0,0 @@ -// 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.mojo - -import java.io.File -import java.nio.channels.Channels -import java.util.jar.JarFile -import java.util.zip.ZipEntry - -import com.yahoo.container.plugin.util.{Files, JarFiles} -import org.apache.maven.archiver.{MavenArchiveConfiguration, MavenArchiver} -import org.apache.maven.execution.MavenSession -import org.apache.maven.plugin.AbstractMojo -import org.apache.maven.plugins.annotations.{Mojo, Parameter, ResolutionScope} -import org.apache.maven.project.MavenProject -import org.codehaus.plexus.archiver.jar.JarArchiver - -import scala.collection.JavaConverters._ - -/** - * @author tonytv - */ -@Mojo(name = "assemble-container-plugin", requiresDependencyResolution = ResolutionScope.COMPILE, threadSafe = true) -class AssembleContainerPluginMojo extends AbstractMojo { - object withDependencies - object withoutDependencies - - @Parameter(defaultValue = "${project}") - var project: MavenProject = null - - @Parameter(defaultValue = "${session}", readonly = true, required = true) - var session: MavenSession = null - - @Parameter - var archiveConfiguration: MavenArchiveConfiguration = new MavenArchiveConfiguration - - @Parameter(alias = "UseCommonAssemblyIds", defaultValue = "false") - var useCommonAssemblyIds: Boolean = false - - - def execute() { - val jarSuffixes = - if (useCommonAssemblyIds) Map(withoutDependencies -> ".jar", withDependencies -> "-jar-with-dependencies.jar") - else Map(withoutDependencies -> "-without-dependencies.jar", withDependencies -> "-deploy.jar") - - val jarFiles = jarSuffixes mapValues jarFileInBuildDirectory(build.getFinalName) - - //force recreating the archive - archiveConfiguration.setForced(true) - archiveConfiguration.setManifestFile(new File(new File(project.getBuild.getOutputDirectory), JarFile.MANIFEST_NAME)) - - val jarWithoutDependencies = new JarArchiver() - addClassesDirectory(jarWithoutDependencies) - createArchive(jarFiles(withoutDependencies), jarWithoutDependencies) - project.getArtifact.setFile(jarFiles(withoutDependencies)) - - val jarWithDependencies = new JarArchiver() - addClassesDirectory(jarWithDependencies) - addDependencies(jarWithDependencies) - createArchive(jarFiles(withDependencies), jarWithDependencies) - } - - private def jarFileInBuildDirectory(name: String)(jarSuffix: String) = { - new File(build.getDirectory, name + jarSuffix) - } - - private def addClassesDirectory(jarArchiver: JarArchiver) { - val classesDirectory = new File(build.getOutputDirectory) - if (classesDirectory.isDirectory) { - jarArchiver.addDirectory(classesDirectory) - } - } - - private def createArchive(jarFile: File, jarArchiver: JarArchiver) { - val mavenArchiver = new MavenArchiver - mavenArchiver.setArchiver(jarArchiver) - mavenArchiver.setOutputFile(jarFile) - mavenArchiver.createArchive(session, project, archiveConfiguration) - } - - private def addDependencies(jarArchiver: JarArchiver) { - Artifacts.getArtifactsToInclude(project).foreach { artifact => - if (artifact.getType == "jar") { - jarArchiver.addFile(artifact.getFile, "dependencies/" + artifact.getFile.getName) - copyConfigDefinitions(artifact.getFile, jarArchiver) - } - else - getLog.warn("Unkown artifact type " + artifact.getType) - } - } - - private def copyConfigDefinitions(file: File, jarArchiver: JarArchiver) { - JarFiles.withJarFile(file) { jarFile => - for { - entry <- jarFile.entries().asScala - name = entry.getName - if name.startsWith("configdefinitions/") && name.endsWith(".def") - - } copyConfigDefinition(jarFile, entry, jarArchiver) - } - } - - private def copyConfigDefinition(jarFile: JarFile, entry: ZipEntry, jarArchiver: JarArchiver) { - JarFiles.withInputStream(jarFile, entry) { input => - val defPath = entry.getName.replace("/", File.separator) - val destinationFile = new File(project.getBuild.getOutputDirectory, defPath) - destinationFile.getParentFile.mkdirs() - - Files.withFileOutputStream(destinationFile) { output => - output.getChannel.transferFrom(Channels.newChannel(input), 0, Long.MaxValue) - } - jarArchiver.addFile(destinationFile, entry.getName) - } - } - - private def build = project.getBuild -} diff --git a/bundle-plugin/src/main/scala/com/yahoo/container/plugin/mojo/GenerateBundleClassPathMappingsMojo.scala b/bundle-plugin/src/main/scala/com/yahoo/container/plugin/mojo/GenerateBundleClassPathMappingsMojo.scala deleted file mode 100644 index 2bd146a3920..00000000000 --- a/bundle-plugin/src/main/scala/com/yahoo/container/plugin/mojo/GenerateBundleClassPathMappingsMojo.scala +++ /dev/null @@ -1,96 +0,0 @@ -// 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.mojo - -import java.io.File -import java.nio.file.Paths - -import com.google.common.base.Preconditions -import com.yahoo.container.plugin.bundle.AnalyzeBundle -import com.yahoo.container.plugin.osgi.ProjectBundleClassPaths -import com.yahoo.container.plugin.osgi.ProjectBundleClassPaths.BundleClasspathMapping -import org.apache.maven.artifact.Artifact -import org.apache.maven.plugin.AbstractMojo -import org.apache.maven.plugins.annotations.{Mojo, Parameter, ResolutionScope} -import org.apache.maven.project.MavenProject - -import scala.collection.JavaConverters._ - - - -/** - * Generates mapping from Bundle-SymbolicName to classpath elements, e.g - * myBundle -> List(.m2/repository/com/mylib/Mylib.jar, myBundleProject/target/classes) - * The mapping in stored in a json file. - * @author tonytv - */ -@Mojo(name = "generate-bundle-classpath-mappings", requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME, threadSafe = true) -class GenerateBundleClassPathMappingsMojo extends AbstractMojo { - @Parameter(defaultValue = "${project}") - private var project: MavenProject = null - - //TODO: Combine with com.yahoo.container.plugin.mojo.GenerateOsgiManifestMojo.bundleSymbolicName - @Parameter(alias = "Bundle-SymbolicName", defaultValue = "${project.artifactId}") - private var bundleSymbolicName: String = null - - - /* Sample output -- target/test-classes/bundle-plugin.bundle-classpath-mappings.json - { - "mainBundle": { - "bundleSymbolicName": "bundle-plugin-test", - "classPathElements": [ - "/Users/tonyv/Repos/vespa/bundle-plugin-test/target/classes", - "/Users/tonyv/.m2/repository/com/yahoo/vespa/jrt/6-SNAPSHOT/jrt-6-SNAPSHOT.jar", - "/Users/tonyv/.m2/repository/com/yahoo/vespa/annotations/6-SNAPSHOT/annotations-6-SNAPSHOT.jar" - ] - }, - "providedDependencies": [ - { - "bundleSymbolicName": "jrt", - "classPathElements": [ - "/Users/tonyv/.m2/repository/com/yahoo/vespa/jrt/6-SNAPSHOT/jrt-6-SNAPSHOT.jar" - ] - } - ] - } - */ - override def execute(): Unit = { - Preconditions.checkNotNull(bundleSymbolicName) - - val (embeddedArtifacts, providedJarArtifacts, _) = asLists(Artifacts.getArtifacts(project)) - - val embeddedArtifactsFiles = embeddedArtifacts.map(_.getFile) - - val classPathElements = (outputDirectory +: embeddedArtifactsFiles).map(_.getAbsolutePath) - - val classPathMappings = new ProjectBundleClassPaths( - new BundleClasspathMapping(bundleSymbolicName, classPathElements.asJava), - providedJarArtifacts.flatMap(createDependencyClasspathMapping).asJava) - - ProjectBundleClassPaths.save( - testOutputPath.resolve(ProjectBundleClassPaths.CLASSPATH_MAPPINGS_FILENAME), - classPathMappings) - } - - private def outputDirectory = new File(project.getBuild.getOutputDirectory) - private def testOutputPath = Paths.get(project.getBuild.getTestOutputDirectory) - - /* TODO: - * 1) add the dependencies of the artifact in the future(i.e. dependencies of dependencies) - * or - * 2) obtain bundles with embedded dependencies from the maven repository, - * and support loading classes from the nested jar files in those bundles. - */ - def createDependencyClasspathMapping(artifact: Artifact): Option[BundleClasspathMapping] = { - for (bundleSymbolicName <- bundleSymbolicNameForArtifact(artifact)) - yield new BundleClasspathMapping(bundleSymbolicName, List(artifact.getFile.getAbsolutePath).asJava) - } - - def bundleSymbolicNameForArtifact(artifact: Artifact): Option[String] = { - if (artifact.getFile.getName.endsWith(".jar")) AnalyzeBundle.bundleSymbolicName(artifact.getFile) - else Some(artifact.getArtifactId) //Not the best heuristic. The other alternatives are parsing the pom file or - //storing information in target/classes when building the provided bundles. - } - - def asLists[A](tuple: (Iterable[A], Iterable[A], Iterable[A])) = - (tuple._1.toList, tuple._2.toList, tuple._3.toList) -} diff --git a/bundle-plugin/src/main/scala/com/yahoo/container/plugin/mojo/GenerateOsgiManifestMojo.scala b/bundle-plugin/src/main/scala/com/yahoo/container/plugin/mojo/GenerateOsgiManifestMojo.scala deleted file mode 100644 index 67ce45ed7c6..00000000000 --- a/bundle-plugin/src/main/scala/com/yahoo/container/plugin/mojo/GenerateOsgiManifestMojo.scala +++ /dev/null @@ -1,286 +0,0 @@ -// 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.mojo - -import java.io.File -import java.util.jar.{Attributes, JarEntry, JarFile} -import java.util.regex.Pattern - -import com.yahoo.container.plugin.bundle.AnalyzeBundle -import com.yahoo.container.plugin.classanalysis.{Analyze, ExportPackageAnnotation, PackageTally} -import com.yahoo.container.plugin.mojo.GenerateOsgiManifestMojo._ -import com.yahoo.container.plugin.osgi.ExportPackages -import com.yahoo.container.plugin.osgi.ExportPackages.Export -import com.yahoo.container.plugin.osgi.ImportPackages.Import -import com.yahoo.container.plugin.osgi.{ExportPackageParser, ExportPackages, ImportPackages} -import com.yahoo.container.plugin.util.Files.allDescendantFiles -import com.yahoo.container.plugin.util.IO.withFileOutputStream -import com.yahoo.container.plugin.util.Iteration.toStream -import com.yahoo.container.plugin.util.JarFiles.{withInputStream, withJarFile} -import com.yahoo.container.plugin.util.Strings -import org.apache.maven.artifact.Artifact -import org.apache.maven.plugin.{AbstractMojo, MojoExecutionException, MojoFailureException} -import org.apache.maven.plugins.annotations.{Mojo, Parameter, ResolutionScope} -import org.apache.maven.project.MavenProject - -import scala.collection.immutable.Map - - -/** - * @author tonytv - */ -@Mojo(name = "generate-osgi-manifest", requiresDependencyResolution = ResolutionScope.TEST, threadSafe = true) -class GenerateOsgiManifestMojo extends AbstractMojo { - - @Parameter(defaultValue = "${project}") - var project: MavenProject = null - - @Parameter - var discApplicationClass: String = null - - @Parameter - var discPreInstallBundle: String = null - - @Parameter(alias = "Bundle-Version", defaultValue = "${project.version}") - var bundleVersion: String = null - - @Parameter(alias = "Bundle-SymbolicName", defaultValue = "${project.artifactId}") - var bundleSymbolicName: String = null - - @Parameter(alias = "Bundle-Activator") - var bundleActivator: String = null - - @Parameter(alias = "X-JDisc-Privileged-Activator") - var jdiscPrivilegedActivator: String = null - - @Parameter(alias = "X-Config-Models") - var configModels: String = null - - @Parameter(alias = "Import-Package") - var importPackage: String = null - - @Parameter(alias = "WebInfUrl") - var webInfUrl: String = null - - @Parameter(alias = "Main-Class") - var mainClass: String = null - - @Parameter(alias = "X-Jersey-Binding") - var jerseyBinding: String = null - - case class PackageInfo(name : String, exportAnnotation : Option[ExportPackageAnnotation]) - - def execute() { - try { - val (jarArtifactsToInclude, jarArtifactsProvided, nonJarArtifacts) = Artifacts.getArtifacts(project) - warnOnUnsupportedArtifacts(nonJarArtifacts) - - val publicPackagesFromProvidedJars = AnalyzeBundle.publicPackagesAggregated(jarArtifactsProvided.map(_.getFile)) - val includedJarPackageTally = definedPackages(jarArtifactsToInclude) - - val projectPackageTally = analyzeProjectClasses() - - val pluginPackageTally = projectPackageTally.combine(includedJarPackageTally) - - warnIfPackagesDefinedOverlapsGlobalPackages(projectPackageTally.definedPackages ++ includedJarPackageTally.definedPackages, - publicPackagesFromProvidedJars.globals) - - if (getLog.isDebugEnabled) { - getLog.debug("Referenced packages = " + pluginPackageTally.referencedPackages) - getLog.debug("Defined packages = " + pluginPackageTally.definedPackages) - getLog.debug("Exported packages of dependencies = " + - publicPackagesFromProvidedJars.exports.map(e => (e.packageNames, e.version getOrElse "")).toSet ) - } - - val calculatedImports = ImportPackages.calculateImports( - pluginPackageTally.referencedPackages, - pluginPackageTally.definedPackages, - ExportPackages.exportsByPackageName(publicPackagesFromProvidedJars.exports)) - - val manualImports = emptyToNone(importPackage) map getManualImports getOrElse Map() - - createManifestFile(new File(project.getBuild.getOutputDirectory), - manifestContent( - project, - jarArtifactsToInclude, - manualImports, - (calculatedImports -- manualImports.keys).values.toSet, - pluginPackageTally)) - - } catch { - case e: MojoFailureException => throw e - case e: MojoExecutionException => throw e - case e: Exception => throw new MojoExecutionException("Failed generating osgi manifest.", e) - } - } - - //TODO: Tell which dependency overlaps - private def warnIfPackagesDefinedOverlapsGlobalPackages(internalPackages: Set[String], globalPackages: List[String]) { - val overlap = internalPackages intersect globalPackages.toSet - if (overlap.nonEmpty) - throw new MojoExecutionException( - "The following packages are both global and included in the bundle:\n%s".format(overlap map (" " + _) mkString ("\n"))) - } - - - def osgiExportPackages(exportedPackages: Map[String, ExportPackageAnnotation]): Iterable[String] = { - for ((name, annotation) <- exportedPackages) - yield name + ";version=" + annotation.osgiVersion - } - - def trimWhitespace(lines: Option[String]): String = { - lines.getOrElse("").split(",").map(_.trim).mkString(",") - } - - def manifestContent(project: MavenProject, jarArtifactsToInclude: Traversable[Artifact], - manualImports: Map[String, Option[String]], imports : Set[Import], - pluginPackageTally : PackageTally) = { - Map[String, String]( - "Created-By" -> "vespa container maven plugin", - "Bundle-ManifestVersion" -> "2", - "Bundle-Name" -> project.getName, - "Bundle-SymbolicName" -> bundleSymbolicName, - "Bundle-Version" -> asBundleVersion(bundleVersion), - "Bundle-Vendor" -> "Yahoo!", - "Bundle-ClassPath" -> bundleClassPath(jarArtifactsToInclude), - "Bundle-Activator" -> bundleActivator, - "X-JDisc-Privileged-Activator" -> jdiscPrivilegedActivator, - "Main-Class" -> mainClass, - "X-JDisc-Application" -> discApplicationClass, - "X-JDisc-Preinstall-Bundle" -> trimWhitespace(Option(discPreInstallBundle)), - "X-Config-Models" -> configModels, - "X-Jersey-Binding" -> jerseyBinding, - "WebInfUrl" -> webInfUrl, - "Import-Package" -> ((manualImports map asOsgiImport) ++ (imports map {_.asOsgiImport})).toList.sorted.mkString(","), - "Export-Package" -> osgiExportPackages(pluginPackageTally.exportedPackages).toList.sorted.mkString(",")) - .filterNot { case (key, value) => value == null || value.isEmpty } - - } - - def asOsgiImport(importSpec: (String, Option[String])) = importSpec match { - case (packageName, Some(version)) => packageName + ";version=" + quote(version) - case (packageName, None) => packageName - } - - def quote(s: String) = '"' + s + '"' - - def createManifestFile(outputDirectory: File, manifestContent: Map[String, String]) { - val manifest = toManifest(manifestContent) - - withFileOutputStream(new File(outputDirectory, JarFile.MANIFEST_NAME)) { - outputStream => - manifest.write(outputStream) - } - } - - def toManifest(manifestContent: Map[String, String]) = { - val manifest = new java.util.jar.Manifest - val mainAttributes = manifest.getMainAttributes - - mainAttributes.put(Attributes.Name.MANIFEST_VERSION, "1.0") - for ((key, value) <- manifestContent) - mainAttributes.putValue(key, value) - - manifest - } - - private def bundleClassPath(artifactsToInclude : Traversable[Artifact]) = - ("." +: artifactsToInclude.map(dependencyPath).toList).mkString(",") - - private def dependencyPath(artifact : Artifact) = - "dependencies/" + artifact.getFile.getName - - private def asBundleVersion(projectVersion: String) = { - require(projectVersion != null, "Missing project version.") - - val parts = projectVersion.split(Pattern.quote("-"), 2) - val numericPart = parts.head.split('.').map(Strings.emptyStringTo("0")).padTo(3, "0").toList - - val majorMinorMicro = numericPart take 3 - majorMinorMicro.mkString(".") - } - - private def warnOnUnsupportedArtifacts(nonJarArtifacts: Traversable[Artifact]) { - val unsupportedArtifacts = nonJarArtifacts.toSet.filter(_.getType != "pom") - - for (artifact <- unsupportedArtifacts) { - getLog.warn(s"Unsupported artifact '${artifact.getId}': Type '${artifact.getType}' is not supported. Please file a feature request.") - } - } - - private def analyzeProjectClasses() : PackageTally = { - val outputDirectory = new File(project.getBuild.getOutputDirectory) - - val analyzedClasses = allDescendantFiles(outputDirectory).filter(file => isClassToAnalyze(file.getName)). - map(Analyze.analyzeClass) - - PackageTally.fromAnalyzedClassFiles(analyzedClasses) - } - - def definedPackages(jarArtifacts: Iterable[Artifact]) : PackageTally = { - PackageTally.combine( - for (jarArtifact <- jarArtifacts) yield { - withJarFile(jarArtifact.getFile) { jarFile => - definedPackages(jarFile) - } - }) - } - - def definedPackages(jarFile: JarFile) = { - val analyzedClasses = - for { - entry <- toStream(jarFile.entries()) - if !entry.isDirectory - if isClassToAnalyze(entry.getName) - metaData = analyzeClass(jarFile, entry) - } yield metaData - - PackageTally.fromAnalyzedClassFiles(analyzedClasses) - } - - def analyzeClass(jarFile : JarFile, entry : JarEntry) = { - try { - withInputStream(jarFile, entry)(Analyze.analyzeClass) - } catch { - case e : Exception => - throw new MojoExecutionException( - "While analyzing the class '%s' in jar file '%s'".format(entry.getName, jarFile.getName), - e) - } - } -} - -object GenerateOsgiManifestMojo { - def getManualImports(importPackage: String): Map[String, Option[String]] = { - try { - (for { - importDirective <- parseImportPackages(importPackage) - packageName <- importDirective.packageNames - } yield packageName -> getVersionThrowOthers(importDirective.parameters)). - toMap - - } catch { - case e: Exception => throw new RuntimeException("Error in Import-Package:" + importPackage, e) - } - } - - def getVersionThrowOthers(parameters: List[ExportPackages.Parameter]): Option[String] = { - parameters match { - case List() => None - case List(ExportPackages.Parameter("version", v)) => Some(v) - case default => throw new RuntimeException("A single, optional version parameter expected, but got " + default) - } - } - - def parseImportPackages(importPackages: String): List[Export] = { - ExportPackageParser.parseAll(importPackages) match { - case ExportPackageParser.NoSuccess(msg, _) => throw new RuntimeException(msg) - case ExportPackageParser.Success(packages, _) => packages - } - } - - def isClassToAnalyze(name: String): Boolean = - name.endsWith(".class") && ! name.endsWith("module-info.class") - - def emptyToNone(str: String) = - Option(str) map {_.trim} filterNot {_.isEmpty} -} diff --git a/bundle-plugin/src/main/scala/com/yahoo/container/plugin/osgi/ExportPackageParser.scala b/bundle-plugin/src/main/scala/com/yahoo/container/plugin/osgi/ExportPackageParser.scala deleted file mode 100644 index 5cd93e84e87..00000000000 --- a/bundle-plugin/src/main/scala/com/yahoo/container/plugin/osgi/ExportPackageParser.scala +++ /dev/null @@ -1,89 +0,0 @@ -// 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.osgi - -import scala.util.parsing.combinator.JavaTokenParsers -import ExportPackages.{Parameter, Export} -import com.yahoo.container.plugin.util.Extractors.ListOf -import scala.util.parsing.input.CharSequenceReader -import scala.annotation.tailrec - -/** - * @author tonytv - */ -object ExportPackageParser extends JavaTokenParsers { - val ListOfParameter = new ListOf(classOf[Parameter]) - - - def exportPackage = rep1sep(export, ",") - - //TODO: remove when fix is in current scala library - //Fix for https://github.com/scala/scala-parser-combinators/pull/4 - def stringLiteral_fixed: Parser[String] = ("\""+"""([^"\p{Cntrl}\\]|\\[\\'"bfnrt]|\\u[a-fA-F0-9]{4})*+"""+"\"").r - - @SuppressWarnings(Array("unchecked")) - def export : Parser[Export] = packageName ~ opt(";" ~> (parameters | export)) ^^ { - case (packageName : String) ~ optional => { - optional match { - case None => Export(List(packageName.asInstanceOf[String]), List()) - case Some(e: Export) => e.copy(packageNames = packageName +: e.packageNames) - case Some(ListOfParameter(parameters)) => Export(List(packageName), parameters) - } - } - } - - def parameters = rep1sep(parameter, ";") - - def parameter = (directive | attribute) ^^ { - case k ~ v => Parameter(k.toString, v.toString) - } - - def directive = (extended_ <~ ":=") ~ argument - def attribute = (extended_ <~ "=") ~ argument - - def packageName = rep1sep(ident_, ".") ^^ { - x => x.mkString(".") - } - - def extended = rep1("""\p{Alnum}""".r | "_" | "-" | ".") ^^ { - _.mkString - } - - def argument = (extended_ | stringLiteral_ | failure("argument expected")) ^^ { - val quote = '"'.toString - _.toString.stripPrefix(quote).stripSuffix(quote) - } - - def parseAll(in: CharSequence): ParseResult[List[Export]] = { - try { - parseAll(exportPackage, in) - } catch { - case e: StackOverflowError => - throw new RuntimeException("Failed parsing Export-Package: '''\n" + in + "\n'''", e) - } - } - - //*** For debugging StackOverflow error **/ - def ident_ = printStackOverflow(ident)("ident") - def stringLiteral_ = printStackOverflow(stringLiteral_fixed)("stringLiteral_fixed") - def extended_ = printStackOverflow(extended)("extended") - - def printStackOverflow[T](p: => Parser[T])(name: String): Parser[T] = Parser{ in => - try { - p(in) - } catch { - case e: StackOverflowError => - val input = in match { - case reader: CharSequenceReader => readerToString(reader) - case other => other.toString - } - println(s"***StackOverflow for $name with input '''$input'''") - throw e - } - } - - @tailrec - def readerToString(reader: CharSequenceReader, current: String = ""): String = { - if (reader.atEnd) current - else readerToString(reader.rest, current + reader.first) - } -} diff --git a/bundle-plugin/src/main/scala/com/yahoo/container/plugin/osgi/ExportPackages.scala b/bundle-plugin/src/main/scala/com/yahoo/container/plugin/osgi/ExportPackages.scala deleted file mode 100644 index 4a973c0b9b1..00000000000 --- a/bundle-plugin/src/main/scala/com/yahoo/container/plugin/osgi/ExportPackages.scala +++ /dev/null @@ -1,27 +0,0 @@ -// 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.osgi - -/** - * @author tonytv - */ -object ExportPackages { - - case class Export(packageNames: List[String], parameters: List[Parameter]) { - def version: Option[String] = { - (for ( - param <- parameters if param.name == "version" - ) yield param.value). - headOption - } - } - - case class Parameter(name: String, value: String) - - def exportsByPackageName(exports: Seq[Export]): Map[String, Export] = { - (for { - export <- exports.reverse //ensure that earlier exports of a package overrides later exports. - packageName <- export.packageNames - } yield packageName -> export). - toMap - } -} diff --git a/bundle-plugin/src/main/scala/com/yahoo/container/plugin/osgi/ImportPackages.scala b/bundle-plugin/src/main/scala/com/yahoo/container/plugin/osgi/ImportPackages.scala deleted file mode 100644 index b6b47b954c0..00000000000 --- a/bundle-plugin/src/main/scala/com/yahoo/container/plugin/osgi/ImportPackages.scala +++ /dev/null @@ -1,51 +0,0 @@ -// 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.osgi - -import ExportPackages.Export -import util.control.Exception - -/** - * @author tonytv - */ -object ImportPackages { - case class Import(packageName : String, version : Option[String]) { - val majorMinorMicroVersion = Exception.handling(classOf[NumberFormatException]). - by( e => throw new IllegalArgumentException( - "Invalid version number '%s' for package '%s'.".format(version.get, packageName), e)) { - - version map { _.split('.') take 3 map {_.toInt} } - } - - def majorVersion = majorMinorMicroVersion map { _.head } - - // TODO: Detecting guava packages should be based on Bundle-SymbolicName, not package name. - def importVersionRange = { - def upperLimit = - if (isGuavaPackage) InfiniteVersion // guava increases major version for each release - else majorVersion.get + 1 - - version map (v => "[%s,%s)".format(majorMinorMicroVersion.get.mkString("."), upperLimit)) - } - - def isGuavaPackage = packageName.equals(GuavaBasePackage) || packageName.startsWith(GuavaBasePackage + ".") - - def asOsgiImport = packageName + (importVersionRange map {";version=\"" + _ + '"'} getOrElse("")) - } - - - val GuavaBasePackage = "com.google.common" - val InfiniteVersion = 99999 - - def calculateImports(referencedPackages : Set[String], - implementedPackages : Set[String], - exportedPackages : Map[String, Export]) : Map[String, Import] = { - (for { - undefinedPackage <- referencedPackages diff implementedPackages - export <- exportedPackages.get(undefinedPackage) - } yield undefinedPackage -> Import(undefinedPackage, version(export)))( - collection.breakOut) - } - - def version(export: Export): Option[String] = - export.parameters.find(_.name == "version").map(_.value) -} diff --git a/bundle-plugin/src/main/scala/com/yahoo/container/plugin/util/Extractors.scala b/bundle-plugin/src/main/scala/com/yahoo/container/plugin/util/Extractors.scala deleted file mode 100644 index 83f23f905fb..00000000000 --- a/bundle-plugin/src/main/scala/com/yahoo/container/plugin/util/Extractors.scala +++ /dev/null @@ -1,17 +0,0 @@ -// 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.util - -/** -* @author tonytv -*/ -object Extractors { - class ListOf[C](val c : Class[C]) { - def unapply[X](xs : X) : Option[List[C]] = { - xs match { - case x :: xr if c.isInstance(x) => unapply(xr) map ( c.cast(x) :: _) - case Nil => Some(Nil) - case _ => None - } - } - } -} diff --git a/bundle-plugin/src/main/scala/com/yahoo/container/plugin/util/Files.scala b/bundle-plugin/src/main/scala/com/yahoo/container/plugin/util/Files.scala deleted file mode 100644 index d32e57784da..00000000000 --- a/bundle-plugin/src/main/scala/com/yahoo/container/plugin/util/Files.scala +++ /dev/null @@ -1,23 +0,0 @@ -// 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.util - -import java.io.{FileOutputStream, File} -import com.yahoo.container.plugin.util.IO._ - -/** - * @author tonytv - */ -object Files { - def allDescendantFiles(file: File): Stream[File] = { - if (file.isFile) - Stream(file) - else if (file.isDirectory) - file.listFiles().toStream.map(allDescendantFiles).flatten - else - Stream.empty - } - - def withFileOutputStream[T](file: File)(f: FileOutputStream => T): T = { - using(new FileOutputStream(file), readOnly = false)(f) - } -} diff --git a/bundle-plugin/src/main/scala/com/yahoo/container/plugin/util/IO.scala b/bundle-plugin/src/main/scala/com/yahoo/container/plugin/util/IO.scala deleted file mode 100644 index 90f3eb3e7fd..00000000000 --- a/bundle-plugin/src/main/scala/com/yahoo/container/plugin/util/IO.scala +++ /dev/null @@ -1,46 +0,0 @@ -// 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.util - -import java.io.{Closeable, FileOutputStream, OutputStream, FileInputStream, File} -import util.control.Exception -import scala.Either - -/** Utility methods relating to IO - * @author tonytv - */ -object IO { - def withFileInputStream[T](file : File)(f : FileInputStream => T) = { - using(new FileInputStream(file), readOnly = true)(f) - } - - /** - * Creates a new file and all it's parent directories, - * and provides a file output stream to the file. - * - * Exceptions from closing have priority over exceptions from f. - */ - def withFileOutputStream[T](file: File)(f: OutputStream => T) { - makeDirectoriesRecursive(file.getParentFile) - using(new FileOutputStream(file), readOnly = false )(f) - } - - def makeDirectoriesRecursive(file: File) { - if (!file.mkdirs() && !file.isDirectory) { - throw new RuntimeException("Could not create directory " + file.getPath) - } - } - - def using[RESOURCE <: Closeable, T](resource : RESOURCE, readOnly : Boolean)(f : RESOURCE => T) : T = { - def catchPromiscuously = Exception.catchingPromiscuously(classOf[Throwable]) - - val resultOrException = catchPromiscuously either f(resource) - val closeException = Exception.allCatch either resource.close() - - prioritizeFirstException( - resultOrException, - if (readOnly) Right(()) else closeException) fold (throw _, identity) - } - - private def prioritizeFirstException[T](first: Either[Throwable, T], second: Either[Throwable, Unit]) = - first fold ( Left(_), value => second fold ( Left(_), _ => Right(value) ) ) -} diff --git a/bundle-plugin/src/main/scala/com/yahoo/container/plugin/util/Iteration.scala b/bundle-plugin/src/main/scala/com/yahoo/container/plugin/util/Iteration.scala deleted file mode 100644 index fa50f5cdd17..00000000000 --- a/bundle-plugin/src/main/scala/com/yahoo/container/plugin/util/Iteration.scala +++ /dev/null @@ -1,14 +0,0 @@ -// 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.util - - /** - * @author tonytv - */ -object Iteration { - def toStream[T](enumeration: java.util.Enumeration[T]): Stream[T] = { - if (enumeration.hasMoreElements) - Stream.cons(enumeration.nextElement(), toStream(enumeration)) - else - Stream.Empty - } -} diff --git a/bundle-plugin/src/main/scala/com/yahoo/container/plugin/util/JarFiles.scala b/bundle-plugin/src/main/scala/com/yahoo/container/plugin/util/JarFiles.scala deleted file mode 100644 index d7578f2b338..00000000000 --- a/bundle-plugin/src/main/scala/com/yahoo/container/plugin/util/JarFiles.scala +++ /dev/null @@ -1,24 +0,0 @@ -// 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.util - -import java.util.jar.JarFile -import java.util.zip.{ZipFile, ZipEntry} -import IO.using -import java.io.{Closeable, InputStream, File} - -/** - * @author tonytv - */ -object JarFiles { - def withJarFile[T](file : File)(f : JarFile => T ) : T = - using(new JarFile(file) with Closeable, readOnly = true)(f) - - def withInputStream[T](zipFile: ZipFile, zipEntry: ZipEntry)(f: InputStream => T): T = - using(zipFile.getInputStream(zipEntry), readOnly = true)(f) - - def getManifest(jarFile : File) : Option[java.util.jar.Manifest] = { - withJarFile(jarFile) { jar => - Option(jar.getManifest) - } - } -} diff --git a/bundle-plugin/src/main/scala/com/yahoo/container/plugin/util/Maps.scala b/bundle-plugin/src/main/scala/com/yahoo/container/plugin/util/Maps.scala deleted file mode 100644 index cafc8431b0e..00000000000 --- a/bundle-plugin/src/main/scala/com/yahoo/container/plugin/util/Maps.scala +++ /dev/null @@ -1,19 +0,0 @@ -// 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.util - -import collection.mutable.MultiMap - -/** - * @author tonytv - */ -object Maps { - def combine[K, V](map1 : Map[K, V], map2 : Map[K, V])(f : (V, V) => V) : Map[K, V] = { - def logicError : V = throw new RuntimeException("Logic error.") - def combineValues(key : K) = key -> f(map1.getOrElse(key, logicError), map2.getOrElse(key, logicError)) - - val keysInBoth = map1.keySet intersect map2.keySet - def notInBoth = !keysInBoth.contains(_ : K) - - map1.filterKeys(notInBoth) ++ map2.filterKeys(notInBoth) ++ keysInBoth.map(combineValues) - } -} diff --git a/bundle-plugin/src/main/scala/com/yahoo/container/plugin/util/Strings.scala b/bundle-plugin/src/main/scala/com/yahoo/container/plugin/util/Strings.scala deleted file mode 100644 index 5f854fda944..00000000000 --- a/bundle-plugin/src/main/scala/com/yahoo/container/plugin/util/Strings.scala +++ /dev/null @@ -1,14 +0,0 @@ -// 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.util - - /** - * @author tonytv - */ -object Strings { - def emptyStringTo(replacement: String)(s: String) = { - if (s.isEmpty) replacement - else s - } - - def noneIfEmpty(s: String) = Option(s).filterNot(_.isEmpty) -} |