![JAR search and dependency download from the Maven repository](/logo.png)
at.spardat.xma.boot.fdm.FastDevelopmentLoader Maven / Gradle / Ivy
/*
* @(#) $Id: $
*
* Copyright 2004/2005 by SPARDAT Sparkassen-Datendienst Ges.m.b.H.,
* A-1110 Wien, Geiselbergstr.21-25.
* All rights reserved.
*
*/
package at.spardat.xma.boot.fdm;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.util.Properties;
import at.spardat.xma.boot.comp.data.XMAComponent;
import at.spardat.xma.boot.logger.LogLevel;
import at.spardat.xma.boot.logger.Logger;
/**
* FastDevelopmentLoader provides the XMA-BootRuntime with a way for loading
* client side components without the need of a build and deployment of client-component-jar-files.
* The class files of the client side component are copied directly from the classes directory
* of the project into a directory which can be added to the XMA application classloader.
*
* To use FastDevelopmentLoader, you have to add it to the classpath of XMA-BootRuntime.
* The FastDevelopmentLoader is activated by setting the following property in bootcfg.properties:
* boot.fdm=true
*
This activation works only for XMA applications loaded from localhost.
*
* The classes directory can be configured with the following property in bootcfg.properties:
* boot.fdm.classes
*
Default is the classes directory of the current project.
*
* The cache directory of the "downloaded" class files can be configured
* with the following property in bootcfg.properties:
* boot.fdm.cache
*
If this property is empty or omitted, the classes will be loaded directly from
* the directory boot.fdm.classes. In this case no strict separation between
* the classes of different components is enforced.
*
* @author s2877
*/
public class FastDevelopmentLoader {
String classDir;
String fdmCacheDir;
Logger logger = Logger.getLogger("boot.fdm");
/**
* Constructs a FastDevelopmentLoader
* @param props which may contain the following properties:
* boot.fdm.classes and boot.fdm.cache. (see above)
* If these properties are not contained defaults are used.
* Additional properties are ignored.
*/
public FastDevelopmentLoader(Properties props) {
classDir = props.getProperty("boot.fdm.classes");
logger.log(LogLevel.CONFIG, "boot.fdm.classes: " + classDir);
if(classDir==null) {
classDir = System.getProperty("user.dir")+"/classes";
logger.log(LogLevel.CONFIG, "boot.fdm.classes default value: " + classDir);
}
fdmCacheDir = props.getProperty("boot.fdm.cache");
logger.log(LogLevel.CONFIG, "boot.fdm.cache: " + fdmCacheDir);
}
public boolean useComponentCache() {
return fdmCacheDir != null;
}
public String getClassDir() {
return classDir;
}
/**
* If a cache directory is specified,
* copy the class files of the client side package of the given component from
* the classes directory into the fdm cache. Both directories can be customized
* using the properties boot.fdm.classes and boot.fdm.cache.
* If no cache directory is specified, the classes are directly loaded from the
* directory boot.fdm.classes.
*/
public void loadComponent(XMAComponent component) throws IOException {
URL fdmUrl = null;
if (useComponentCache()) {
String strPackage = component.getImplPackage_();
strPackage = strPackage.replace('.', '/');
File sourcePackage = new File(classDir,strPackage);
File targetClasses = new File(fdmCacheDir,component.getName_());
File targetPackage = new File(targetClasses,strPackage);
updateDir(sourcePackage, targetPackage);
fdmUrl = targetClasses.toURL();
logger.log(LogLevel.FINE, "Loading package '" + strPackage + "' from: " + fdmUrl);
}
component.setFdmUrl(fdmUrl);
}
/**
* Copy all newer files of the source directory and all its subdirectories, except directories
* namded "server", to the target directory. The timestamps of the files and directories are preserved.
*/
public void updateDir(File source, File target) throws IOException {
if("server".equals(source.getName())) return;
if(!source.exists()) throw new FileNotFoundException(source.getAbsolutePath());
if(!target.exists()) {
boolean success = target.mkdirs();
if(!success) throw new IOException("error creating "+target.getAbsolutePath());
}
File[] files = source.listFiles();
for(int i=0;i=source.lastModified()) return;
FileInputStream in = null;
FileOutputStream out= null;
try {
in = new FileInputStream(source);
out= new FileOutputStream(target);
byte[] buffer = new byte[64*1024];
for(int size=in.read(buffer);size>0;size=in.read(buffer)) {
out.write(buffer,0,size);
}
} finally {
if(in!=null) try { in.close(); } catch(IOException e) {}
if(out!=null) try { out.close(); } catch(IOException e) {}
}
// reset modification timestamp
target.setLastModified(source.lastModified());
}
}