public class SystemPropertiesServiceLookup extends XfsServiceLookup {

  private static final Logger LOG = LoggerFactory.getLogger(SystemPropertiesServiceLookup.class);

  private List<ServiceEntry> lookup() {
    final String method = "lookup()";
    final List<ServiceEntry> services = new ArrayList<ServiceEntry>();
    for (Map.Entry<Object, Object> entry : System.getProperties().entrySet()) {
      if (LOG.isDebugEnabled()) {
        LOG.debug(method, entry.getKey() + "=" + entry.getValue());
      }
      XfsServiceClass serviceClass =
          XfsServiceClass.getForServiceClassName(String.valueOf(entry.getKey()));
      if (serviceClass != null) {
        String logicalName = String.valueOf(entry.getValue());
        if (LOG.isInfoEnabled()) {
          LOG.info(method, serviceClass.name() + ": " + logicalName);
        }
        services.add(new ServiceEntry(logicalName, getServicClass(serviceClass)));
      }
    }
    return services;
  }

  @Override
  public Iterator<ServiceEntry> iterator() {
    return lookup().iterator();
  }
}
예제 #2
0
final class VelocityChecking {

  private static final Logger LOG = LoggerFactory.getLogger(VelocityChecking.class);

  private final EMVTransaction transaction;

  VelocityChecking(EMVTransaction transaction) {
    this.transaction = transaction;
  }

  void doVelocityChecking() {
    final String method = "doVelocityChecking()";
    try {
      int lowerLimit =
          BinaryNumber.toInt(transaction.getData(EMVTag.LOWER_CONSECUTIVE_OFFLINE_LIMIT));
      int upperLimit =
          BinaryNumber.toInt(transaction.getData(EMVTag.UPPER_CONSECUTIVE_OFFLINE_LIMIT));
      int lastOnlineATC = readLastOnlineATC();
      if (lastOnlineATC == 0) {
        indicateNewCard();
      }
      int atc = readATC();
      if (LOG.isInfoEnabled()) {
        LOG.info(method, "ATC: " + atc + ", Last Online ATC: " + lastOnlineATC);
      }
      int consecutiveOffline = atc - lastOnlineATC;
      TVR tvr = transaction.getTVR();
      if (consecutiveOffline > lowerLimit) {
        tvr.getByte4().lowerConsecutiveOfflineLimitExceeded();
      }
      if (consecutiveOffline > upperLimit) {
        tvr.getByte4().upperConsecutiveOfflineLimitExceeded();
      }
    } catch (IOException e) {
      if (LOG.isErrorEnabled()) {
        LOG.error(method, "Error reading data from ICC", e);
      }
    } catch (ProcessingStateException e) {
      if (LOG.isErrorEnabled()) {
        LOG.error(method, "Error reading data from ICC", e);
      }
      TVR tvr = transaction.getTVR();
      tvr.getByte4().lowerConsecutiveOfflineLimitExceeded();
      tvr.getByte4().upperConsecutiveOfflineLimitExceeded();
    } catch (DataNotFoundException e) {
      if (LOG.isDebugEnabled()) {
        LOG.debug(method, "Data not found: " + e.getEMVTag());
      }
    }
  }

  private int readATC() throws ProcessingStateException, IOException {
    final String method = "readATC()";
    try {
      return BinaryNumber.toInt(read(EMVTag.APPLICATION_TRANSACTION_COUNTER));
    } catch (ProcessingStateException e) {
      if (LOG.isInfoEnabled()) {
        LOG.info(method, "ATC is missing");
      }
      TVR tvr = transaction.getTVR();
      tvr.getByte1().iccDataMissing();
      throw e;
    }
  }

  private int readLastOnlineATC() throws ProcessingStateException, IOException {
    final String method = "readLastOnlineATC()";
    try {
      return BinaryNumber.toInt(read(EMVTag.LAST_ONLINE_ATC_REGISTER));
    } catch (ProcessingStateException e) {
      if (LOG.isInfoEnabled()) {
        LOG.info(method, "Last Online ATC Register is missing");
      }
      throw e;
    }
  }

  private byte[] read(EMVTag emvTag) throws IOException, ProcessingStateException {
    GetDataCommand getDataCommand = GetDataCommand.create(emvTag.getTag());
    RAPDU response = transaction.getICReader().transmit(getDataCommand);
    new ProcessingState(response.getSW()).assertSuccessful();
    return TLV.parse(response.getData()).getValue();
  }

  private void indicateNewCard() {
    final String method = "indicateNewCard()";
    if (LOG.isInfoEnabled()) {
      LOG.info(method, "New card");
    }
    TVR tvr = transaction.getTVR();
    tvr.getByte2().newCard();
  }
}
예제 #3
0
final class RandomTransactionSelection {

