~hjd/ubuntu/wily/xmlgraphics-commons/debian-merged

« back to all changes in this revision

Viewing changes to src/java/org/apache/xmlgraphics/image/loader/impl/AbstractImageSessionContext.java

  • Committer: Bazaar Package Importer
  • Author(s): Vincent Fourmond
  • Date: 2011-02-11 14:15:14 UTC
  • mfrom: (8.1.2 experimental)
  • Revision ID: james.westby@ubuntu.com-20110211141514-h67achft6x31gju1
Tags: 1.4.dfsg-3
Uploading to unstable, hoping we won't break too many things ;-)...

Show diffs side-by-side

added added

removed removed

Lines of Context:
5
5
 * The ASF licenses this file to You under the Apache License, Version 2.0
6
6
 * (the "License"); you may not use this file except in compliance with
7
7
 * the License.  You may obtain a copy of the License at
8
 
 * 
 
8
 *
9
9
 *      http://www.apache.org/licenses/LICENSE-2.0
10
 
 * 
 
10
 *
11
11
 * Unless required by applicable law or agreed to in writing, software
12
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
15
 * limitations under the License.
16
16
 */
17
17
 
18
 
/* $Id: AbstractImageSessionContext.java 662487 2008-06-02 16:54:59Z jeremias $ */
19
 
 
 
18
/* $Id: AbstractImageSessionContext.java 828814 2009-10-22 18:52:33Z jeremias $ */
 
19
 
20
20
package org.apache.xmlgraphics.image.loader.impl;
21
21
 
22
22
import java.io.File;
23
23
import java.io.FileNotFoundException;
24
24
import java.io.IOException;
25
25
import java.io.InputStream;
 
26
import java.lang.reflect.InvocationHandler;
 
27
import java.lang.reflect.Method;
 
28
import java.lang.reflect.Proxy;
26
29
import java.net.MalformedURLException;
27
30
import java.net.URL;
28
31
 
52
55
    private static Log log = LogFactory.getLog(AbstractImageSessionContext.class);
53
56
 
54
57
    private static boolean noSourceReuse = false;
55
 
    
 
58
 
56
59
    static {
57
60
        //TODO Temporary measure to track down a problem
58
61
        //See: http://markmail.org/message/k6mno3jsxmovaz2e
60
63
                AbstractImageSessionContext.class.getName() + ".no-source-reuse");
61
64
        noSourceReuse = Boolean.valueOf(v).booleanValue();
62
65
    }
63
 
    
 
66
 
64
67
    /**
65
68
     * Attempts to resolve the given URI.
66
69
     * @param uri URI to access
67
70
     * @return A {@link javax.xml.transform.Source} object, or null if the URI
68
 
     * cannot be resolved. 
 
71
     * cannot be resolved.
69
72
     */
70
73
    protected abstract Source resolveURI(String uri);
71
74
 
82
85
            //Return any non-stream Sources and let the ImageLoaders deal with them
83
86
            return source;
84
87
        }
85
 
        
 
88
 
86
89
        ImageSource imageSource = null;
87
 
        
 
90
 
88
91
        String resolvedURI = source.getSystemId();
89
92
        URL url;
90
93
        try {
91
94
            url = new URL(resolvedURI);
92
95
        } catch (MalformedURLException e) {
93
96
            url = null;
94
 
        } 
 
97
        }
95
98
        File f = /*FileUtils.*/toFile(url);
96
99
        if (f != null) {
97
100
            boolean directFileAccess = true;
121
124
                    return null;
122
125
                }
123
126
            }
124
 
            
 
127
 
125
128
            if (directFileAccess) {
126
129
                //Close as the file is reopened in a more optimal way
127
130
                IOUtils.closeQuietly(in);
128
131
                try {
129
 
                    //We let the OS' file system cache do the caching for us
130
 
                    //--> lower Java memory consumption, probably no speed loss
131
 
                    imageSource = new ImageSource(ImageIO.createImageInputStream(f),
132
 
                            resolvedURI, true);
 
132
                    // We let the OS' file system cache do the caching for us
 
133
                    // --> lower Java memory consumption, probably no speed loss
 
134
                    final ImageInputStream newInputStream = ImageIO
 
135
                            .createImageInputStream(f);
 
136
                    if (newInputStream == null) {
 
137
                        log.error("Unable to create ImageInputStream for local file "
 
138
                                        + f
 
139
                                        + " from system identifier '"
 
140
                                        + source.getSystemId() + "'");
 
141
                        return null;
 
142
                    } else {
 
143
                        imageSource = new ImageSource(newInputStream,
 
144
                                resolvedURI, true);
 
145
                    }
133
146
                } catch (IOException ioe) {
134
147
                    log.error("Unable to create ImageInputStream for local file"
135
148
                            + " from system identifier '"
137
150
                }
138
151
            }
139
152
        }
140
 
        
 
153
 
