All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.codename1.designer.css.CN1CSSCompileTask Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2012, Codename One and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Codename One designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *  
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 * 
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 * 
 * Please contact Codename One through http://www.codenameone.com/ if you 
 * need additional information or have any questions.
 */
package com.codename1.designer.css;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.taskdefs.Java;
import org.apache.tools.ant.types.Commandline.Argument;
import org.apache.tools.ant.types.Path;

/**
 *
 * @author shannah
 */
public class CN1CSSCompileTask extends Task {

    @Override
    public void execute() throws BuildException {
        
        String srcDirPath = getProject().getProperty("src.dir");
        if (srcDirPath == null || "".equals(srcDirPath)) {
            srcDirPath = "src";
        }
        
        File cssDir = new File(getProject().getBaseDir(), "css");
        if (!cssDir.exists()) {
            log("Skipping CSS task because no 'css' directory found in project.");
            return;
        }
        
        File srcDir = new File(getProject().getBaseDir(), srcDirPath);
        //System.out.println(getProject().getProperties());
        
        String runClasspath = getProject().getProperty("run.classpath");
        if (runClasspath == null || "".equals(runClasspath)) {
            runClasspath = "JavaSE.jar";
        }
        String[] classPath = runClasspath.split(":");
        String javaSEJarPath = null;
        for (String path : classPath) {
            if (path.endsWith("JavaSE.jar")) {
                javaSEJarPath = path;
                break;
            }
        }
        
        String codenameOneTempPath = System.getProperty("user.home") + File.separator + ".codenameone";
        
        String designerJarPath = cssDir.getAbsolutePath() + File.separator + "designer_1.jar";
        File designerJar = new File(designerJarPath);
        if (!designerJar.exists()) {
            designerJarPath = codenameOneTempPath + File.separator + "designer_1.jar";

            designerJar = new File(designerJarPath);
            if (!designerJar.exists()) {
                throw new BuildException("Could not find designer_1.jar file at path "+designerJar);
            }
        }
        
        File javaSEJar = new File(getProject().getBaseDir(), javaSEJarPath);
        if (!javaSEJar.exists()) {
            throw new BuildException("Could not find JavaSE.jar file at path "+javaSEJar);
        }
        
        
        File cssJar = new File(codenameOneTempPath, "cn1css.jar");
        
        
        if (!cssJar.exists()) {
            try {
                exportResource("cn1css.jar", cssJar);
            } catch (IOException ex) {
                throw new BuildException("Failed to export cn1css.jar to temp directory.", ex);
            }
        }
        
        try {
            String jarChecksum = getMD5Checksum(cssJar.getAbsolutePath());
            String newChecksum = getResourceAsString(getClass(), "cn1css.jar.MD5");
            if (!jarChecksum.equals(newChecksum)) {
                exportResource("cn1css.jar", cssJar);
            }
        } catch (IOException ex) {
            throw new BuildException("Failed to get checksum for "+cssJar, ex);
        }
        
        
        
        String[] cssFiles = cssDir.list((dir, name) -> {
            return name.endsWith(".css");
            
        });
        
        Map checksums = loadChecksums();
        
        for (String cssFile : cssFiles) {
            try {
                File f = new File(cssDir, cssFile);
                File destFile = new File(srcDir, cssFile + ".res");
                if (destFile.exists() && f.lastModified() < destFile.lastModified()) {
                    log("Not compiling " + f + " because " + destFile + " has a newer modification time.");
                    
                    continue;
                }
                
                if (destFile.exists()) {
                    String checksum = getMD5Checksum(destFile.getAbsolutePath());
                    
                    String lastChecksum = checksums.get(cssFile);
                    
                    if (lastChecksum != null && !lastChecksum.equals(checksum)) {
                        throw new BuildException("The file "+destFile+" has been modified since it was last generated.  To avoid overwriting manual changes, please, delete this file and try to recompile.");
                    }
                    
                    
                }
                
                Java javaTask = (Java)getProject().createTask("java");
                Path cp = javaTask.createClasspath();
                //cp.add(new Path(getProject(), javaSEJar.getAbsolutePath()));
                cp.add(new Path(getProject(), designerJar.getAbsolutePath()));
                cp.add(new Path(getProject(), cssJar.getAbsolutePath()));
                
                javaTask.setClasspath(cp);
                javaTask.setFork(true);
                javaTask.setClassname("com.codename1.ui.css.CN1CSSCLI");
                javaTask.setFailonerror(true);
                String maxMemory = getProject().getProperty("cn1css.max.memory");
                if (maxMemory != null) {
                    javaTask.setMaxmemory("4096m");
                } else {
                    javaTask.setMaxmemory(maxMemory);
                }
                
                Argument arg = javaTask.createArg();
                arg.setValue(f.getAbsolutePath());
                
                Argument destArg = javaTask.createArg();
                destArg.setValue(destFile.getAbsolutePath());
                
                Argument swPipeline = javaTask.createJvmarg();
                swPipeline.setValue("-Dprism.order=sw");
                
                javaTask.execute();
                
                String checksum = getMD5Checksum(destFile.getAbsolutePath());
                checksums.put(cssFile, checksum);
                saveChecksums(checksums);
                

            } catch (Exception ex) {
                Logger.getLogger(CN1CSSCompileTask.class.getName()).log(Level.SEVERE, null, ex);
                throw new BuildException(ex.getMessage());
            }

        }

        super.execute(); //To change body of generated methods, choose Tools | Templates.
    }

    
    private static byte[] createChecksum(String filename) throws IOException  {
        try {
            InputStream fis =  new FileInputStream(filename);
            
            byte[] buffer = new byte[1024];
            MessageDigest complete = MessageDigest.getInstance("MD5");
            int numRead;
            
            do {
                numRead = fis.read(buffer);
                if (numRead > 0) {
                    complete.update(buffer, 0, numRead);
                }
            } while (numRead != -1);
            
            fis.close();
            return complete.digest();
        } catch (NoSuchAlgorithmException ex) {
            throw new RuntimeException(ex);
        }
   }

