//[C] 2002 Sun Microsystems, Inc.--- 
 
import java.io.IOException; 
import java.io.Serializable; 
import java.rmi.Naming; 
import java.rmi.Remote; 
import java.rmi.RemoteException; 
import java.rmi.server.UnicastRemoteObject; 
import java.util.ArrayList; 
import java.util.Calendar; 
import java.util.Date; 
import java.util.HashMap; 
 
public class RunTransactionPattern { 
  private static Calendar dateCreator = Calendar.getInstance(); 
 
  public static void main(String[] arguments) { 
    System.out.println("Example for the Transaction pattern"); 
    System.out.println("This code example shows how a Transaction can"); 
    System.out 
        .println(" be applied to support change across a distributed"); 
    System.out.println(" system. In ths case, a distributed transaction"); 
    System.out.println(" is used to coordinate the change of dates in"); 
    System.out.println(" appointment books."); 
 
    System.out.println("Running the RMI compiler (rmic)"); 
    System.out.println(); 
    try { 
      Process p1 = Runtime.getRuntime().exec("rmic AppointmentBook"); 
      p1.waitFor(); 
    } catch (IOException exc) { 
      System.err 
          .println("Unable to run rmic utility. Exiting application."); 
      System.exit(1); 
    } catch (InterruptedException exc) { 
      System.err 
          .println("Threading problems encountered while using the rmic utility."); 
    } 
 
    System.out.println("Starting the rmiregistry"); 
    System.out.println(); 
    try { 
      Process rmiProcess = Runtime.getRuntime().exec("rmiregistry"); 
      Thread.sleep(15000); 
    } catch (IOException exc) { 
      System.err 
          .println("Unable to start the rmiregistry. Exiting application."); 
      System.exit(1); 
    } catch (InterruptedException exc) { 
      System.err 
          .println("Threading problems encountered when starting the rmiregistry."); 
    } 
 
    System.out.println("Creating three appointment books"); 
    System.out.println(); 
    AppointmentBook apptBookOne = new AppointmentBook(); 
    AppointmentBook apptBookTwo = new AppointmentBook(); 
    AppointmentBook apptBookThree = new AppointmentBook(); 
 
    System.out.println("Creating appointments"); 
    System.out.println(); 
    Appointment apptOne = new AppointmentImpl( 
        "Swim relay to Kalimantan (or Java)", new ArrayList(), 
        new LocationImpl("Sidney, Australia"), createDate(2001, 11, 5, 
            11, 0)); 
    Appointment apptTwo = new AppointmentImpl( 
        "Conference on World Patternization", new ArrayList(), 
        new LocationImpl("London, England"), createDate(2001, 11, 5, 
            14, 0)); 
    Appointment apptThree = new AppointmentImpl( 
        "Society for the Preservation of Java - Annual Outing", 
        new ArrayList(), new LocationImpl("Kyzyl, Tuva"), createDate( 
            2001, 11, 5, 10, 0)); 
 
    System.out.println("Adding appointments to the appointment books"); 
    System.out.println(); 
    apptBookOne.addAppointment(apptThree); 
    apptBookTwo.addAppointment(apptOne); 
    apptBookOne.addAppointment(apptTwo); 
    apptBookTwo.addAppointment(apptTwo); 
    apptBookThree.addAppointment(apptTwo); 
 
    System.out.println("AppointmentBook contents:"); 
    System.out.println(); 
    System.out.println(apptBookOne); 
    System.out.println(apptBookTwo); 
    System.out.println(apptBookThree); 
    System.out.println(); 
 
    System.out.println("Rescheduling an appointment"); 
    System.out.println(); 
    System.out.println(); 
    boolean result = apptBookThree.changeAppointment(apptTwo, getDates( 
        2001, 11, 5, 10, 3), lookUpParticipants(new String[] { 
        apptBookOne.getUrl(), apptBookTwo.getUrl(), 
        apptBookThree.getUrl() }), 20000L); 
 
    System.out.println("Result of rescheduling was " + result); 
    System.out.println("AppointmentBook contents:"); 
    System.out.println(); 
    System.out.println(apptBookOne); 
    System.out.println(apptBookTwo); 
    System.out.println(apptBookThree); 
  } 
 
  private static AppointmentTransactionParticipant[] lookUpParticipants( 
      String[] remoteUrls) { 
    AppointmentTransactionParticipant[] returnValues = new AppointmentTransactionParticipant[remoteUrls.length]; 
    for (int i = 0; i < remoteUrls.length; i++) { 
      try { 
        returnValues[i] = (AppointmentTransactionParticipant) Naming 
            .lookup(remoteUrls[i]); 
      } catch (Exception exc) { 
        System.out 
            .println("Error using RMI to look up a transaction participant"); 
      } 
    } 
    return returnValues; 
  } 
 
