Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ jobs:
with:
java-version: 11
- name: Publish jars
run: ./gradlew :timebase-collections:publish :timebase-lang:publish :timebase-messages:publish :timebase-util:publish
run: ./gradlew publishAll uploadArtifactsToCentralPortal
env:
SONATYPE_REPOSITORY: ${{ secrets.SONATYPE_REPOSITORY }}
SONATYPE_NEXUS_USERNAME: ${{ secrets.SONATYPE_NEXUS_USERNAME }}
Expand Down
21 changes: 15 additions & 6 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ def leafProjects = subprojects.findAll { subproject ->
}
ext.leafProjects = leafProjects // Publish as external variable

ext {
sonaUser = findProperty('SONATYPE_NEXUS_USERNAME') ?: System.getenv('SONATYPE_NEXUS_USERNAME') ?: "FakeUser"
sonaPass = findProperty('SONATYPE_NEXUS_PASSWORD') ?: System.getenv('SONATYPE_NEXUS_PASSWORD') ?: "FakePass"
}

// Default test categories
ext.categories = 'Unit'

Expand Down Expand Up @@ -288,14 +293,18 @@ configure(leafProjects) {

required { isReleaseVersion }
}
}

// //tasks.test { enabled = false }
// test {
// useJUnit {
// setIncludeCategories categories.split(',').collect { "deltix.util.CommonsJUnitCategories\$${it}".toString() } as Set
// }
// }
task publishAll(dependsOn: leafProjects.collect { it.path + ":publish" }) {
group 'publishing'
description 'Publish All Artifacts'
}

tasks.register('uploadArtifactsToCentralPortal', com.epam.deltix.buildsrc.SonatypeCentralPortalUploadRepositoryTask) {
portalUsername.set(sonaUser)
portalPassword.set(sonaPass)
groupId.set('com.epam.deltix')
snapshotRelease.set(false)
}

