Source for java.applet.Applet

   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>&lt;APPLET&gt;</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