import java.applet.*; import java.awt.*; import java.awt.image.*; import java.io.*; import java.net.*; import java.util.*; import javax.servlet.*; import javax.servlet.http.*; import Acme.JPM.Encoders.GifEncoder; import Acme.MainFrameModified; public class AppletViewer extends HttpServlet { static final int WIDTH = 450; static final int HEIGHT = 320; public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { ServletOutputStream out = res.getOutputStream(); MainFrameModified frame = null; Graphics g = null; Applet applet = null; try { String appletParam = req.getParameter("applet"); String widthParam = req.getParameter("width"); String heightParam = req.getParameter("height"); // Load the given applet // Must be in the standard CLASSPATH try { applet = (Applet) Class.forName(appletParam).newInstance(); } catch (Exception e) { throw new ServletException("Could not load applet:" + e); } // Convert width/height to integers // Use default values if they weren't given or there's a problem int width = WIDTH; int height = HEIGHT; try { width = Integer.parseInt(widthParam); } catch (NumberFormatException e) { /* leave as default */ } try { height = Integer.parseInt(heightParam); } catch (NumberFormatException e) { /* leave as default */ } // Get a list of the other parameters in a format MainFrame understands // (Specifically, an array of "name=value" Strings) Vector temp = new Vector(); Enumeration names = req.getParameterNames(); while (names.hasMoreElements()) { String name = (String) names.nextElement(); if (name != "applet" && name != "width" && name != "height") temp.addElement(name + "=" + req.getParameter(name)); } temp.addElement("barebones=true"); // run without a menu bar // Now from Vector to array int size = temp.size(); String args[] = new String[size]; for (int i = 0; i < size; i++) { args[i] = (String) temp.elementAt(i); } // Put the applet in its frame // addNotify() is called by MainFrameModified frame = new MainFrameModified(applet, args, width, height); // Get a graphics region to match the applet size, using the Frame Image image = frame.createImage(width, height); g = image.getGraphics(); // Ask the applet to paint its children and itself applet.validate(); paintContainerChildren(g, applet); applet.paint(g); // Encode and return what it painted res.setContentType("image/gif"); GifEncoder encoder = new GifEncoder(image, out); encoder.encode(); } finally { // Clean up resources if (applet != null) { applet.stop(); applet.destroy(); applet.removeAll(); } if (g != null) { g.dispose(); } if (frame != null) { frame.removeAll(); frame.removeNotify(); frame.dispose(); } } } // Recursively paints all the Components of a Container. // It's different than paintComponents(Graphics) because // paintComponents(Graphics) does not paint to the passed-in // Graphics! It uses it only to get the clipping region. void paintContainerChildren(Graphics g, Container c) { Component[] children = c.getComponents(); for (int i = 0; i < children.length; i++) { if (children[i] != null) { children[i].paintAll(g); // get lightweights too if (children[i] instanceof Container) { paintContainerChildren(g, (Container)children[i]); } } } } }