-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/modules/samples-java.iml b/.idea/modules/samples-java.iml
deleted file mode 100644
index 19b4065..0000000
--- a/.idea/modules/samples-java.iml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/modules/samples-java.main.iml b/.idea/modules/samples-java.main.iml
deleted file mode 100644
index 9a2896e..0000000
--- a/.idea/modules/samples-java.main.iml
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/modules/samples-java.test.iml b/.idea/modules/samples-java.test.iml
deleted file mode 100644
index 100a3c5..0000000
--- a/.idea/modules/samples-java.test.iml
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/runConfigurations/Run Tests.xml b/.idea/runConfigurations/Run Tests.xml
new file mode 100644
index 0000000..2d4326e
--- /dev/null
+++ b/.idea/runConfigurations/Run Tests.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/scopes/Source.xml b/.idea/scopes/Source.xml
deleted file mode 100644
index 942e059..0000000
--- a/.idea/scopes/Source.xml
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
\ No newline at end of file
diff --git a/.idea/uiDesigner.xml b/.idea/uiDesigner.xml
deleted file mode 100644
index e96534f..0000000
--- a/.idea/uiDesigner.xml
+++ /dev/null
@@ -1,124 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
index 94a25f7..35eb1dd 100644
--- a/.idea/vcs.xml
+++ b/.idea/vcs.xml
@@ -1,6 +1,6 @@
-
+
\ No newline at end of file
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 48c5805..0000000
--- a/.travis.yml
+++ /dev/null
@@ -1,26 +0,0 @@
-language: java
-dist: trusty
-
-env:
- global:
- - CI=true
-
-#install:
-# - git fetch --unshallow --tags
-
-addons:
- sonarcloud:
- organization: "ethauvin-github"
-
-jdk:
- - oraclejdk8
- - openjdk14
-
-before_install:
- - chmod +x gradlew
-
-after_success:
- - |
- if [ "${TRAVIS_TEST_RESULT}" == 0 ] && [ "$TRAVIS_JDK_VERSION" == "openjdk14" ]; then
- ./gradlew sonarqube
- fi
diff --git a/.vscode/launch.json b/.vscode/launch.json
new file mode 100644
index 0000000..f25500c
--- /dev/null
+++ b/.vscode/launch.json
@@ -0,0 +1,11 @@
+{
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "type": "java",
+ "name": "Run Tests",
+ "request": "launch",
+ "mainClass": "net.thauvin.erik.pinboard.PinboardPosterTest"
+ }
+ ]
+}
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..ba429d0
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,15 @@
+{
+ "java.project.sourcePaths": [
+ "src/main/java",
+ "src/main/resources",
+ "src/test/java",
+ "src/test/resources",
+ "src/bld/java",
+ "src/bld/resources"
+ ],
+ "java.configuration.updateBuildConfiguration": "automatic",
+ "java.project.referencedLibraries": [
+ "${HOME}/.bld/dist/bld-2.2.1.jar",
+ "lib/**/*.jar"
+ ]
+}
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 366e7bd..9c318e1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,26 @@
# Changelog
-## [1.0.2](https://github.com/ethauvin/pinboard-poster/tree/1.0.2) (2021-03-21)
+## [1.1.0](https://github.com/ethauvin/pinboard-poster/tree/1.1.0) (2023-09-28)
+
+[Full Changelog](https://github.com/ethauvin/pinboard-poster/compare/1.0.3...1.1.0)
+
+**Implemented enhancements:**
+
+- Add pin config builder [\#10](https://github.com/ethauvin/pinboard-poster/issues/10)
+
+**Fixed bugs:**
+
+- Fixed potential resource leak [\#11](https://github.com/ethauvin/pinboard-poster/issues/11)
+
+## [1.0.3](https://github.com/ethauvin/pinboard-poster/tree/1.0.3) (2021-03-22)
+
+[Full Changelog](https://github.com/ethauvin/pinboard-poster/compare/1.0.2...1.0.3)
+
+**Fixed bugs:**
+
+- 1.0.2 only compiled for Java 15 [\#4](https://github.com/ethauvin/pinboard-poster/issues/4)
+
+## [1.0.2](https://github.com/ethauvin/pinboard-poster/tree/1.0.2) (2021-03-22)
[Full Changelog](https://github.com/ethauvin/pinboard-poster/compare/1.0.1...1.0.2)
diff --git a/LICENSE.txt b/LICENSE.txt
index 8e33202..9926d00 100644
--- a/LICENSE.txt
+++ b/LICENSE.txt
@@ -1,4 +1,4 @@
-Copyright (c) 2017-2021, Erik C. Thauvin (erik@thauvin.net)
+Copyright (c) 2017-2025, Erik C. Thauvin (erik@thauvin.net)
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/README.md b/README.md
index 1d2bd5a..cdf7df5 100644
--- a/README.md
+++ b/README.md
@@ -1,10 +1,18 @@
-# [Pinboard](https://pinboard.in) Poster for Kotlin/Java
+# [Pinboard](https://pinboard.in) Poster for Kotlin, Java and Android
-[](http://opensource.org/licenses/BSD-3-Clause) [](https://github.com/ethauvin/pinboard-poster/releases/latest) [](https://search.maven.org/search?q=g:%22net.thauvin.erik%22%20AND%20a:%22pinboard-poster%22)
+[](https://opensource.org/licenses/BSD-3-Clause)
+[](https://kotlinlang.org/)
+[](https://rife2.com/bld)
+[](https://github.com/ethauvin/pinboard-poster/releases/latest)
+[](https://central.sonatype.com/artifact/net.thauvin.erik/pinboard-poster)
+[](https://oss.sonatype.org/content/repositories/snapshots/net/thauvin/erik/pinboard-poster/)
-[](https://snyk.io/test/github/ethauvin/pinboard-poster?targetFile=pom.xml) [](https://sonarcloud.io/dashboard?id=ethauvin_pinboard-poster) [](https://travis-ci.com/ethauvin/pinboard-poster) [](https://circleci.com/gh/ethauvin/pinboard-poster/tree/master)
-A small Kotlin/Java/Android library for posting to [Pinboard](https://pinboard.in).
+[](https://sonarcloud.io/dashboard?id=ethauvin_pinboard-poster)
+[](https://github.com/ethauvin/pinboard-poster/actions/workflows/bld.yml)
+[](https://circleci.com/gh/ethauvin/pinboard-poster/tree/master)
+
+A small library for posting to [Pinboard](https://pinboard.in).
## Examples
@@ -14,51 +22,80 @@ A small Kotlin/Java/Android library for posting to [Pinboard](https://pinboard.i
val poster = PinboardPoster("user:TOKEN")
-poster.addPin("http://www.example.com/foo", "This is a test")
-poster.deletePin("http:///www.example.com/bar")
+poster.addPin("https://example.com/foo", "This is a test")
+poster.addPin("https://example.com", "This is a test", tags = arrayOf("foo", "bar"))
+poster.deletePin("https://example.com/bar")
```
-[View Example](https://github.com/ethauvin/pinboard-poster/blob/master/samples/kotlin/src/main/kotlin/net/thauvin/erik/pinboard/samples/KotlinExample.kt)
+
+[View Examples](https://github.com/ethauvin/pinboard-poster/blob/master/examples)
### Java
+
```java
final PinboardPoster poster = new PinBboardPoster("user:TOKEN");
-poster.addPin("http://www.example.com/foo", "This is a test");
-poster.deletePin("http:///www.example.com/bar");
+poster.addPin("https://example.com/foo", "This is a test");
+poster.addPin(new PinConfig.Builder("https://example.com", "This is a test")
+ .tags("foo", "bar")
+ .build());
+poster.deletePin("https://example.com/bar");
```
-[View Example](https://github.com/ethauvin/pinboard-poster/blob/master/samples/java/src/main/java/net/thauvin/erik/pinboard/samples/JavaExample.java)
+
+[View Examples](https://github.com/ethauvin/pinboard-poster/blob/master/examples)
Your API authentication token is available on the [Pinboard settings page](https://pinboard.in/settings/password).
-## Usage with Gradle, Maven, etc.
+## bld
-To install and run from Gradle, add the following to the build.gradle file:
+To use with [bld](https://rife2.com/bld), include the following dependency in your [build](https://github.com/ethauvin/pinboard-poster/blob/master/examples/bld/src/bld/java/net/thauvin/erik/pinboard/samples/ExampleBuild.java) file:
+
+```java
+repositories = List.of(MAVEN_CENTRAL, SONATYPE_SNAPSHOTS_LEGACY);
+
+scope(compile)
+ .include(dependency("net.thauvin.erik:pinboard-poster:1.2.0"));
+```
+Be sure to use the [bld Kotlin extension](https://github.com/rife2/bld-kotlin) in your project.
+
+[View Example](https://github.com/ethauvin/pinboard-poster/blob/master/examples/bld/)
+
+## Gradle, Maven, etc.
+
+To install and run from Gradle, add the following to the `build.gradle` file:
```gradle
+repositories {
+ mavenCentral()
+}
+
dependencies {
- compile 'net.thauvin.erik:pinboard-poster:1.0.3'
+ compile 'net.thauvin.erik:pinboard-poster:1.2.0'
}
```
-[View Example](https://github.com/ethauvin/pinboard-poster/blob/master/samples/java/build.gradle)
-[View Kotlin DSL Example](https://github.com/ethauvin/pinboard-poster/blob/master/samples/kotlin/build.gradle.kts)
-Instructions for using with Maven, Ivy, etc. can be found on [Maven Central](https://search.maven.org/artifact/net.thauvin.erik/pinboard-poster/1.0.3/jar).
+[View Examples](https://github.com/ethauvin/pinboard-poster/blob/master/examples/gradle/)
+
+Instructions for using with Maven, Ivy, etc. can be found on [Maven Central](https://central.sonatype.com/artifact/net.thauvin.erik/pinboard-poster).
## Adding
The `addPin` function support all of the [Pinboard API parameters](https://pinboard.in/api/#posts_add):
```kotlin
-poster.addPin(url = "http://www.example.com",
- description = "This is the title",
- extended = "This is the extended description.",
- tags = "tag1 tag2 tag3",
- dt = "2010-12-11T19:48:02Z",
- replace = true,
- shared = true,
- toRead = false)
+import java.time.ZonedDateTime
+
+poster.addPin(
+ url = "https://www.example.com",
+ description = "This is the title",
+ extended = "This is the extended description.",
+ tags = arrayOf("tag1", "tag2", "tag3"),
+ dt = ZonedDateTime.now(),
+ replace = true,
+ shared = true,
+ toRead = false
+)
```
`url` and `description` are required.
@@ -70,7 +107,7 @@ It returns `true` if the bookmark was added successfully, `false` otherwise.
The `deletePin` function support all of the [Pinboard API parameters](https://pinboard.in/api/#posts_delete):
```kotlin
-poster.deletePin(url = "http://www.example.com/")
+poster.deletePin(url = "https://www.example.com/")
```
It returns `true` if the bookmark was deleted successfully, `false` otherwise.
@@ -80,19 +117,24 @@ It returns `true` if the bookmark was deleted successfully, `false` otherwise.
The library used [`java.util.logging`](https://docs.oracle.com/javase/8/docs/api/java/util/logging/package-summary.html) to log errors. Logging can be configured as follows:
#### Kotlin
+
```kotlin
with(poster.logger) {
addHandler(ConsoleHandler().apply { level = Level.FINE })
level = Level.FINE
+ useParentHandlers = false
}
```
+
#### Java
+
```java
final ConsoleHandler consoleHandler = new ConsoleHandler();
consoleHandler.setLevel(Level.FINE);
final Logger logger = poster.getLogger();
logger.addHandler(consoleHandler);
logger.setLevel(Level.FINE);
+logger.setUseParentHandlers(false);
```
or using a logging properties file.
@@ -155,3 +197,21 @@ The API end point is automatically configured to `https://api.pinboard.in/v1/`.
```kotlin
poster.apiEndPoint = "https://www.example.com/v1"
```
+
+## Contributing
+
+If you want to contribute to this project, all you have to do is clone the GitHub
+repository:
+
+```console
+git clone git@github.com:ethauvin/pinboard-poster.git
+```
+
+Then use [bld](https://rife2.com/bld) to build:
+
+```console
+cd pinboard-poster
+./bld compile
+```
+
+The project has an [IntelliJ IDEA](https://www.jetbrains.com/idea/) project structure. You can just open it after all the dependencies were downloaded and peruse the code.
diff --git a/bitbucket-pipelines.yml b/bitbucket-pipelines.yml
index 7d98402..ace99d2 100644
--- a/bitbucket-pipelines.yml
+++ b/bitbucket-pipelines.yml
@@ -1,9 +1,20 @@
-image: openjdk:8
+image: ubuntu:latest
pipelines:
default:
- step:
- caches:
- - gradle
+ name: Test with bld
script:
- - bash ./gradlew check
+ # Install latest Java & Kotlin via SDKMAN!
+ - apt-get update -qq && apt-get install -y curl zip
+ - curl -s "https://get.sdkman.io" | bash
+ - echo sdkman_auto_answer=true > $HOME/.sdkman/etc/config
+ - echo sdkman_auto_selfupdate=true >> $HOME/.sdkman/etc/config
+ - source "$HOME/.sdkman/bin/sdkman-init.sh"
+ - sdk install java
+ - sdk install kotlin
+ - source "$HOME/.sdkman/bin/sdkman-init.sh"
+ # Download, compile and test with bld
+ - ./bld download
+ - ./bld compile
+ - ./bld test
diff --git a/bld b/bld
new file mode 100755
index 0000000..3c1df97
--- /dev/null
+++ b/bld
@@ -0,0 +1,2 @@
+#!/usr/bin/env sh
+java -jar "$(dirname "$0")/lib/bld/bld-wrapper.jar" "$0" --build net.thauvin.erik.pinboard.PinboardPosterBuild "$@"
diff --git a/bld.bat b/bld.bat
new file mode 100644
index 0000000..1262822
--- /dev/null
+++ b/bld.bat
@@ -0,0 +1,4 @@
+@echo off
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+java -jar "%DIRNAME%/lib/bld/bld-wrapper.jar" "%0" --build net.thauvin.erik.pinboard.PinboardPosterBuild %*
diff --git a/build.gradle.kts b/build.gradle.kts
deleted file mode 100644
index 01b2d22..0000000
--- a/build.gradle.kts
+++ /dev/null
@@ -1,194 +0,0 @@
-import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
-
-plugins {
- jacoco
- java
- kotlin("jvm") version "1.4.31"
- `maven-publish`
- signing
- id("com.github.ben-manes.versions") version "0.38.0"
- id("io.gitlab.arturbosch.detekt") version "1.16.0"
- id("org.jetbrains.dokka") version "1.4.30"
- id("org.sonarqube") version "3.1.1"
-}
-
-group = "net.thauvin.erik"
-version = "1.0.3"
-description = "Pinboard Poster for Kotlin/Java"
-
-val gitHub = "ethauvin/$name"
-val mavenUrl = "https://github.com/$gitHub"
-val deployDir = "deploy"
-var isRelease = "release" in gradle.startParameter.taskNames
-
-val publicationName = "mavenJava"
-
-object VersionInfo {
- const val okhttp = "4.9.1"
-}
-
-val versions: VersionInfo by extra { VersionInfo }
-
-repositories {
- mavenCentral()
- jcenter() // needed for Dokka
-}
-
-dependencies {
- implementation("com.squareup.okhttp3:okhttp:${versions.okhttp}")
- implementation("com.squareup.okhttp3:logging-interceptor:${versions.okhttp}")
-
- testImplementation("org.testng:testng:7.4.0")
-}
-
-java {
- sourceCompatibility = JavaVersion.VERSION_1_8
- targetCompatibility = JavaVersion.VERSION_1_8
- withSourcesJar()
-}
-
-detekt {
- baseline = project.rootDir.resolve("config/detekt/baseline.xml")
-}
-
-sonarqube {
- properties {
- property("sonar.projectKey", "ethauvin_pinboard-poster")
- property("sonar.sourceEncoding", "UTF-8")
- }
-}
-
-val javadocJar by tasks.creating(Jar::class) {
- dependsOn(tasks.dokkaJavadoc)
- from(tasks.dokkaJavadoc)
- archiveClassifier.set("javadoc")
- description = "Assembles a JAR of the generated Javadoc."
- group = JavaBasePlugin.DOCUMENTATION_GROUP
-}
-
-tasks {
- withType {
- useTestNG()
- }
-
- withType {
- reports {
- xml.isEnabled = true
- html.isEnabled = true
- }
- }
-
- withType {
- kotlinOptions.jvmTarget = "1.8"
- }
-
- withType {
- destination = file("$projectDir/pom.xml")
- }
-
- assemble {
- dependsOn(javadocJar)
- }
-
- clean {
- doLast {
- project.delete(fileTree(deployDir))
- }
- }
-
- val copyToDeploy by registering(Copy::class) {
- from(configurations.runtime) {
- exclude("annotations-*.jar")
- }
- from(jar)
- into(deployDir)
- }
-
- register("deploy") {
- description = "Copies all needed files to the $deployDir directory."
- group = PublishingPlugin.PUBLISH_TASK_GROUP
- dependsOn("build", "jar")
- outputs.dir(deployDir)
- inputs.files(copyToDeploy)
- mustRunAfter("clean")
- }
-
- val gitIsDirty by registering(Exec::class) {
- description = "Fails if git has uncommitted changes."
- group = "verification"
- commandLine("git", "diff", "--quiet", "--exit-code")
- }
-
- val gitTag by registering(Exec::class) {
- description = "Tags the local repository with version ${project.version}"
- group = PublishingPlugin.PUBLISH_TASK_GROUP
- dependsOn(gitIsDirty)
- if (isRelease) {
- commandLine("git", "tag", "-a", project.version, "-m", "Version ${project.version}")
- }
- }
-
- buildScan {
- termsOfServiceUrl = "https://gradle.com/terms-of-service"
- setTermsOfServiceAgree("yes")
- }
-
- register("release") {
- description = "Publishes version ${project.version} to local repository."
- group = PublishingPlugin.PUBLISH_TASK_GROUP
- dependsOn("wrapper", "deploy", "gitTag", "publishToMavenLocal")
- }
-
- "sonarqube" {
- dependsOn("jacocoTestReport")
- }
-}
-
-publishing {
- publications {
- create(publicationName) {
- from(components["java"])
- artifact(javadocJar)
- pom {
- name.set(project.name)
- description.set(project.description)
- url.set(mavenUrl)
- licenses {
- license {
- name.set("BSD 3-Clause")
- url.set("https://opensource.org/licenses/BSD-3-Clause")
- }
- }
- developers {
- developer {
- id.set("ethauvin")
- name.set("Erik C. Thauvin")
- email.set("erik@thauvin.net")
- url.set("https://erik.thauvin.net/")
- }
- }
- scm {
- connection.set("scm:git:git://github.com/$gitHub.git")
- developerConnection.set("scm:git:git@github.com:$gitHub.git")
- url.set("$mavenUrl")
- }
- issueManagement {
- system.set("GitHub")
- url.set("$mavenUrl/issues")
- }
- }
- }
- }
- repositories {
- maven {
- name = "ossrh"
- url = uri("https://oss.sonatype.org/service/local/staging/deploy/maven2/")
- credentials(PasswordCredentials::class)
- }
- }
-}
-
-signing {
- useGpgCmd()
- sign(publishing.publications[publicationName])
-}
diff --git a/config/detekt/baseline.xml b/config/detekt/baseline.xml
index 23161d0..3f97ec1 100644
--- a/config/detekt/baseline.xml
+++ b/config/detekt/baseline.xml
@@ -1,11 +1,11 @@
-
-
- ComplexMethod:PinboardPoster.kt$PinboardPoster$private fun executeMethod(method: String, params: List<Pair<String, String>>): Boolean
- LongParameterList:PinboardPoster.kt$PinboardPoster$( url: String, description: String, extended: String = "", tags: String = "", dt: String = "", replace: Boolean = true, shared: Boolean = true, toRead: Boolean = false )
- NestedBlockDepth:PinboardPoster.kt$PinboardPoster$private fun executeMethod(method: String, params: List<Pair<String, String>>): Boolean
- ThrowsCount:PinboardPoster.kt$PinboardPoster$internal fun parseMethodResponse(method: String, response: String)
- TooGenericExceptionCaught:PinboardPoster.kt$PinboardPoster$e: Exception
-
-
\ No newline at end of file
+
+
+ LongParameterList:PinConfig.kt$PinConfig$( var url: String, var description: String, var extended: String = "", var tags: Array<out String> = emptyArray(), var dt: ZonedDateTime = ZonedDateTime.now(), var replace: Boolean = true, var shared: Boolean = true, var toRead: Boolean = false )
+ LongParameterList:PinboardPoster.kt$PinboardPoster$( url: String, description: String, extended: String = "", vararg tags: String = emptyArray(), dt: ZonedDateTime = ZonedDateTime.now(), replace: Boolean = true, shared: Boolean = true, toRead: Boolean = false )
+ NestedBlockDepth:PinboardPoster.kt$PinboardPoster$private fun executeMethod(method: String, params: Map<String, String>): Boolean
+ ThrowsCount:PinboardPoster.kt$PinboardPoster$@Throws(IOException::class) internal fun parseMethodResponse(method: String, response: String)
+ TooManyFunctions:PinConfig.kt$PinConfig$Builder
+
+
diff --git a/examples/bld/.gitignore b/examples/bld/.gitignore
new file mode 100644
index 0000000..a2805aa
--- /dev/null
+++ b/examples/bld/.gitignore
@@ -0,0 +1,55 @@
+.gradle
+.DS_Store
+build
+lib/bld/**
+!lib/bld/bld-wrapper.jar
+!lib/bld/bld-wrapper.properties
+lib/compile/
+lib/runtime/
+lib/standalone/
+lib/test/
+
+# IDEA ignores
+
+# User-specific
+.idea/**/workspace.xml
+.idea/**/tasks.xml
+.idea/**/usage.statistics.xml
+.idea/**/dictionaries
+.idea/**/shelf
+
+# AWS User-specific
+.idea/**/aws.xml
+
+# Generated files
+.idea/**/contentModel.xml
+
+# Sensitive or high-churn files
+.idea/**/dataSources/
+.idea/**/dataSources.ids
+.idea/**/dataSources.local.xml
+.idea/**/sqlDataSources.xml
+.idea/**/dynamic.xml
+.idea/**/uiDesigner.xml
+.idea/**/dbnavigator.xml
+
+# Gradle
+.idea/**/gradle.xml
+
+# Mongo Explorer plugin
+.idea/**/mongoSettings.xml
+
+# mpeltonen/sbt-idea plugin
+.idea_modules/
+
+# JIRA plugin
+atlassian-ide-plugin.xml
+
+# Cursive Clojure plugin
+.idea/replstate.xml
+
+# SonarLint plugin
+.idea/sonarlint/
+
+# Editor-based Rest Client
+.idea/httpRequests
\ No newline at end of file
diff --git a/examples/bld/.idea/.gitignore b/examples/bld/.idea/.gitignore
new file mode 100644
index 0000000..26d3352
--- /dev/null
+++ b/examples/bld/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/examples/bld/.idea/.name b/examples/bld/.idea/.name
new file mode 100644
index 0000000..6782949
--- /dev/null
+++ b/examples/bld/.idea/.name
@@ -0,0 +1 @@
+pinboard-poster-examples-bld
\ No newline at end of file
diff --git a/examples/bld/.idea/app.iml b/examples/bld/.idea/app.iml
new file mode 100644
index 0000000..2d05353
--- /dev/null
+++ b/examples/bld/.idea/app.iml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/examples/bld/.idea/bld.iml b/examples/bld/.idea/bld.iml
new file mode 100644
index 0000000..e63e11e
--- /dev/null
+++ b/examples/bld/.idea/bld.iml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/examples/bld/.idea/bld.xml b/examples/bld/.idea/bld.xml
new file mode 100644
index 0000000..6600cee
--- /dev/null
+++ b/examples/bld/.idea/bld.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/examples/bld/.idea/inspectionProfiles/Project_Default.xml b/examples/bld/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000..1e01b48
--- /dev/null
+++ b/examples/bld/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/examples/bld/.idea/libraries/bld.xml b/examples/bld/.idea/libraries/bld.xml
new file mode 100644
index 0000000..153a060
--- /dev/null
+++ b/examples/bld/.idea/libraries/bld.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/examples/bld/.idea/libraries/compile.xml b/examples/bld/.idea/libraries/compile.xml
new file mode 100644
index 0000000..99cc0c0
--- /dev/null
+++ b/examples/bld/.idea/libraries/compile.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/examples/bld/.idea/libraries/runtime.xml b/examples/bld/.idea/libraries/runtime.xml
new file mode 100644
index 0000000..d4069f2
--- /dev/null
+++ b/examples/bld/.idea/libraries/runtime.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/examples/bld/.idea/libraries/test.xml b/examples/bld/.idea/libraries/test.xml
new file mode 100644
index 0000000..57ed5ef
--- /dev/null
+++ b/examples/bld/.idea/libraries/test.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/examples/bld/.idea/misc.xml b/examples/bld/.idea/misc.xml
new file mode 100644
index 0000000..f522a9e
--- /dev/null
+++ b/examples/bld/.idea/misc.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
diff --git a/examples/bld/.idea/modules.xml b/examples/bld/.idea/modules.xml
new file mode 100644
index 0000000..55adcb9
--- /dev/null
+++ b/examples/bld/.idea/modules.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/examples/bld/.idea/runConfigurations/Run Tests.xml b/examples/bld/.idea/runConfigurations/Run Tests.xml
new file mode 100644
index 0000000..e5f873f
--- /dev/null
+++ b/examples/bld/.idea/runConfigurations/Run Tests.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/examples/bld/.idea/vcs.xml b/examples/bld/.idea/vcs.xml
new file mode 100644
index 0000000..b2bdec2
--- /dev/null
+++ b/examples/bld/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/examples/bld/.vscode/launch.json b/examples/bld/.vscode/launch.json
new file mode 100644
index 0000000..b183bbe
--- /dev/null
+++ b/examples/bld/.vscode/launch.json
@@ -0,0 +1,11 @@
+{
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "type": "java",
+ "name": "Run Tests",
+ "request": "launch",
+ "mainClass": "net.thauvin.erik.pinboard.samples.JavaExampleTest"
+ }
+ ]
+}
diff --git a/examples/bld/.vscode/settings.json b/examples/bld/.vscode/settings.json
new file mode 100644
index 0000000..ba429d0
--- /dev/null
+++ b/examples/bld/.vscode/settings.json
@@ -0,0 +1,15 @@
+{
+ "java.project.sourcePaths": [
+ "src/main/java",
+ "src/main/resources",
+ "src/test/java",
+ "src/test/resources",
+ "src/bld/java",
+ "src/bld/resources"
+ ],
+ "java.configuration.updateBuildConfiguration": "automatic",
+ "java.project.referencedLibraries": [
+ "${HOME}/.bld/dist/bld-2.2.1.jar",
+ "lib/**/*.jar"
+ ]
+}
diff --git a/examples/bld/README.md b/examples/bld/README.md
new file mode 100644
index 0000000..ad5401c
--- /dev/null
+++ b/examples/bld/README.md
@@ -0,0 +1,18 @@
+## Kotlin Example
+To compile & run the Kotlin example:
+
+```console
+./bld compile
+
+./bld run
+```
+
+## Java Example
+
+To compile & run the Java example:
+
+```console
+./bld compile
+
+./bld run-java
+```
diff --git a/examples/bld/bld b/examples/bld/bld
new file mode 100755
index 0000000..1a39c97
--- /dev/null
+++ b/examples/bld/bld
@@ -0,0 +1,2 @@
+#!/usr/bin/env sh
+java -jar "$(dirname "$0")/lib/bld/bld-wrapper.jar" "$0" --build net.thauvin.erik.pinboard.samples.ExampleBuild "$@"
diff --git a/examples/bld/bld.bat b/examples/bld/bld.bat
new file mode 100644
index 0000000..6357553
--- /dev/null
+++ b/examples/bld/bld.bat
@@ -0,0 +1,4 @@
+@echo off
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+java -jar "%DIRNAME%/lib/bld/bld-wrapper.jar" "%0" --build net.thauvin.erik.pinboard.samples.ExampleBuild %*
diff --git a/examples/bld/lib/bld/bld-wrapper.jar b/examples/bld/lib/bld/bld-wrapper.jar
new file mode 100644
index 0000000..968a8ab
Binary files /dev/null and b/examples/bld/lib/bld/bld-wrapper.jar differ
diff --git a/examples/bld/lib/bld/bld-wrapper.properties b/examples/bld/lib/bld/bld-wrapper.properties
new file mode 100644
index 0000000..1f1009d
--- /dev/null
+++ b/examples/bld/lib/bld/bld-wrapper.properties
@@ -0,0 +1,7 @@
+bld.downloadExtensionJavadoc=false
+bld.downloadExtensionSources=true
+bld.downloadLocation=
+bld.extension-kotlin=com.uwyn.rife2:bld-kotlin:1.1.0-SNAPSHOT
+bld.repositories=MAVEN_LOCAL,MAVEN_CENTRAL,RIFE2_SNAPSHOTS,RIFE2_RELEASES
+bld.sourceDirectories=
+bld.version=2.2.1
diff --git a/examples/bld/src/bld/java/net/thauvin/erik/pinboard/samples/ExampleBuild.java b/examples/bld/src/bld/java/net/thauvin/erik/pinboard/samples/ExampleBuild.java
new file mode 100644
index 0000000..6fc8142
--- /dev/null
+++ b/examples/bld/src/bld/java/net/thauvin/erik/pinboard/samples/ExampleBuild.java
@@ -0,0 +1,54 @@
+package net.thauvin.erik.pinboard.samples;
+
+import rife.bld.BaseProject;
+import rife.bld.BuildCommand;
+import rife.bld.extension.CompileKotlinOperation;
+import rife.bld.extension.kotlin.CompileOptions;
+import rife.bld.operations.RunOperation;
+
+import java.util.List;
+
+import static rife.bld.dependencies.Repository.*;
+import static rife.bld.dependencies.Scope.compile;
+
+public class ExampleBuild extends BaseProject {
+ public ExampleBuild() {
+ pkg = "net.thauvin.erik.pinboard.samples";
+ name = "Example";
+ version = version(0, 1, 0);
+
+ mainClass = pkg + ".KotlinExampleKt";
+
+ javaRelease = 11;
+ downloadSources = true;
+ autoDownloadPurge = true;
+
+ repositories = List.of(MAVEN_LOCAL, MAVEN_CENTRAL, SONATYPE_SNAPSHOTS_LEGACY);
+
+ scope(compile)
+ .include(dependency("net.thauvin.erik", "pinboard-poster", version(1, 2, 1, "SNAPSHOT")));
+ }
+
+ public static void main(String[] args) {
+ new ExampleBuild().start(args);
+ }
+
+ @Override
+ public void compile() throws Exception {
+ new CompileKotlinOperation()
+ .fromProject(this)
+ .compileOptions(new CompileOptions().verbose(true))
+ .execute();
+
+ // Also compile the Java source code
+ super.compile();
+ }
+
+ @BuildCommand(value = "run-java", summary = "Runs the Java example")
+ public void runJava() throws Exception {
+ new RunOperation()
+ .fromProject(this)
+ .mainClass(pkg + ".JavaExample")
+ .execute();
+ }
+}
diff --git a/examples/bld/src/main/java/net/thauvin/erik/pinboard/samples/JavaExample.java b/examples/bld/src/main/java/net/thauvin/erik/pinboard/samples/JavaExample.java
new file mode 100644
index 0000000..1ef224b
--- /dev/null
+++ b/examples/bld/src/main/java/net/thauvin/erik/pinboard/samples/JavaExample.java
@@ -0,0 +1,47 @@
+package net.thauvin.erik.pinboard.samples;
+
+import net.thauvin.erik.pinboard.PinConfig;
+import net.thauvin.erik.pinboard.PinboardPoster;
+
+import java.nio.file.Paths;
+import java.util.logging.ConsoleHandler;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+public class JavaExample {
+ public static void main(String[] args) {
+ final String url = "https://example.com/pinboard";
+ final PinboardPoster poster;
+
+ if (args.length == 1) {
+ // API Token is an argument
+ poster = new PinboardPoster(args[0]);
+ } else {
+ // API Token is in local.properties or PINBOARD_API_TOKEN environment variable
+ poster = new PinboardPoster(Paths.get("local.properties"));
+ }
+
+ // Set logging levels
+ final ConsoleHandler consoleHandler = new ConsoleHandler();
+ consoleHandler.setLevel(Level.FINE);
+ final Logger logger = poster.getLogger();
+ logger.addHandler(consoleHandler);
+ logger.setLevel(Level.FINE);
+ logger.setUseParentHandlers(false);
+
+ if (poster.validate()) {
+ // Add Pin
+ if (poster.addPin(new PinConfig.Builder(url, "Testing")
+ .extended("Extra")
+ .tags("test", "java")
+ .build())) {
+ System.out.println("Added: " + url);
+ }
+
+ // Delete Pin
+ if (poster.deletePin(url)) {
+ System.out.println("Deleted: " + url);
+ }
+ }
+ }
+}
diff --git a/examples/bld/src/main/kotlin/net/thauvin/erik/pinboard/samples/KotlinExample.kt b/examples/bld/src/main/kotlin/net/thauvin/erik/pinboard/samples/KotlinExample.kt
new file mode 100644
index 0000000..1b48e82
--- /dev/null
+++ b/examples/bld/src/main/kotlin/net/thauvin/erik/pinboard/samples/KotlinExample.kt
@@ -0,0 +1,37 @@
+package net.thauvin.erik.pinboard.samples
+
+import net.thauvin.erik.pinboard.PinboardPoster
+import java.nio.file.Paths
+import java.util.logging.ConsoleHandler
+import java.util.logging.Level
+
+fun main(args: Array) {
+ val url = "https://example.com/pinboard"
+
+ val poster = if (args.size == 1) {
+ // API Token is an argument
+ PinboardPoster(args[0])
+ } else {
+ // API Token is in local.properties or PINBOARD_API_TOKEN environment variable
+ PinboardPoster(Paths.get("local.properties"))
+ }
+
+ // Set logging levels
+ with(poster.logger) {
+ addHandler(ConsoleHandler().apply { level = Level.FINE })
+ level = Level.FINE
+ useParentHandlers = false
+ }
+
+ if (poster.validate()) {
+ // Add Pin
+ if (poster.addPin(url, "Testing", "Extended test", tags = arrayOf("test", "kotlin"))) {
+ println("Added: $url")
+ }
+
+ // Delete Pin
+ if (poster.deletePin(url)) {
+ println("Deleted: $url")
+ }
+ }
+}
diff --git a/samples/java/.editorconfig b/examples/gradle/java/.editorconfig
similarity index 100%
rename from samples/java/.editorconfig
rename to examples/gradle/java/.editorconfig
diff --git a/samples/java/.gitignore b/examples/gradle/java/.gitignore
similarity index 100%
rename from samples/java/.gitignore
rename to examples/gradle/java/.gitignore
diff --git a/examples/gradle/java/.idea/.gitignore b/examples/gradle/java/.idea/.gitignore
new file mode 100644
index 0000000..26d3352
--- /dev/null
+++ b/examples/gradle/java/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/examples/gradle/java/.idea/.name b/examples/gradle/java/.idea/.name
new file mode 100644
index 0000000..4f5dba1
--- /dev/null
+++ b/examples/gradle/java/.idea/.name
@@ -0,0 +1 @@
+pinboard-poster-examples-gradle-java
\ No newline at end of file
diff --git a/examples/gradle/java/.idea/compiler.xml b/examples/gradle/java/.idea/compiler.xml
new file mode 100644
index 0000000..fb7f4a8
--- /dev/null
+++ b/examples/gradle/java/.idea/compiler.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/examples/gradle/java/.idea/inspectionProfiles/Project_Default.xml b/examples/gradle/java/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000..1e01b48
--- /dev/null
+++ b/examples/gradle/java/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/jarRepositories.xml b/examples/gradle/java/.idea/jarRepositories.xml
similarity index 84%
rename from .idea/jarRepositories.xml
rename to examples/gradle/java/.idea/jarRepositories.xml
index 3d4ac96..a529ef2 100644
--- a/.idea/jarRepositories.xml
+++ b/examples/gradle/java/.idea/jarRepositories.xml
@@ -17,9 +17,9 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 18b708b..64767c7 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,16 +1,12 @@
-
-
-
-
-
-
+4.0.0net.thauvin.erikpinboard-poster
- 1.0.3
+ 1.2.1-SNAPSHOTpinboard-poster
- Pinboard Poster for Kotlin/Java
+ A small library for posting to Pinboardhttps://github.com/ethauvin/pinboard-poster
@@ -18,6 +14,38 @@
https://opensource.org/licenses/BSD-3-Clause
+
+
+ org.jetbrains.kotlin
+ kotlin-stdlib
+ 2.1.20
+ compile
+
+
+ org.jetbrains.kotlin
+ kotlin-stdlib-common
+ 2.1.20
+ compile
+
+
+ org.jetbrains.kotlin
+ kotlin-stdlib-jdk8
+ 2.1.20
+ compile
+
+
+ com.squareup.okhttp3
+ okhttp
+ 4.12.0
+ compile
+
+
+ com.squareup.okhttp3
+ logging-interceptor
+ 4.12.0
+ compile
+
+ ethauvin
@@ -27,32 +55,8 @@
- scm:git:git://github.com/ethauvin/pinboard-poster.git
+ scm:git:https://github.com/ethauvin/pinboard-poster.gitscm:git:git@github.com:ethauvin/pinboard-poster.githttps://github.com/ethauvin/pinboard-poster
-
- GitHub
- https://github.com/ethauvin/pinboard-poster/issues
-
-
-
- org.jetbrains.kotlin
- kotlin-stdlib-jdk8
- 1.4.31
- compile
-
-
- com.squareup.okhttp3
- okhttp
- 4.9.1
- runtime
-
-
- com.squareup.okhttp3
- logging-interceptor
- 4.9.1
- runtime
-
-
diff --git a/preflightcheck.sh b/preflightcheck.sh
deleted file mode 100644
index ed82ca7..0000000
--- a/preflightcheck.sh
+++ /dev/null
@@ -1,213 +0,0 @@
-#!/bin/bash
-
-# set source and test locations
-src="src/main/kotlin/net/thauvin/erik/pinboard"
-test="src/main/kotlin/net/thauvin/erik/pinboard"
-# e.g: .java, .kt, etc.
-ext=".kt"
-java8=true
-# e.g:
-declare -a examples=(
- "samples/java run"
- "samples/kotlin run")
-# e.g: empty or javadoc, etc.
-gradle_doc="dokka"
-# e.g. empty or sonarqube
-gradle_sonar="sonarqube"
-# gradle options for examples
-gradle_opts="--console=plain --no-build-cache --no-daemon"
-# maven arguments for examples
-maven_args=""
-
-#
-# Version: 1.1.4
-#
-
-if [ "$java8" = true ]
-then
- export JAVA_HOME="$JAVA8_HOME"
- export PATH="$(cygpath "$JAVA_HOME")/bin:$PATH"
-fi
-
-pwd=$PWD
-red=$(tput setaf 1)
-cyan=$(tput setaf 6)
-std=$(tput sgr0)
-date=$(date +%Y)
-
-pause() {
- read -p "Press [Enter] key to continue..."
-}
-
-checkCopyright() {
- if [ "$(grep -c "$date" "$1")" -eq 0 ]
- then
- echo -e " Invalid: ${red}$f${std}"
- else
- echo -e " Checked: $1"
- fi
-}
-
-runGradle() {
- cd "$1" || exit 1
- clear
- reset
- echo -e "> Project: ${cyan}${1}${std} [Gradle]"
- shift
- ./gradlew $@ || exit 1
- pause
- cd "$pwd"
-}
-
-runKobalt() {
- cd "$1" || exit 1
- if [ -f kobalt/src/Build.kt ]
- then
- clear
- reset
- echo -e "> Project: ${cyan}${1}${std} [Kobalt]"
- shift
- ./kobaltw $@ || exit 1
- pause
- fi
- cd "$pwd"
-}
-
-runMaven() {
- cd "$1" || exit 1
- if [ -f pom.xml ]
- then
- clear
- reset
- echo -e "> Project: ${cyan}${1}${std} [Maven]"
- shift
- mvn $@ || exit 1
- pause
- fi
- cd "$pwd"
-}
-
-updateWrappers() {
- clear
- ./updatewrappers.sh
- pause
-}
-
-checkDeps() {
- clear
- echo -e "${cyan}Checking depencencies...${std}"
- gradle --console=plain dU || exit 1
- read -p "Check Examples depencencies? [y/n] " cont
- clear
- case $cont in
- [Nn] ) return ;;
- * ) for ex in "${!examples[@]}"
- do
- runGradle $(echo "${examples[ex]}" | cut -d " " -f 1) dU
- # runKobalt $(echo "${examples[ex]}" | cut -d " " -f 1) checkVersions
- runMaven $(echo "${examples[ex]}" | cut -d " " -f 1) versions:display-dependency-updates
- if [ "$ex" -eq "${#examples}" ]
- then
- read -p "Continue? [y/n]: " cont
- clear
- case $cont in
- * ) continue ;;
- [Nn] ) return ;;
- esac
- fi
- done ;;
- esac
-}
-
-gradleCheck() {
- clear
- echo -e "${cyan}Checking Gradle build....${std}"
- gradle $gradle_opts clean check $gradle_doc $gradle_sonar || exit 1
- pause
-}
-
-runExamples() {
- for ex in "${!examples[@]}"
- do
- runGradle ${examples[ex]} clean $gradle_opts
- # runKobalt ${examples[ex]} clean
- runMaven $(echo "${examples[ex]}" | cut -d " " -f 1) clean $maven_args
- done
-}
-
-examplesMenu() {
- clear
- echo -e "${cyan}Examples${std}"
- for ex in "${!examples[@]}"
- do
- printf ' %d. %s\n' $(($ex + 1)) $(echo "${examples[ex]}" | cut -d " " -f 1)
- done
- echo " $((${#examples[@]} + 1)). Run All Examples"
- read -p "Enter choice [1-${#examples[@]}]: " choice
- clear
- case $choice in
- [0-9] ) if [ "$choice" -gt "${#examples[@]}" ]
- then
- runExamples
- examplesMenu
- else
- runGradle ${examples[$(($choice - 1))]}
- # runKobalt ${examples[$(($choice - 1))]}
- runMaven $(echo "${examples[$(($choice - 1))]}" | cut -d " " -f 1) $maven_args
- examplesMenu
- fi ;;
- * ) return ;;
- esac
-}
-
-validateCopyrights() {
- clear
- echo -e "${cyan}Validating copyrights...${std}"
- for f in "LICENSE.TXT" ${src}/*${ext} ${test}/*${ext}
- do
- if [ -f "$f" ]
- then
- checkCopyright "$f"
- fi
- done
- pause
-}
-
-everything() {
- updateWrappers
- checkDeps
- gradleCheck
- runExamples
- validateCopyrights
-}
-
-showMenu() {
- clear
- echo "${cyan}Preflight Check${std}"
- echo " 1. Update Wrappers"
- echo " 2. Check Dependencies"
- echo " 3. Check Gradle Build"
- echo " 4. Run Examples"
- echo " 5. Validate Copyrights"
- echo " 6. Check Everything"
-}
-
-readOptions() {
- local choice
- read -p "Enter choice [1-6]: " choice
- case $choice in
- 1) updateWrappers ;;
- 2) checkDeps ;;
- 3) gradleCheck ;;
- 4) examplesMenu ;;
- 5) validateCopyrights ;;
- 6) everything ;;
- *) exit 0 ;;
- esac
-}
-
-while true
-do
- showMenu
- readOptions
-done
diff --git a/samples/examples.sh b/samples/examples.sh
deleted file mode 100644
index 99926d3..0000000
--- a/samples/examples.sh
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/bin/bash
-
-# Version 1.0
-
-if [ $# -eq 0 ]; then
- echo "Usage: $0 "
- exit 1
-fi
-
-# set the examples directories
-declare -a examples=(
- "java"
- "kotlin")
-
-dir=$(dirname "$(readlink -f "$0")")
-cyan=$(tput setaf 6)
-normal=$(tput sgr0)
-
-i=0
-for ex in "${examples[@]}"; do
- if [ $i -ne 0 ]
- then
- read -p "Press [Enter] key to continue..."
- clear
- fi
- cd "$dir/$ex" || exit 1
- echo "> Project: ${cyan}${ex}${normal}"
- ./gradlew --console=plain --no-build-cache clean "$@" || exit 1
- (( i++ ))
-done
diff --git a/samples/java/build.gradle b/samples/java/build.gradle
deleted file mode 100644
index 01c54f4..0000000
--- a/samples/java/build.gradle
+++ /dev/null
@@ -1,19 +0,0 @@
-plugins {
- id 'java'
- id 'application'
-}
-
-// ./gradlew run
-
-defaultTasks 'run'
-
-mainClassName = 'net.thauvin.erik.pinboard.samples.JavaExample'
-
-repositories {
- mavenLocal()
- mavenCentral()
-}
-
-dependencies {
- compile 'net.thauvin.erik:pinboard-poster:1.0.3'
-}
diff --git a/samples/java/gradle/wrapper/gradle-wrapper.jar b/samples/java/gradle/wrapper/gradle-wrapper.jar
deleted file mode 100644
index e708b1c..0000000
Binary files a/samples/java/gradle/wrapper/gradle-wrapper.jar and /dev/null differ
diff --git a/samples/java/gradlew b/samples/java/gradlew
deleted file mode 100755
index 4f906e0..0000000
--- a/samples/java/gradlew
+++ /dev/null
@@ -1,185 +0,0 @@
-#!/usr/bin/env sh
-
-#
-# Copyright 2015 the original author or authors.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# https://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-##############################################################################
-##
-## Gradle start up script for UN*X
-##
-##############################################################################
-
-# Attempt to set APP_HOME
-# Resolve links: $0 may be a link
-PRG="$0"
-# Need this for relative symlinks.
-while [ -h "$PRG" ] ; do
- ls=`ls -ld "$PRG"`
- link=`expr "$ls" : '.*-> \(.*\)$'`
- if expr "$link" : '/.*' > /dev/null; then
- PRG="$link"
- else
- PRG=`dirname "$PRG"`"/$link"
- fi
-done
-SAVED="`pwd`"
-cd "`dirname \"$PRG\"`/" >/dev/null
-APP_HOME="`pwd -P`"
-cd "$SAVED" >/dev/null
-
-APP_NAME="Gradle"
-APP_BASE_NAME=`basename "$0"`
-
-# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
-
-# Use the maximum available, or set MAX_FD != -1 to use that value.
-MAX_FD="maximum"
-
-warn () {
- echo "$*"
-}
-
-die () {
- echo
- echo "$*"
- echo
- exit 1
-}
-
-# OS specific support (must be 'true' or 'false').
-cygwin=false
-msys=false
-darwin=false
-nonstop=false
-case "`uname`" in
- CYGWIN* )
- cygwin=true
- ;;
- Darwin* )
- darwin=true
- ;;
- MINGW* )
- msys=true
- ;;
- NONSTOP* )
- nonstop=true
- ;;
-esac
-
-CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
-
-
-# Determine the Java command to use to start the JVM.
-if [ -n "$JAVA_HOME" ] ; then
- if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
- # IBM's JDK on AIX uses strange locations for the executables
- JAVACMD="$JAVA_HOME/jre/sh/java"
- else
- JAVACMD="$JAVA_HOME/bin/java"
- fi
- if [ ! -x "$JAVACMD" ] ; then
- die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
-
-Please set the JAVA_HOME variable in your environment to match the
-location of your Java installation."
- fi
-else
- JAVACMD="java"
- which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
-
-Please set the JAVA_HOME variable in your environment to match the
-location of your Java installation."
-fi
-
-# Increase the maximum file descriptors if we can.
-if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
- MAX_FD_LIMIT=`ulimit -H -n`
- if [ $? -eq 0 ] ; then
- if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
- MAX_FD="$MAX_FD_LIMIT"
- fi
- ulimit -n $MAX_FD
- if [ $? -ne 0 ] ; then
- warn "Could not set maximum file descriptor limit: $MAX_FD"
- fi
- else
- warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
- fi
-fi
-
-# For Darwin, add options to specify how the application appears in the dock
-if $darwin; then
- GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
-fi
-
-# For Cygwin or MSYS, switch paths to Windows format before running java
-if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
- APP_HOME=`cygpath --path --mixed "$APP_HOME"`
- CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
-
- JAVACMD=`cygpath --unix "$JAVACMD"`
-
- # We build the pattern for arguments to be converted via cygpath
- ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
- SEP=""
- for dir in $ROOTDIRSRAW ; do
- ROOTDIRS="$ROOTDIRS$SEP$dir"
- SEP="|"
- done
- OURCYGPATTERN="(^($ROOTDIRS))"
- # Add a user-defined pattern to the cygpath arguments
- if [ "$GRADLE_CYGPATTERN" != "" ] ; then
- OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
- fi
- # Now convert the arguments - kludge to limit ourselves to /bin/sh
- i=0
- for arg in "$@" ; do
- CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
- CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
-
- if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
- eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
- else
- eval `echo args$i`="\"$arg\""
- fi
- i=`expr $i + 1`
- done
- case $i in
- 0) set -- ;;
- 1) set -- "$args0" ;;
- 2) set -- "$args0" "$args1" ;;
- 3) set -- "$args0" "$args1" "$args2" ;;
- 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
- 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
- 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
- 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
- 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
- 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
- esac
-fi
-
-# Escape application args
-save () {
- for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
- echo " "
-}
-APP_ARGS=`save "$@"`
-
-# Collect all arguments for the java command, following the shell quoting and substitution rules
-eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
-
-exec "$JAVACMD" "$@"
diff --git a/samples/java/src/main/java/net/thauvin/erik/pinboard/samples/JavaExample.java b/samples/java/src/main/java/net/thauvin/erik/pinboard/samples/JavaExample.java
deleted file mode 100644
index e6da4fc..0000000
--- a/samples/java/src/main/java/net/thauvin/erik/pinboard/samples/JavaExample.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * JavaExample.java
- *
- * Copyright (c) 2017-2018, Erik C. Thauvin (erik@thauvin.net)
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * Neither the name of this project nor the names of its contributors may be
- * used to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-package net.thauvin.erik.pinboard.samples;
-
-import net.thauvin.erik.pinboard.PinboardPoster;
-
-import java.nio.file.Paths;
-import java.util.logging.ConsoleHandler;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-public class JavaExample {
- public static void main(String[] args) {
- final String url = "http://www.example.com/pinboard";
- final PinboardPoster poster;
-
- if (args.length == 1) {
- // API Token is an argument
- poster = new PinboardPoster(args[0]);
- } else {
- // API Token is in local.properties or PINBOARD_API_TOKEN environment variable
- poster = new PinboardPoster(Paths.get("local.properties"));
- }
-
- // Set logging levels
- final ConsoleHandler consoleHandler = new ConsoleHandler();
- consoleHandler.setLevel(Level.FINE);
- final Logger logger = poster.getLogger();
- logger.addHandler(consoleHandler);
- logger.setLevel(Level.FINE);
-
- // Add Pin
- if (poster.addPin(url, "Testing", "Extended test", "test java")) {
- System.out.println("Added: " + url);
- }
-
- // Delete Pin
- if (poster.deletePin(url)) {
- System.out.println("Deleted: " + url);
- }
- }
-}
diff --git a/samples/kotlin/build.gradle.kts b/samples/kotlin/build.gradle.kts
deleted file mode 100644
index 5fa0d8e..0000000
--- a/samples/kotlin/build.gradle.kts
+++ /dev/null
@@ -1,21 +0,0 @@
-plugins {
- application
- kotlin("jvm") version "1.4.31"
-}
-
-// ./gradlew run
-
-defaultTasks(ApplicationPlugin.TASK_RUN_NAME)
-
-repositories {
- mavenLocal()
- mavenCentral()
-}
-
-dependencies {
- compile("net.thauvin.erik:pinboard-poster:1.0.3")
-}
-
-application {
- mainClassName = "net.thauvin.erik.pinboard.samples.KotlinExampleKt"
-}
diff --git a/samples/kotlin/gradle/wrapper/gradle-wrapper.jar b/samples/kotlin/gradle/wrapper/gradle-wrapper.jar
deleted file mode 100644
index e708b1c..0000000
Binary files a/samples/kotlin/gradle/wrapper/gradle-wrapper.jar and /dev/null differ
diff --git a/samples/kotlin/gradle/wrapper/gradle-wrapper.properties b/samples/kotlin/gradle/wrapper/gradle-wrapper.properties
deleted file mode 100644
index 442d913..0000000
--- a/samples/kotlin/gradle/wrapper/gradle-wrapper.properties
+++ /dev/null
@@ -1,5 +0,0 @@
-distributionBase=GRADLE_USER_HOME
-distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-bin.zip
-zipStoreBase=GRADLE_USER_HOME
-zipStorePath=wrapper/dists
diff --git a/samples/kotlin/gradlew b/samples/kotlin/gradlew
deleted file mode 100755
index 4f906e0..0000000
--- a/samples/kotlin/gradlew
+++ /dev/null
@@ -1,185 +0,0 @@
-#!/usr/bin/env sh
-
-#
-# Copyright 2015 the original author or authors.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# https://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-##############################################################################
-##
-## Gradle start up script for UN*X
-##
-##############################################################################
-
-# Attempt to set APP_HOME
-# Resolve links: $0 may be a link
-PRG="$0"
-# Need this for relative symlinks.
-while [ -h "$PRG" ] ; do
- ls=`ls -ld "$PRG"`
- link=`expr "$ls" : '.*-> \(.*\)$'`
- if expr "$link" : '/.*' > /dev/null; then
- PRG="$link"
- else
- PRG=`dirname "$PRG"`"/$link"
- fi
-done
-SAVED="`pwd`"
-cd "`dirname \"$PRG\"`/" >/dev/null
-APP_HOME="`pwd -P`"
-cd "$SAVED" >/dev/null
-
-APP_NAME="Gradle"
-APP_BASE_NAME=`basename "$0"`
-
-# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
-
-# Use the maximum available, or set MAX_FD != -1 to use that value.
-MAX_FD="maximum"
-
-warn () {
- echo "$*"
-}
-
-die () {
- echo
- echo "$*"
- echo
- exit 1
-}
-
-# OS specific support (must be 'true' or 'false').
-cygwin=false
-msys=false
-darwin=false
-nonstop=false
-case "`uname`" in
- CYGWIN* )
- cygwin=true
- ;;
- Darwin* )
- darwin=true
- ;;
- MINGW* )
- msys=true
- ;;
- NONSTOP* )
- nonstop=true
- ;;
-esac
-
-CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
-
-
-# Determine the Java command to use to start the JVM.
-if [ -n "$JAVA_HOME" ] ; then
- if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
- # IBM's JDK on AIX uses strange locations for the executables
- JAVACMD="$JAVA_HOME/jre/sh/java"
- else
- JAVACMD="$JAVA_HOME/bin/java"
- fi
- if [ ! -x "$JAVACMD" ] ; then
- die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
-
-Please set the JAVA_HOME variable in your environment to match the
-location of your Java installation."
- fi
-else
- JAVACMD="java"
- which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
-
-Please set the JAVA_HOME variable in your environment to match the
-location of your Java installation."
-fi
-
-# Increase the maximum file descriptors if we can.
-if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
- MAX_FD_LIMIT=`ulimit -H -n`
- if [ $? -eq 0 ] ; then
- if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
- MAX_FD="$MAX_FD_LIMIT"
- fi
- ulimit -n $MAX_FD
- if [ $? -ne 0 ] ; then
- warn "Could not set maximum file descriptor limit: $MAX_FD"
- fi
- else
- warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
- fi
-fi
-
-# For Darwin, add options to specify how the application appears in the dock
-if $darwin; then
- GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
-fi
-
-# For Cygwin or MSYS, switch paths to Windows format before running java
-if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
- APP_HOME=`cygpath --path --mixed "$APP_HOME"`
- CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
-
- JAVACMD=`cygpath --unix "$JAVACMD"`
-
- # We build the pattern for arguments to be converted via cygpath
- ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
- SEP=""
- for dir in $ROOTDIRSRAW ; do
- ROOTDIRS="$ROOTDIRS$SEP$dir"
- SEP="|"
- done
- OURCYGPATTERN="(^($ROOTDIRS))"
- # Add a user-defined pattern to the cygpath arguments
- if [ "$GRADLE_CYGPATTERN" != "" ] ; then
- OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
- fi
- # Now convert the arguments - kludge to limit ourselves to /bin/sh
- i=0
- for arg in "$@" ; do
- CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
- CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
-
- if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
- eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
- else
- eval `echo args$i`="\"$arg\""
- fi
- i=`expr $i + 1`
- done
- case $i in
- 0) set -- ;;
- 1) set -- "$args0" ;;
- 2) set -- "$args0" "$args1" ;;
- 3) set -- "$args0" "$args1" "$args2" ;;
- 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
- 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
- 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
- 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
- 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
- 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
- esac
-fi
-
-# Escape application args
-save () {
- for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
- echo " "
-}
-APP_ARGS=`save "$@"`
-
-# Collect all arguments for the java command, following the shell quoting and substitution rules
-eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
-
-exec "$JAVACMD" "$@"
diff --git a/samples/kotlin/gradlew.bat b/samples/kotlin/gradlew.bat
deleted file mode 100644
index 107acd3..0000000
--- a/samples/kotlin/gradlew.bat
+++ /dev/null
@@ -1,89 +0,0 @@
-@rem
-@rem Copyright 2015 the original author or authors.
-@rem
-@rem Licensed under the Apache License, Version 2.0 (the "License");
-@rem you may not use this file except in compliance with the License.
-@rem You may obtain a copy of the License at
-@rem
-@rem https://www.apache.org/licenses/LICENSE-2.0
-@rem
-@rem Unless required by applicable law or agreed to in writing, software
-@rem distributed under the License is distributed on an "AS IS" BASIS,
-@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-@rem See the License for the specific language governing permissions and
-@rem limitations under the License.
-@rem
-
-@if "%DEBUG%" == "" @echo off
-@rem ##########################################################################
-@rem
-@rem Gradle startup script for Windows
-@rem
-@rem ##########################################################################
-
-@rem Set local scope for the variables with windows NT shell
-if "%OS%"=="Windows_NT" setlocal
-
-set DIRNAME=%~dp0
-if "%DIRNAME%" == "" set DIRNAME=.
-set APP_BASE_NAME=%~n0
-set APP_HOME=%DIRNAME%
-
-@rem Resolve any "." and ".." in APP_HOME to make it shorter.
-for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
-
-@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
-
-@rem Find java.exe
-if defined JAVA_HOME goto findJavaFromJavaHome
-
-set JAVA_EXE=java.exe
-%JAVA_EXE% -version >NUL 2>&1
-if "%ERRORLEVEL%" == "0" goto execute
-
-echo.
-echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
-echo.
-echo Please set the JAVA_HOME variable in your environment to match the
-echo location of your Java installation.
-
-goto fail
-
-:findJavaFromJavaHome
-set JAVA_HOME=%JAVA_HOME:"=%
-set JAVA_EXE=%JAVA_HOME%/bin/java.exe
-
-if exist "%JAVA_EXE%" goto execute
-
-echo.
-echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
-echo.
-echo Please set the JAVA_HOME variable in your environment to match the
-echo location of your Java installation.
-
-goto fail
-
-:execute
-@rem Setup the command line
-
-set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
-
-
-@rem Execute Gradle
-"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
-
-:end
-@rem End local scope for the variables with windows NT shell
-if "%ERRORLEVEL%"=="0" goto mainEnd
-
-:fail
-rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
-rem the _cmd.exe /c_ return code!
-if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
-exit /b 1
-
-:mainEnd
-if "%OS%"=="Windows_NT" endlocal
-
-:omega
diff --git a/samples/kotlin/settings.gradle.kts b/samples/kotlin/settings.gradle.kts
deleted file mode 100644
index 28613c7..0000000
--- a/samples/kotlin/settings.gradle.kts
+++ /dev/null
@@ -1 +0,0 @@
-rootProject.name = "samples-kotlin"
diff --git a/samples/kotlin/src/main/kotlin/net/thauvin/erik/pinboard/samples/KotlinExample.kt b/samples/kotlin/src/main/kotlin/net/thauvin/erik/pinboard/samples/KotlinExample.kt
deleted file mode 100644
index 77c8ba5..0000000
--- a/samples/kotlin/src/main/kotlin/net/thauvin/erik/pinboard/samples/KotlinExample.kt
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * KotlinExample.kt
- *
- * Copyright (c) 2017-2018, Erik C. Thauvin (erik@thauvin.net)
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * Neither the name of this project nor the names of its contributors may be
- * used to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-package net.thauvin.erik.pinboard.samples
-
-import net.thauvin.erik.pinboard.PinboardPoster
-import java.nio.file.Paths
-import java.util.logging.ConsoleHandler
-import java.util.logging.Level
-
-fun main(args: Array) {
- val url = "http://www.example.com/pinboard"
-
- val poster = if (args.size == 1) {
- // API Token is an argument
- PinboardPoster(args[0])
- } else {
- // API Token is in local.properties or PINBOARD_API_TOKEN environment variable
- PinboardPoster(Paths.get("local.properties"))
- }
-
- // Set logging levels
- with(poster.logger) {
- addHandler(ConsoleHandler().apply { level = Level.FINE })
- level = Level.FINE
- }
-
- // Add Pin
- if (poster.addPin(url, "Testing", "Extended test", "test kotlin")) {
- println("Added: $url")
- }
-
- // Delete Pin
- if (poster.deletePin(url)) {
- println("Deleted: $url")
- }
-}
diff --git a/settings.gradle.kts b/settings.gradle.kts
deleted file mode 100644
index 754ad3d..0000000
--- a/settings.gradle.kts
+++ /dev/null
@@ -1,11 +0,0 @@
-plugins {
- id("com.gradle.enterprise").version("3.1.1")
-}
-
-rootProject.name = "pinboard-poster"
-
-gradleEnterprise {
- buildScan {
- // plugin configuration
- }
-}
diff --git a/sonar-project.properties b/sonar-project.properties
new file mode 100644
index 0000000..20487a7
--- /dev/null
+++ b/sonar-project.properties
@@ -0,0 +1,7 @@
+sonar.organization=ethauvin-github
+sonar.projectKey=ethauvin_pinboard-poster
+sonar.coverage.jacoco.xmlReportPaths=build/reports/jacoco/test/jacocoTestReport.xml
+sonar.sources=src/main/kotlin/
+sonar.tests=src/test/kotlin/
+sonar.java.binaries=build/main,build/test
+sonar.java.libraries=lib/compile/*.jar
diff --git a/src/bld/java/net/thauvin/erik/pinboard/PinboardPosterBuild.java b/src/bld/java/net/thauvin/erik/pinboard/PinboardPosterBuild.java
new file mode 100644
index 0000000..d4689ac
--- /dev/null
+++ b/src/bld/java/net/thauvin/erik/pinboard/PinboardPosterBuild.java
@@ -0,0 +1,201 @@
+/*
+ * PinboardPosterBuild.java
+ *
+ * Copyright (c) 2017-2025, Erik C. Thauvin (erik@thauvin.net)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of this project nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package net.thauvin.erik.pinboard;
+
+import rife.bld.BuildCommand;
+import rife.bld.Project;
+import rife.bld.extension.CompileKotlinOperation;
+import rife.bld.extension.DetektOperation;
+import rife.bld.extension.DokkaOperation;
+import rife.bld.extension.JacocoReportOperation;
+import rife.bld.extension.dokka.LoggingLevel;
+import rife.bld.extension.dokka.OutputFormat;
+import rife.bld.extension.kotlin.CompileOptions;
+import rife.bld.operations.exceptions.ExitStatusException;
+import rife.bld.publish.PomBuilder;
+import rife.bld.publish.PublishDeveloper;
+import rife.bld.publish.PublishLicense;
+import rife.bld.publish.PublishScm;
+import rife.tools.exceptions.FileUtilsErrorException;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+import java.util.logging.ConsoleHandler;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import static rife.bld.dependencies.Repository.*;
+import static rife.bld.dependencies.Scope.compile;
+import static rife.bld.dependencies.Scope.test;
+
+public class PinboardPosterBuild extends Project {
+ final File srcMainKotlin = new File(srcMainDirectory(), "kotlin");
+
+ public PinboardPosterBuild() {
+ pkg = "net.thauvin.erik";
+ name = "pinboard-poster";
+ version = version(1, 2, 1, "SNAPSHOT");
+
+ mainClass = pkg + ".PinboardPoster";
+
+ javaRelease = 11;
+ downloadSources = true;
+ autoDownloadPurge = true;
+ repositories = List.of(MAVEN_LOCAL, MAVEN_CENTRAL);
+
+ final var okHttp = version(4, 12, 0);
+ final var kotlin = version(2, 1, 20);
+ scope(compile)
+ // Kotlin
+ .include(dependency("org.jetbrains.kotlin", "kotlin-stdlib", kotlin))
+ .include(dependency("org.jetbrains.kotlin", "kotlin-stdlib-common", kotlin))
+ .include(dependency("org.jetbrains.kotlin", "kotlin-stdlib-jdk8", kotlin))
+ // OkHttp
+ .include(dependency("com.squareup.okhttp3", "okhttp", okHttp))
+ .include(dependency("com.squareup.okhttp3", "logging-interceptor", okHttp));
+ scope(test)
+ .include(dependency("org.jetbrains.kotlin", "kotlin-test-junit5", kotlin))
+ .include(dependency("org.junit.jupiter", "junit-jupiter", version(5, 12, 1)))
+ .include(dependency("org.junit.platform", "junit-platform-console-standalone", version(1, 12, 1)))
+ .include(dependency("org.junit.platform", "junit-platform-launcher", version(1, 12, 1)));
+
+ publishOperation()
+ .repository(version.isSnapshot() ? repository(SONATYPE_SNAPSHOTS_LEGACY.location())
+ .withCredentials(property("sonatype.user"), property("sonatype.password"))
+ : repository(SONATYPE_RELEASES_LEGACY.location())
+ .withCredentials(property("sonatype.user"), property("sonatype.password")))
+ .repository(repository("github"))
+ .info()
+ .groupId(pkg)
+ .artifactId(name)
+ .description("A small library for posting to Pinboard")
+ .url("https://github.com/ethauvin/" + name)
+ .developer(new PublishDeveloper()
+ .id("ethauvin")
+ .name("Erik C. Thauvin")
+ .email("erik@thauvin.net")
+ .url("https://erik.thauvin.net/")
+ )
+ .license(new PublishLicense()
+ .name("BSD 3-Clause")
+ .url("https://opensource.org/licenses/BSD-3-Clause")
+ )
+ .scm(new PublishScm()
+ .connection("scm:git:https://github.com/ethauvin/" + name + ".git")
+ .developerConnection("scm:git:git@github.com:ethauvin/" + name + ".git")
+ .url("https://github.com/ethauvin/" + name)
+ )
+ .signKey(property("sign.key"))
+ .signPassphrase(property("sign.passphrase"));
+
+ jarSourcesOperation().sourceDirectories(srcMainKotlin);
+ }
+
+ public static void main(final String[] args) {
+ // Enable detailed logging for the extensions
+ var level = Level.ALL;
+ var logger = Logger.getLogger("rife.bld.extension");
+ var consoleHandler = new ConsoleHandler();
+
+ consoleHandler.setLevel(level);
+ logger.addHandler(consoleHandler);
+ logger.setLevel(level);
+ logger.setUseParentHandlers(false);
+
+ new PinboardPosterBuild().start(args);
+ }
+
+ @BuildCommand(summary = "Compiles the Kotlin project")
+ @Override
+ public void compile() throws Exception {
+ new CompileKotlinOperation()
+ .fromProject(this)
+ .compileOptions(new CompileOptions().verbose(true))
+ .execute();
+ }
+
+ @BuildCommand(summary = "Checks source with Detekt")
+ public void detekt() throws ExitStatusException, IOException, InterruptedException {
+ new DetektOperation()
+ .fromProject(this)
+ .baseline("config/detekt/baseline.xml")
+ .execute();
+ }
+
+ @BuildCommand(value = "detekt-baseline", summary = "Creates the Detekt baseline")
+ public void detektBaseline() throws ExitStatusException, IOException, InterruptedException {
+ new DetektOperation()
+ .fromProject(this)
+ .baseline("config/detekt/baseline.xml")
+ .createBaseline(true)
+ .execute();
+ }
+
+ @BuildCommand(summary = "Generates JaCoCo Reports")
+ public void jacoco() throws Exception {
+ new JacocoReportOperation()
+ .fromProject(this)
+ .sourceFiles(srcMainKotlin)
+ .execute();
+ }
+
+ @Override
+ public void javadoc() throws ExitStatusException, IOException, InterruptedException {
+ new DokkaOperation()
+ .fromProject(this)
+ .loggingLevel(LoggingLevel.INFO)
+ .moduleName("CryptoPrice")
+ .moduleVersion(version.toString())
+ .outputDir(new File(buildDirectory(), "javadoc"))
+ .outputFormat(OutputFormat.JAVADOC)
+ .execute();
+ }
+
+ @Override
+ public void publish() throws Exception {
+ super.publish();
+ pomRoot();
+ }
+
+ @Override
+ public void publishLocal() throws Exception {
+ super.publishLocal();
+ pomRoot();
+ }
+
+ @BuildCommand(value = "pom-root", summary = "Generates the POM file in the root directory")
+ public void pomRoot() throws FileUtilsErrorException {
+ PomBuilder.generateInto(publishOperation().fromProject(this).info(), dependencies(),
+ new File(workDirectory, "pom.xml"));
+ }
+}
diff --git a/src/main/kotlin/net/thauvin/erik/pinboard/PinConfig.kt b/src/main/kotlin/net/thauvin/erik/pinboard/PinConfig.kt
new file mode 100644
index 0000000..a41e563
--- /dev/null
+++ b/src/main/kotlin/net/thauvin/erik/pinboard/PinConfig.kt
@@ -0,0 +1,144 @@
+/*
+ * PinConfig.kt
+ *
+ * Copyright (c) 2017-2025, Erik C. Thauvin (erik@thauvin.net)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of this project nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package net.thauvin.erik.pinboard
+
+import java.time.ZonedDateTime
+
+/**
+ * Provides a builder to add a pin.
+ *
+ * Supports of all the [Pinboard API Parameters](https://pinboard.in/api/#posts_add).
+ */
+class PinConfig private constructor(builder: Builder) {
+ val url: String = builder.url
+ val description: String = builder.description
+ val extended = builder.extended
+ val tags = builder.tags
+ val dt = builder.dt
+ val replace = builder.replace
+ val shared = builder.shared
+ val toRead = builder.toRead
+
+ /**
+ * Configures the parameters to add a pin.
+ *
+ * @param url The URL of the bookmark.
+ * @param description The title of the bookmark.
+ */
+ data class Builder(var url: String, var description: String) {
+ var extended: String = ""
+ var tags: Array = emptyArray()
+ var dt: ZonedDateTime = ZonedDateTime.now()
+ var replace: Boolean = true
+ var shared: Boolean = true
+ var toRead: Boolean = false
+
+ /**
+ * The URL of the bookmark.
+ */
+ fun url(url: String): Builder = apply { this.url = url }
+
+ /**
+ * The title of the bookmark.
+ */
+ fun description(description: String): Builder = apply { this.description = description }
+
+ /**
+ * The description of the bookmark.
+ */
+ fun extended(extended: String): Builder = apply { this.extended = extended }
+
+ /**
+ * A list of up to 100 tags.
+ */
+ fun tags(vararg tag: String): Builder = apply { this.tags = tag }
+
+ /**
+ * The creation time of the bookmark.
+ */
+ fun dt(datetime: ZonedDateTime): Builder = apply { this.dt = datetime }
+
+ /**
+ * Replace any existing bookmark with the specified URL. Default `true`.
+ */
+ fun replace(replace: Boolean): Builder = apply { this.replace = replace }
+
+ /**
+ * Make bookmark public. Default is `true`.
+ */
+ fun shared(shared: Boolean): Builder = apply { this.shared = shared }
+
+ /**
+ * Mark the bookmark as unread. Default is `false`.
+ */
+ fun toRead(toRead: Boolean): Builder = apply { this.toRead = toRead }
+
+ /**
+ * Builds a new configuration.
+ */
+ fun build() = PinConfig(this)
+
+ override fun equals(other: Any?): Boolean {
+ if (this === other) return true
+ if (javaClass != other?.javaClass) return false
+
+ other as Builder
+
+ if (url != other.url) return false
+ if (description != other.description) return false
+ if (extended != other.extended) return false
+ if (!tags.contentEquals(other.tags)) return false
+ if (dt != other.dt) return false
+ if (replace != other.replace) return false
+ if (shared != other.shared) return false
+ if (toRead != other.toRead) return false
+
+ return true
+ }
+
+ override fun hashCode(): Int {
+ var result = url.hashCode()
+ result = 31 * result + description.hashCode()
+ result = 31 * result + extended.hashCode()
+ result = 31 * result + tags.contentHashCode()
+ result = 31 * result + dt.hashCode()
+ result = 31 * result + replace.hashCode()
+ result = 31 * result + shared.hashCode()
+ result = 31 * result + toRead.hashCode()
+ return result
+ }
+
+ override fun toString(): String {
+ return "Builder(url='$url', description='$description', extended='$extended'," +
+ "tags=${tags.contentToString()}, dt=$dt, replace=$replace, shared=$shared, toRead=$toRead)"
+ }
+ }
+}
diff --git a/src/main/kotlin/net/thauvin/erik/pinboard/PinboardPoster.kt b/src/main/kotlin/net/thauvin/erik/pinboard/PinboardPoster.kt
index ef2a864..00d2cc1 100644
--- a/src/main/kotlin/net/thauvin/erik/pinboard/PinboardPoster.kt
+++ b/src/main/kotlin/net/thauvin/erik/pinboard/PinboardPoster.kt
@@ -1,8 +1,7 @@
/*
* PinboardPoster.kt
*
- * Copyright (c) 2017-2021, Erik C. Thauvin (erik@thauvin.net)
- * All rights reserved.
+ * Copyright (c) 2017-2025, Erik C. Thauvin (erik@thauvin.net)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -40,10 +39,12 @@ import org.xml.sax.InputSource
import java.io.File
import java.io.IOException
import java.io.StringReader
-import java.net.MalformedURLException
-import java.net.URL
+import java.net.URI
+import java.net.URISyntaxException
import java.nio.file.Files
import java.nio.file.Path
+import java.time.ZonedDateTime
+import java.time.format.DateTimeFormatter
import java.util.*
import java.util.logging.Level
import java.util.logging.Logger
@@ -63,7 +64,7 @@ object Constants {
*
* @constructor Creates a new instance.
*
- * @author [Erik C. Thauvin](https://erik.thauvin.net/)
+ * @author Erik C. Thauvin
*/
open class PinboardPoster() {
/**
@@ -81,7 +82,6 @@ open class PinboardPoster() {
* @param properties The properties.
* @param key The property key.
*/
- @Suppress("unused")
@JvmOverloads
constructor(properties: Properties, key: String = Constants.ENV_API_TOKEN) : this() {
apiToken = properties.getProperty(key, apiToken)
@@ -121,7 +121,6 @@ open class PinboardPoster() {
var apiEndPoint: String = Constants.API_ENDPOINT
/** The logger instance. **/
- @Suppress("MemberVisibilityCanBePrivate")
val logger: Logger by lazy { Logger.getLogger(PinboardPoster::class.java.simpleName) }
private val client by lazy {
@@ -134,6 +133,22 @@ open class PinboardPoster() {
}.build()
}
+ /**
+ * Adds a bookmark to Pinboard using a [PinConfig] builder.
+ */
+ fun addPin(config: PinConfig): Boolean {
+ return addPin(
+ url = config.url,
+ description = config.description,
+ extended = config.extended,
+ tags = config.tags,
+ dt = config.dt,
+ replace = config.replace,
+ shared = config.shared,
+ toRead = config.toRead
+ )
+ }
+
/**
* Adds a bookmark to Pinboard.
*
@@ -155,8 +170,8 @@ open class PinboardPoster() {
url: String,
description: String,
extended: String = "",
- tags: String = "",
- dt: String = "",
+ vararg tags: String = emptyArray(),
+ dt: ZonedDateTime = ZonedDateTime.now(),
replace: Boolean = true,
shared: Boolean = true,
toRead: Boolean = false
@@ -167,15 +182,15 @@ open class PinboardPoster() {
} else if (description.isBlank()) {
logger.severe("Please specify a valid description to pin: `$url`")
} else {
- val params = listOf(
- Pair("url", url),
- Pair("description", description),
- Pair("extended", extended),
- Pair("tags", tags),
- Pair("dt", dt),
- Pair("replace", yesNo(replace)),
- Pair("shared", yesNo(shared)),
- Pair("toread", yesNo(toRead))
+ val params = mapOf(
+ "url" to url,
+ "description" to description,
+ "extended" to extended,
+ "tags" to tags.joinToString(","),
+ "dt" to DateTimeFormatter.ISO_INSTANT.format(dt.withNano(0)),
+ "replace" to yesNo(replace),
+ "shared" to yesNo(shared),
+ "toread" to yesNo(toRead)
)
return executeMethod("posts/add", params)
}
@@ -198,13 +213,14 @@ open class PinboardPoster() {
if (!validateUrl(url)) {
logger.severe("Please specify a valid URL to delete.")
} else {
- return executeMethod("posts/delete", listOf(Pair("url", url)))
+ return executeMethod("posts/delete", mapOf("url" to url))
}
}
return false
}
+ @Throws(IOException::class)
internal fun parseMethodResponse(method: String, response: String) {
val factory = DocumentBuilderFactory.newInstance().apply {
isValidating = false
@@ -228,39 +244,40 @@ open class PinboardPoster() {
} else {
throw IOException("An error has occurred while executing $method.")
}
- } catch (e: Exception) {
+ } catch (e: org.xml.sax.SAXException) {
throw IOException("Could not parse $method response.", e)
+ } catch (e: IllegalArgumentException) {
+ throw IOException("Invalid input source for $method response", e)
}
}
private fun cleanEndPoint(method: String): String {
- return if (apiEndPoint.endsWith('/')) {
+ return if (apiEndPoint.last() == '/') {
"$apiEndPoint$method"
} else {
"$apiEndPoint/$method"
}
}
- private fun executeMethod(method: String, params: List>): Boolean {
+ private fun executeMethod(method: String, params: Map): Boolean {
try {
val apiUrl = cleanEndPoint(method).toHttpUrlOrNull()
if (apiUrl != null) {
val httpUrl = apiUrl.newBuilder().apply {
params.forEach {
- addQueryParameter(it.first, it.second)
+ addQueryParameter(it.key, it.value)
}
addQueryParameter("auth_token", apiToken)
}.build()
val request = Request.Builder().url(httpUrl).build()
- val result = client.newCall(request).execute()
- val response = result.body?.string()
-
- if (response != null) {
- if (response.contains("done")) {
- return true
- } else {
- parseMethodResponse(method, response)
+ client.newCall(request).execute().use { result ->
+ result.body?.string()?.let { response ->
+ if (response.contains("done")) {
+ return true
+ } else {
+ parseMethodResponse(method, response)
+ }
}
}
} else {
@@ -273,7 +290,10 @@ open class PinboardPoster() {
return false
}
- private fun validate(): Boolean {
+ /**
+ * Ensures that the API token and end point are valid.
+ */
+ fun validate(): Boolean {
var isValid = true
if (!apiToken.contains(':')) {
logger.severe("Please specify a valid API token. (eg. user:TOKEN)")
@@ -289,8 +309,8 @@ open class PinboardPoster() {
var isValid = url.isNotBlank()
if (isValid) {
try {
- URL(url)
- } catch (e: MalformedURLException) {
+ URI(url)
+ } catch (e: URISyntaxException) {
logger.log(Level.FINE, "Invalid URL: $url", e)
isValid = false
}
diff --git a/src/test/kotlin/net/thauvin/erik/pinboard/PinboardPosterTest.kt b/src/test/kotlin/net/thauvin/erik/pinboard/PinboardPosterTest.kt
index 0c724c7..9281df5 100644
--- a/src/test/kotlin/net/thauvin/erik/pinboard/PinboardPosterTest.kt
+++ b/src/test/kotlin/net/thauvin/erik/pinboard/PinboardPosterTest.kt
@@ -1,8 +1,7 @@
/*
* PinboardPosterTest.kt
*
- * Copyright (c) 2017-2021, Erik C. Thauvin (erik@thauvin.net)
- * All rights reserved.
+ * Copyright (c) 2017-2025, Erik C. Thauvin (erik@thauvin.net)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -32,20 +31,24 @@
package net.thauvin.erik.pinboard
-import org.testng.Assert.assertFalse
-import org.testng.Assert.assertTrue
-import org.testng.Assert.expectThrows
-import org.testng.annotations.Test
+import org.junit.jupiter.api.assertThrows
import java.io.IOException
import java.nio.file.Files
import java.nio.file.Paths
-import java.util.Properties
+import java.time.ZonedDateTime
+import java.util.*
import java.util.logging.Level
+import kotlin.test.Test
+import kotlin.test.assertFalse
+import kotlin.test.assertTrue
class PinboardPosterTest {
- private val url = "http://www.foo.com/"
+ private val url = randomUrl()
private val desc = "This is a test."
private val localProps = Paths.get("local.properties")
+ private val isCi = "true" == System.getenv("CI")
+
+ private fun randomUrl(): String = "https://www.example.com/?random=" + (1000..10000).random()
@Test
fun testAddPin() {
@@ -61,8 +64,53 @@ class PinboardPosterTest {
// assertFalse(poster.addPin(url, desc), "apiToken: ${poster.apiToken}")
poster = PinboardPoster(localProps)
- poster.logger.level = Level.FINE
- assertTrue(poster.addPin(url, desc), "apiToken: ${Constants.ENV_API_TOKEN}")
+ if (!isCi) {
+ poster.logger.level = Level.FINE
+ }
+
+ assertTrue(poster.validate(), "validate()")
+
+ assertTrue(poster.addPin(url, desc), "addPin($url, $desc)")
+
+ assertTrue(poster.deletePin(url), "deletePin($url)")
+ }
+
+ @Test
+ fun testAddPinConfig() {
+ val poster = PinboardPoster(localProps)
+ if (!isCi) {
+ poster.logger.level = Level.FINE
+ }
+
+ assertTrue(poster.validate(), "validate()")
+
+ var config = PinConfig.Builder(url, desc).extended("extra")
+
+ assertTrue(poster.addPin(config.build()), "apiToken: ${Constants.ENV_API_TOKEN}")
+
+ config = config.tags("foo", "bar")
+ assertTrue(poster.addPin(config.build()), "tags(foo,bar)")
+
+ config = config.shared(false)
+ assertTrue(poster.addPin(config.build()), "shared(false)")
+
+ try {
+ assertFalse(poster.addPin(config.replace(false).build()))
+ } catch (e: IOException) {
+ assertTrue(e.message!!.contains("item already exists"))
+ }
+
+ config = config.description("Yet another test.").replace(true).toRead(true)
+ assertTrue(poster.addPin(config.build()), "toRead(true)")
+
+ config = config.dt(ZonedDateTime.now())
+ assertTrue(poster.addPin(config.build()), "dt(now)")
+
+ assertTrue(poster.deletePin(url), "deletePin($url)")
+
+ config = config.url(randomUrl())
+ assertTrue(poster.addPin(config.build()), "add($url)")
+ assertTrue(poster.deletePin(config.url), "delete($url)")
}
@Test
@@ -78,25 +126,29 @@ class PinboardPosterTest {
}
var poster = PinboardPoster(props)
- poster.logger.level = Level.FINE
+ if (!isCi) {
+ poster.logger.level = Level.FINE
+ }
+
+ assertTrue(poster.validate(), "validate()")
poster.apiEndPoint = ""
assertFalse(poster.deletePin(url), "apiEndPoint: ")
poster = PinboardPoster(localProps, Constants.ENV_API_TOKEN)
- poster.logger.level = Level.FINE
poster.apiEndPoint = Constants.API_ENDPOINT
- assertTrue(poster.deletePin(url), "apiEndPoint: ${Constants.API_ENDPOINT}")
+ assertTrue(poster.addPin(url, desc), "addPin($url, $desc)")
+ assertTrue(poster.deletePin(url), "deletePin($url)")
- expectThrows(IOException::class.java) {
+ assertThrows {
poster.parseMethodResponse("post/delete", "")
}
- expectThrows(IOException::class.java) {
+ assertThrows {
poster.parseMethodResponse("post/delete", "")
}
- assertFalse(poster.deletePin("foo.com"), "url: foo.com")
+ assertFalse(poster.deletePin("foo.com"), "deletePin(foo.com)")
}
}
diff --git a/updatewrappers.sh b/updatewrappers.sh
deleted file mode 100644
index a79d31e..0000000
--- a/updatewrappers.sh
+++ /dev/null
@@ -1,60 +0,0 @@
-#!/bin/bash
-
-#
-# Version: 1.0.1
-#
-
-# set the examples directories
-declare -a dirs=(
- "${PWD##*/}"
- "samples/java"
- "samples/kotlin")
-java8=true
-
-###
-
-pwd=$PWD
-cyan=$(tput setaf 6)
-green=$(tput setaf 2)
-red=$(tput setaf 1)
-std=$(tput sgr0)
-
-if [ "$java8" = true ]
-then
- export JAVA_HOME="$JAVA8_HOME"
- export PATH="$(cygpath "$JAVA_HOME")/bin:$PATH"
-fi
-
-kVer=$(kobaltw --version | awk '{print substr($2, 1, length($2)-1)}')
-updateWrappers() {
- curVer="$(gradle --version | awk '/Gradle/ {print $2}')"
- if [ -d gradle ]; then
- if [ "$curVer" != "$(./gradlew --version | awk '/Gradle/ {print $2}')" ]; then
- gradle -q --console=plain wrapper
- echo -e " $(./gradlew --version | awk '/Gradle/') ${green}UPDATED${std}"
- else
- echo -e " Gradle $curVer UP-TO-DATE"
- fi
- fi
- if [ -d kobalt ]; then
- kw=$(cut -d "=" -f 2 kobalt/wrapper/kobalt-wrapper.properties)
- if [ "$kw" = "$kVer" ]
- then
- echo -e " Kobalt $kw UP-TO-DATE"
- else
- echo -e "kobalt.version=$kVer" > kobalt/wrapper/kobalt-wrapper.properties
- echo -e " Kobalt $kVer ${green}UPDATED${std}"
- fi
- fi
-}
-
-echo -e "Updating wrappers..."
-
-for d in "${dirs[@]}"; do
- if [ -d "$d" ]; then
- cd "$d" || exit 1
- fi
- echo -e " ${cyan}${d}${std}"
- updateWrappers
- cd "$pwd"
-done