Search in sources :

Example 1 with GroovityClassListener

use of com.disney.groovity.compile.GroovityClassListener in project groovity by disney.

the class Groovity method loadClasses.

// for first-time load ONLY
protected void loadClasses(boolean init) throws IOException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
    HashMap<String, Collection<String>> newScriptDependencies = new HashMap<String, Collection<String>>();
    Map<String, Boolean> newScriptInits = new HashMap<String, Boolean>();
    // first, look on classpath for packaged groovity scripts
    ClassLoader loader = parentLoader;
    if (loader == null) {
        loader = Thread.currentThread().getContextClassLoader();
    }
    long time1 = System.currentTimeMillis();
    int manifestCount = 0;
    List<String[]> manifestLines = new ArrayList<>();
    Enumeration<URL> classpathJarManifests = loader.getResources(GROOVITY_JAR_MANIFEST);
    while (classpathJarManifests.hasMoreElements()) {
        URL manifest = classpathJarManifests.nextElement();
        if (log.isLoggable(Level.FINEST)) {
            log.finest("Found groovity manifest " + manifest);
        }
        String baseUrl = manifest.toString();
        baseUrl = baseUrl.substring(0, baseUrl.length() - 8);
        String jarName = baseUrl;
        int bang = jarName.indexOf("!");
        if (bang > 0) {
            jarName = jarName.substring(0, bang);
        }
        int slash = jarName.lastIndexOf("/");
        if (slash > 0) {
            jarName = jarName.substring(slash + 1);
        }
        try {
            BufferedReader reader = new BufferedReader(new InputStreamReader(manifest.openStream(), "UTF-8"));
            try {
                String line;
                while ((line = reader.readLine()) != null) {
                    if (line != null && !line.isEmpty()) {
                        manifestLines.add(new String[] { baseUrl, line });
                    }
                }
            } finally {
                reader.close();
            }
        } catch (Exception e) {
            log.log(Level.SEVERE, "Error loading groovity from mainfest", e);
        }
        manifestCount++;
    }
    int lastLineCount = manifestLines.size() + 1;
    Map<String, Throwable> loadErrors = new HashMap<>();
    int count = 0;
    while (!manifestLines.isEmpty() && (manifestLines.size() < lastLineCount)) {
        lastLineCount = manifestLines.size();
        Iterator<String[]> manifestIterator = manifestLines.iterator();
        while (manifestIterator.hasNext()) {
            String[] manifestLine = manifestIterator.next();
            String baseUrl = manifestLine[0];
            String line = manifestLine[1];
            String sourcePath = "/".concat(line.substring(0, line.length() - 4));
            try {
                URL grvtJar = new URL(baseUrl.concat(line));
                URLConnection conn = grvtJar.openConnection();
                long modTime = conn.getLastModified();
                InputStream jarStream = conn.getInputStream();
                try {
                    loadClasses(sourcePath, jarStream, modTime, true, newScriptDependencies, newScriptInits);
                    count++;
                } finally {
                    jarStream.close();
                }
                if (log.isLoggable(Level.FINEST)) {
                    log.finest("Loaded " + sourcePath + " from " + baseUrl);
                }
                manifestIterator.remove();
                loadErrors.remove(sourcePath);
            } catch (Throwable e) {
                loadErrors.put(sourcePath, e);
            // we will retry in the loop to recover from dependency ordering issues
            }
        }
    }
    if (count > 0) {
        log.info("Loaded " + count + " embedded scripts from " + manifestCount + " manifest files in " + (System.currentTimeMillis() - time1));
    }
    if (!loadErrors.isEmpty()) {
        log.severe("There were " + loadErrors.size() + " errors loading manifest scripts ");
        loadErrors.entrySet().stream().forEach(entry -> {
            log.log(Level.SEVERE, entry.getKey(), entry.getValue());
        });
    }
    // next, load from app jar directory
    if (jarPhases != null && jarPhases.contains(GroovityPhase.STARTUP) && jarDirectory != null && jarDirectory.isDirectory()) {
        List<File> jarList = new ArrayList<>();
        findJarFiles(jarDirectory, jarList);
        if (!jarList.isEmpty()) {
            long jarStart = System.currentTimeMillis();
            Map<String, Throwable> jarErrors = new HashMap<>();
            int loadedJars = 0;
            int lastJarCount = jarList.size() + 1;
            while (!jarList.isEmpty() && (jarList.size() < lastJarCount)) {
                lastJarCount = jarList.size();
                Iterator<File> jarIter = jarList.iterator();
                while (jarIter.hasNext()) {
                    File j = jarIter.next();
                    String path = j.getPath();
                    try {
                        loadClasses(j, newScriptDependencies, newScriptInits);
                        jarIter.remove();
                        jarErrors.remove(path);
                        loadedJars++;
                    } catch (Throwable e) {
                        jarErrors.put(path, e);
                    }
                }
            }
            if (!jarErrors.isEmpty()) {
                log.severe("There were " + jarErrors.size() + " errors loading jar files ");
                jarErrors.entrySet().stream().forEach(entry -> {
                    log.log(Level.SEVERE, entry.getKey(), entry.getValue());
                });
            }
            if (loadedJars > 0) {
                log.info("Loaded " + count + " jar files in " + (System.currentTimeMillis() - jarStart));
            }
        }
    }
    List<String> sortedScripts = sortDependencies(newScriptDependencies, newScriptInits);
    for (String scriptName : sortedScripts) {
        Class<Script> theClass = getScriptClass(scriptName);
        if (init) {
            initClass(theClass);
        }
        if (listeners != null) {
            for (GroovityClassListener listener : listeners) {
                listener.scriptUpdated(this, scriptName, theClass);
            }
        }
    }
}
Also used : LinkedHashMap(java.util.LinkedHashMap) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) HashMap(java.util.HashMap) CopyOnWriteArrayList(java.util.concurrent.CopyOnWriteArrayList) ArrayList(java.util.ArrayList) URL(java.net.URL) GroovyClassLoader(groovy.lang.GroovyClassLoader) GroovityClassLoader(com.disney.groovity.compile.GroovityClassLoader) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) GroovityClassListener(com.disney.groovity.compile.GroovityClassListener) Script(groovy.lang.Script) InputStreamReader(java.io.InputStreamReader) JarInputStream(java.util.jar.JarInputStream) FileInputStream(java.io.FileInputStream) InputStream(java.io.InputStream) InvocationTargetException(java.lang.reflect.InvocationTargetException) IOException(java.io.IOException) FileNotFoundException(java.io.FileNotFoundException) URLConnection(java.net.URLConnection) BufferedReader(java.io.BufferedReader) Collection(java.util.Collection) File(java.io.File)