  private static final Logger LOG = LoggerFactory.getLogger(RandomTransactionSelection.class);

  private final EMVTransaction transaction;

  /** Amount, Authorised */
  private BigInteger amount = null;

  /** Terminal Floor Limit */
  private BigInteger floorLimit = null;

  /** Target Percentage to be Used for Random Selection */
  private int targetPercentage = -1;

  /** Maximum Target Percentage to be used for Biased Random Selection */
  private int maxTargetPercentage = -1;

  /** Threshold Value for Biased Random Selection */
  private BigInteger thresholdValue = null;

  private int randomNumber = -1;

  RandomTransactionSelection(EMVTransaction transaction) {
    this.transaction = transaction;
  }

  void perform() {
    final String method = "perform()";
    try {
      prerequisites();
      if (amount.compareTo(thresholdValue) < 0) {
        randomSelection();
      } else {
        biasedRandomSelection();
      }
    } catch (DataNotFoundException e) {
      if (LOG.isErrorEnabled()) {
        LOG.error(method, "Data not found: " + e.getEMVTag(), e);
      }
    }
  }

  private void prerequisites() throws DataNotFoundException {
    final String method = "prerequisites()";
    amount = BinaryNumber.toBigInteger(transaction.getData(EMVTag.AMOUNT_AUTHORISED_BINARY));
    floorLimit = BinaryNumber.toBigInteger(transaction.getData(EMVTag.TERMINAL_FLOOR_LIMIT));
    RandomTransactionSelectionData selectionData =
        transaction.getApplication().getRandomTransactionSelectionData();
    targetPercentage = selectionData.getTargetPercentage();
    maxTargetPercentage = selectionData.getMaxTargetPercentage();
    thresholdValue = BinaryNumber.toBigInteger(selectionData.getThresholdValue());
    if (thresholdValue.compareTo(floorLimit) >= 0) {
      if (LOG.isWarnEnabled()) {
        LOG.warn(
            method,
            "Threshold Value ("
                + thresholdValue
                + ") is greater or equals to floor limit ("
                + floorLimit
                + ")");
      }
      thresholdValue = BigInteger.ZERO;
    }
    randomNumber = generateRandomNumber();
    if (LOG.isDebugEnabled()) {
      LOG.debug(
          method,
          "Amount: "
              + amount
              + ", Floor Limit: "
              + floorLimit
              + ", Target Percentage: "
              + targetPercentage
              + ", Max Target Percentage: "
              + maxTargetPercentage
              + ", Threshold Value: "
              + thresholdValue
              + ", Random Number: "
              + randomNumber);
    }
  }

  private void biasedRandomSelection() {
    double factor = interpolationFactor();
    int transactionTargetPercent =
        (int) (((maxTargetPercentage - targetPercentage) * factor) + targetPercentage);
    if (randomNumber <= transactionTargetPercent) {
      selectForOnlineProcessing();
    }
  }

  private double interpolationFactor() {
    double dividend = amount.subtract(thresholdValue).doubleValue();
    double divisor = floorLimit.subtract(thresholdValue).doubleValue();
    return dividend / divisor;
  }

  private void randomSelection() {
    final String method = "randomSelection()";
    if (LOG.isDebugEnabled()) {
      LOG.debug(
          method, "Target Percentage: " + targetPercentage + ", Random number: " + randomNumber);
    }
    if (randomNumber <= targetPercentage) {
      selectForOnlineProcessing();
    }
  }

  private void selectForOnlineProcessing() {
    TVR tvr = transaction.getTVR();
    tvr.getByte4().transactionSelectedRandomlyForOnlineProcessing();
  }

  private int generateRandomNumber() {
    return new Random().nextInt(99) + 1;
  }
}
예제 #4
0
파일: O2XfsConf.java 프로젝트: Zengwn/O2Xfs
/** @author Andreas Fagschlunger */
public class O2XfsConf {

  static {
    System.loadLibrary("at.o2xfs.win32");
    System.loadLibrary("at.o2xfs.xfs.conf");
  }

  private static final Logger LOG = LoggerFactory.getLogger(O2XfsConf.class);

  private class ValuePair implements Map.Entry<String, String> {

    private String name = null;

    private String data = null;

    private ValuePair(final String name, final String data) {
      this.name = name;
      this.data = data;
    }

    @Override
    public String getKey() {
      return name;
    }

    @Override
    public String getValue() {
      return data;
    }

    @Override
    public String setValue(String value) {
      throw new UnsupportedOperationException();
    }
  }

  private static final int SIZE_LIMIT = 256;

  public static final HKEY WFS_CFG_HKEY_XFS_ROOT = new HKEY(1L);

  /** @since 3.0 */
  public static final HKEY WFS_CFG_HKEY_MACHINE_XFS_ROOT = new HKEY(2L);

  /** @since 3.0 */
  public static final HKEY WFS_CFG_HKEY_USER_DEFAULT_XFS_ROOT = new HKEY(3L);

  private List<HKEY> openKeys = null;

  private static O2XfsConf instance = null;

  private O2XfsConf() {
    openKeys = new ArrayList<HKEY>();
  }

  public static O2XfsConf getInstance() {
    if (instance == null) {
      synchronized (O2XfsConf.class) {
        if (instance == null) {
          instance = new O2XfsConf();
        }
      }
    }
    return instance;
  }

  /**
   * Closes the specified key.
   *
   * @param hKey Handle to the currently open key that is to be closed.
   * @throws XfsException
   */
  public void wfmCloseKey(final HKEY hKey) throws XfsException {
    final int errorCode = wfmCloseKey0(hKey);
    XfsException.throwFor(errorCode);
    synchronized (openKeys) {
      openKeys.remove(hKey);
    }
  }

  private native int wfmCloseKey0(Type hKey);

  /** Opens the specified key. */
  public HKEY wfmOpenKey(final HKEY hKey, final String subKey) throws XfsException {
    HKEY hkResult = new HKEY();
    final int errorCode = wfmOpenKey0(hKey, (subKey == null ? null : new ZSTR(subKey)), hkResult);
    XfsException.throwFor(errorCode);
    synchronized (openKeys) {
      openKeys.add(hkResult);
    }
    return hkResult;
  }

  private native int wfmOpenKey0(Type hKey, Type lpszSubKey, Type phkResult);

  /** Retrieves the data for the value with the specified name, within the specified open key. */
  public String wfmQueryValue(final HKEY hKey, final String valueName) throws XfsException {
    final ZSTR data = new ZSTR(SIZE_LIMIT, true);
    final DWORD cchData = new DWORD(0L);
    final int errorCode = wfmQueryValue0(hKey, new ZSTR(valueName), data, cchData);
    XfsException.throwFor(errorCode);
    return data.toString();
  }

  private native int wfmQueryValue0(Type hKey, Type lpszValueName, Type lpszData, Type lpcchData);

  /**
   * Enumerates the subkeys of the specified open key. Retrieves information about one subkey each
   * time it is called.
   *
   * @param hKey Handle to a currently open key, or the predefined handle value: {@link
   *     #WFS_CFG_HKEY_XFS_ROOT}
   * @return the name of the subkey
   */
  public String wfmEnumKey(final HKEY key, final DWORD iSubKey) throws XfsException {
    final ZSTR name = new ZSTR(SIZE_LIMIT, true);
    DWORD cchName = new DWORD(name.length);
    FILETIME lastWrite = new FILETIME();
    final int errorCode = wfmEnumKey0(key, iSubKey, name, cchName, lastWrite);
    XfsException.throwFor(errorCode);
    return name.toString();
  }

  private native int wfmEnumKey0(
      Type hKey, Type iSubKey, Type lpszName, Type lpcchName, Type lpftLastWrite);

  /**
   * Enumerates the values of the specified open key. Retrieves the name and data for one value each
   * time it is called.
   */
  public Map.Entry<String, String> wfmEnumValue(final HKEY hKey, final DWORD iValue)
      throws XfsException {
    ZSTR value = new ZSTR(SIZE_LIMIT, true);
    ZSTR data = new ZSTR(SIZE_LIMIT, true);
    final int errorCode = wfmEnumValue0(hKey, iValue, value, data);
    XfsException.throwFor(errorCode);
    return new ValuePair(value.toString(), data.toString());
  }

  private native int wfmEnumValue0(Type hKey, Type iValue, Type lpszValue, Type lpszData);

  @Override
  protected void finalize() throws Throwable {
    super.finalize();
    final String method = "finalize()";
    synchronized (openKeys) {
      if (openKeys.size() > 0) {
        if (LOG.isWarnEnabled()) {
          LOG.warn(method, "Closing " + openKeys.size() + " open key(s)");
        }
      }
      while (openKeys.size() > 0) {
        HKEY hKey = openKeys.get(0);
        try {
          wfmCloseKey(hKey);
        } catch (XfsException e) {
          if (LOG.isErrorEnabled()) {
            LOG.error(method, "Error closing HKEY: " + hKey, e);
          }
        }
      }
    }
  }
}