Skip to content

Commit

Permalink
Merge remote-tracking branch 'jpos/master' into feature/hibernate_6
Browse files Browse the repository at this point in the history
  • Loading branch information
aVolpe committed Oct 4, 2023
2 parents 63d48da + 558669e commit 8b0dcf8
Show file tree
Hide file tree
Showing 30 changed files with 781 additions and 83 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/jpos-ee.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ jobs:
strategy:
fail-fast: false
matrix:
java: [ 1.8, 9, 10, 11, 12, 13, 14, 15 ]
java: [ 1.8, 11 ]
os: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
Expand Down
4 changes: 2 additions & 2 deletions libraries.gradle
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
ext {
jposVersion = '2.1.8-SNAPSHOT'
jposVersion = '2.1.9-SNAPSHOT'
slf4jVersion = '1.7.28'
logbackVersion = '1.2.8'
hibernateVersion = '6.1.5.Final'
hibernateEhcacheVersion = '6.0.0.Alpha7'
geronimoVersion = '1.1.1'
jettyVersion = '9.4.44.v20210927'
jettyVersion = '9.4.50.v20221201'
servletApiVersion = '4.0.1'
websocketApiVersion = '1.1'
jgroupsVersion = '4.1.5.Final'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,11 @@
import java.io.IOException;
import java.io.FileInputStream;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import org.jpos.core.Environment;
import org.jpos.iso.*;
import org.jpos.iso.packager.XMLPackager;
import org.jpos.util.Logger;
Expand All @@ -42,13 +46,16 @@ public class TestRunner
MUX mux;
ISOPackager packager;
Interpreter bsh;

long timeout;
private static final String NL = System.getProperty("line.separator");
public static final long TIMEOUT = 60000;
public TestRunner () {
super();
}
protected void initService() throws ISOException {
String packagerClass = cfg.get("packager", null);
timeout = cfg.getLong ("timeout", TIMEOUT);
if (packagerClass != null) {
try {
packager = (ISOPackager) Class.forName(packagerClass).newInstance();
Expand All @@ -60,8 +67,23 @@ protected void initService() throws ISOException {
}
}
protected void startService() {
for (int i=0; i<cfg.getInt("sessions", 1); i++)
new Thread(this).start();
int sessions = cfg.getInt("sessions", 1);
ExecutorService executor = Executors.newCachedThreadPool();
for (int i=0; i<sessions; i++)
executor.execute(this);
executor.shutdown();
if (cfg.getBoolean ("shutdown")) {
Executors.newSingleThreadExecutor().execute( () -> {
try {
if (!executor.awaitTermination(timeout, TimeUnit.MILLISECONDS)) {
log.warn("Runners didn't finish before global timeout");
}
} catch (InterruptedException e) {
log.warn("interrupted while awaiting workers termination", e);
}
getServer().shutdown();
});
}
}
public void run () {
try {
Expand All @@ -77,8 +99,6 @@ public void run () {
} catch (Throwable t) {
getLog().error (t);
}
if (cfg.getBoolean ("shutdown"))
getServer().shutdown();
}
private void runSuite (List suite, MUX mux, Interpreter bsh)
throws ISOException, IOException, EvalError
Expand Down Expand Up @@ -146,7 +166,7 @@ private void runSuite (List suite, MUX mux, Interpreter bsh)
);
ISOUtil.sleep (100); // let the channel do its logging first
if (cfg.getBoolean ("shutdown"))
evt.addMessage ("Shutting down");
evt.addMessage ("waiting for shutdown");

Logger.log (evt);
}
Expand Down Expand Up @@ -179,7 +199,7 @@ private List<TestCase> initSuite (Element suite)
if (to != null)
tc.setTimeout (Long.parseLong (to));
else
tc.setTimeout (cfg.getLong ("timeout", TIMEOUT));
tc.setTimeout (timeout);
l.add (tc);

}
Expand Down Expand Up @@ -352,14 +372,17 @@ private ISOMsg applyRequestProps (ISOMsg m, Interpreter bsh)
if (c instanceof ISOMsg) {
applyRequestProps ((ISOMsg) c, bsh);
} else if (c instanceof ISOField) {
String value = (String) c.getValue();
String value = Environment.get((String) c.getValue());
if (value.length() > 0) {
try {
if (value.charAt (0) == '!') {
m.set (i, bsh.eval (value.substring(1)).toString());
}
else if (value.charAt (0) == '#') {
m.set (i, ISOUtil.hex2byte(bsh.eval (value.substring(1)).toString()));
}
else if (!value.equals(c.getValue())) {
m.set (i, value);
}
} catch (NullPointerException e) {
m.unset (i);
Expand Down
23 changes: 14 additions & 9 deletions modules/cmf/src/main/java/org/jpos/cmf/AdditionalAmount.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@
import java.math.BigDecimal;
import java.util.Objects;

/**
* @deprecated Use {@link org.jpos.cmf.CMFAdditionalAmount}
*/
@Deprecated
@SuppressWarnings("WeakerAccess")
public class AdditionalAmount {

Expand Down Expand Up @@ -111,16 +115,17 @@ public String serialize() {

long absAmt= getAmount().movePointRight(getCurrencyMinorUnit()).abs().longValue();

@SuppressWarnings("StringBufferReplaceableByString")
StringBuilder sb = new StringBuilder();
sb.append(getAccountType());
sb.append(getAmountType().toString());
sb.append(getCurrencyCode());
sb.append(getCurrencyMinorUnit());
sb.append(getAmount().compareTo(BigDecimal.ZERO) >= 0 ? "C" : "D");
sb.append(StringUtils.leftPad(Long.toString(absAmt), 12, '0'));
return getAccountType() +
getAmountType().toString() +
getCurrencyCode() +
getCurrencyMinorUnit() +
(getAmount().compareTo(BigDecimal.ZERO) >= 0 ? "C" : "D") +
StringUtils.leftPad(Long.toString(absAmt), 12, '0');
}

return sb.toString();
@Override
public String toString() {
return amount + String.format ("{%s,%s,%s,%d}", accountType, amountType, currencyCode, currencyMinorUnit);
}

static AdditionalAmount parse(String data) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@

/**
* Handles additional amounts field content - DE-054
*
* @deprecated Use {@link org.jpos.iso.AdditionalAmountsWrapper}
*/
@Deprecated
public final class AdditionalAmountsWrapper extends LinkedHashSet<AdditionalAmount> {

private static final long serialVersionUID = 2526355280704001241L;
Expand Down
70 changes: 52 additions & 18 deletions modules/cmf/src/main/java/org/jpos/cmf/AmountType.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* jPOS Project [http://jpos.org]
* Copyright (C) 2000-2021 jPOS Software SRL
* Copyright (C) 2000-2023 jPOS Software SRL
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
Expand All @@ -18,18 +18,21 @@

package org.jpos.cmf;

import org.jpos.iso.AdditionalAmountType;
import org.jpos.iso.AdditionalAmountTypeConverter;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
* See jPOS-CMF.pdf DE-054 <br>
* Some extra entries are based on ISO-8583:2003
* Some extra entries are based on ISO-8583:2003 and other common specs.
*/
public enum AmountType {
public enum AmountType implements AdditionalAmountType {
ISO_RESERVED("00"),

// Account related balances
// 0x..1x - Account related balances
ACCOUNT_LEDGER_CURRENT_BALANCE("01"),
ACCOUNT_AVAILABLE_BALANCE("02"),
AMOUNT_OWING("03"),
Expand All @@ -40,6 +43,7 @@ public enum AmountType {
DESTINATION_ACCOUNT_AVAILABLE_BALANCE("08"),
CREDIT_LINE("09"),
AMOUNT_ON_HOLD("10"),
PREPAID_ONLINE_BILL_FEE("17"), // Mastercard

// 2x - Card related amounts
AMOUNT_REMAINING_THIS_CYCLE("20"),
Expand All @@ -48,17 +52,32 @@ public enum AmountType {
AMOUNT_CASH("40"),
AMOUNT_GOODS_AND_SERVICES("41"),
AMOUNT_SURCHARGE("42"),
TOTAL_CUMULATIVE_AMOUNT("43"), // Visa: total cumulative, for series of incremental transactions
AMOUNT_PRE_CURRENCY_CONVERSION("45"), // Visa

// 5x - Electronic benefit amounts
BEGINNING_BALANCE("50"),
PRE_AUTH_AMOUNT("51"),
CLIENT_PROVIDED_FEES("56"), // Visa

// Visa, Mastercard, others, usually used for partials.
// Left as reference/placeholder/pragmatism here, but in jPOS-CMF is more appropriate to use DE-030
ORIGINAL_AMOUNT("57"),

// custom CMF
// other custom mappings
GRATUITY("80"),
AMOUNT_TAXABLE("81"),
TRANSIT_AMOUNT("4T"), // Visa

// HEALTHCARE USA
HEALTHCARE_AMOUNT_COPAYMENT("3S"), // Visa
HEALTHCARE_AMOUNT_ELIGIBILITY("4S"), // Mastercard: 10
HEALTHCARE_AMOUNT_PRESCRIPTION("4U"), // Mastercard: 11
HEALTHCARE_AMOUNT_VISION("4V"), // Mastercard: 12
HEALTHCARE_AMOUNT_CLINIC("4W"), // Visa: clinic/other qualified medical
HEALTHCARE_AMOUNT_DENTAL("4X"), // Visa

// PRIVATE RESERVED
// OTHER PRIVATE RESERVED (may be repurposed/renamed in the future)
PRIVATE_RESERVED_1S("1S"),
PRIVATE_RESERVED_1T("1T"),
PRIVATE_RESERVED_1U("1U"),
Expand All @@ -77,7 +96,6 @@ public enum AmountType {
PRIVATE_RESERVED_2Y("2Y"),
PRIVATE_RESERVED_2Z("2Z"),

PRIVATE_RESERVED_3S("3S"),
PRIVATE_RESERVED_3T("3T"),
PRIVATE_RESERVED_3U("3U"),
PRIVATE_RESERVED_3V("3V"),
Expand All @@ -86,12 +104,6 @@ public enum AmountType {
PRIVATE_RESERVED_3Y("3Y"),
PRIVATE_RESERVED_3Z("3Z"),

PRIVATE_RESERVED_4S("4S"),
PRIVATE_RESERVED_4T("4T"),
PRIVATE_RESERVED_4U("4U"),
PRIVATE_RESERVED_4V("4V"),
PRIVATE_RESERVED_4W("4W"),
PRIVATE_RESERVED_4X("4X"),
PRIVATE_RESERVED_4Y("4Y"),
PRIVATE_RESERVED_4Z("4Z"),

Expand All @@ -118,18 +130,40 @@ public enum AmountType {
this.code = code;
}

public String getCode() {
return code;
}

/** shorter alias for getCode, in the style of enum name(), required by {@link AdditionalAmountType} */
@Override
public String toString() {
public String code() {
return code;
}
public String getCode() {

@Override
public String toString() {
return code;
}

public static AmountType fromCode(String code) {
Objects.requireNonNull(code);
AmountType ret = byCode.get(code.toUpperCase());
if (ret == null) throw new IllegalArgumentException("Invalid amount type: " + code);
return ret;
return byCode.get(code.toUpperCase());
}


// ----- inner converter (dummy, since this is from CMF to CMF, but left here as reference implementation)

public static AdditionalAmountTypeConverter CONVERTER = new AdditionalAmountTypeConverter() {
public String toCMF(String code) {
Objects.requireNonNull(code);
AmountType t = byCode.get(code.toUpperCase());
return t != null ? t.code() : null;
}

public String fromCMF(String cmfCode) {
Objects.requireNonNull(cmfCode);
AmountType t = byCode.get(cmfCode.toUpperCase());
return t != null ? t.code() : null;
}
};
}
83 changes: 83 additions & 0 deletions modules/cmf/src/main/java/org/jpos/cmf/CMFAdditionalAmount.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/*
* jPOS Project [http://jpos.org]
* Copyright (C) 2000-2023 jPOS Software SRL
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package org.jpos.cmf;

import org.apache.commons.lang3.StringUtils;
import org.jpos.iso.AdditionalAmount;

import java.math.BigDecimal;
import java.util.Objects;

/**
* Represents one occurrence of an Additional Amount (from DE-54) in jPOS-CMF format.
*/
public class CMFAdditionalAmount extends AdditionalAmount {

public final static int SERIALIZED_DATA_LENGTH = 21;

public CMFAdditionalAmount() {
}

public CMFAdditionalAmount(String accountType, BigDecimal amount, String currencyCode,
String amountType, int currencyMinorUnit) {
super(accountType, amount, currencyCode, amountType, currencyMinorUnit);
}

@Override
public String serialize() {
if (getAmountTypeCode() == null)
throw new IllegalStateException("Amount type not set");

if (getAmount() == null)
throw new IllegalStateException("Amount not set");

long absAmt= getAmount().movePointRight(getCurrencyMinorUnit()).abs().longValue();

return getAccountType() +
getAmountTypeCode() +
getCurrencyCode() +
getCurrencyMinorUnit() +
(getAmount().compareTo(BigDecimal.ZERO) >= 0 ? "C" : "D") +
StringUtils.leftPad(Long.toString(absAmt), 12, '0');
}

public static AdditionalAmount parse(String data) {
Objects.requireNonNull(data);

if (data.length() != SERIALIZED_DATA_LENGTH)
throw new IllegalArgumentException("Invalid data length");

String accountType = StringUtils.mid(data, 0, 2);
String amountType = StringUtils.mid(data, 2, 2);
String currencyCode = StringUtils.mid(data, 4, 3);
int minorUnit = Integer.parseInt(StringUtils.mid(data, 7, 1));

String amountSign = StringUtils.mid(data, 8, 1);
BigDecimal amount = new BigDecimal(StringUtils.right(data, 12)).movePointLeft(minorUnit);

if (!"C.D".contains(amountSign))
throw new IllegalArgumentException("Invalid amount sign");

if ("D".equalsIgnoreCase(amountSign))
amount = amount.negate();

return new CMFAdditionalAmount(accountType, amount, currencyCode, amountType, minorUnit);
}

}
Loading

0 comments on commit 8b0dcf8

Please sign in to comment.