home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 25 / CDROM25.iso / Share / prog / VJ11 / VJTRIAL.EXE / IE30Java.exe / classd.exe / sun / awt / image / InputStreamImageSource.java < prev    next >
Encoding:
Java Source  |  1997-01-27  |  13.6 KB  |  532 lines

  1. /*
  2.  * @(#)InputStreamImageSource.java    1.30 96/03/18 Jim Graham
  3.  *
  4.  * Copyright (c) 1994 Sun Microsystems, Inc. All Rights Reserved.
  5.  *
  6.  * Permission to use, copy, modify, and distribute this software
  7.  * and its documentation for NON-COMMERCIAL purposes and without
  8.  * fee is hereby granted provided that this copyright notice
  9.  * appears in all copies. Please refer to the file "copyright.html"
  10.  * for further important copyright and licensing information.
  11.  *
  12.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
  13.  * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
  14.  * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
  15.  * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
  16.  * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
  17.  * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
  18.  */
  19.  
  20. package sun.awt.image;
  21.  
  22. import java.awt.image.*;
  23. import java.io.InputStream;
  24. import java.io.IOException;
  25. import java.io.BufferedInputStream;
  26. import java.util.Hashtable;
  27.  
  28. abstract public class InputStreamImageSource implements ImageProducer, ImageFetchable {
  29.     PixelStore    pixelstore;
  30.  
  31.     private ConsumerQueue consumers;
  32.  
  33.     private boolean awaitingFetch = false;
  34.     private Thread latestFetcher;
  35.     private ImageDecoder decoder;
  36.  
  37.     abstract boolean checkSecurity(Object context, boolean quiet);
  38.  
  39.     synchronized int countConsumers() {
  40.     ConsumerQueue cq = consumers;
  41.     int i = 0;
  42.     while (cq != null) {
  43.         i++;
  44.         cq = cq.next;
  45.     }
  46.     return i;
  47.     }
  48.  
  49.     public void addConsumer(ImageConsumer ic) {
  50.     addConsumer(ic, false);
  51.     }
  52.  
  53.     synchronized void addConsumer(ImageConsumer ic, boolean produce) {
  54.     checkSecurity(null, false);
  55.     ConsumerQueue cq = consumers;
  56.     while (cq != null && cq.consumer != ic) {
  57.         cq = cq.next;
  58.     }
  59.     if (cq == null) {
  60.         cq = new ConsumerQueue(this, ic);
  61.         cq.next = consumers;
  62.         consumers = cq;
  63.     } else {
  64.         if (!cq.secure) {
  65.                 Object context = null;
  66.                 SecurityManager security = System.getSecurityManager();
  67.                 if (security != null) {
  68.                     context = security.getSecurityContext();
  69.                 }
  70.         if (cq.securityContext == null) {
  71.             cq.securityContext = context;
  72.         } else if (cq.securityContext != context) {
  73.             // If there are two different security contexts that both
  74.             // have a handle on the same ImageConsumer, then there has
  75.             // been a security breach and whether or not they trade
  76.             // image data is small fish compared to what they could be
  77.             // trading.  Throw a Security exception anyway...
  78.             errorConsumer(cq);
  79.             throw new SecurityException("Applets are trading image data!");
  80.         }
  81.         }
  82.         cq.interested = true;
  83.     }
  84.     if (produce && cq.feeder == null &&
  85.         !awaitingFetch && latestFetcher == null)
  86.     {
  87.         startProduction();
  88.     }
  89.     }
  90.  
  91.     public synchronized boolean isConsumer(ImageConsumer ic) {
  92.     ConsumerQueue cq = consumers;
  93.     while (cq != null) {
  94.         if (cq.consumer == ic) {
  95.         return true;
  96.         }
  97.         cq = cq.next;
  98.     }
  99.     return false;
  100.     }
  101.  
  102.     synchronized void errorConsumer(ConsumerQueue cq) {
  103.     cq.consumer.imageComplete(ImageConsumer.IMAGEERROR);
  104.     removeConsumer(cq.consumer);
  105.     }
  106.  
  107.     public synchronized void removeConsumer(ImageConsumer ic) {
  108.     ConsumerQueue cq = consumers;
  109.     ConsumerQueue cqprev = null;
  110.     while (cq != null) {
  111.         if (cq.consumer == ic) {
  112.         if (cqprev == null) {
  113.             consumers = cq.next;
  114.         } else {
  115.             cqprev.next = cq.next;
  116.         }
  117.         cq.interested = false;
  118.         break;
  119.         }
  120.         cqprev = cq;
  121.         cq = cq.next;
  122.     }
  123.     }
  124.  
  125.     public void startProduction(ImageConsumer ic) {
  126.     addConsumer(ic, true);
  127.     }
  128.  
  129.     private synchronized void startProduction() {
  130.     if (!awaitingFetch) {
  131.         ImageFetcher.add(this);
  132.         awaitingFetch = true;
  133.     }
  134.     }
  135.  
  136.     public void requestTopDownLeftRightResend(ImageConsumer ic) {
  137.     PixelStore store;
  138.     synchronized(this) {
  139.         store = pixelstore;
  140.     }
  141.     if (store != null) {
  142.         store.replay(this, ic, false);
  143.     }
  144.     }
  145.  
  146.     protected abstract ImageDecoder getDecoder();
  147.  
  148.     protected ImageDecoder decoderForType(InputStream is,
  149.                       String content_type) {
  150.     if (content_type.equals("image/gif")) {
  151.         return new GifImageDecoder(this, is);
  152.     } else if (content_type.equals("image/jpeg")) {
  153.         return new JPEGImageDecoder(this, is);
  154.     } else if (content_type.equals("image/x-xbitmap")) {
  155.         return new XbmImageDecoder(this, is);
  156.     }
  157.     /*
  158.     else if (content_type == URL.content_jpeg) {
  159.         return new JpegImageDecoder(this, is);
  160.     } else if (content_type == URL.content_xbitmap) {
  161.         return new XbmImageDecoder(this, is);
  162.     } else if (content_type == URL.content_xpixmap) {
  163.         return new Xpm2ImageDecoder(this, is);
  164.     }
  165.     */
  166.  
  167.     return null;
  168.     }
  169.  
  170.     protected ImageDecoder getDecoder(InputStream is) {
  171.     if (!is.markSupported())
  172.         is = new BufferedInputStream(is);
  173.     try {
  174.         is.mark(1000);
  175.         int c1 = is.read();
  176.         int c2 = is.read();
  177.         int c3 = is.read();
  178.         int c4 = is.read();
  179.         int c5 = is.read();
  180.         int c6 = is.read();
  181.         is.reset();
  182.  
  183.         if (c1 == 'G' && c2 == 'I' && c3 == 'F' && c4 == '8') {
  184.         return new GifImageDecoder(this, is);
  185.         } else if ((c1 == '\377' && c2 == '\330'
  186.             && c3 == '\377' && c4 == '\340') ||
  187.                (c1 == '\377' && c2 == '\330'
  188.             && c3 == '\377' && c4 == '\356')) {
  189.         return new JPEGImageDecoder(this, is);
  190.         } else if (c1 == '#' && c2 == 'd' && c3 == 'e' && c4 == 'f') {
  191.         return new XbmImageDecoder(this, is);
  192. //        } else if (c1 == '!' && c2 == ' ' && c3 == 'X' && c4 == 'P' && 
  193. //               c5 == 'M' && c6 == '2') {
  194. //        return new Xpm2ImageDecoder(this, is);
  195.         }
  196.     } catch (IOException e) {
  197.     }
  198.  
  199.     return null;
  200.     }
  201.  
  202.     public void doFetch() {
  203.     Thread me = Thread.currentThread();
  204.     ImageDecoder imgd = null;
  205.     try {
  206.         if (latchConsumers(me) > 0) {
  207.         if (updateFromStore(me)) {
  208.             return;
  209.         }
  210.         imgd = getDecoder();
  211.         // if (imgd == null), then finally clause will send an error.
  212.         if (imgd != null) {
  213.             setDecoder(imgd, me);
  214.             try {
  215.             imgd.produceImage();
  216.             } catch (IOException e) {
  217.             e.printStackTrace();
  218.             // the finally clause will send an error.
  219.             } catch (ImageFormatException e) {
  220.             e.printStackTrace();
  221.             // the finally clause will send an error.
  222.             }
  223.         }
  224.         }
  225.     } finally {
  226.         // Send an error to all remaining consumers.
  227.         // They should have removed themselves by now if all is OK.
  228.         imageComplete(ImageConsumer.IMAGEERROR);
  229.         unlatchConsumers(imgd, me);
  230.     }
  231.     }
  232.  
  233.     private boolean updateFromStore(Thread me) {
  234.     PixelStore store;
  235.     ConsumerQueue cq;
  236.     synchronized(this) {
  237.         store = pixelstore;
  238.         if (store == null) {
  239.         return false;
  240.         }
  241.         cq = consumers;
  242.     }
  243.     while (cq != null) {
  244.         synchronized(this) {
  245.         if (cq.feeder == null) {
  246.             if (!checkSecurity(cq.securityContext, true)) {
  247.             errorConsumer(cq);
  248.             } else {
  249.             cq.feeder = me;
  250.             }
  251.         }
  252.         if (cq.feeder != me) {
  253.             cq = cq.next;
  254.             continue;
  255.         }
  256.         }
  257.         if (!store.replay(this, cq.consumer)) {
  258.         return false;
  259.         }
  260.         synchronized(this) {
  261.         cq = cq.next;
  262.         }
  263.     }
  264.     return true;
  265.     }
  266.  
  267.     private synchronized void setDecoder(ImageDecoder decoder, Thread me) {
  268.     ConsumerQueue cq = consumers;
  269.     while (cq != null) {
  270.         if (cq.feeder == me) {
  271.         // Now that there is a decoder, security may have changed
  272.         // so reverify it here, just in case.
  273.         if (!checkSecurity(cq.securityContext, true)) {
  274.             errorConsumer(cq);
  275.         } else {
  276.             cq.decoder = decoder;
  277.         }
  278.         }
  279.         cq = cq.next;
  280.     }
  281.     if (latestFetcher == me) {
  282.         this.decoder = decoder;
  283.     }
  284.     }
  285.  
  286.     private synchronized int latchConsumers(Thread me) {
  287.     latestFetcher = me;
  288.     awaitingFetch = false;
  289.     ConsumerQueue cq = consumers;
  290.     int count = 0;
  291.     while (cq != null) {
  292.         if (cq.feeder == null) {
  293.         if (!checkSecurity(cq.securityContext, true)) {
  294.             errorConsumer(cq);
  295.         } else {
  296.             cq.feeder = me;
  297.             count++;
  298.         }
  299.         }
  300.         cq = cq.next;
  301.     }
  302.     return count;
  303.     }
  304.  
  305.     private synchronized void unlatchConsumers(ImageDecoder imgd, Thread me) {
  306.     // All consumers should have removed themselves by now.
  307.     // In case any are remaining, we dump them on the floor.
  308.     if (latestFetcher == me) {
  309.         latestFetcher = null;
  310.     }
  311.     ConsumerQueue cq = consumers;
  312.     ConsumerQueue cqprev = null;
  313.     while (cq != null) {
  314.         if (cq.feeder == me) {
  315.         // Just let them drop now...
  316.         if (cqprev == null) {
  317.             consumers = cq.next;
  318.         } else {
  319.             cqprev.next = cq.next;
  320.         }
  321.         } else {
  322.         if (cq.feeder == null) {
  323.             //System.out.println(">>>>>> found unfed consumer while unlatching");
  324.             startProduction();
  325.         }
  326.         cqprev = cq;
  327.         }
  328.         cq = cq.next;
  329.     }
  330.     }
  331.  
  332.     private ConsumerQueue nextConsumer(ConsumerQueue cq, Thread me) {
  333.     synchronized(this) {
  334.         if (cq == null) {
  335.         cq = consumers;
  336.         } else {
  337.         cq = cq.next;
  338.         }
  339.         while (cq != null) {
  340.         if (!cq.interested) {
  341.             continue;
  342.         }
  343.         if (cq.feeder == me) {
  344.             return cq;
  345.         }
  346.         if (cq.feeder == null && latestFetcher == me) {
  347.             break;
  348.         }
  349.         cq = cq.next;
  350.         }
  351.     }
  352.     if (cq != null) {
  353.         // assert(cq.feeder == null);
  354.         // assert(latestFetcher == me);
  355.         if (decoder != null
  356.         && decoder.catchupConsumer(this, cq.consumer))
  357.         {
  358.         synchronized(this) {
  359.             if (cq.interested) {
  360.             if (!checkSecurity(cq.securityContext, true)) {
  361.                 errorConsumer(cq);
  362.             } else {
  363.                 cq.feeder = me;
  364.                 cq.decoder = decoder;
  365.                 return cq;
  366.             }
  367.             }
  368.         }
  369.         return nextConsumer(cq, me);
  370.         } else {
  371.         // We couldn't catch the guy up, so unhook us and refetch...
  372.         synchronized(this) {
  373.             latestFetcher = null;
  374.             startProduction();
  375.         }
  376.         }
  377.     }
  378.     return cq;
  379.     }
  380.  
  381.     synchronized void flush() {
  382.     ConsumerQueue cq = consumers;
  383.     consumers = null;
  384.     while (cq != null) {
  385.         cq.interested = false;
  386.         try {
  387.         if (cq.feeder != null) {
  388.             cq.feeder.interrupt();
  389.         }
  390.         } catch (NoSuchMethodError t) {
  391.         break;
  392.         }
  393.         if (cq.decoder != null) {
  394.         cq.decoder.close();
  395.         }
  396.         cq = cq.next;
  397.     }
  398.     pixelstore = null;
  399.     }
  400.  
  401.     synchronized void setPixelStore(PixelStore storage) {
  402.     pixelstore = storage;
  403.     }
  404.  
  405.     int setDimensions(int w, int h) {
  406.     ConsumerQueue cq = null;
  407.     Thread me = Thread.currentThread();
  408.     int count = 0;
  409.     while ((cq = nextConsumer(cq, me)) != null) {
  410.         cq.consumer.setDimensions(w, h);
  411.         count++;
  412.     }
  413.     return count;
  414.     }
  415.  
  416.     int setProperties(Hashtable props) {
  417.     ConsumerQueue cq = null;
  418.     Thread me = Thread.currentThread();
  419.     int count = 0;
  420.     while ((cq = nextConsumer(cq, me)) != null) {
  421.         cq.consumer.setProperties(props);
  422.         count++;
  423.     }
  424.     return count;
  425.     }
  426.  
  427.     int setColorModel(ColorModel model) {
  428.     ConsumerQueue cq = null;
  429.     Thread me = Thread.currentThread();
  430.     int count = 0;
  431.     while ((cq = nextConsumer(cq, me)) != null) {
  432.         cq.consumer.setColorModel(model);
  433.         count++;
  434.     }
  435.     return count;
  436.     }
  437.  
  438.     int setHints(int hints) {
  439.     ConsumerQueue cq = null;
  440.     Thread me = Thread.currentThread();
  441.     int count = 0;
  442.     while ((cq = nextConsumer(cq, me)) != null) {
  443.         cq.consumer.setHints(hints);
  444.         count++;
  445.     }
  446.     return count;
  447.     }
  448.  
  449.     int setPixels(int x, int y, int w, int h, ColorModel model,
  450.           byte pix[], int off, int scansize) {
  451.     ConsumerQueue cq = null;
  452.     Thread me = Thread.currentThread();
  453.     if (me.getPriority() > ImageFetcher.LOW_PRIORITY) {
  454.         me.setPriority(ImageFetcher.LOW_PRIORITY);
  455.         //me.yield();
  456.     }
  457.     int count = 0;
  458.     while ((cq = nextConsumer(cq, me)) != null) {
  459.         cq.consumer.setPixels(x, y, w, h, model, pix, off, scansize);
  460.         count++;
  461.     }
  462.     return count;
  463.     }
  464.  
  465.     int setPixels(int x, int y, int w, int h, ColorModel model,
  466.           int pix[], int off, int scansize) {
  467.     ConsumerQueue cq = null;
  468.     Thread me = Thread.currentThread();
  469.     if (me.getPriority() > ImageFetcher.LOW_PRIORITY) {
  470.         me.setPriority(ImageFetcher.LOW_PRIORITY);
  471.         //me.yield();
  472.     }
  473.     int count = 0;
  474.     while ((cq = nextConsumer(cq, me)) != null) {
  475.         cq.consumer.setPixels(x, y, w, h, model, pix, off, scansize);
  476.         count++;
  477.     }
  478.     return count;
  479.     }
  480.  
  481.     int imageComplete(int status) {
  482.     ConsumerQueue cq = null;
  483.     Thread me = Thread.currentThread();
  484.     int count = 0;
  485.     while ((cq = nextConsumer(cq, me)) != null) {
  486.         cq.consumer.imageComplete(status);
  487.         count++;
  488.     }
  489.     return count;
  490.     }
  491. }
  492.  
  493. class ConsumerQueue {
  494.     ImageConsumer consumer;
  495.     Thread feeder;
  496.     ImageDecoder decoder;
  497.     ConsumerQueue next;
  498.     boolean interested;
  499.     Object securityContext;
  500.     boolean secure;
  501.  
  502.     ConsumerQueue(InputStreamImageSource src, ImageConsumer ic) {
  503.     consumer = ic;
  504.     interested = true;
  505.     // ImageReps and InfoGrabbers do their own security at access time.
  506.     if (ic instanceof ImageRepresentation) {
  507.         ImageRepresentation ir = (ImageRepresentation) ic;
  508.         if (ir.image.source != src) {
  509.         throw new SecurityException("ImageRep added to wrong image source");
  510.         }
  511.         secure = true;
  512.     } else if (ic instanceof ImageInfoGrabber) {
  513.         ImageInfoGrabber ig = (ImageInfoGrabber) ic;
  514.         if (ig.image.source != src) {
  515.         throw new SecurityException("ImageRep added to wrong image source");
  516.         }
  517.         secure = true;
  518.     } else {
  519.             SecurityManager security = System.getSecurityManager();
  520.             if (security != null) {
  521.                 securityContext = security.getSecurityContext();
  522.             } else {
  523.                 securityContext = null;
  524.             }
  525.     }
  526.     }
  527.  
  528.     public String toString() {
  529.     return "[" + consumer + " " + securityContext + "]";
  530.     }
  531. }
  532.