Frames | No Frames |
1: /* Applet.java -- Java base applet class 2: Copyright (C) 1999, 2002, 2004, 2005 Free Software Foundation, Inc. 3: 4: This file is part of GNU Classpath. 5: 6: GNU Classpath is free software; you can redistribute it and/or modify 7: it under the terms of the GNU General Public License as published by 8: the Free Software Foundation; either version 2, or (at your option) 9: any later version. 10: 11: GNU Classpath is distributed in the hope that it will be useful, but 12: WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14: General Public License for more details. 15: 16: You should have received a copy of the GNU General Public License 17: along with GNU Classpath; see the file COPYING. If not, write to the 18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19: 02110-1301 USA. 20: 21: Linking this library statically or dynamically with other modules is 22: making a combined work based on this library. Thus, the terms and 23: conditions of the GNU General Public License cover the whole 24: combination. 25: 26: As a special exception, the copyright holders of this library give you 27: permission to link this library with independent modules to produce an 28: executable, regardless of the license terms of these independent 29: modules, and to copy and distribute the resulting executable under 30: terms of your choice, provided that you also meet, for each linked 31: independent module, the terms and conditions of the license of that 32: module. An independent module is a module which is not derived from 33: or based on this library. If you modify this library, you may extend 34: this exception to your version of the library, but you are not 35: obligated to do so. If you do not wish to do so, delete this 36: exception statement from your version. */ 37: 38: 39: package java.applet; 40: 41: import java.awt.Component; 42: import java.awt.Dimension; 43: import java.awt.GraphicsEnvironment; 44: import java.awt.HeadlessException; 45: import java.awt.Image; 46: import java.awt.Panel; 47: import java.io.IOException; 48: import java.io.ObjectInputStream; 49: import java.net.MalformedURLException; 50: import java.net.URL; 51: import java.util.Locale; 52: 53: import javax.accessibility.AccessibleContext; 54: import javax.accessibility.AccessibleRole; 55: import javax.accessibility.AccessibleState; 56: import javax.accessibility.AccessibleStateSet; 57: import javax.sound.sampled.AudioSystem; 58: import javax.sound.sampled.Clip; 59: import javax.sound.sampled.LineUnavailableException; 60: import javax.sound.sampled.UnsupportedAudioFileException; 61: 62: /** 63: * This is the base applet class. An applet is a Java program that 64: * runs inside a web browser or other applet viewer in a restricted 65: * environment. 66: * 67: * <p>To be useful, a subclass should override at least start(). Also useful 68: * are init, stop, and destroy for control purposes, and getAppletInfo and 69: * getParameterInfo for descriptive purposes. 70: * 71: * @author Aaron M. Renn (arenn@urbanophile.com) 72: * @author Eric Blake (ebb9@email.byu.edu) 73: * @since 1.0 74: * @status updated to 1.4 75: */ 76: public class Applet extends Panel 77: { 78: /** 79: * Compatible with JDK 1.0+. 80: */ 81: private static final long serialVersionUID = -5836846270535785031L; 82: 83: /** The applet stub for this applet. */ 84: private transient AppletStub stub; 85: 86: /** Some applets call setSize in their constructors. In that case, 87: these fields are used to store width and height values until a 88: stub is set. */ 89: private transient int width; 90: private transient int height; 91: 92: /** 93: * The accessibility context for this applet. 94: * 95: * @serial the accessibleContext for this 96: * @since 1.2 97: */ 98: private AccessibleContext accessibleContext; 99: 100: /** 101: * Default constructor for subclasses. 102: * 103: * @throws HeadlessException if in a headless environment 104: */ 105: public Applet() 106: { 107: if (GraphicsEnvironment.isHeadless()) 108: throw new HeadlessException(); 109: } 110: 111: /** 112: * The browser calls this method to set the applet's stub, which is the 113: * low level interface to the browser. Manually setting this to null is 114: * asking for problems down the road. 115: * 116: * @param stub the applet stub for this applet 117: */ 118: public final void setStub(AppletStub stub) 119: { 120: this.stub = stub; 121: 122: if (width != 0 && height != 0) 123: stub.appletResize (width, height); 124: } 125: 126: /** 127: * Tests whether or not this applet is currently active. An applet is active 128: * just before the browser invokes start(), and becomes inactive just 129: * before the browser invokes stop(). 130: * 131: * @return <code>true</code> if this applet is active 132: */ 133: public boolean isActive() 134: { 135: return stub.isActive(); 136: } 137: 138: /** 139: * Returns the basename URL of the document this applet is embedded in. This 140: * is everything up to the final '/'. 141: * 142: * @return the URL of the document this applet is embedded in 143: * @see #getCodeBase() 144: */ 145: public URL getDocumentBase() 146: { 147: return stub.getDocumentBase(); 148: } 149: 150: /** 151: * Returns the URL of the code base for this applet. 152: * 153: * @return the URL of the code base for this applet 154: */ 155: public URL getCodeBase() 156: { 157: return stub.getCodeBase(); 158: } 159: 160: /** 161: * Returns the value of the specified parameter that was specified in 162: * the <code><APPLET></code> tag for this applet. 163: * 164: * @param name the parameter name 165: * @return the parameter value, or null if the parameter does not exist 166: * @throws NullPointerException if name is null 167: */ 168: public String getParameter(String name) 169: { 170: return stub.getParameter(name); 171: } 172: 173: /** 174: * Returns the applet context for this applet. 175: * 176: * @return the applet context for this applet 177: */ 178: public AppletContext getAppletContext() 179: { 180: return stub.getAppletContext(); 181: } 182: 183: /** 184: * Requests that the applet window for this applet be resized. 185: * 186: * @param width the new width in pixels 187: * @param height the new height in pixels 188: */ 189: public void resize(int width, int height) 190: { 191: if (stub == null) 192: { 193: this.width = width; 194: this.height = height; 195: } 196: else 197: stub.appletResize(width, height); 198: } 199: 200: /** 201: * Requests that the applet window for this applet be resized. 202: * 203: * @param dim the requested dimensions 204: * @throws NullPointerException if dim is null 205: */ 206: public void resize(Dimension dim) 207: { 208: resize(dim.width, dim.height); 209: } 210: 211: /** 212: * Displays the specified message in the status window if that window 213: * exists. 214: * 215: * @param message the status message, may be null 216: */ 217: public void showStatus(String message) 218: { 219: getAppletContext().showStatus(message); 220: } 221: 222: /** 223: * Returns an image from the specified URL. Note that the image is not 224: * actually retrieved until the applet attempts to display it, so this 225: * method returns immediately. 226: * 227: * @param url the URL of the image 228: * @return the retrieved image 229: * @throws NullPointerException if url is null 230: */ 231: public Image getImage(URL url) 232: { 233: return getAppletContext().getImage(url); 234: } 235: 236: /** 237: * Returns an image from the specified absolute URL, and relative path 238: * from that URL. Note that the image is not actually retrieved until the 239: * applet attempts to display it, so this method returns immediately. 240: * This calls <code>getImage(new URL(url, name))</code>, but if building 241: * the new URL fails, this returns null. 242: * 243: * @param url the base URL of the image 244: * @param name the name of the image relative to the URL 245: * @return the retrieved image, or null on failure 246: * @see #getImage(URL) 247: */ 248: public Image getImage(URL url, String name) 249: { 250: try 251: { 252: return getImage(new URL(url, name)); 253: } 254: catch (MalformedURLException e) 255: { 256: return null; 257: } 258: } 259: 260: /** 261: * Returns an audio clip from the specified URL. This clip is not tied to 262: * any particular applet. 263: * 264: * @param url the URL of the audio clip 265: * @return the retrieved audio clip 266: * @throws NullPointerException if url is null 267: * @see #getAudioClip(URL) 268: * @since 1.2 269: */ 270: public static final AudioClip newAudioClip(URL url) 271: { 272: return new URLAudioClip(url); 273: } 274: 275: /** 276: * Returns an audio clip from the specified URL. Note that the clip is not 277: * actually retrieved until the applet attempts to play it, so this method 278: * returns immediately. 279: * 280: * @param url the URL of the audio clip 281: * @return the retrieved audio clip 282: * @throws NullPointerException if url is null 283: */ 284: public AudioClip getAudioClip(URL url) 285: { 286: return getAppletContext().getAudioClip(url); 287: } 288: 289: /** 290: * Returns an audio clip from the specified absolute URL, and relative path 291: * from that URL. Note that the clip is not actually retrieved until the 292: * applet attempts to play it, so this method returns immediately. This 293: * calls <code>getAudioClip(new URL(url, name))</code>, but if building 294: * the new URL fails, this returns null. 295: * 296: * @param url the base URL of the audio clip 297: * @param name the name of the clip relative to the URL 298: * @return the retrieved audio clip, or null on failure 299: * @see #getAudioClip(URL) 300: */ 301: public AudioClip getAudioClip(URL url, String name) 302: { 303: try 304: { 305: return getAudioClip(new URL(url, name)); 306: } 307: catch (MalformedURLException e) 308: { 309: return null; 310: } 311: } 312: 313: /** 314: * Returns a descriptive string with applet defined information. The 315: * implementation in this class returns <code>null</code>, so subclasses 316: * must override to return information. 317: * 318: * @return a string describing the author, version, and applet copyright 319: */ 320: public String getAppletInfo() 321: { 322: return null; 323: } 324: 325: /** 326: * Returns the locale for this applet, if it has been set. If no applet 327: * specific locale has been set, the default locale is returned. 328: * 329: * @return the locale for this applet 330: * @see Component#setLocale(Locale) 331: * @since 1.1 332: */ 333: public Locale getLocale() 334: { 335: return super.getLocale(); 336: } 337: 338: /** 339: * Returns a list of parameters this applet supports. Each element of 340: * the outer array is an array of three strings with the name of the 341: * parameter, the data type or valid values, and a description. This 342: * method is optional and the default implementation returns null. 343: * 344: * @return the list of parameters supported by this applet 345: */ 346: public String[][] getParameterInfo() 347: { 348: return null; 349: } 350: 351: /** 352: * Loads and plays the audio clip pointed to by the specified URL. This does 353: * nothing if the URL does not point to a valid audio clip. 354: * 355: * @param url the URL of the audio clip 356: * @throws NullPointerException if url is null 357: * @see #getAudioClip(URL) 358: */ 359: public void play(URL url) 360: { 361: AudioClip ac = getAudioClip(url); 362: try 363: { 364: ac.play(); 365: } 366: catch (Exception ignored) 367: { 368: } 369: } 370: 371: /** 372: * Loads and plays the audio clip pointed to by the specified absolute URL, 373: * and relative path from that URL. This does nothing if the URL cannot be 374: * constructed, or if it does not point to a valid audio clip. 375: * 376: * @param url the base URL of the audio clip 377: * @param name the name of the audio clip relative to the URL 378: * @see #getAudioClip(URL, String) 379: * @see #play(URL) 380: */ 381: public void play(URL url, String name) 382: { 383: try 384: { 385: getAudioClip(url, name).play(); 386: } 387: catch (Exception ignored) 388: { 389: } 390: } 391: 392: /** 393: * This method is called when the applet is first loaded, before start(). 394: * The default implementation does nothing; override to do any one-time 395: * initialization. 396: * 397: * @see #start() 398: * @see #stop() 399: * @see #destroy() 400: */ 401: public void init() 402: { 403: } 404: 405: /** 406: * This method is called when the applet should start running. This is 407: * normally each time a web page containing it is loaded. The default 408: * implemention does nothing; override for your applet to be useful. 409: * 410: * @see #init() 411: * @see #stop() 412: * @see #destroy() 413: */ 414: public void start() 415: { 416: } 417: 418: /** 419: * This method is called when the applet should stop running. This is 420: * normally when the next web page is loaded. The default implementation 421: * does nothing; override for your applet to stop using resources when 422: * it is no longer visible, but may be restarted soon. 423: * 424: * @see #init() 425: * @see #start() 426: * @see #destroy() 427: */ 428: public void stop() 429: { 430: } 431: 432: /** 433: * This method is called when the applet is being unloaded. The default 434: * implementation does nothing; override for your applet to clean up 435: * resources on exit. 436: * 437: * @see #init() 438: * @see #start() 439: * @see #stop() 440: */ 441: public void destroy() 442: { 443: } 444: 445: /** 446: * Gets the AccessibleContext associated with this applet, creating one if 447: * necessary. This always returns an instance of {@link AccessibleApplet}. 448: * 449: * @return the accessibility context of this applet 450: * @since 1.3 451: */ 452: public AccessibleContext getAccessibleContext() 453: { 454: if (accessibleContext == null) 455: accessibleContext = new AccessibleApplet(); 456: return accessibleContext; 457: } 458: 459: /** 460: * Read an applet from an object stream. This checks for a headless 461: * environment, then does the normal read. 462: * 463: * @param s the stream to read from 464: * @throws ClassNotFoundException if a class is not found 465: * @throws IOException if deserialization fails 466: * @throws HeadlessException if this is a headless environment 467: * @see GraphicsEnvironment#isHeadless() 468: * @since 1.4 469: */ 470: private void readObject(ObjectInputStream s) 471: throws ClassNotFoundException, IOException 472: { 473: if (GraphicsEnvironment.isHeadless()) 474: throw new HeadlessException(); 475: s.defaultReadObject(); 476: } 477: 478: /** 479: * This class provides accessibility support for Applets, and is the 480: * runtime type returned by {@link #getAccessibleContext()}. 481: * 482: * @author Eric Blake (ebb9@email.byu.edu) 483: * @since 1.3 484: */ 485: protected class AccessibleApplet extends AccessibleAWTPanel 486: { 487: /** 488: * Compatible with JDK 1.4+. 489: */ 490: private static final long serialVersionUID = 8127374778187708896L; 491: 492: /** 493: * The default constructor. 494: */ 495: protected AccessibleApplet() 496: { 497: } 498: 499: /** 500: * Get the role of this accessible object, a frame. 501: * 502: * @return the role of the object 503: * @see AccessibleRole#FRAME 504: */ 505: public AccessibleRole getAccessibleRole() 506: { 507: return AccessibleRole.FRAME; 508: } 509: 510: /** 511: * Get the state set of this accessible object. In addition to the default 512: * states of a Component, the applet can also be active. 513: * 514: * @return the role of the object 515: * @see AccessibleState 516: */ 517: public AccessibleStateSet getAccessibleStateSet() 518: { 519: AccessibleStateSet s = super.getAccessibleStateSet(); 520: if (isActive()) 521: s.add(AccessibleState.ACTIVE); 522: return s; 523: } 524: } // class AccessibleApplet 525: 526: private static class URLAudioClip implements AudioClip 527: { 528: // The URL we will try to play. 529: // This is null if we have already tried to create an 530: // audio input stream from this URL. 531: private URL url; 532: 533: // The real audio clip. This is null before the URL is read, 534: // and might be null afterward if we were unable to read the URL 535: // for some reason. 536: private Clip clip; 537: 538: public URLAudioClip(URL url) 539: { 540: this.url = url; 541: } 542: 543: private synchronized Clip getClip() 544: { 545: if (url == null) 546: return clip; 547: try 548: { 549: clip = AudioSystem.getClip(); 550: clip.open(AudioSystem.getAudioInputStream(url)); 551: } 552: catch (LineUnavailableException _) 553: { 554: // Ignore. 555: } 556: catch (IOException _) 557: { 558: // Ignore. 559: } 560: catch (UnsupportedAudioFileException _) 561: { 562: // Ignore. 563: } 564: url = null; 565: return clip; 566: } 567: 568: public void loop() 569: { 570: Clip myclip = getClip(); 571: if (myclip != null) 572: myclip.loop(Clip.LOOP_CONTINUOUSLY); 573: } 574: 575: public void play() 576: { 577: Clip myclip = getClip(); 578: if (myclip != null) 579: myclip.start(); 580: } 581: 582: public void stop() 583: { 584: Clip myclip = getClip(); 585: if (myclip != null) 586: { 587: myclip.stop(); 588: myclip.setFramePosition(0); 589: } 590: } 591: } 592: } // class Applet