diff --git a/CodenameOne/src/com/codename1/ui/TextArea.java b/CodenameOne/src/com/codename1/ui/TextArea.java
index 104fa9be81..07ec8187d7 100644
--- a/CodenameOne/src/com/codename1/ui/TextArea.java
+++ b/CodenameOne/src/com/codename1/ui/TextArea.java
@@ -781,6 +781,7 @@ private void initRowString() {
                 return;
             }
         }
+        System.out.println("Test5");
         Style style = getUnselectedStyle();
         rowStrings= new ArrayList();
         widthForRowCalculations = getWidth() - style.getPadding(false, RIGHT) - style.getPadding(false, LEFT);
diff --git a/Ports/iOSPort/nativeSources/libzbar.a b/Ports/iOSPort/nativeSources/libzbar.a
index 7533efb95c..422e024023 100644
Binary files a/Ports/iOSPort/nativeSources/libzbar.a and b/Ports/iOSPort/nativeSources/libzbar.a differ
diff --git a/vm/ByteCodeTranslator/src/com/codename1/tools/translator/ByteCodeClass.java b/vm/ByteCodeTranslator/src/com/codename1/tools/translator/ByteCodeClass.java
index 6eff701ead..eb20ffa972 100644
--- a/vm/ByteCodeTranslator/src/com/codename1/tools/translator/ByteCodeClass.java
+++ b/vm/ByteCodeTranslator/src/com/codename1/tools/translator/ByteCodeClass.java
@@ -86,6 +86,9 @@ public String generateCSharpCode() {
     }
 
     public static void markDependencies(List<ByteCodeClass> lst) {
+        if (mainClass == null) {
+            throw new RuntimeException("Missing main class..");
+        }
         mainClass.markDependent(lst);
         for(ByteCodeClass bc : lst) {
             if(bc.clsName.equals("java_lang_Boolean")) {
@@ -1522,5 +1525,8 @@ public boolean isUsedByNative() {
         return usedByNative;
     }
 
-    
+    @Override
+    public String toString() {
+        return "[ByteCodeClass "+clsName+"]";
+    }
 }
diff --git a/vm/ByteCodeTranslator/src/com/codename1/tools/translator/ByteCodeTranslator.java b/vm/ByteCodeTranslator/src/com/codename1/tools/translator/ByteCodeTranslator.java
index 05b3d64812..e445f57bfe 100644
--- a/vm/ByteCodeTranslator/src/com/codename1/tools/translator/ByteCodeTranslator.java
+++ b/vm/ByteCodeTranslator/src/com/codename1/tools/translator/ByteCodeTranslator.java
@@ -61,8 +61,9 @@ public String extension() {
         public abstract String extension();
     };
     public static OutputType output = OutputType.OUTPUT_TYPE_IOS;
-    public static boolean verbose = true;
-    
+    public static boolean verbose = Boolean.parseBoolean(System.getProperty("ByteCodeTranslator.verbose","true"));
+    public static boolean draft = Boolean.parseBoolean(System.getProperty("ByteCodeTranslator.draft","false"));
+
     ByteCodeTranslator() {
     }
     
@@ -95,7 +96,9 @@ public boolean accept(File pathname) {
                 } else {
                     if(!f.isDirectory()) {
                         // copy the file to the dest dir
-                        copy(new FileInputStream(f), new FileOutputStream(new File(outputDir, f.getName())));
+                        if (f.getName().equals("package.html"))
+                            continue;
+                        copy(new FileInputStream(f), new PreservingFileOutputStream(new File(outputDir, f.getName())));
                     }
                 }
             }
@@ -111,17 +114,23 @@ public boolean accept(File pathname) {
         }
     }
     
