
package exercise2;

import java.io.*;
import java.net.*;
import java.util.*;
import commons.*;

public aspect Monitor {
	pointcut scope()  : if(true);	

	/* property 1 : 
	 * it is not allowed to call a set-method on a URLConnection 
	 * object after a get-method has been called.
	 */
	
	WeakIdentityHashSet connections  = new WeakIdentityHashSet();
	
    pointcut getparam(URLConnection c) :
    	target(c) && call(* URLConnection.get*(..));
	
	pointcut setparam(URLConnection c) :
		target(c) && call(* URLConnection.set*(..));

    before(URLConnection c) : getparam(c) && scope() {
    	connections.add(c);
    }
	
	before(URLConnection c) : setparam(c) && scope() {
		if (connections.contains(c)) {
			System.out.println("*** it is illegal to set after get");
		}
	}
	
	/* property 2 : 
	 * an input stream that has been obtained from a URLConnection 
	 * object using the getInputStream method should be closed 
	 * before the main program terminates.
	 */
	
	IdentityHashSet<InputStream> inputstreams  = new IdentityHashSet<InputStream>();
	
	pointcut getInputStream(URLConnection c) : 
		target(c) &&
		call(InputStream URLConnection.getInputStream());
		
	pointcut closeInputStream(InputStream i) :
		target(i) && call(void InputStream.close());
	
	after(URLConnection c) returning (InputStream i) : 
		getInputStream(c) && scope()
	{
		inputstreams.add(i);
		System.out.println(">>> inputstream opened : " + i);
	}
		
	after(InputStream i) : closeInputStream(i) && scope() {
		inputstreams.remove(i);
		System.out.println(">>> application closes inputstream " + i);
	}
	
	after() : execution(static void Test.main(..)) && scope() {
		System.out.println("--- begin inputsteam test ---");
		Iterator it = inputstreams.iterator();
		while(it.hasNext()) {
			System.out.println("*** inputstream not closed : " + it.next());
		}
		System.out.println("--- end inputsteam test ---");
	}
}
