package coreservlets;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.*;

/** Servlet that processes a request to generate n
* prime numbers, each with at least m digits.
* It performs the calculations in a low-priority background
* thread, returning only the results it has found so far.
* If these results are not complete, it sends a Refresh
* header instructing the browser to ask for new results a
* little while later. It also maintains a list of a
* small number of previously calculated prime lists
* to return immediately to anyone who supplies the
* same n and m as a recent completed computation.
*/
public class PrimeNumbers extends HttpServlet {
	private Vector primeListVector = new Vector();
	private int maxPrimeLists = 30;

	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		int numPrimes = ServletUtilities.getIntParameter(request,	"numPrimes", 50);
		int numDigits =	ServletUtilities.getIntParameter(request, "numDigits", 120);
		PrimeList primeList = findPrimeList(primeListVector, numPrimes, numDigits);
		if (primeList == null) { 
			primeList = new PrimeList(numPrimes, numDigits, true);
			// Multiple servlet request threads share the instance
			// variables (fields) of PrimeNumbers. So
			// synchronize all access to servlet fields.
			synchronized(primeListVector) {
				if (primeListVector.size() >= maxPrimeLists)
					primeListVector.removeElementAt(0);
				primeListVector.addElement(primeList);
			}	
		}
		
		Vector currentPrimes = primeList.getPrimes();
		int numCurrentPrimes = currentPrimes.size();
		int numPrimesRemaining = (numPrimes - numCurrentPrimes);
		boolean isLastResult = (numPrimesRemaining == 0);
		if (!isLastResult) {
			response.setHeader("Refresh", "5");
		}
		response.setContentType("text/html");
		PrintWriter out = response.getWriter();
		String title = "Some " + numDigits + "-Digit Prime Numbers";
		out.println(ServletUtilities.headWithTitle(title) +
			"<BODY BGCOLOR=\"#FDF5E6\">\n" +
			"<H2 ALIGN=CENTER>" + title + "</H2>\n" +
			"<H3>Primes found with " + numDigits +
			" or more digits: " + numCurrentPrimes +
			".</H3>");
		if (isLastResult)
			out.println("<B>Done searching.</B>");
		else
			out.println("<B>Still looking for " + numPrimesRemaining +
			" more<BLINK>...</BLINK></B>");
		out.println("<OL>");
		for(int i=0; i<numCurrentPrimes; i++) {
			out.println(" <LI>" + currentPrimes.elementAt(i));
		}
		out.println("</OL>");
		out.println("</BODY></HTML>");
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}

	// See if there is an existing ongoing or completed
	// calculation with the same number of primes and number
	// of digits per prime. If so, return those results instead
	// of starting a new background thread. Keep this list
	// small so that the Web server doesn’t use too much memory.
	// Synchronize access to the list since there may be
	// multiple simultaneous requests.

	private PrimeList findPrimeList(Vector primeListVector, int numPrimes, int numDigits) {
		synchronized(primeListVector) {
			for(int i=0; i<primeListVector.size(); i++) {
				PrimeList primes = (PrimeList)primeListVector.elementAt(i);
				if ((numPrimes == primes.numPrimes()) &&
					(numDigits == primes.numDigits()))
					return(primes);
			}
			return(null);
		}
	}
}