001 /* 002 * Copyright 2002-2004 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 package org.springframework.richclient.image; 017 018 import java.awt.Image; 019 import java.awt.Toolkit; 020 import java.awt.image.ImageObserver; 021 import java.io.File; 022 import java.io.IOException; 023 import java.io.InputStream; 024 import java.net.URL; 025 026 import org.springframework.core.io.AbstractResource; 027 import org.springframework.core.io.Resource; 028 import org.springframework.util.Assert; 029 import org.springframework.util.FileCopyUtils; 030 031 /** 032 * A resource decorator that represents an underlying graphical AWT image, such 033 * as a GIF, JPEG, or PNG. 034 * 035 * @author Keith Donald 036 */ 037 public class AwtImageResource extends AbstractResource implements ImageObserver { 038 private Resource wrappedResource; 039 040 private boolean imageLoaded; 041 042 private boolean imageError; 043 044 public static final String RESOURCE_PREFIX = "image:"; 045 046 /** 047 * Constructs a AwtImageResource for the following io.core.Resource. This 048 * assumes the wrapped resource actually points to a underlying image. 049 * 050 * @param resource 051 * The wrapped resource. 052 * @throws IllegalArgumentException, 053 * if the resource is invalid. 054 */ 055 public AwtImageResource(Resource resource) { 056 Assert.notNull(resource); 057 if (resource instanceof AwtImageResource) { 058 throw new IllegalArgumentException("Wrapping another AwtImageResource instance is illegal."); 059 } 060 this.wrappedResource = resource; 061 } 062 063 public String getDescription() { 064 return wrappedResource.getDescription(); 065 } 066 067 public Resource createRelative(String relativePath) throws IOException { 068 return wrappedResource.createRelative(relativePath); 069 } 070 071 public boolean exists() { 072 return wrappedResource.exists(); 073 } 074 075 public boolean isOpen() { 076 return wrappedResource.isOpen(); 077 } 078 079 public URL getURL() throws IOException { 080 return wrappedResource.getURL(); 081 } 082 083 public File getFile() throws IOException { 084 return wrappedResource.getFile(); 085 } 086 087 public String getFilename() throws IllegalStateException { 088 return wrappedResource.getFilename(); 089 } 090 091 public InputStream getInputStream() throws IOException { 092 return wrappedResource.getInputStream(); 093 } 094 095 /** 096 * Loads the image from the underlying <code>core.io.Resource.</code> 097 * 098 * This method does not cache. Calling it successively will result in a new 099 * image being loaded each time. 100 * 101 * @throws java.io.IOException 102 * If an error occurred while reading from the resource input 103 * stream. 104 */ 105 public Image getImage() throws IOException { 106 return loadImage(getInputStream()); 107 } 108 109 /** 110 * Load an image from the underlying resource's input stream. Constructs a 111 * new <code>Image</code> object from the data read from the input stream 112 * on each call. 113 * <p> 114 * This method loads the image fully into memory. This improves UI 115 * responsiveness when the image is needed by the GUI event-dispatching 116 * thread. 117 * 118 * @param stream 119 * The input stream. 120 * @return The resulting <code>Image</code> object. 121 * @throws java.io.IOException 122 * If an error occurred while reading from the stream. 123 */ 124 private synchronized Image loadImage(InputStream stream) throws IOException { 125 Toolkit toolkit = Toolkit.getDefaultToolkit(); 126 byte data[] = FileCopyUtils.copyToByteArray(stream); 127 128 Image image = toolkit.createImage(data); 129 imageLoaded = false; 130 imageError = false; 131 // fully loads the image into memory 132 toolkit.prepareImage(image, -1, -1, this); 133 while (!imageLoaded && !imageError) { 134 try { 135 wait(); 136 } 137 catch (InterruptedException ex) { 138 } 139 } 140 if (imageError) { 141 throw new IOException("Error preparing image from resource."); 142 } 143 return image; 144 } 145 146 public synchronized boolean imageUpdate(Image img, int infoflags, int x, int y, int w, int h) { 147 if ((infoflags & (ALLBITS | FRAMEBITS)) != 0) { 148 imageLoaded = true; 149 notifyAll(); 150 } 151 else { 152 if ((infoflags & ERROR) != 0) { 153 imageError = true; 154 notifyAll(); 155 } 156 } 157 return true; 158 } 159 160 public boolean equals(Object o) { 161 if (!(o instanceof AwtImageResource)) { 162 return false; 163 } 164 AwtImageResource r = (AwtImageResource)o; 165 return wrappedResource.equals(r.wrappedResource); 166 } 167 168 public int hashCode() { 169 return wrappedResource.hashCode(); 170 } 171 }