  private static Date[] getDates(int year, int month, int day, int hour, 
      int increment) { 
    Date[] returnDates = new Date[increment]; 
    for (int i = 0; i < increment; i++) { 
      returnDates[i] = createDate(year, month, day, hour + i, 0); 
    } 
    return returnDates; 
  } 
 
  public static Date createDate(int year, int month, int day, int hour, 
      int minute) { 
    dateCreator.set(year, month, day, hour, minute); 
    return dateCreator.getTime(); 
  } 
} 
 
interface Location extends Serializable { 
  public String getLocation(); 
 
  public void setLocation(String newLocation); 
} 
 
class LocationImpl implements Location { 
  private String location; 
 
  public LocationImpl() { 
  } 
 
  public LocationImpl(String newLocation) { 
    location = newLocation; 
  } 
 
  public String getLocation() { 
    return location; 
  } 
 
  public void setLocation(String newLocation) { 
    location = newLocation; 
  } 
 
  public String toString() { 
    return location; 
  } 
} 
 
interface Contact extends Serializable { 
  public static final String SPACE = " "; 
 
  public String getFirstName(); 
 
  public String getLastName(); 
 
  public String getTitle(); 
 
  public String getOrganization(); 
 
  public void setFirstName(String newFirstName); 
 
  public void setLastName(String newLastName); 
 
  public void setTitle(String newTitle); 
 
  public void setOrganization(String newOrganization); 
} 
 
class ContactImpl implements Contact { 
  private String firstName; 
 
  private String lastName; 
 
  private String title; 
 
  private String organization; 
 
  public ContactImpl() { 
  } 
 
  public ContactImpl(String newFirstName, String newLastName, 
      String newTitle, String newOrganization) { 
    firstName = newFirstName; 
    lastName = newLastName; 
    title = newTitle; 
    organization = newOrganization; 
  } 
 
  public String getFirstName() { 
    return firstName; 
  } 
 
  public String getLastName() { 
    return lastName; 
  } 
 
  public String getTitle() { 
    return title; 
  } 
 
  public String getOrganization() { 
    return organization; 
  } 
 
  public void setFirstName(String newFirstName) { 
    firstName = newFirstName; 
  } 
 
  public void setLastName(String newLastName) { 
    lastName = newLastName; 
  } 
 
  public void setTitle(String newTitle) { 
    title = newTitle; 
  } 
 
  public void setOrganization(String newOrganization) { 
    organization = newOrganization; 
  } 
 
  public String toString() { 
    return firstName + SPACE + lastName; 
  } 
} 
 
interface Appointment extends Serializable { 
  public static final String EOL_STRING = System 
      .getProperty("line.separator"); 
 
  public Date getStartDate(); 
 
  public String getDescription(); 
 
  public ArrayList getAttendees(); 
 
  public Location getLocation(); 
 
  public void setDescription(String newDescription); 
 
  public void setLocation(Location newLocation); 
 
  public void setStartDate(Date newStartDate); 
 
  public void setAttendees(ArrayList newAttendees); 
 
  public void addAttendee(Contact attendee); 
 
  public void removeAttendee(Contact attendee); 
} 
 
class AppointmentImpl implements Appointment { 
  private Date startDate; 
 
  private String description; 
 
  private ArrayList attendees = new ArrayList(); 
 
  private Location location; 
 
  public AppointmentImpl(String newDescription, ArrayList newAttendees, 
      Location newLocation, Date newStartDate) { 
    description = newDescription; 
    attendees = newAttendees; 
    location = newLocation; 
    startDate = newStartDate; 
  } 
 
  public Date getStartDate() { 
    return startDate; 
  } 
 
  public String getDescription() { 
    return description; 
  } 
 
  public ArrayList getAttendees() { 
    return attendees; 
  } 
 
  public Location getLocation() { 
    return location; 
  } 
 
  public void setDescription(String newDescription) { 
    description = newDescription; 
  } 
 
  public void setLocation(Location newLocation) { 
    location = newLocation; 
  } 
 
  public void setStartDate(Date newStartDate) { 
    startDate = newStartDate; 
  } 
 
  public void setAttendees(ArrayList newAttendees) { 
    if (newAttendees != null) { 
      attendees = newAttendees; 
    } 
  } 
 
  public void addAttendee(Contact attendee) { 
    if (!attendees.contains(attendee)) { 
      attendees.add(attendee); 
    } 
  } 
 
  public void removeAttendee(Contact attendee) { 
    attendees.remove(attendee); 
  } 
 
  public int hashCode() { 
    return description.hashCode() ^ startDate.hashCode(); 
  } 
 
  public boolean equals(Object object) { 
    if (!(object instanceof AppointmentImpl)) { 
      return false; 
    } 
    if (object.hashCode() != hashCode()) { 
      return false; 
    } 
    return true; 
  } 
 
  public String toString() { 
    return "  Description: " + description + EOL_STRING + "  Start Date: " 
        + startDate + EOL_STRING + "  Location: " + location 
        + EOL_STRING + "  Attendees: " + attendees; 
  } 
} 
 
