Skip to content

Commit

Permalink
code maintenance and media-col value supported stuff
Browse files Browse the repository at this point in the history
  • Loading branch information
gmuth committed Nov 2, 2023
1 parent e7b6fb6 commit b654165
Show file tree
Hide file tree
Showing 44 changed files with 345 additions and 354 deletions.
34 changes: 20 additions & 14 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import org.jetbrains.dokka.gradle.DokkaTask
plugins {
id("org.jetbrains.kotlin.jvm") version "1.7.22"
id("org.jetbrains.dokka") version "1.7.20"
id("org.sonarqube") version "4.3.1.3277" // https://plugins.gradle.org/plugin/org.sonarqube
id("org.sonarqube") version "4.4.1.3373" // https://plugins.gradle.org/plugin/org.sonarqube
//id("org.sonarqube") version "3.5.0.2730" // supports java 8, dropped with 4.1
id("maven-publish")
id("java-library")
Expand Down Expand Up @@ -158,12 +158,17 @@ repo?.run { // tasks for publishing on maven repo
val isRunningOnGithub = System.getenv("CI")?.toBoolean() ?: false
println("isRunningOnGithub=$isRunningOnGithub")

// https://docs.gradle.org/current/userguide/jacoco_plugin.html
jacoco {
// https://mvnrepository.com/artifact/org.jacoco/jacoco-maven-plugin
toolVersion = "0.8.11"
}

// required for sonarqube code coverage
// https://docs.sonarqube.org/latest/analysis/test-coverage/java-test-coverage
tasks.jacocoTestReport {
dependsOn(tasks.test)
// https://stackoverflow.com/questions/67725347/jacoco-fails-on-gradle-7-0-2-and-kotlin-1-5-10
//version = "0.8.7"
reports {
xml.required.set(true)
csv.required.set(false)
Expand All @@ -175,18 +180,19 @@ tasks.jacocoTestReport {
// https://docs.sonarqube.org/latest/analysis/scan/sonarscanner-for-gradle/
// configure token with 'publish analysis' permission in file ~/.gradle/gradle.properties:
// systemProp.sonar.login=<token>
sonar {
properties {
property("sonar.host.url", "https://sonarcloud.io")
property("sonar.projectKey", "gmuth_ipp-client-kotlin")
property("sonar.organization", "gmuth")
//property("sonar.verbose", "true")
//property("sonar.junit.reportPaths", "build/test-results/test")
//property("sonar.jacoco.reportPaths", "build/jacoco/test.exec")
//property("sonar.coverage.jacoco.xmlReportPaths", "build/reports/jacoco/test/")
}
}

//sonar {
// properties {
// property("sonar.host.url", "https://sonarcloud.io")
// property("sonar.projectKey", "gmuth_ipp-client-kotlin")
// property("sonar.organization", "gmuth")
// //property("sonar.verbose", "true")
// //property("sonar.junit.reportPaths", "build/test-results/test")
// //property("sonar.jacoco.reportPaths", "build/jacoco/test.exec")
// //property("sonar.coverage.jacoco.xmlReportPaths", "build/reports/jacoco/test/")
// }
//}

// https://docs.sonarsource.com/sonarqube/latest/analyzing-source-code/scanners/sonarscanner-for-gradle/
tasks.sonar {
dependsOn(tasks.jacocoTestReport) // for coverage
}
Expand Down
7 changes: 6 additions & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,9 @@ org.gradle.jvmargs=-XX:MetaspaceSize=512M -XX:MaxMetaspaceSize=512M
# java -XX:+PrintFlagsFinal -version|grep MaxHeapSize
# Oracle-arm 11.0.5: MaxHeapSize = 2147483648

#org.gradle.daemon=false
#org.gradle.daemon=false

# sonarcloud
systemProp.sonar.host.url=https://sonarcloud.io
systemProp.sonar.projectKey=gmuth_ipp-client-kotlin
systemProp.sonar.organization=gmuth
3 changes: 1 addition & 2 deletions src/main/kotlin/de/gmuth/ipp/attributes/ColorMode.kt
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ class ColorMode(private val keyword: String) : IppAttributeBuilder {
else "Required attribute not found (print-color-mode-supported or output-mode-supported)"
)
},
Keyword,
keyword
Keyword, keyword
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,4 @@ class CommunicationChannel(
}
}
}

}
4 changes: 2 additions & 2 deletions src/main/kotlin/de/gmuth/ipp/attributes/Marker.kt
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,9 @@ class Marker(
UNKNOWN("#?");

companion object {
val log = getLogger(Color::class.java.name)
private val logger = getLogger(Color::class.java.name)
fun fromString(code: String) = values().find { it.code == code.uppercase() }
?: UNKNOWN.apply { log.warning { "Unknown color code: $code" } }
?: UNKNOWN.apply { logger.warning { "Unknown color code: $code" } }
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/main/kotlin/de/gmuth/ipp/attributes/MediaMargin.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ package de.gmuth.ipp.attributes
import de.gmuth.ipp.core.IppAttribute
import de.gmuth.ipp.core.IppTag.Integer

open class MediaMargin(
class MediaMargin(
val left: Int? = null,
val right: Int? = null,
val top: Int? = null,
Expand Down
12 changes: 6 additions & 6 deletions src/main/kotlin/de/gmuth/ipp/attributes/MediaSize.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ import de.gmuth.ipp.core.IppTag.Integer

// unit: 1/100 mm, e.g. 2540 = 1 inch
class MediaSize(val xDimension: Int, val yDimension: Int) : IppAttributeBuilder {
override fun buildIppAttribute(printerAttributes: IppAttributesGroup) =
IppAttribute(
"media-size", BegCollection, IppCollection(
IppAttribute("x-dimension", Integer, xDimension),
IppAttribute("y-dimension", Integer, yDimension)
)
override fun buildIppAttribute(printerAttributes: IppAttributesGroup) = IppAttribute(
"media-size", BegCollection,
IppCollection(
IppAttribute("x-dimension", Integer, xDimension),
IppAttribute("y-dimension", Integer, yDimension)
)
)
}
40 changes: 24 additions & 16 deletions src/main/kotlin/de/gmuth/ipp/attributes/MediaSource.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,33 @@ import de.gmuth.ipp.core.IppAttribute
import de.gmuth.ipp.core.IppAttributeBuilder
import de.gmuth.ipp.core.IppAttributesGroup
import de.gmuth.ipp.core.IppTag.Keyword
import java.util.logging.Logger.getLogger

open class MediaSource(val keyword: String) : IppAttributeBuilder {
class MediaSource(val keyword: String) : IppAttributeBuilder {

val log = getLogger(javaClass.name)
companion object {
@JvmField
val Auto = MediaSource("auto")

@JvmField
val Main = MediaSource("main")

@JvmField
val Manual = MediaSource("manual")

@JvmField
val Envelope = MediaSource("envelope")

@JvmField
val Alternate = MediaSource("alternate")

@JvmField
val ByPassTray = MediaSource("by-pass-tray")

@JvmField
val LargeCapacity = MediaSource("large-capacity")
}

override fun buildIppAttribute(printerAttributes: IppAttributesGroup) =
IppAttribute("media-source", Keyword, keyword)
.apply { validateSource(printerAttributes) }

private fun validateSource(printerAttributes: IppAttributesGroup) {
val mediaSourceSupported = printerAttributes["media-source-supported"]
if (mediaSourceSupported == null) {
log.fine { "printer does not provide attribute 'media-source-supported'" }
} else {
if (!mediaSourceSupported.values.contains(keyword)) {
log.warning { "media-source '$keyword' not supported by printer" }
log.warning { mediaSourceSupported.toString() }
}
}
}

}
2 changes: 1 addition & 1 deletion src/main/kotlin/de/gmuth/ipp/attributes/PrinterState.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ enum class PrinterState(val code: Int) : IppAttributeBuilder {
IppAttribute("printer-state", IppTag.Enum, code)

companion object {
private fun fromInt(code: Int) = values().single { it.code == code }
fun fromInt(code: Int) = values().single { it.code == code }
fun fromAttributes(attributes: IppAttributesGroup) = fromInt(attributes.getValue("printer-state"))
}

Expand Down
3 changes: 0 additions & 3 deletions src/main/kotlin/de/gmuth/ipp/attributes/PrinterType.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,10 @@ import de.gmuth.ipp.core.IppTag
import java.util.logging.Level
import java.util.logging.Level.INFO
import java.util.logging.Logger
import java.util.logging.Logger.getLogger

// https://www.cups.org/doc/spec-ipp.html
class PrinterType(val value: Int) : IppAttributeBuilder {

val log = getLogger(javaClass.name)

enum class Capability(val bit: Int, val description: String) {
IsAPrinterClass(0, "Is a printer class."),
IsARemoteDestination(1, "Is a remote destination."),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,13 @@ object TemplateAttributes {
fun mediaSource(keyword: String) =
IppAttribute("media-source", Keyword, keyword)

@JvmStatic // input tray
fun mediaColWithSource(mediaSource: MediaSource) =
MediaCollection(source = mediaSource)

@JvmStatic // input tray
fun mediaColWithSource(keyword: String) =
MediaCollection(source = MediaSource(keyword))
mediaColWithSource(MediaSource(keyword))

@JvmStatic // unit: hundreds of mm
fun mediaColWithSize(xDimension: Int, yDimension: Int) =
Expand Down
34 changes: 17 additions & 17 deletions src/main/kotlin/de/gmuth/ipp/client/CupsClient.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class CupsClient(
) {
constructor(host: String = "localhost") : this(URI.create("ipp://$host"))

private val log = getLogger(javaClass.name)
private val logger = getLogger(javaClass.name)
val config: IppConfig by ippClient::config
var userName: String? by config::userName
var cupsClientWorkDirectory = File("CUPS/${cupsUri.host}")
Expand All @@ -40,7 +40,7 @@ class CupsClient(

private fun cupsPrinterUri(printerName: String) =
cupsUri.run { URI("$scheme://$host${if (port > 0) ":$port" else ""}/printers/$printerName") }
.apply { log.finer { "cupsPrinterUri($printerName) = $this" } }
.apply { logger.finer { "cupsPrinterUri($printerName) = $this" } }

val version: String by lazy {
getPrinters().run {
Expand Down Expand Up @@ -70,7 +70,7 @@ class CupsClient(
.apply { workDirectory = cupsClientWorkDirectory }
} catch (clientErrorNotFoundException: ClientErrorNotFoundException) {
with(getPrinters()) {
if (isNotEmpty()) log.warning { "Available CUPS printers: ${map { it.name }}" }
if (isNotEmpty()) logger.warning { "Available CUPS printers: ${map { it.name }}" }
}
throw clientErrorNotFoundException
}
Expand Down Expand Up @@ -105,7 +105,7 @@ class CupsClient(

fun deletePrinter(printerName: String) =
exchange(cupsPrinterRequest(CupsDeletePrinter, printerName))
.apply { log.info { "Printer deleted: $printerName" } }
.apply { logger.info { "Printer deleted: $printerName" } }

// https://www.cups.org/doc/spec-ipp.html#CUPS_CREATE_LOCAL_PRINTER
fun createLocalPrinter(
Expand All @@ -126,7 +126,7 @@ class CupsClient(
ppdName
)
).run {
log.info { "$statusMessage ${printerGroup.getValues<Any>("printer-uri-supported")}" }
logger.info { "$statusMessage ${printerGroup.getValues<Any>("printer-uri-supported")}" }
return IppPrinter(printerGroup, ippClient)
}
}
Expand Down Expand Up @@ -219,18 +219,18 @@ class CupsClient(
ppdName = "everywhere"
).apply {
updateAttributes("printer-name")
log.info(toString())
log.info { "CUPS now generates IPP Everywhere PPD." } // https://github.com/apple/cups/issues/5919
logger.info(toString())
logger.info { "CUPS now generates IPP Everywhere PPD." } // https://github.com/apple/cups/issues/5919
do {
updateAttributes("printer-make-and-model")
Thread.sleep(500)
} while (!makeAndModel.text.lowercase().contains("everywhere"))
log.info { "Make printer permanent." }
logger.info { "Make printer permanent." }
exchange(
cupsPrinterRequest(CupsAddModifyPrinter, printerName)
.apply { printerGroup.attribute("printer-is-temporary", IppTag.Boolean, false) }
)
log.info { "Make printer operational." }
logger.info { "Make printer operational." }
enable()
resume()
updateAttributes()
Expand Down Expand Up @@ -263,7 +263,7 @@ class CupsClient(
)
.onEach { job -> // update attributes and lookup job owners
if (updateJobAttributes) job.updateAttributes()
log.info { job.toString() }
logger.info { job.toString() }
job.getOriginatingUserNameOrAppleJobOwnerOrNull()?.let { jobOwners.add(it) }
}
.onEach { job -> // keep stats and save documents
Expand All @@ -272,9 +272,9 @@ class CupsClient(
.apply { numberOfSavedDocuments.addAndGet(size) }
}
.apply {
log.info { "Found ${jobOwners.size} job ${if (jobOwners.size == 1) "owner" else "owners"}: $jobOwners" }
log.info { "Found $size jobs (which=$whichJobs) where $numberOfJobsWithoutDocuments jobs have no documents" }
log.info { "Saved $numberOfSavedDocuments documents of ${size.minus(numberOfJobsWithoutDocuments.toInt())} jobs with documents to directory: ${cupsServer.workDirectory}" }
logger.info { "Found ${jobOwners.size} job ${if (jobOwners.size == 1) "owner" else "owners"}: $jobOwners" }
logger.info { "Found $size jobs (which=$whichJobs) where $numberOfJobsWithoutDocuments jobs have no documents" }
logger.info { "Saved $numberOfSavedDocuments documents of ${size.minus(numberOfJobsWithoutDocuments.toInt())} jobs with documents to directory: ${cupsServer.workDirectory}" }
}
}

Expand All @@ -292,10 +292,10 @@ class CupsClient(
) {
createSubscription(whichJobEvents, notifyLeaseDuration = leaseDuration)
.pollAndHandleNotifications(pollEvery, autoRenewSubscription = autoRenewLease) { event ->
log.info { event.toString() }
logger.info { event.toString() }
with(event.getJob()) {
while (isIncoming()) {
log.info { toString() }
logger.info { toString() }
Thread.sleep(1000)
updateAttributes()
}
Expand All @@ -319,15 +319,15 @@ class CupsClient(
if (documents.isNotEmpty() && onSuccessUpdateJobAttributes) job.updateAttributes()
true
} catch (ippExchangeException: IppExchangeException) {
log.info { "Get documents for job #${job.id} failed: ${ippExchangeException.message}" }
logger.info { "Get documents for job #${job.id} failed: ${ippExchangeException.message}" }
ippExchangeException.httpStatus!! != 401
}

if (!getDocuments()) {
val configuredUserName = config.userName
jobOwners.forEach {
config.userName = it
log.fine { "set userName '${config.userName}'" }
logger.fine { "set userName '${config.userName}'" }
if (getDocuments()) return@forEach
}
config.userName = configuredUserName
Expand Down
Loading

0 comments on commit b654165

Please sign in to comment.