<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <modelVersion>4.0.0</modelVersion>
  <groupId>io.github.atkawa7</groupId>
  <artifactId>s3-client</artifactId>
  <version>1.0.2</version>
  <name>s3-client</name>
  <description>s3-client</description>
  <url>https://github.com/atkawa7/alt-sdk</url>
  <licenses>
    <license>
      <name>Apache License</name>
      <url>https://raw.githubusercontent.com/atkawa7/alt-sdk/LICENSE.txt</url>
      <distribution>https://github.com/atkawa7/alt-sdk</distribution>
    </license>
  </licenses>
  <developers>
    <developer>
      <name>atkawa7</name>
      <email>atkawa7@yahoo.com</email>
      <organization>atkawa7</organization>
      <organizationUrl>https://github.com/atkawa7</organizationUrl>
    </developer>
  </developers>
  <scm>
    <connection>scm:git:git://github.com/atkawa7/alt-sdk.git</connection>
    <developerConnection>scm:git:git@github.com:atkawa7/alt-sdk.git</developerConnection>
    <tag>s3-client-1.0.2</tag>
    <url>https://github.com/atkawa7/alt-sdk</url>
  </scm>
  <properties>
    <maven.compiler.target>1.8</maven.compiler.target>
    <maven.compiler.source>1.8</maven.compiler.source>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>
  <dependencies>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-annotations</artifactId>
      <version>2.20</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.20.0</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.dataformat</groupId>
      <artifactId>jackson-dataformat-xml</artifactId>
      <version>2.20.0</version>
    </dependency>
    <dependency>
      <groupId>io.github.atkawa7</groupId>
      <artifactId>polly-http</artifactId>
      <version>0.0.19</version>
    </dependency>
    <dependency>
      <groupId>org.apache.commons</groupId>
      <artifactId>commons-lang3</artifactId>
      <version>3.19.0</version>
    </dependency>
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>1.18.30</version>
    </dependency>
  </dependencies>
  <build>
    <plugins>
      <plugin>
        <artifactId>maven-source-plugin</artifactId>
        <version>3.2.1</version>
        <executions>
          <execution>
            <id>attach-sources</id>
            <phase>verify</phase>
            <goals>
              <goal>jar-no-fork</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <artifactId>maven-javadoc-plugin</artifactId>
        <version>3.2.0</version>
        <executions>
          <execution>
            <id>attach-javadocs</id>
            <phase>deploy</phase>
            <goals>
              <goal>jar</goal>
            </goals>
          </execution>
        </executions>
        <configuration>
          <source>8</source>
          <detectJavaApiLink>false</detectJavaApiLink>
          <additionalJOption>-Xdoclint:none</additionalJOption>
        </configuration>
      </plugin>
      <plugin>
        <artifactId>maven-gpg-plugin</artifactId>
        <version>1.6</version>
        <executions>
          <execution>
            <id>sign-artifacts</id>
            <phase>verify</phase>
            <goals>
              <goal>sign</goal>
            </goals>
          </execution>
        </executions>
        <configuration>
          <gpgArguments>
            <arg>--pinentry-mode</arg>
            <arg>loopback</arg>
          </gpgArguments>
        </configuration>
      </plugin>
      <plugin>
        <artifactId>maven-antrun-plugin</artifactId>
        <version>3.1.0</version>
        <executions>
          <execution>
            <id>hash-artifacts</id>
            <phase>verify</phase>
            <goals>
              <goal>run</goal>
            </goals>
            <configuration>
              <target>
                <checksum fileext=".sha256" algorithm="SHA-256">
                  <fileset dir="${project.build.directory}">
                    <include name="*.jar" />
                    <include name="*.pom" />
                  </fileset>
                </checksum>
                <checksum fileext=".md5" algorithm="MD5">
                  <fileset dir="${project.build.directory}">
                    <include name="*.jar" />
                    <include name="*.pom" />
                  </fileset>
                </checksum>
                <checksum fileext=".sha1" algorithm="SHA-1">
                  <fileset dir="${project.build.directory}">
                    <include name="*.jar" />
                    <include name="*.pom" />
                  </fileset>
                </checksum>
              </target>
            </configuration>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <artifactId>maven-assembly-plugin</artifactId>
        <version>3.5.0</version>
        <executions>
          <execution>
            <id>make-project-zip</id>
            <phase>verify</phase>
            <goals>
              <goal>single</goal>
            </goals>
            <configuration>
              <finalName>${project.artifactId}-${project.version}</finalName>
              <appendAssemblyId>false</appendAssemblyId>
              <descriptors>
                <descriptor>../central/central-upload.xml</descriptor>
              </descriptors>
            </configuration>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <groupId>org.codehaus.gmavenplus</groupId>
        <artifactId>gmavenplus-plugin</artifactId>
        <version>3.0.2</version>
        <executions>
          <execution>
            <id>upload-bundle</id>
            <phase>none</phase>
            <goals>
              <goal>execute</goal>
            </goals>
            <configuration>
              <scripts>
                <script>import java.net.HttpURLConnection
