FileDocCategorySizeDatePackage
Account3_Impl.javaAPI DocExample3453Thu Nov 08 00:22:34 GMT 2001com.ora.rmibook.chapter12.bank

Account3_Impl.java

package com.ora.rmibook.chapter12.bank;


import com.ora.rmibook.chapter12.bank.valueobjects.*;
import java.rmi.*;
import java.rmi.server.*;


/*
 Has timer-based lock management on server-side
 */

public class Account3_Impl extends UnicastRemoteObject implements Account3 {
    private static final int TIMER_DURATION = 120000;	// Two minutes
    private static final int THREAD_SLEEP_TIME = 10000;	// 10 seconds

    private Money _balance;
    private String _currentClient;
    private int _timeLeftUntilLockIsReleased;

    public Account3_Impl(Money startingBalance)
        throws RemoteException {
        _balance = startingBalance;
        _timeLeftUntilLockIsReleased = 0;
        new Thread(new CountDownTimer()).start();
    }

    public synchronized Money getBalance()
        throws RemoteException, LockedAccountException {
        checkAccess();
        return _balance;
    }

    public synchronized void makeDeposit(Money amount)
        throws RemoteException, LockedAccountException, NegativeAmountException {
        checkAccess();
        checkForNegativeAmount(amount);
        _balance.add(amount);
        return;
    }

    public synchronized void makeWithdrawal(Money amount)
        throws RemoteException, OverdraftException, LockedAccountException, NegativeAmountException {
        checkAccess();
        checkForNegativeAmount(amount);
        checkForOverdraft(amount);
        _balance.subtract(amount);
        return;
    }

    private void checkAccess() throws LockedAccountException {
        String clientHost = wrapperAroundGetClientHost();

        if (null == _currentClient) {
            _currentClient = clientHost;
        } else {
            if (!_currentClient.equals(clientHost)) {
                throw new LockedAccountException();
            }
        }
        resetCounter();
        return;
    }

    private void resetCounter() {
        _timeLeftUntilLockIsReleased = TIMER_DURATION;
    }

    private void releaseLock() {
        if (null != _currentClient) {
            _currentClient = null;
        }
    }

    private String wrapperAroundGetClientHost() {
        String clientHost = null;

        try {
            clientHost = getClientHost();
        } catch (ServerNotActiveException ignored) {
        }
        return clientHost;
    }

    private void checkForNegativeAmount(Money amount)
        throws NegativeAmountException {
        int cents = amount.getCents();

        if (0 > cents) {
            throw new NegativeAmountException();
        }
    }

    private void checkForOverdraft(Money amount)
        throws OverdraftException {
        if (amount.greaterThan(_balance)) {
            throw new OverdraftException(false);
        }
        return;
    }

    private class CountDownTimer implements Runnable {
        public void run() {
            while (true) {
                try {
                    Thread.sleep(THREAD_SLEEP_TIME);
                } catch (Exception ignored) {
                }
                synchronized (Account3_Impl.this) {
                    if (_timeLeftUntilLockIsReleased > 0) {
                        _timeLeftUntilLockIsReleased -= THREAD_SLEEP_TIME;
                    } else {
                        releaseLock();
                    }
                }
            }
        }
    }
}