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);
}
}
}
}
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());
}
}
Aggregations