class AppointmentBook implements AppointmentTransactionParticipant { 
  private static final String TRANSACTION_SERVICE_PREFIX = "transactionParticipant"; 
 
  private static final String TRANSACTION_HOSTNAME = "localhost"; 
 
  private static int index = 1; 
 
  private String serviceName = TRANSACTION_SERVICE_PREFIX + index++; 
 
  private HashMap appointments = new HashMap(); 
 
  private long currentTransaction; 
 
  private Appointment currentAppointment; 
 
  private Date updateStartDate; 
 
  public AppointmentBook() { 
    try { 
      UnicastRemoteObject.exportObject(this); 
      Naming.rebind(serviceName, this); 
    } catch (Exception exc) { 
      System.err 
          .println("Error using RMI to register the AppointmentBook " 
              + exc); 
    } 
  } 
 
  public String getUrl() { 
    return "//" + TRANSACTION_HOSTNAME + "/" + serviceName; 
  } 
 
  public void addAppointment(Appointment appointment) { 
    if (!appointments.containsValue(appointment)) { 
      if (!appointments.containsKey(appointment.getStartDate())) { 
        appointments.put(appointment.getStartDate(), appointment); 
      } 
    } 
  } 
 
  public void removeAppointment(Appointment appointment) { 
    if (appointments.containsValue(appointment)) { 
      appointments.remove(appointment.getStartDate()); 
    } 
  } 
 
  public boolean join(long transactionID) { 
    if (currentTransaction != 0) { 
      return false; 
    } else { 
      currentTransaction = transactionID; 
      return true; 
    } 
  } 
 
  public void commit(long transactionID) throws TransactionException { 
    if (currentTransaction != transactionID) { 
      throw new TransactionException("Invalid TransactionID"); 
    } else { 
      removeAppointment(currentAppointment); 
      currentAppointment.setStartDate(updateStartDate); 
      appointments.put(updateStartDate, currentAppointment); 
    } 
  } 
 
  public void cancel(long transactionID) { 
    if (currentTransaction == transactionID) { 
      currentTransaction = 0; 
      appointments.remove(updateStartDate); 
    } 
  } 
 
  public boolean changeDate(long transactionID, Appointment appointment, 
      Date newStartDate) throws TransactionException { 
    if ((appointments.containsValue(appointment)) 
        && (!appointments.containsKey(newStartDate))) { 
      appointments.put(newStartDate, null); 
      updateStartDate = newStartDate; 
      currentAppointment = appointment; 
      return true; 
    } 
    return false; 
  } 
 
  public boolean changeAppointment(Appointment appointment, 
      Date[] possibleDates, 
      AppointmentTransactionParticipant[] participants, long transactionID) { 
    try { 
      for (int i = 0; i < participants.length; i++) { 
        if (!participants[i].join(transactionID)) { 
          return false; 
        } 
      } 
      for (int i = 0; i < possibleDates.length; i++) { 
        if (isDateAvailable(transactionID, appointment, 
            possibleDates[i], participants)) { 
          try { 
            commitAll(transactionID, participants); 
            return true; 
          } catch (TransactionException exc) { 
          } 
        } 
      } 
    } catch (RemoteException exc) { 
    } 
    try { 
      cancelAll(transactionID, participants); 
    } catch (RemoteException exc) { 
    } 
    return false; 
  } 
 
  private boolean isDateAvailable(long transactionID, 
      Appointment appointment, Date date, 
      AppointmentTransactionParticipant[] participants) { 
    try { 
      for (int i = 0; i < participants.length; i++) { 
        try { 
          if (!participants[i].changeDate(transactionID, appointment, 
              date)) { 
            return false; 
          } 
        } catch (TransactionException exc) { 
          return false; 
        } 
      } 
    } catch (RemoteException exc) { 
      return false; 
    } 
    return true; 
  } 
 
  private void commitAll(long transactionID, 
      AppointmentTransactionParticipant[] participants) 
      throws TransactionException, RemoteException { 
    for (int i = 0; i < participants.length; i++) { 
      participants[i].commit(transactionID); 
    } 
  } 
 
  private void cancelAll(long transactionID, 
      AppointmentTransactionParticipant[] participants) 
      throws RemoteException { 
    for (int i = 0; i < participants.length; i++) { 
      participants[i].cancel(transactionID); 
    } 
  } 
 
  public String toString() { 
    return serviceName + " " + appointments.values().toString(); 
  } 
} 
 
interface AppointmentTransactionParticipant extends Remote { 
  public boolean join(long transactionID) throws RemoteException; 
 
  public void commit(long transactionID) throws TransactionException, 
      RemoteException; 
 
  public void cancel(long transactionID) throws RemoteException; 
 
  public boolean changeDate(long transactionID, Appointment appointment, 
      Date newStartDate) throws TransactionException, RemoteException; 
} 
 
class TransactionException extends Exception { 
  public TransactionException(String msg) { 
    super(msg); 
  } 
} 
 
 
            
       
  |