allprojects {
Expand Down
7 changes: 7 additions & 0 deletions buildSrc/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
repositories {
mavenCentral()
}

dependencies {
implementation 'org.json:json:20240303'
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
/*
* Copyright 2014-2025 Real Logic Limited.
*
* 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.
*/
package com.epam.deltix.buildsrc;

import org.gradle.api.DefaultTask;
import org.gradle.api.provider.Property;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.TaskAction;
import org.json.JSONArray;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

/**
* This task performs manual steps to publish artifacts to Central Portal via OSSRH Staging API.
*/
public class SonatypeCentralPortalUploadRepositoryTask extends DefaultTask {
private static final String CENTRAL_PORTAL_OSSRH_API_URI = "https://ossrh-staging-api.central.sonatype.com";
private static final int CONNECTION_TIMEOUT = 30000;

private final Property<String> portalUsername;
private final Property<String> portalPassword;
private final Property<String> groupId;
private final Property<Boolean> snapshotRelease;

/**
* Create new task instance.
*/
public SonatypeCentralPortalUploadRepositoryTask() {
portalUsername = getProject().getObjects().property(String.class);
portalPassword = getProject().getObjects().property(String.class);
groupId = getProject().getObjects().property(String.class);
snapshotRelease = getProject().getObjects().property(Boolean.class);
}

/**
* Return property to set Central Portal username.
*
* @return Central Portal username.
*/
@Input
public Property<String> getPortalUsername() {
return portalUsername;
}

/**
* Return property to set Central Portal password.
*
* @return Central Portal password.
*/
@Input
public Property<String> getPortalPassword() {
return portalPassword;
}

/**
* Return property to set {@code groupId} of the project.
*
* @return {@code groupId} of the project.
*/
@Input
public Property<String> getGroupId() {
return groupId;
}

/**
* Return property to set snapshot release.
*
* @return {@code true} if snapshot release.
*/
@Input
public Property<Boolean> getSnapshotRelease() {
return snapshotRelease;
}

/**
* Publish staging repository to the Central Portal.
*/
@TaskAction
public void run() throws IOException, InterruptedException {
if (!portalUsername.isPresent()) {
return;
}

if (snapshotRelease.get()) {
return;
}

String userNameAndPassword = portalUsername.get() + ":" + portalPassword.get();
String bearer = Base64.getEncoder().encodeToString(userNameAndPassword.getBytes(StandardCharsets.US_ASCII));
URI apiUri = URI.create(CENTRAL_PORTAL_OSSRH_API_URI);

String repositoryKey = findOpenRepository(apiUri, bearer);
uploadRepositoryToPortal(apiUri, bearer, repositoryKey);
dropRepository(apiUri, bearer, repositoryKey);
}

private String findOpenRepository(URI apiUri, String bearer) throws IOException {
String endpoint = apiUri.resolve("/manual/search/repositories?ip=client").toString();
HttpURLConnection conn = (HttpURLConnection) new URL(endpoint).openConnection();
conn.setConnectTimeout(CONNECTION_TIMEOUT);
conn.setReadTimeout(CONNECTION_TIMEOUT);
conn.setRequestMethod("GET");
conn.setRequestProperty("Authorization", "Bearer " + bearer);

int status = conn.getResponseCode();
String body = readBody(conn);
if (status != 200) {
throw new IllegalStateException("Failed to query repositories: " +
"status=" + status + ", response=" + body);
}

JSONArray repositories = new JSONObject(body).getJSONArray("repositories");
if (repositories.isEmpty()) {
throw new IllegalStateException("No open repositories found!");
}

String repositoryKey = null;
String group = groupId.get();
for (int i = 0; i < repositories.length(); i++) {
JSONObject repo = (JSONObject) repositories.get(i);
if ("open".equals(repo.getString("state"))) {
String key = repo.getString("key");
if (key.contains(group)) {
repositoryKey = key;
break;
}
}
}

if (null == repositoryKey) {
throw new IllegalStateException("No open repositories found!");
}
return repositoryKey;
}

private static void uploadRepositoryToPortal(URI apiUri, String bearer, String repositoryKey) throws IOException {
String endpoint = apiUri.resolve("/manual/upload/repository/" + repositoryKey + "?publishing_type=user_managed").toString();
HttpURLConnection conn = (HttpURLConnection) new URL(endpoint).openConnection();
conn.setConnectTimeout(CONNECTION_TIMEOUT);
conn.setReadTimeout(CONNECTION_TIMEOUT);
conn.setRequestMethod("POST");
conn.setRequestProperty("Authorization", "Bearer " + bearer);
conn.setDoOutput(true);
conn.getOutputStream().close();

int status = conn.getResponseCode();
String body = readBody(conn);
if (status != 200) {
throw new IllegalStateException("Failed to upload repository: repository_key=" + repositoryKey + ", status=" + status + ", response=" + body);
}
}

private static void dropRepository(URI apiUri, String bearer, String repositoryKey) throws IOException {
String endpoint = apiUri.resolve("/manual/drop/repository/" + repositoryKey).toString();
HttpURLConnection conn = (HttpURLConnection) new URL(endpoint).openConnection();
conn.setConnectTimeout(CONNECTION_TIMEOUT);
conn.setReadTimeout(CONNECTION_TIMEOUT);
conn.setRequestMethod("DELETE");
conn.setRequestProperty("Authorization", "Bearer " + bearer);

int status = conn.getResponseCode();
String body = readBody(conn);
if (status != 204) {
throw new IllegalStateException("Failed to drop repository: repository_key=" + repositoryKey + ", status=" + status + ", response=" + body);
}
}

private static String readBody(HttpURLConnection conn) throws IOException {
InputStream stream;
try {
stream = (conn.getResponseCode() < 400) ? conn.getInputStream() : conn.getErrorStream();
if (stream == null) {
return "";
}
} catch (IOException e) {
return "";
}

StringBuilder body = new StringBuilder();
try (BufferedReader in = new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8))) {
String line;
while ((line = in.readLine()) != null) {
body.append(line);
}
}
return body.toString();
}
}
18 changes: 9 additions & 9 deletions lang/src/main/java/com/epam/deltix/util/lang/MathUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public static int sign (float x) {
* greater, less than, or equal to 0 respectively.
*/
public static int sign (int x) {
return (x > 0 ? 1 : x < 0 ? -1 : 0);
return (Integer.compare(x, 0));
}

/**
Expand All @@ -65,7 +65,7 @@ public static int sign (long x) {
* Returns 1, -1, or 0 depending on the difference between arguments.
*/
public static int compare (int x, int y) {
return (x > y ? 1 : x < y ? -1 : 0);
return (Integer.compare(x, y));
}

/**
Expand All @@ -86,7 +86,7 @@ public static int compare (double x, double y) {
* Returns 1, -1, or 0 depending on the difference between arguments.
*/
public static int compare (long x, long y) {
return (x > y ? 1 : x < y ? -1 : 0);
return Long.compare(x, y);
}

/**
Expand Down Expand Up @@ -224,22 +224,22 @@ public static double cumulativeStdNormalDistribution (double X) {

public static Number negate (Number n) {
if (n instanceof Integer)
return (new Integer (-n.intValue ()));
return (-n.intValue());

if (n instanceof Long)
return (new Long (-n.longValue ()));
return (-n.longValue());

if (n instanceof Double)
return (new Double (-n.doubleValue ()));
return (-n.doubleValue());

if (n instanceof Float)
return (new Float (-n.floatValue ()));
return (-n.floatValue());

if (n instanceof Byte)
return (new Byte ((byte) -n.byteValue ()));
return ((byte) -n.byteValue());

if (n instanceof Short)
return (new Short ((short) -n.shortValue ()));
return ((short) -n.shortValue());

if (n instanceof BigDecimal)
return (((BigDecimal) n).negate ());
Expand Down
32 changes: 32 additions & 0 deletions lang/src/main/java/com/epam/deltix/util/lang/StringUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -728,6 +728,11 @@ public static boolean isEmpty (CharSequence value) {
return true;
}

/** @return true if trimmed input is not blank string and is not null */
public static boolean isNotEmpty (CharSequence value) {
return !isEmpty(value);
}

/** @return true if input is null or empty string contains only whitespaces */
public static boolean isWhitespace (CharSequence value) {
if (value == null)
Expand Down Expand Up @@ -1276,4 +1281,31 @@ private static boolean isWildcardQuoted(CharSequence expression, int pos) {
("_%".indexOf(expression.charAt(pos + 1)) != -1);
}

public static boolean equals(CharSequence s1, CharSequence s2) {
if (s1 == null) {
return s2 == null;
}

if (s2 == null) {
return false;
}

final int len1 = s1.length();
final int len2 = s2.length();

final int diff = len1 - len2;

if (diff != 0) {
return false;
}

for (int i = 0; i < len1; i++) {
if (s1.charAt(i) != s2.charAt(i)) {
return false;
}
}

return true;
}

}
Loading