141
154
        if (imageSource == null) {
142
155
            if (ImageUtil.hasReader(source) && !ImageUtil.hasInputStream(source)) {
143
156
                //We don't handle Reader instances here so return the Source unchanged
149
162
                try {
150
163
                    in = url.openStream();
151
164
                } catch (Exception ex) {
152
 
                    log.error("Unable to obtain stream from system identifier '" 
 
165
                    log.error("Unable to obtain stream from system identifier '"
153
166
                        + source.getSystemId() + "'");
154
167
                }
155
168
            }
163
176
                //Buffer and uncompress if necessary
164
177
                in = ImageUtil.autoDecorateInputStream(in);
165
178
                imageSource = new ImageSource(
166
 
                        ImageIO.createImageInputStream(in), source.getSystemId(), false);
 
179
                        createImageInputStream(in), source.getSystemId(), false);
167
180
            } catch (IOException ioe) {
168
181
                log.error("Unable to create ImageInputStream for InputStream"
169
182
                        + " from system identifier '"
172
185
        }
173
186
        return imageSource;
174
187
    }
175
 
    
 
188
 
 
189
    protected ImageInputStream createImageInputStream(InputStream in) throws IOException {
 
190
        ImageInputStream iin = ImageIO.createImageInputStream(in);
 
191
        return (ImageInputStream)Proxy.newProxyInstance(
 
192
                ImageInputStream.class.getClassLoader(),
 
193
                new Class[] {ImageInputStream.class},
 
194
                new ObservingImageInputStreamInvocationHandler(iin, in));
 
195
    }
 
196
 
 
197
    private static class ObservingImageInputStreamInvocationHandler
 
198
        implements InvocationHandler {
 
199
 
 
200
        private ImageInputStream iin;
 
201
        private InputStream in;
 
202
 
 
203
        public ObservingImageInputStreamInvocationHandler(ImageInputStream iin,
 
204
                InputStream underlyingStream) {
 
205
            this.iin = iin;
 
206
            this.in = underlyingStream;
 
207
        }
 
208
 
 
209
        /** {@inheritDoc} */
 
210
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
 
211
            if ("close".equals(method.getName())) {
 
212
                try {
 
213
                    return method.invoke(iin, args);
 
214
                } finally {
 
215
                    IOUtils.closeQuietly(this.in);
 
216
                    this.in = null;
 
217
                }
 
218
            } else {
 
219
                return method.invoke(iin, args);
 
220
            }
 
221
        }
 
222
 
 
223
    }
 
224
 
176
225
    /**
177
226
     * Convert from a <code>URL</code> to a <code>File</code>.
178
227
     * <p>
192
241
        if (url == null || !url.getProtocol().equals("file")) {
193
242
            return null;
194
243
        } else {
195
 
            String filename = "";
196
 
            if (url.getHost() != null) {
197
 
                filename += Character.toString(File.separatorChar)
198
 
                        + Character.toString(File.separatorChar)
199
 
                        + url.getHost();
200
 
            }
201
 
            filename += url.getFile().replace('/', File.separatorChar);
202
 
            int pos = 0;
203
 
            while ((pos = filename.indexOf('%', pos)) >= 0) {
204
 
                if (pos + 2 < filename.length()) {
205
 
                    String hexStr = filename.substring(pos + 1, pos + 3);
206
 
                    char ch = (char) Integer.parseInt(hexStr, 16);
207
 
                    filename = filename.substring(0, pos) + ch + filename.substring(pos + 3);
208
 
                }
209
 
            }
210
 
            return new File(filename);
 
244
            try {
 
245
                String filename = "";
 
246
                if (url.getHost() != null && url.getHost().length() > 0) {
 
247
                    filename += Character.toString(File.separatorChar)
 
248
                            + Character.toString(File.separatorChar)
 
249
                            + url.getHost();
 
250
                }
 
251
                filename += url.getFile().replace('/', File.separatorChar);
 
252
                filename = java.net.URLDecoder.decode(filename, "UTF-8");
 
253
                final File f = new File(filename);
 
254
                if (!f.isFile()) {
 
255
                    return null;
 
256
                }
 
257
                return f;
 
258
            } catch (java.io.UnsupportedEncodingException uee) {
 
259
                assert false;
 
260
                return null;
 
261
            }
211
262
        }
212
263
    }
213
 
    
 
264
 
214
265
    private SoftMapCache sessionSources = new SoftMapCache(false); //no need for synchronization
215
 
    
 
266
 
216
267
    /** {@inheritDoc} */
217
268
    public Source getSource(String uri) {
218
269
        return (Source)sessionSources.remove(uri);
219
270
    }
220
 
    
 
271
 
221
272
    /** {@inheritDoc} */
222
273
    public Source needSource(String uri) throws FileNotFoundException {
223
274
        Source src = getSource(uri);
224
275
        if (src == null) {
225
276
            if (log.isDebugEnabled()) {
226
277
                log.debug("Creating new Source for " + uri);
227
 
                
 
278
 
228
279
            }
229
280
            src = newSource(uri);
230
281
            if (src == null) {
237
288
        }
238
289
        return src;
239
290
    }
240
 
    
 
291
 
241
292
    /** {@inheritDoc} */
242
293
    public void returnSource(String uri, Source src) {
243
294
        //Safety check to make sure the Preloaders behave
250
301
            //Ignore exception
251
302
            ImageUtil.closeQuietly(src);
252
303
        }
253
 
        
 
304
 
254
305
        if (isReusable(src)) {
255
306
            //Only return the Source if it's reusable
256
307
            log.debug("Returning Source for " + uri);
260
311
            ImageUtil.closeQuietly(src);
261
312
        }
262
313
    }
263
 
    
 
314
 
264
315
    /**
265
316
     * Indicates whether a Source is reusable. A Source object is reusable if it's an
266
317
     * {@link ImageSource} (containing an {@link ImageInputStream}) or a {@link DOMSource}.