-    private void copyDir(File source, File destDir) throws IOException {
+    private boolean copyDir(File source, File destDir) throws IOException {
         File destFile = new File(destDir, source.getName());
         destFile.mkdirs();
         File[] files = source.listFiles();
+        boolean retval = false;
         for(File f : files) {
             if(f.isDirectory()) {
-                copyDir(f, destFile);
+                long savedModified = destFile.lastModified();
+                boolean modified = copyDir(f, destFile);
+                if (!modified) {
+                    destFile.setLastModified(savedModified);
+                }
             } else {
-                copy(new FileInputStream(f), new FileOutputStream(new File(destFile, f.getName())));
+                retval |= copy(new FileInputStream(f), new PreservingFileOutputStream(new File(destFile, f.getName())));
             }
         }
+        return retval;
     }
     
     /**
@@ -145,6 +154,7 @@ public static void main(String[] args) throws Exception {
         final String appVersion = args[6];
         final String appType = args[7];
         final String addFrameworks = args[8];
+        StringBuilder appFonts = new StringBuilder("\n");
         // we accept 3 arguments output type, input directory & output directory
         if(args[0].equalsIgnoreCase("csharp")) {
             output = OutputType.OUTPUT_TYPE_CSHARP;
@@ -179,11 +189,11 @@ public static void main(String[] args) throws Exception {
             imagesXcassets.mkdirs();
             File  launchImageLaunchimage = new File(imagesXcassets, "LaunchImage.launchimage");
             launchImageLaunchimage.mkdirs();
-            copy(ByteCodeTranslator.class.getResourceAsStream("/LaunchImages.json"), new FileOutputStream(new File(launchImageLaunchimage, "Contents.json")));
+            copy(ByteCodeTranslator.class.getResourceAsStream("/LaunchImages.json"), new PreservingFileOutputStream(new File(launchImageLaunchimage, "Contents.json")));
 
             File appIconAppiconset = new File(imagesXcassets, "AppIcon.appiconset");
             appIconAppiconset.mkdirs();
-            copy(ByteCodeTranslator.class.getResourceAsStream("/Icons.json"), new FileOutputStream(new File(appIconAppiconset, "Contents.json")));
+            copy(ByteCodeTranslator.class.getResourceAsStream("/Icons.json"), new PreservingFileOutputStream(new File(appIconAppiconset, "Contents.json")));
             
             
             File xcproj = new File(root, appName + ".xcodeproj");
@@ -196,35 +206,38 @@ public static void main(String[] args) throws Exception {
             b.execute(sources, srcRoot);
 
             File cn1Globals = new File(srcRoot, "cn1_globals.h");
-            copy(ByteCodeTranslator.class.getResourceAsStream("/cn1_globals.h"), new FileOutputStream(cn1Globals));
+            copy(ByteCodeTranslator.class.getResourceAsStream("/cn1_globals.h"), new PreservingFileOutputStream(cn1Globals));
             File cn1GlobalsM = new File(srcRoot, "cn1_globals.m");
-            copy(ByteCodeTranslator.class.getResourceAsStream("/cn1_globals.m"), new FileOutputStream(cn1GlobalsM));
+            copy(ByteCodeTranslator.class.getResourceAsStream("/cn1_globals.m"), new PreservingFileOutputStream(cn1GlobalsM));
             File nativeMethods = new File(srcRoot, "nativeMethods.m");
-            copy(ByteCodeTranslator.class.getResourceAsStream("/nativeMethods.m"), new FileOutputStream(nativeMethods));
+            copy(ByteCodeTranslator.class.getResourceAsStream("/nativeMethods.m"), new PreservingFileOutputStream(nativeMethods));
 
             Parser.writeOutput(srcRoot);
             
-            File templateInfoPlist = new File(srcRoot, appName + "-Info.plist");
-            copy(ByteCodeTranslator.class.getResourceAsStream("/template/template/template-Info.plist"), new FileOutputStream(templateInfoPlist));
+            File templateInfoPlist = new File(srcRoot, appName + "-Info.plist" + PreservingFileOutputStream.NEW_SUFFIX);
+            copy(ByteCodeTranslator.class.getResourceAsStream("/template/template/template-Info.plist"), new PreservingFileOutputStream(templateInfoPlist));
             
             File templatePch = new File(srcRoot, appName + "-Prefix.pch");
-            copy(ByteCodeTranslator.class.getResourceAsStream("/template/template/template-Prefix.pch"), new FileOutputStream(templatePch));
+            copy(ByteCodeTranslator.class.getResourceAsStream("/template/template/template-Prefix.pch"), new PreservingFileOutputStream(templatePch));
 
             File xmlvm = new File(srcRoot, "xmlvm.h");
-            copy(ByteCodeTranslator.class.getResourceAsStream("/xmlvm.h"), new FileOutputStream(xmlvm));
+            copy(ByteCodeTranslator.class.getResourceAsStream("/xmlvm.h"), new PreservingFileOutputStream(xmlvm));
             
-            File projectWorkspaceData = new File(projectXCworkspace, "contents.xcworkspacedata");
-            copy(ByteCodeTranslator.class.getResourceAsStream("/template/template.xcodeproj/project.xcworkspace/contents.xcworkspacedata"), new FileOutputStream(projectWorkspaceData));
+            File projectWorkspaceData = new File(projectXCworkspace, "contents.xcworkspacedata"+ PreservingFileOutputStream.NEW_SUFFIX);
+            copy(ByteCodeTranslator.class.getResourceAsStream("/template/template.xcodeproj/project.xcworkspace/contents.xcworkspacedata"), new PreservingFileOutputStream(projectWorkspaceData));
             replaceInFile(projectWorkspaceData, "KitchenSink", appName);
             
             
-            File projectPbx = new File(xcproj, "project.pbxproj");
-            copy(ByteCodeTranslator.class.getResourceAsStream("/template/template.xcodeproj/project.pbxproj"), new FileOutputStream(projectPbx));            
+            File projectPbx = new File(xcproj, "project.pbxproj"+ PreservingFileOutputStream.NEW_SUFFIX);
+            copy(ByteCodeTranslator.class.getResourceAsStream("/template/template.xcodeproj/project.pbxproj"), new PreservingFileOutputStream(projectPbx));
             
             String[] sourceFiles = srcRoot.list(new FilenameFilter() {
                 @Override
-                public boolean accept(File pathname, String string) {
-                    return string.endsWith(".bundle") || string.endsWith(".xcdatamodeld") || !pathname.isHidden() && !string.startsWith(".") && !"Images.xcassets".equals(string);
+                public boolean accept(File pathname, String filename) {
+                    if (filename.endsWith(".ttf")) {
+                        appFonts.append("<string>"+filename+"</string>\n");
+                    }
+                    return filename.endsWith(".bundle") || filename.endsWith(".xcdatamodeld") || !pathname.isHidden() && !filename.startsWith(".") && !"Images.xcassets".equals(filename);
                 }
             });
             
@@ -278,6 +291,11 @@ public boolean accept(File pathname, String string) {
             arr.addAll(Arrays.asList(sourceFiles));
             
             for(String file : arr) {
+                if (file.endsWith(PreservingFileOutputStream.NEW_SUFFIX)) {
+                    file = file.substring(0, file.length()-PreservingFileOutputStream.NEW_SUFFIX.length());
+                } else {
+                    if (arr.contains(file + PreservingFileOutputStream.NEW_SUFFIX)) continue;   // remove duplicates
+                }
                 fileListEntry.append("		0");
                 currentValue++;
                 String fileOneValue = Integer.toHexString(currentValue).toUpperCase();
@@ -417,7 +435,15 @@ public boolean accept(File pathname, String string) {
             }
 
             String bundleVersion = System.getProperty("bundleVersionNumber", appVersion);
-            replaceInFile(templateInfoPlist, "com.codename1pkg", appPackageName, "${PRODUCT_NAME}", appDisplayName, "VERSION_VALUE", appVersion, "VERSION_BUNDLE_VALUE", bundleVersion);
+            replaceInFile(templateInfoPlist,
+                    "com.codename1pkg", appPackageName,
+                    "${PRODUCT_NAME}", appDisplayName,
+                    "VERSION_VALUE", appVersion,
+                    "VERSION_BUNDLE_VALUE", bundleVersion,
+                    "${APP_FONTS}", appFonts.toString());
+            PreservingFileOutputStream.finishWithNewFile(projectPbx);
+            PreservingFileOutputStream.finishWithNewFile(templateInfoPlist);
+            PreservingFileOutputStream.finishWithNewFile(projectWorkspaceData);
         } else {
             b.execute(sources, dest);
             Parser.writeOutput(dest);
@@ -495,8 +521,8 @@ private static void replaceInFile(File sourceFile, String... values) throws IOEx
      * @param i source
      * @param o destination
      */
-    public static void copy(InputStream i, OutputStream o) throws IOException {
-        copy(i, o, 8192);
+    public static boolean copy(InputStream i, OutputStream o) throws IOException {
+        return copy(i, o, 8192);
     }
 
     /**
@@ -507,7 +533,8 @@ public static void copy(InputStream i, OutputStream o) throws IOException {
      * @param o destination
      * @param bufferSize the size of the buffer, which should be a power of 2 large enoguh
      */
-    public static void copy(InputStream i, OutputStream o, int bufferSize) throws IOException {
+    public static boolean copy(InputStream i, OutputStream o, int bufferSize) throws IOException {
+        boolean modified = true;
         try {
             byte[] buffer = new byte[bufferSize];
             int size = i.read(buffer);
@@ -516,9 +543,10 @@ public static void copy(InputStream i, OutputStream o, int bufferSize) throws IO
                 size = i.read(buffer);
             }
         } finally {
-            cleanup(o);
             cleanup(i);
+            modified = cleanup(o);
         }
+        return modified;
     }
 
     /**
@@ -526,19 +554,24 @@ public static void copy(InputStream i, OutputStream o, int bufferSize) throws IO
      * object is null
      *
      * @param o Connection, Stream or other closeable object
+     * @return true if modified
      */
-    public static void cleanup(Object o) {
+    public static boolean cleanup(Object o) {
         try {
             if(o instanceof OutputStream) {
                 ((OutputStream)o).close();
-                return;
+                if (o instanceof PreservingFileOutputStream) {
+                    return !((PreservingFileOutputStream)o).equal;
+                }
+                return true;
             }
             if(o instanceof InputStream) {
                 ((InputStream)o).close();
-                return;
+                return false;
             }
         } catch(IOException err) {
             err.printStackTrace();
         }
+        return true;
     }
 }
diff --git a/vm/ByteCodeTranslator/src/com/codename1/tools/translator/BytecodeMethod.java b/vm/ByteCodeTranslator/src/com/codename1/tools/translator/BytecodeMethod.java
index 81e22e3397..2ff3229505 100644
--- a/vm/ByteCodeTranslator/src/com/codename1/tools/translator/BytecodeMethod.java
+++ b/vm/ByteCodeTranslator/src/com/codename1/tools/translator/BytecodeMethod.java
@@ -824,7 +824,12 @@ public void addDebugInfo(int line) {
     }
     
     public void addLabel(Label l) {
-        addInstruction(new com.codename1.tools.translator.bytecodes.LabelInstruction(l));
+        addInstruction(new com.codename1.tools.translator.bytecodes.LabelInstruction(l) {
+            @Override
+            public String toString() {
+                return "BL_"+clsName+"__"+methodName+"__"+instructions.size();
+            }
+        });
     }
     
     public void addInvoke(int opcode, String owner, String name, String desc, boolean itf) {
diff --git a/vm/ByteCodeTranslator/src/com/codename1/tools/translator/Parser.java b/vm/ByteCodeTranslator/src/com/codename1/tools/translator/Parser.java
index 0f59b907f8..96b8955ee2 100644
--- a/vm/ByteCodeTranslator/src/com/codename1/tools/translator/Parser.java
+++ b/vm/ByteCodeTranslator/src/com/codename1/tools/translator/Parser.java
@@ -23,12 +23,7 @@
 
 package com.codename1.tools.translator;
 
-import java.io.DataInputStream;
-import java.io.File;
-import java.io.FileFilter;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
+import java.io.*;
 import java.util.ArrayList;
 import java.util.List;
 import org.objectweb.asm.AnnotationVisitor;
@@ -42,6 +37,7 @@
 import org.objectweb.asm.Opcodes;
 import org.objectweb.asm.TypePath;
 import org.objectweb.asm.commons.JSRInlinerAdapter;
+import org.objectweb.asm.tree.LabelNode;
 
 /**
  *
@@ -56,10 +52,20 @@ public static void parse(File sourceFile) throws Exception {
         if(ByteCodeTranslator.verbose) {
             System.out.println("Parsing: " + sourceFile.getAbsolutePath());
         }
-        ClassReader r = new ClassReader(new FileInputStream(sourceFile));
-        /*if(ByteCodeTranslator.verbose) {
-            System.out.println("Class: " + r.getClassName() + " derives from: " + r.getSuperName() + " interfaces: " + Arrays.asList(r.getInterfaces()));
-        }*/
+        ClassReader r = new ClassReader(new FileInputStream(sourceFile)) {
+            String clsName;
+            @Override
+            protected Label readLabel(int offset, Label[] labels) {
+                if (clsName == null) {
+                    clsName = getClassName().replace('/', '_').replace('$', '_');
+                }
+                if (labels[offset] == null) {
+                    final String labelName = "L" + clsName + "___" + offset;
+                    labels[offset] = new MyLabel(labelName);
+                }
+                return labels[offset];
+            }
+        };
         Parser p = new Parser();
         p.clsName = r.getClassName().replace('/', '_').replace('$', '_');
         if(p.clsName.startsWith("java_lang_annotation") || p.clsName.startsWith("java_lang_Deprecated")
@@ -322,10 +328,10 @@ private static void generateClassAndMethodIndexHeader(File outputDirectory) thro
         
         bld.append("\n\n#endif // __CN1_CLASS_METHOD_INDEX_H__\n");        
         
-        FileOutputStream fos = new FileOutputStream(new File(outputDirectory, "cn1_class_method_index.h"));
+        OutputStream fos = new PreservingFileOutputStream(new File(outputDirectory, "cn1_class_method_index.h"));
         fos.write(bld.toString().getBytes("UTF-8"));
         fos.close();
-        fos = new FileOutputStream(new File(outputDirectory, "cn1_class_method_index.m"));
+        fos = new PreservingFileOutputStream(new File(outputDirectory, "cn1_class_method_index.m"));
         fos.write(bldM.toString().getBytes("UTF-8"));
         fos.close();
     }
@@ -374,6 +380,7 @@ public static void writeOutput(File outputDirectory) throws Exception {
         System.out.println("outputDirectory is: " + outputDirectory.getAbsolutePath() );
         String file = "Unknown File";
         try {
+            System.out.println("Iterate first..");
             for(ByteCodeClass bc : classes) {
                 // special case for object
                 if(bc.getClsName().equals("java_lang_Object")) {
@@ -387,24 +394,33 @@ public static void writeOutput(File outputDirectory) throws Exception {
                 }
                 bc.setBaseInterfacesObject(lst);
             }
+            if(ByteCodeTranslator.verbose) System.out.println("Iterate second..");
             for(ByteCodeClass bc : classes) {
                 file = bc.getClsName();
                 bc.updateAllDependencies();
-            }   
+            }
+            if(ByteCodeTranslator.verbose) System.out.println("Mark deps..");
             ByteCodeClass.markDependencies(classes);
             classes = ByteCodeClass.clearUnmarked(classes);
 
             // load the native sources (including user native code) 
+            if(ByteCodeTranslator.verbose) System.out.println("Load natives..");
             readNativeFiles(outputDirectory);
 
             // loop over methods and start eliminating the body of unused methods
-            eliminateUnusedMethods();
+            if(ByteCodeTranslator.verbose) System.out.println("Eliminate unused..");
+            if (!ByteCodeTranslator.draft)
+                eliminateUnusedMethods();
 
+            if(ByteCodeTranslator.verbose) System.out.println("Generate common header..");
             generateClassAndMethodIndexHeader(outputDirectory);
+            if(ByteCodeTranslator.verbose) System.out.println("Generate all classes..");
             for(ByteCodeClass bc : classes) {
                 file = bc.getClsName();
                 writeFile(bc.getClsName(), bc, outputDirectory);
             }
+            int created = PreservingFileOutputStream.total - PreservingFileOutputStream.preserved;
+            if(ByteCodeTranslator.verbose) System.out.println("Updated/created: "+created+" files");
         } catch(Throwable t) {
             System.out.println("Error while working with the class: " + file);
             t.printStackTrace();
@@ -577,11 +593,11 @@ private static boolean isMethodUsed(BytecodeMethod m) {
         
         return false;
     }
-    
+
     private static void writeFile(String clsName, ByteCodeClass cls, File outputDir) throws Exception {
         String fileName = clsName + "." + ByteCodeTranslator.output.extension();
-        
-        FileOutputStream outMain = new FileOutputStream(new File(outputDir, fileName));
+
+        PreservingFileOutputStream outMain = new PreservingFileOutputStream(new File(outputDir, fileName));
         
         // we also need to write the header file for iOS
         if(ByteCodeTranslator.output == ByteCodeTranslator.OutputType.OUTPUT_TYPE_IOS) {
@@ -589,7 +605,7 @@ private static void writeFile(String clsName, ByteCodeClass cls, File outputDir)
             outMain.close();
             String headerName = clsName + ".h";
 
-            FileOutputStream outHeader = new FileOutputStream(new File(outputDir, headerName));
+            PreservingFileOutputStream outHeader = new PreservingFileOutputStream(new File(outputDir, headerName));
             outHeader.write(cls.generateCHeader().getBytes());
 
             outHeader.close();
@@ -612,7 +628,20 @@ public void visitEnd() {
     public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
         BytecodeMethod mtd = new BytecodeMethod(clsName, access, name, desc, signature, exceptions);
         cls.addMethod(mtd);
-        JSRInlinerAdapter a = new JSRInlinerAdapter(new MethodVisitorWrapper(super.visitMethod(access, name, desc, signature, exceptions), mtd), access, name, desc, signature, exceptions);
+        final int labelN = cls.getMethods().size();
+        JSRInlinerAdapter a = new JSRInlinerAdapter(Opcodes.ASM5,
+                new MethodVisitorWrapper(
+                        super.visitMethod(access, name, desc, signature, exceptions),
+                        mtd),
+                access, name, desc, signature, exceptions) {
+            @Override
+            protected LabelNode getLabelNode(Label l) {
+                if (!(l.info instanceof LabelNode)) {
+                    l.info = new LabelNode(new MyLabel("JSRL_"+labelN+"_"+l.toString()));
+                }
+                return (LabelNode) l.info;
+            }
+        };
         return a; 
     }
 
@@ -671,8 +700,28 @@ public void visit(int version, int access, String name, String signature, String
             cls.setFinalClass(true);
         }
         super.visit(version, access, name, signature, superName, interfaces); 
-    }    
-    
+    }
+
+    public static class MyLabel extends Label {
+        private final String labelName;
+
+        public MyLabel(String labelName) {
+            this.labelName = labelName;
+        }
+
+        int count = 0;
+
+        @Override
+        public String toString() {
+            // persistence of label names causes non-regeneration of resulting sources.
+            return labelName;
+        }
+    }
+
+
+
+
+
     class MethodVisitorWrapper extends MethodVisitor {
         private BytecodeMethod mtd;
         public MethodVisitorWrapper(MethodVisitor mv, BytecodeMethod mtd) {
diff --git a/vm/ByteCodeTranslator/src/com/codename1/tools/translator/PreservingFileOutputStream.java b/vm/ByteCodeTranslator/src/com/codename1/tools/translator/PreservingFileOutputStream.java
new file mode 100644
index 0000000000..5f21788eff
--- /dev/null
+++ b/vm/ByteCodeTranslator/src/com/codename1/tools/translator/PreservingFileOutputStream.java
@@ -0,0 +1,104 @@
+package com.codename1.tools.translator;
+
+import java.io.*;
+import java.util.Arrays;
+import java.util.HashSet;
+
+/**
+ * Created by admin on 8/17/15.
+ */
+public class PreservingFileOutputStream extends OutputStream {
+
+    final public static String NEW_SUFFIX = ".new_by_translator";
+
+    static int total;
+    static int preserved;
+    boolean equal;
+
+    ByteArrayOutputStream baos = new ByteArrayOutputStream();
+    File file;
+
+
+    public PreservingFileOutputStream(File file) throws FileNotFoundException {
+        this.file = file;
+        total++;
+    }
+
+    @Override
+    public void write(int b) throws IOException {
+        baos.write(b);
+    }
+
+    @Override
+    public void close() throws IOException {
+        equal = false;
+        if (file.exists() && file.length() == baos.size()) {
+            byte[] oldCopy = new byte[baos.size()];
+            FileInputStream fis = new FileInputStream(file);
+            fis.read(oldCopy);
+            fis.close();
+            final byte[] thisCopy = baos.toByteArray();
+            equal = true;
+            for (int i = 0; i < thisCopy.length; i++) {
+                if (thisCopy[i] != oldCopy[i]) {
+                    equal = false;
+                    break;
+                }
+            }
+            if (equal) {
+                preserved++;
+                return;
+            }
+        }
+        System.out.println("Producing(stream): " + file.getName());
+        FileOutputStream x = new FileOutputStream(file);
+        baos.writeTo(x);
+        x.close();
+    }
+
+
+    /**
+     * move temporary created file to its final destination. If final destination doesn't differ from
+     * new file, do nothing (remove new file), thus keeping timestamps.
+     */
+    public static boolean preservingMove(File from, File to) throws IOException {
+        if (from.exists() && to.exists() && to.length() == from.length()) {
+            byte[] thisCopy = new byte[(int)from.length()];
+            FileInputStream fis = new FileInputStream(from);
+            fis.read(thisCopy);
+            fis.close();
+
+            byte[] oldCopy = new byte[(int)to.length()];
+            fis = new FileInputStream(to);
+            fis.read(oldCopy);
+            fis.close();
+
+            boolean equal = true;
+            for (int i = 0; i < thisCopy.length; i++) {
+                if (thisCopy[i] != thisCopy[i]) {
+                    equal = false;
+                    break;
+                }
+            }
+
+            if (equal) {
+                // preserve
+                return from.delete();   // keep old
+            }
+        }
+        if(ByteCodeTranslator.verbose) {
+            System.out.println("Producing(move): " + to.getName());
+        }
+        to.delete();
+        return from.renameTo(to);
+    }
+
+    public static boolean finishWithNewFile(File newFile) throws IOException {
+        String path = newFile.getPath();
+        if (path.endsWith(NEW_SUFFIX)) {
+            String finalDestination = path.substring(0, path.length() - NEW_SUFFIX.length());
+            return preservingMove(newFile, new File(finalDestination));
+        }
+        return true;    // not a new file
+    }
+}
diff --git a/vm/ByteCodeTranslator/src/template/template/template-Info.plist b/vm/ByteCodeTranslator/src/template/template/template-Info.plist
index 0faec8023e..1c2bac0bf6 100644
--- a/vm/ByteCodeTranslator/src/template/template/template-Info.plist
+++ b/vm/ByteCodeTranslator/src/template/template/template-Info.plist
@@ -50,5 +50,7 @@
 		<string>UIInterfaceOrientationLandscapeLeft</string>
 		<string>UIInterfaceOrientationLandscapeRight</string>
 	</array>
+    <key>UIAppFonts</key>
+    <array>${APP_FONTS}</array>
 </dict>
 </plist>