import java.net.URL
import java.nio.file.Files
import java.nio.file.Paths
import java.util.Base64
import java.io.OutputStreamWriter
import java.security.MessageDigest

// ----------------------
// Helper: mask secrets
// ----------------------
def maskSecret = { value, visibleStart = 2, visibleEnd = 2 ->
    if (value == null || value.length() &lt;= visibleStart + visibleEnd) {
        return "*" * (value?.length() ?: 0)
    }
    value.substring(0, visibleStart) + ("*" * (value.length() - visibleStart - visibleEnd)) + value.substring(value.length() - visibleEnd)
}

// ----------------------
// Helper: strip ${env. ... } syntax
// ----------------------
def stripEnvSyntax = { value ->
    if (value == null) return null
    value = value.trim()
    if (value.startsWith('${env.') &amp;&amp; value.endsWith('}')) {
        return value.substring(6, value.length() - 1)
    }
    return value
}

// ----------------------
// Paths &amp; artifact info
// ----------------------
def artifactId = project.artifactId
def version = project.version
def zipPath = Paths.get(project.basedir.toString())
                   .resolve("target")
                   .resolve("${artifactId}-${version}.zip")

if (!Files.exists(zipPath)) throw new FileNotFoundException(zipPath.toString())
println "Found ZIP: ${zipPath}"

// ----------------------
// Load credentials
// ----------------------
def server = session.settings.getServer("ossrh")
if (!server) throw new RuntimeException("Missing &lt;server> with id='ossrh' in settings.xml")

// Strip env syntax if needed
def username = stripEnvSyntax(server.username)?.trim()
def password = stripEnvSyntax(server.password)?.trim()

if (!username || !password) throw new RuntimeException("Username or password is empty")

println "Username: ${maskSecret(username, visibleStart = 1, visibleEnd = 1)}"
println "Password: ${maskSecret(password)}"
def credentials = "${username}:${password}"
// ----------------------
// Prepare multipart request
// ----------------------
def boundary = "----Boundary${System.currentTimeMillis()}"
def lineEnd = "\r\n"
def twoHyphens = "--"

def url = new URL("https://central.sonatype.com/api/v1/publisher/upload")
def connection = (HttpURLConnection) url.openConnection()
connection.setDoOutput(true)
connection.setRequestMethod("POST")

// Base64 encode username:password for Bearer token
def base64Token = credentials.bytes.encodeBase64().toString()
connection.setRequestProperty("Authorization", "Bearer ${base64Token}")
connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=${boundary}")

def output = connection.outputStream
def writer = new OutputStreamWriter(output, "UTF-8")

// -- bundle (zip file)
writer.write(twoHyphens + boundary + lineEnd)
writer.write("Content-Disposition: form-data; name=\"bundle\"; filename=\"${zipPath.fileName}\"" + lineEnd)
writer.write("Content-Type: application/zip" + lineEnd + lineEnd)
writer.flush()
Files.copy(zipPath, output)
output.flush()
writer.write(lineEnd)

// -- name field
writer.write(twoHyphens + boundary + lineEnd)
writer.write("Content-Disposition: form-data; name=\"name\"" + lineEnd + lineEnd)
writer.write("${artifactId}-${version}" + lineEnd)

// -- publishingType field
writer.write(twoHyphens + boundary + lineEnd)
writer.write("Content-Disposition: form-data; name=\"publishingType\"" + lineEnd + lineEnd)
writer.write("USER_MANAGED" + lineEnd)

// -- end boundary
writer.write(twoHyphens + boundary + twoHyphens + lineEnd)
writer.flush()
writer.close()

// ----------------------
// Execute request
// ----------------------
def responseCode = connection.responseCode
def responseBody = responseCode >= 200 &amp;&amp; responseCode &lt; 300 ? connection.inputStream.text : connection.errorStream.text

println "Response Code: ${responseCode}"
println "Response Body: ${responseBody}"

if (responseCode &lt; 200 || responseCode >= 300) {
    throw new RuntimeException("Upload failed with HTTP ${responseCode}: ${responseBody}")
}

connection.disconnect()
println "Upload successful!"
</script>
              </scripts>
            </configuration>
          </execution>
        </executions>
        <dependencies>
          <dependency>
            <groupId>org.codehaus.groovy</groupId>
            <artifactId>groovy</artifactId>
            <version>3.0.25</version>
          </dependency>
          <dependency>
            <groupId>org.codehaus.groovy</groupId>
            <artifactId>groovy-ant</artifactId>
            <version>3.0.25</version>
          </dependency>
        </dependencies>
      </plugin>
    </plugins>
  </build>
</project>
