blob: 6aa475059a20b4df7cd5437f5eb858dbf717b19f [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.myfaces.extensions.scripting.cdi.context;
import org.apache.myfaces.extensions.scripting.cdi.compiler.CompilationException;
import org.apache.myfaces.extensions.scripting.cdi.compiler.CompilationResult;
import org.apache.myfaces.extensions.scripting.cdi.compiler.Compiler;
import org.apache.myfaces.extensions.scripting.cdi.loaders.ReloadingClassLoader;
import org.apache.myfaces.extensions.scripting.cdi.monitor.resources.Resource;
import org.apache.myfaces.extensions.scripting.cdi.monitor.resources.ResourceMonitor;
import java.io.File;
import java.util.Stack;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
*/
public class CompilationResourceMonitor implements ResourceMonitor {
private static final Logger logger = Logger.getLogger(CompilationResourceMonitor.class.getName());
private ReloadingClassLoader classLoader;
private Compiler compiler;
private File sourcePath;
private File targetPath;
// -------------------------------------- Constructors
public CompilationResourceMonitor(
ReloadingClassLoader classLoader, Compiler compiler, File sourcePath, File targetPath) {
this.classLoader = classLoader;
this.compiler = compiler;
this.sourcePath = sourcePath;
this.targetPath = targetPath;
}
// -------------------------------------- ResourceMonitor methods
@Override
public boolean resourceModified(Resource resource) {
try {
File file = resource.getFile();
if (logger.isLoggable(Level.INFO)) {
logger.info("Found a more recent source file '"
+ file.getName() + "' which the compilation monitor will compile now.");
}
CompilationResult result = compiler.compile(sourcePath, targetPath, file, classLoader);
if (result.hasErrors()) {
logger.severe("An error occurred while compiling the source file '"
+ file.getAbsolutePath() + "': Errors: '" + result.getErrors());
} else {
String className = buildClassName(sourcePath, file);
if (logger.isLoggable(Level.INFO)) {
logger.info("The reloading class loader is going to be told to reloaded the class '"
+ className + "'.");
}
classLoader.reloadClass(className);
}
} catch (CompilationException ex) {
logger.log(Level.SEVERE, "An error occurred while compiling the source file '" + resource + "'.", ex);
}
return true;
}
// ------------------------------------------ Utility methods
/**
* <p>Builds the name of a class given the relative location of its source file, i.e.
* if you've got the source file com/acme/Test.java this method will tell you that
* the name of the class is "com.acme.Test". In order to specify the relative location
* of the source file, you have to provide two absolute paths: the path to the source
* file and the path to the root source path.</p>
*
* @param rootSourcePath the root source path containing all Java source files
* @param sourceFile the Java source file containing the class you want to retrieve the name for
*
* @return the name of the class that the given source file contains
*/
private String buildClassName(File rootSourcePath, File sourceFile) {
Stack classNameElements = new Stack();
// At first strip the ".java" extension from the file name.
classNameElements.push(
sourceFile.getName().substring(0, sourceFile.getName().indexOf(".java")));
// Walk up the hierarchy and save the directory names in a stack.
sourceFile = sourceFile.getParentFile();
while (!rootSourcePath.equals(sourceFile)) {
classNameElements.push(sourceFile.getName());
sourceFile = sourceFile.getParentFile();
}
// Pop one directory name after another from the stack to determine the class name.
StringBuffer className = new StringBuffer();
while (!classNameElements.empty()) {
className.append(classNameElements.pop());
// If we're dealing with the last element we shouldn't add the "." anymore,
// otherwise we'll end up with a class name like "com.acme.Test."
if (!classNameElements.empty()) {
className.append(".");
}
}
return className.toString();
}
}