   // see this How-to for a faster way to convert
   // a byte array to a HEX string
   private static String getMD5Checksum(String filename) throws IOException {
       byte[] b = createChecksum(filename);
       String result = "";

       for (int i=0; i < b.length; i++) {
           result += Integer.toString( ( b[i] & 0xff ) + 0x100, 16).substring( 1 );
       }
       return result;
   }
   
   private Map loadChecksums() {
       File checkSums = getChecksumsFile();
       if (!checkSums.exists()){
           return new HashMap();
       }
       HashMap out = new HashMap();
       try {
            Scanner scanner = new Scanner(checkSums);

            //now read the file line by line...
            int lineNum = 0;
            while (scanner.hasNextLine()) {
                String line = scanner.nextLine();
                lineNum++;
                String[] parts = line.split(":");
                if (parts.length == 2) {
                    out.put(parts[0], parts[1]);
                }
            }
            return out;
        } catch(Exception e) { 
            //handle this
            return out;
        }
       
   }
   
   private File getChecksumsFile() {
       return new File(getProject().getBaseDir(), ".cn1_css_checksums");
   }
   
   private void saveChecksums(Map map) throws IOException {
        try (PrintWriter out = new PrintWriter(new FileOutputStream(getChecksumsFile()))) {
            for (String key : map.keySet()) {
                out.println(key+":"+map.get(key));
            }
        }
       
   }
   
   static void exportResource(String resourceName, File targetFile) throws IOException {
        InputStream stream = null;
        OutputStream resStreamOut = null;
        try {
            stream = CN1CSSCompileTask.class.getResourceAsStream(resourceName);//note that each / is a directory down in the "jar tree" been the jar the root of the tree
            if(stream == null) {
                throw new Exception("Cannot get resource \"" + resourceName + "\" from Jar file.");
            }

            int readBytes;
            byte[] buffer = new byte[4096];
            resStreamOut = new FileOutputStream(targetFile);
            while ((readBytes = stream.read(buffer)) > 0) {
                resStreamOut.write(buffer, 0, readBytes);
            }
        } catch (Exception ex) {
            throw new IOException(ex);
        } finally {
            stream.close();
            resStreamOut.close();
        }

    }
   
   static String getResourceAsString(Class cls, String resourceName) throws IOException {
       return new Scanner(cls.getResourceAsStream(resourceName), "UTF-8").useDelimiter("\\A").next();
   }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy