diff options
author | Sven Gothel <[email protected]> | 2014-09-30 23:07:50 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2014-09-30 23:07:50 +0200 |
commit | bd24599b21f9787ac989e65b44dc1ba762162f22 (patch) | |
tree | 48bf52d4ebdd5e4172dd83a4d6d7f75f961c7574 /src/jogl/classes | |
parent | f197d38d0ea31416645ac69cebb3f9b3544d903f (diff) |
Refine Graph/Font InputStream Capabilities (commit 628509b39ea7c16210315d191860511d6be4aa69)
FontFactory Remove:
- Font get(final URLConnection conn)
- Font get(final InputStream stream)
FontFactory Add:
- [1] Font get(final InputStream stream, final int streamLen, final boolean closeStream)
- Direct usage of font InputStream w/ determined length,
may instantiate BufferedInputStream in case given stream
doesn't support mark/reset!
- [2] Font get(final InputStream stream, final boolean closeStream)
- Copy font InputStream w/o determined length,
resulting in BufferedInputStream supporting mark/reset!
Security Related:
- Only perform priviledged code on determine InputStream,
_not_ when parsing the font stream itself!
- Hence PrivilegedAction only happens in FontFactory's
InputStream preparation.
Misc:
- Use Uri class
Diffstat (limited to 'src/jogl/classes')
6 files changed, 226 insertions, 164 deletions
diff --git a/src/jogl/classes/com/jogamp/graph/font/FontFactory.java b/src/jogl/classes/com/jogamp/graph/font/FontFactory.java index cfd06cf6c..ba355f4e6 100644 --- a/src/jogl/classes/com/jogamp/graph/font/FontFactory.java +++ b/src/jogl/classes/com/jogamp/graph/font/FontFactory.java @@ -27,12 +27,15 @@ */ package com.jogamp.graph.font; +import java.io.BufferedInputStream; import java.io.File; +import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; -import java.net.URI; -import java.net.URLConnection; +import java.security.AccessController; +import java.security.PrivilegedAction; +import com.jogamp.common.net.Uri; import com.jogamp.common.util.IOUtil; import com.jogamp.common.util.PropertyAccess; import com.jogamp.common.util.ReflectionUtil; @@ -88,32 +91,113 @@ public class FontFactory { } } + /** + * Creates a Font instance. + * @param file font file + * @return the new Font instance + * @throws IOException + */ public static final Font get(final File file) throws IOException { return fontConstr.create(file); } - public static final Font get(final InputStream stream) throws IOException { - return fontConstr.create(stream); + /** + * Creates a Font instance based on a determinated font stream with its given length + * of the font segment. + * <p> + * No explicit stream copy is performed as in {@link #get(InputStream, boolean)} + * due to the known {@code streamLen}. + * </p> + * @param stream font stream + * @param streamLen length of the font segment within this font stream + * @param closeStream {@code true} to close the {@code stream} + * @return the new Font instance + * @throws IOException + */ + public static final Font get(final InputStream stream, final int streamLen, final boolean closeStream) throws IOException { + try { + return fontConstr.create(stream, streamLen); + } finally { + if( closeStream ) { + stream.close(); + } + } } - public static final Font get(final URLConnection conn) throws IOException { - return fontConstr.create(conn); + /** + * Creates a Font instance based on an undeterminated font stream length. + * <p> + * The font stream is temporarily copied into a temp file + * to gather it's size and to gain random access. + * The temporary file will be deleted at exit. + * </p> + * @param stream dedicated font stream + * @param closeStream {@code true} to close the {@code stream} + * @return the new Font instance + * @throws IOException + */ + public static final Font get(final InputStream stream, final boolean closeStream) throws IOException { + final IOException[] ioe = { null }; + final int[] streamLen = { 0 }; + final File tempFile[] = { null }; + + final InputStream bis = AccessController.doPrivileged(new PrivilegedAction<InputStream>() { + @Override + public InputStream run() { + InputStream bis = null; + try { + tempFile[0] = IOUtil.createTempFile( "jogl.font", ".ttf", false); + streamLen[0] = IOUtil.copyStream2File(stream, tempFile[0], -1); + if( 0 == streamLen[0] ) { + throw new IOException("Font stream has zero bytes"); + } + bis = new BufferedInputStream(new FileInputStream(tempFile[0]), streamLen[0]); + } catch (final IOException e) { + ioe[0] = e; + if( null != tempFile[0] ) { + tempFile[0].delete(); + tempFile[0] = null; + } + streamLen[0] = 0; + } finally { + if( closeStream ) { + IOUtil.close(stream, ioe, System.err); + } + } + return bis; + } }); + if( null != ioe[0] ) { + throw ioe[0]; + } + if( null == bis ) { + throw new IOException("Could not cache font stream"); // should not be reached + } + try { + return fontConstr.create(bis, streamLen[0]); + } finally { + if( null != bis ) { + bis.close(); + } + if( null != tempFile[0] ) { + tempFile[0].delete(); + } + } } public static final Font get(final Class<?> context, final String fname, final boolean useTempJarCache) throws IOException { - URLConnection conn = null; + InputStream stream = null; if( useTempJarCache ) { try { - final URI uri = TempJarCache.getResource(fname); - conn = null != uri ? uri.toURL().openConnection() : null; + final Uri uri = TempJarCache.getResourceUri(fname); + stream = null != uri ? uri.toURL().openConnection().getInputStream() : null; } catch (final Exception e) { throw new IOException(e); } } else { - conn = IOUtil.getResource(context, fname); + stream = IOUtil.getResource(context, fname).getInputStream(); } - if(null != conn) { - return FontFactory.get ( conn ) ; + if( null != stream ) { + return FontFactory.get ( stream, true ) ; } return null; } diff --git a/src/jogl/classes/jogamp/graph/font/FontConstructor.java b/src/jogl/classes/jogamp/graph/font/FontConstructor.java index 76b5dbb8b..fa176ead9 100644 --- a/src/jogl/classes/jogamp/graph/font/FontConstructor.java +++ b/src/jogl/classes/jogamp/graph/font/FontConstructor.java @@ -30,12 +30,10 @@ package jogamp.graph.font; import java.io.File; import java.io.IOException; import java.io.InputStream; -import java.net.URLConnection; import com.jogamp.graph.font.Font; public interface FontConstructor { - Font create(File file) throws IOException ; - Font create(InputStream stream) throws IOException ; - Font create(URLConnection url) throws IOException ; + Font create(final File file) throws IOException ; + Font create(final InputStream stream, int streamLen) throws IOException ; } diff --git a/src/jogl/classes/jogamp/graph/font/JavaFontLoader.java b/src/jogl/classes/jogamp/graph/font/JavaFontLoader.java index 1bb2bb5f3..da651cca9 100644 --- a/src/jogl/classes/jogamp/graph/font/JavaFontLoader.java +++ b/src/jogl/classes/jogamp/graph/font/JavaFontLoader.java @@ -27,8 +27,11 @@ */ package jogamp.graph.font; +import java.io.BufferedInputStream; import java.io.File; +import java.io.FileInputStream; import java.io.IOException; +import java.io.InputStream; import java.security.AccessController; import java.security.PrivilegedAction; @@ -89,6 +92,9 @@ public class JavaFontLoader implements FontSet { @Override public Font get(final int family, final int style) throws IOException { + if(null == javaFontPath) { + throw new GLException("java font path undefined"); + } Font font = (Font)fontMap.get( ( family << 8 ) | style ); if (font != null) { return font; @@ -139,20 +145,41 @@ public class JavaFontLoader implements FontSet { } Font abspath(final String fname, final int family, final int style) throws IOException { - if(null == javaFontPath) { - throw new GLException("java font path undefined"); - } - final String err = "Problem loading font "+fname+", file "+javaFontPath+fname ; - try { - final Font f = FontFactory.get( new File(javaFontPath+fname) ); + final Font f = abspathImpl(javaFontPath+fname, family, style); if(null != f) { - fontMap.put( ( family << 8 ) | style, f ); return f; } - throw new IOException (err); + throw new IOException (String.format("Problem loading font %s, file %s%s", fname, javaFontPath, fname)); } catch (final IOException ioe) { - throw new IOException(err, ioe); + throw new IOException(String.format("Problem loading font %s, file %s%s", fname, javaFontPath, fname), ioe); + } + } + private Font abspathImpl(final String fname, final int family, final int style) throws IOException { + final Exception[] privErr = { null }; + final int[] streamLen = { 0 }; + final InputStream stream = AccessController.doPrivileged(new PrivilegedAction<InputStream>() { + @Override + public InputStream run() { + try { + final File file = new File(fname); + streamLen[0] = (int) file.length(); + return new BufferedInputStream(new FileInputStream(file), streamLen[0]); + } catch (final Exception e) { + privErr[0] = e; + return null; + } + } } ); + if( null != privErr[0] ) { + throw new IOException(privErr[0]); + } + if(null != stream) { + final Font f= FontFactory.get ( stream, streamLen[0], true ) ; + if(null != f) { + fontMap.put( ( family << 8 ) | style, f ); + return f; + } } + return null; } } diff --git a/src/jogl/classes/jogamp/graph/font/UbuntuFontLoader.java b/src/jogl/classes/jogamp/graph/font/UbuntuFontLoader.java index 76947873e..bbf022657 100644 --- a/src/jogl/classes/jogamp/graph/font/UbuntuFontLoader.java +++ b/src/jogl/classes/jogamp/graph/font/UbuntuFontLoader.java @@ -28,18 +28,17 @@ package jogamp.graph.font; import java.io.IOException; +import java.io.InputStream; +import com.jogamp.common.net.Uri; import com.jogamp.common.os.Platform; import com.jogamp.common.util.IntObjectHashMap; -import com.jogamp.common.util.IOUtil; import com.jogamp.common.util.JarUtil; import com.jogamp.common.util.cache.TempJarCache; import com.jogamp.graph.font.Font; import com.jogamp.graph.font.FontSet; import com.jogamp.graph.font.FontFactory; -import java.net.URI; -import java.net.URLConnection; import java.security.AccessController; import java.security.PrivilegedAction; @@ -48,8 +47,8 @@ public class UbuntuFontLoader implements FontSet { // FIXME: Add cache size to limit memory usage private static final IntObjectHashMap fontMap = new IntObjectHashMap(); - private static final String jarSubDir = "atomic/" ; - private static final String jarName = "jogl-fonts-p0.jar" ; + private static final Uri.Encoded jarSubDir = Uri.Encoded.cast("atomic/"); + private static final Uri.Encoded jarName = Uri.Encoded.cast("jogl-fonts-p0.jar"); private static final String relFontPath = "fonts/ubuntu/" ; private static final String absFontPath = "jogamp/graph/font/fonts/ubuntu/" ; @@ -130,71 +129,64 @@ public class UbuntuFontLoader implements FontSet { } private static boolean attemptedJARLoading = false; - private static boolean useTempJarCache = false; + private static boolean useTempJARCache = false; private synchronized Font abspath(final String fname, final int family, final int style) throws IOException { - final String err = "Problem loading font "+fname+", stream "+relFontPath+fname; - final Exception[] privErr = { null }; - try { - final Font f0 = abspathImpl(fname, family, style); - if(null != f0) { - return f0; - } - if( !attemptedJARLoading ) { - attemptedJARLoading = true; - Platform.initSingleton(); - if( TempJarCache.isInitialized() ) { - final URI uri = JarUtil.getRelativeOf(UbuntuFontLoader.class, jarSubDir, jarName); - AccessController.doPrivileged(new PrivilegedAction<Object>() { + if( !attemptedJARLoading ) { + attemptedJARLoading = true; + Platform.initSingleton(); + if( TempJarCache.isInitialized() ) { + try { + final Uri uri = JarUtil.getRelativeOf(UbuntuFontLoader.class, jarSubDir, jarName); + final Exception e0 = AccessController.doPrivileged(new PrivilegedAction<Exception>() { @Override - public Object run() { + public Exception run() { try { TempJarCache.addResources(UbuntuFontLoader.class, uri); - } catch (final Exception e) { privErr[0] = e; } - return null; + useTempJARCache = true; + return null; + } catch (final Exception e) { + return e; + } } } ); - if( null == privErr[0] ) { - useTempJarCache = true; - final Font f1 = abspathImpl(fname, family, style); - if(null != f1) { - return f1; - } + if( null != e0 ) { + throw e0; } + } catch(final Exception e1) { + System.err.println("Caught "+e1.getMessage()); + e1.printStackTrace(); } } - } catch(final Exception e) { - throw new IOException(err, e); } - if( null != privErr[0] ) { - throw new IOException(err, privErr[0]); + final String path = useTempJARCache ? absFontPath : relFontPath; + try { + final Font f = abspathImpl(path+fname, family, style); + if( null != f ) { + return f; + } + throw new IOException(String.format("Problem loading font %s, stream %s%s", fname, path, fname)); + } catch(final Exception e) { + throw new IOException(String.format("Problem loading font %s, stream %s%s", fname, path, fname), e); } - throw new IOException(err); } private Font abspathImpl(final String fname, final int family, final int style) throws IOException { - final URLConnection conn; - if( useTempJarCache ) { - // this code-path throws .. all exceptions - final Exception[] privErr = { null }; - final URLConnection[] privConn = { null }; - AccessController.doPrivileged(new PrivilegedAction<Object>() { - @Override - public Object run() { - try { - final URI uri = TempJarCache.getResource(absFontPath+fname); - privConn[0] = null != uri ? uri.toURL().openConnection() : null; - } catch (final Exception e) { privErr[0] = e; } + final Exception[] privErr = { null }; + final InputStream stream = AccessController.doPrivileged(new PrivilegedAction<InputStream>() { + @Override + public InputStream run() { + try { + final Uri uri = TempJarCache.getResourceUri(fname); + return null != uri ? uri.toURL().openConnection().getInputStream() : null; + } catch (final Exception e) { + privErr[0] = e; return null; - } } ); - if( null != privErr[0] ) { - throw new IOException(privErr[0]); - } - conn = privConn[0]; - } else { - // no exceptions .. - conn = IOUtil.getResource(UbuntuFontLoader.class, relFontPath+fname); + } + } } ); + if( null != privErr[0] ) { + throw new IOException(privErr[0]); } - if(null != conn) { - final Font f= FontFactory.get ( conn ) ; + if(null != stream) { + final Font f= FontFactory.get ( stream, true ) ; if(null != f) { fontMap.put( ( family << 8 ) | style, f ); return f; diff --git a/src/jogl/classes/jogamp/graph/font/typecast/TypecastFontConstructor.java b/src/jogl/classes/jogamp/graph/font/typecast/TypecastFontConstructor.java index 0b42a65d4..ef7f38e64 100644 --- a/src/jogl/classes/jogamp/graph/font/typecast/TypecastFontConstructor.java +++ b/src/jogl/classes/jogamp/graph/font/typecast/TypecastFontConstructor.java @@ -30,89 +30,21 @@ package jogamp.graph.font.typecast; import java.io.File; import java.io.IOException; import java.io.InputStream; -import java.net.URLConnection; -import java.security.AccessController; -import java.security.PrivilegedAction; - -import javax.media.opengl.GLException; import jogamp.graph.font.FontConstructor; import jogamp.graph.font.typecast.ot.OTFontCollection; -import com.jogamp.common.util.IOUtil; import com.jogamp.graph.font.Font; public class TypecastFontConstructor implements FontConstructor { @Override public Font create(final File ffile) throws IOException { - final Object o = AccessController.doPrivileged(new PrivilegedAction<Object>() { - @Override - public Object run() { - OTFontCollection fontset; - try { - fontset = OTFontCollection.create(ffile); - return new TypecastFont(fontset); - } catch (final IOException e) { - return e; - } - } - }); - if(o instanceof Font) { - return (Font)o; - } - if(o instanceof IOException) { - throw (IOException)o; - } - throw new InternalError("Unexpected Object: "+o); + return new TypecastFont( OTFontCollection.create(ffile) ); } @Override - public Font create(final InputStream istream) throws IOException { - final Object o = AccessController.doPrivileged(new PrivilegedAction<Object>() { - @Override - public Object run() { - OTFontCollection fontset; - try { - fontset = OTFontCollection.create(istream); - return new TypecastFont(fontset); - } catch (final IOException e) { - return e; - } - } - }); - if(o instanceof Font) { - return (Font)o; - } - if(o instanceof IOException) { - throw (IOException)o; - } - throw new InternalError("Unexpected Object: "+o); + public Font create(final InputStream istream, final int streamLen) throws IOException { + return new TypecastFont( OTFontCollection.create(istream, streamLen) ); } - - @Override - public Font create(final URLConnection fconn) throws IOException { - return AccessController.doPrivileged(new PrivilegedAction<Font>() { - @Override - public Font run() { - File tf = null; - int len=0; - Font f = null; - try { - tf = IOUtil.createTempFile( "jogl.font", ".ttf", false); - len = IOUtil.copyURLConn2File(fconn, tf); - if(len==0) { - tf.delete(); - throw new GLException("Font of stream "+fconn.getURL()+" was zero bytes"); - } - f = create(tf); - tf.delete(); - } catch (final IOException e) { - e.printStackTrace(); - } - return f; - } - }); - } - } diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/OTFontCollection.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/OTFontCollection.java index 87c68eae8..be84a951c 100644 --- a/src/jogl/classes/jogamp/graph/font/typecast/ot/OTFontCollection.java +++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/OTFontCollection.java @@ -59,9 +59,19 @@ public class OTFontCollection { /** * @param file The OpenType font file */ - public static OTFontCollection create(final InputStream istream) throws IOException { + public static OTFontCollection create(final File file) throws IOException { final OTFontCollection fc = new OTFontCollection(); - fc.read(istream); + fc.read(file); + return fc; + } + + /** + * @param istream The OpenType font input stream + * @param streamLen TODO + */ + public static OTFontCollection create(final InputStream istream, final int streamLen) throws IOException { + final OTFontCollection fc = new OTFontCollection(); + fc.read(istream, streamLen); return fc; } @@ -120,20 +130,40 @@ public class OTFontCollection { } _resourceFork = true; } - - read(new FileInputStream(file)); + final int streamLen = (int) file.length(); + final BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file), streamLen); + try { + readImpl(bis, streamLen); + } finally { + bis.close(); + } } - + /** - * @param inputstream The OpenType font stream + * @param is The OpenType font stream + * @param streamLen the total length of the stream */ - protected void read(InputStream file) throws IOException { - - final DataInputStream dis = new DataInputStream( - new BufferedInputStream( - file)); - //dis.mark((int) file.length()); + protected void read(final InputStream is, final int streamLen) throws IOException { + _pathName = ""; + _fileName = ""; + final InputStream bis; + if( is.markSupported() ) { + bis = is; + } else { + bis = new BufferedInputStream(is, streamLen); + } + readImpl(bis, streamLen); + } + /** + * @param is The OpenType font stream, must {@link InputStream#markSupported() support mark}! + */ + private void readImpl(final InputStream bis, final int streamLen) throws IOException { + if( !bis.markSupported() ) { + throw new IllegalArgumentException("stream of type "+bis.getClass().getName()+" doesn't support mark"); + } + bis.mark(streamLen); + final DataInputStream dis = new DataInputStream(bis); if (_resourceFork || _pathName.endsWith(".dfont")) { // This is a Macintosh font suitcase resource @@ -174,6 +204,5 @@ public class OTFontCollection { _fonts[0] = new OTFont(this); _fonts[0].read(dis, 0, 0); } - dis.close(); } } |