001: /*
002: * $Id: DynamicImageResource.java,v 1.20 2006/03/01 15:29:47 joco01 Exp $
003: * $Revision: 1.20 $ $Date: 2006/03/01 15:29:47 $
004: *
005: * ==============================================================================
006: * Licensed under the Apache License, Version 2.0 (the "License"); you may not
007: * use this file except in compliance with the License. You may obtain a copy of
008: * the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing, software
013: * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
014: * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
015: * License for the specific language governing permissions and limitations under
016: * the License.
017: */
018: package wicket.markup.html;
019:
020: import java.io.ByteArrayInputStream;
021: import java.io.IOException;
022: import java.io.InputStream;
023: import java.util.Locale;
024:
025: import wicket.util.resource.IResourceStream;
026: import wicket.util.resource.ResourceStreamNotFoundException;
027: import wicket.util.time.Time;
028:
029: /**
030: * An WebResource subclass for dynamic resources (resources created
031: * programmatically).
032: *
033: * @author Jonathan Locke
034: * @author Johan Compagner
035: * @author Gili Tzabari
036: */
037: public abstract class DynamicWebResource extends WebResource {
038: /**
039: * The resource state returned by the getResourceState() method. This state
040: * needs to be thread-safe and its methods must return the same values no
041: * matter how many times they are invoked. A ResourceState may assume
042: * getParameters() will remain unchanged during its lifetime.
043: *
044: * @author jcompagner
045: */
046: public static abstract class ResourceState {
047: protected Time lastModifiedTime;
048:
049: /**
050: * @return The Byte array for this resource
051: */
052: public abstract byte[] getData();
053:
054: /**
055: * @return The content type of this resource
056: */
057: public abstract String getContentType();
058:
059: /**
060: * @return The last modified time of this resource
061: */
062: public Time lastModifiedTime() {
063: if (lastModifiedTime == null)
064: lastModifiedTime = Time.now();
065: return lastModifiedTime;
066: }
067:
068: /**
069: * @return The length of the data
070: */
071: public int getLength() {
072: byte[] data = getData();
073: return data != null ? data.length : 0;
074: }
075: }
076:
077: /**
078: * The resource locale.
079: */
080: private Locale locale;
081:
082: /**
083: * Creates a dynamic resource.
084: */
085: public DynamicWebResource() {
086: setCacheable(false);
087: }
088:
089: /**
090: * Creates a dynamic resource from for the given locale
091: *
092: * @param locale
093: * The locale of this resource
094: */
095: public DynamicWebResource(Locale locale) {
096: this ();
097: this .locale = locale;
098: }
099:
100: /**
101: * Returns the resource locale.
102: *
103: * @return The locale of this resource
104: */
105: public Locale getLocale() {
106: return locale;
107: }
108:
109: /**
110: * @return Gets the resource to attach to the component.
111: */
112: // this method is deliberately non-final. some users depend on it
113: public IResourceStream getResourceStream() {
114: return new IResourceStream() {
115: private static final long serialVersionUID = 1L;
116:
117: private Locale locale = DynamicWebResource.this .getLocale();
118:
119: /** Transient input stream to resource */
120: private transient InputStream inputStream = null;
121:
122: /**
123: * Transient ResourceState of the resources, will always be deleted
124: * in the close
125: */
126: private transient ResourceState data = null;
127:
128: /**
129: * @see wicket.util.resource.IResourceStream#close()
130: */
131: public void close() throws IOException {
132: if (inputStream != null) {
133: inputStream.close();
134: inputStream = null;
135: }
136: data = null;
137: }
138:
139: /**
140: * @see wicket.util.resource.IResourceStream#getContentType()
141: */
142: public String getContentType() {
143: checkLoadData();
144: return data.getContentType();
145: }
146:
147: /**
148: * @see wicket.util.resource.IResourceStream#getInputStream()
149: */
150: public InputStream getInputStream()
151: throws ResourceStreamNotFoundException {
152: checkLoadData();
153: if (inputStream == null) {
154: inputStream = new ByteArrayInputStream(data
155: .getData());
156: }
157: return inputStream;
158: }
159:
160: /**
161: * @see wicket.util.watch.IModifiable#lastModifiedTime()
162: */
163: public Time lastModifiedTime() {
164: checkLoadData();
165: return data.lastModifiedTime();
166: }
167:
168: /**
169: * @see wicket.util.resource.IResourceStream#length()
170: */
171: public long length() {
172: checkLoadData();
173: return data.getLength();
174: }
175:
176: /**
177: * @see wicket.util.resource.IResourceStream#getLocale()
178: */
179: public Locale getLocale() {
180: return locale;
181: }
182:
183: /**
184: * @see wicket.util.resource.IResourceStream#setLocale(java.util.Locale)
185: */
186: public void setLocale(Locale loc) {
187: locale = loc;
188: }
189:
190: /**
191: * Check whether the data was loaded yet. If not, load it now.
192: */
193: private void checkLoadData() {
194: if (data == null) {
195: data = getResourceState();
196: }
197: }
198: };
199: }
200:
201: /**
202: * Gets the byte array for our dynamic resource. If the subclass regenerates
203: * the data, it should set the lastModifiedTime too. This ensures that
204: * resource caching works correctly.
205: *
206: * @return The byte array for this dynamic resource.
207: */
208: protected abstract ResourceState getResourceState();
209: }
|