import java.security.Principal;
import java.util.concurrent.atomic.AtomicLong;

import javax.security.auth.Subject;

public class JI9029414 implements Principal {
	
	 private static AtomicLong 
     hashCodeInvocationCount = new AtomicLong(), 
     equalsInvocationCount = new AtomicLong() 
 ; 

 private final String name; 

 public JI9029414(String name) { 
     this.name = name; 
 } 

 @Override 
 public String getName() { 
     return name; 
 } 

 @Override 
 public int hashCode() { 
     hashCodeInvocationCount.incrementAndGet(); 
     final int prime = 31; 
     int result = 1; 
     result = prime * result + ((name == null) ? 0 : name.hashCode()); 
     return result; 
 } 

 @Override 
 public boolean equals(Object obj) { 
     equalsInvocationCount.incrementAndGet(); 
     if (this == obj) 
         return true; 
     if (obj == null) 
         return false; 
     if (getClass() != obj.getClass()) 
         return false; 
     JI9029414 other = (JI9029414) obj; 
     if (name == null) { 
         if (other.name != null) 
             return false; 
     } else if (!name.equals(other.name)) 
         return false; 
     return true; 
 } 

 

	public static void main(String[] args) {
		 // This is pretty much a login. 
        Subject s = new Subject(); 
        final int theAmountOfPrincipalsTheUserHas = 100; 
        for (int i = 0; i < theAmountOfPrincipalsTheUserHas; ++i) s.getPrincipals().add(new JI9029414("Principal #" + i)); 

        // This is after a cache hit, e.g. in an application server. We're copying the principals. 
        final int theAmountOfInvocationsWithCacheHits = 5; 
        for (int i = 0; i < theAmountOfInvocationsWithCacheHits; ++i) { 
            Subject copy = new Subject(); 
            for (Principal e : s.getPrincipals()) copy.getPrincipals().add(e); 
            for (Object e : s.getPublicCredentials()) copy.getPublicCredentials().add(e); 
            for (Object e : s.getPrivateCredentials()) copy.getPrivateCredentials().add(e); 
        } 

        System.out.println(hashCodeInvocationCount.get() + " hashCode invocations"); 
        System.out.println(equalsInvocationCount.get() + " equals invocations"); 
	}

}