Example 2 with GroovityClassListener

use of com.disney.groovity.compile.GroovityClassListener in project groovity by disney.

the class Groovity method compile.

/**
 * Compare the timestamp of the source against an existing compiled version, only recompiling
 * if they do not match.  The force parameter is used to force a recompile regardless of dates.
 *
 * @param sources
 * @param force
 */
@SuppressWarnings("rawtypes")
protected void compile(boolean force, boolean init, ConcurrentHashMap<String, Class> compilerTraits, GroovitySource... sources) {
    // take multiple sources and compile as a set, only initing() classes once all are loaded
    HashMap<String, Class<Script>> newScripts = new HashMap<String, Class<Script>>();
    HashMap<String, Long> newScriptDates = new HashMap<String, Long>();
    HashMap<String, File> deletedScripts = new HashMap<String, File>();
    HashMap<String, Collection<String>> scriptDependencies = new HashMap<String, Collection<String>>();
    HashMap<String, Boolean> scriptInits = new HashMap<String, Boolean>();
    compileLoop(newScripts, newScriptDates, deletedScripts, scriptDependencies, scriptInits, force, init, 0, compilerTraits, sources);
    List<Class<Script>> toDestroy = new ArrayList<Class<Script>>();
    HashSet<String> sourceNames = new HashSet<>();
    for (GroovitySource source : sources) {
        sourceNames.add(getScriptName(source.getPath()));
    }
    List<String> sortedScripts = sortDependencies(scriptDependencies, scriptInits);
    // load order for dependencies!
    for (String scriptName : sortedScripts) {
        String scriptNameFixed = fixCase(scriptName);
        Class<Script> theClass = newScripts.get(scriptName);
        if (init) {
            initClass(theClass);
        }
        scriptDates.put(scriptNameFixed, newScriptDates.get(scriptName));
        Class<Script> oldClass = scripts.put(scriptNameFixed, theClass);
        if (listeners != null) {
            for (GroovityClassListener listener : listeners) {
                listener.scriptUpdated(this, scriptName, theClass);
            }
        }
        if (oldClass != null) {
            toDestroy.add(oldClass);
        } else if (embeddedScripts.containsKey(scriptNameFixed)) {
            toDestroy.add(embeddedScripts.get(scriptNameFixed));
        }
    }
    for (Map.Entry<String, File> deleted : deletedScripts.entrySet()) {
        String name = deleted.getKey();
        String nameCaseFixed = fixCase(name);
        Class<Script> oldClass = scripts.remove(nameCaseFixed);
        scriptDates.remove(nameCaseFixed);
        // notify listeners
        if (listeners != null) {
            for (GroovityClassListener listener : listeners) {
                listener.scriptDeleted(name);
            }
        }
        if (oldClass != null) {
            log.info("Deleting removed source " + name + " / class " + oldClass.getName());
            toDestroy.add(oldClass);
            Class<Script> embeddedClass = embeddedScripts.get(nameCaseFixed);
            if (embeddedClass != null && init) {
                initClass(embeddedClass);
                newScripts.put(nameCaseFixed, embeddedClass);
            }
        }
        if (deleted.getValue() != null) {
            deleted.getValue().delete();
        }
    }
    if (init) {
        // now destroy
        for (Class<Script> del : toDestroy) {
            ((GroovityClassLoader) del.getClassLoader()).destroy();
        }
        if (started.get()) {
            // now start new scripts
            newScripts.values().forEach(cls -> {
                startClass(cls);
            });
        }
    }
    Map<String, Throwable> errors = new LinkedHashMap<String, Throwable>();
    for (Entry<String, GroovityCompilerEvent> entry : getCompilerEvents().entrySet()) {
        if (entry.getValue().getError() != null) {
            if (sourceNames.contains(entry.getKey())) {
                errors.put(entry.getKey(), entry.getValue().getError());
            }
        }
    }
    if (errors.size() > 0) {
        StringBuilder messageBuilder = new StringBuilder(String.valueOf(errors.size())).append(" script");
        if (errors.size() > 1) {
            messageBuilder.append("s");
        }
        messageBuilder.append(" failed to compile");
        for (Entry<String, Throwable> entry : errors.entrySet()) {
            messageBuilder.append(LINE_SEPARATOR);
            messageBuilder.append(LINE_SEPARATOR);
            messageBuilder.append("Error compiling ").append(entry.getKey()).append(".grvt :");
            messageBuilder.append(LINE_SEPARATOR);
            messageBuilder.append(LINE_SEPARATOR);
            messageBuilder.append(entry.getValue().getMessage());
        }
        log.severe(messageBuilder.toString());
    }
}
Also used : LinkedHashMap(java.util.LinkedHashMap) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) HashMap(java.util.HashMap) CopyOnWriteArrayList(java.util.concurrent.CopyOnWriteArrayList) ArrayList(java.util.ArrayList) LinkedHashMap(java.util.LinkedHashMap) GroovitySource(com.disney.groovity.source.GroovitySource) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) GroovityCompilerEvent(com.disney.groovity.compile.GroovityCompilerEvent) HashSet(java.util.HashSet) GroovityClassListener(com.disney.groovity.compile.GroovityClassListener) Script(groovy.lang.Script) GroovityClassLoader(com.disney.groovity.compile.GroovityClassLoader) Collection(java.util.Collection) GroovyClass(org.codehaus.groovy.tools.GroovyClass) File(java.io.File) Map(java.util.Map) LinkedHashMap(java.util.LinkedHashMap) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) HashMap(java.util.HashMap)

Aggregations

GroovityClassListener (com.disney.groovity.compile.GroovityClassListener)2 GroovityClassLoader (com.disney.groovity.compile.GroovityClassLoader)2 Script (groovy.lang.Script)2 File (java.io.File)2 ArrayList (java.util.ArrayList)2 Collection (java.util.Collection)2 HashMap (java.util.HashMap)2 LinkedHashMap (java.util.LinkedHashMap)2 ConcurrentHashMap (java.util.concurrent.ConcurrentHashMap)2 CopyOnWriteArrayList (java.util.concurrent.CopyOnWriteArrayList)2 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)2 GroovityCompilerEvent (com.disney.groovity.compile.GroovityCompilerEvent)1 GroovitySource (com.disney.groovity.source.GroovitySource)1 GroovyClassLoader (groovy.lang.GroovyClassLoader)1 BufferedReader (java.io.BufferedReader)1 FileInputStream (java.io.FileInputStream)1 FileNotFoundException (java.io.FileNotFoundException)1 IOException (java.io.IOException)1 InputStream (java.io.InputStream)1 InputStreamReader (java.io.InputStreamReader)1