Skip to content
Snippets Groups Projects
Commit 18c0eefc authored by Nils Christian Ehmke's avatar Nils Christian Ehmke
Browse files

Classloader issue

parent acf1eb36
No related branches found
No related tags found
No related merge requests found
......@@ -38,9 +38,12 @@ import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Service;
import org.springframework.util.FileCopyUtils;
import org.springframework.util.FileSystemUtils;
import org.springframework.util.WeakReferenceMonitor;
import org.springframework.util.WeakReferenceMonitor.ReleaseListener;
......@@ -75,6 +78,7 @@ public class FSProjectDAOImpl implements IProjectDAO, ReleaseListener {
private static final String LIB_EXTENSION = "jar";
private static final String LIB_DIRECTORY = "lib";
private static final String ROOT_DIRECTORY = "data";
private static final String TEMP_DIRECTORY = "temp";
/**
* The library for kieker which is contained in the war-file as a resource.
*/
......@@ -86,6 +90,7 @@ public class FSProjectDAOImpl implements IProjectDAO, ReleaseListener {
private final MIAnalysisMetaModelFactory factory = new MAnalysisMetaModelFactory();
private final Map<CloseableURLClassLoader, WeakReference<Object>> classLoaders = new ConcurrentHashMap<CloseableURLClassLoader, WeakReference<Object>>();
private final Map<File, WeakReference<Object>> tempDirs = new ConcurrentHashMap<File, WeakReference<Object>>();
/**
* Default constructor. <b>Do not use this constructor. This bean is Spring managed.</b>
......@@ -102,13 +107,22 @@ public class FSProjectDAOImpl implements IProjectDAO, ReleaseListener {
*/
@PostConstruct
public void initialize() throws IOException {
// Check for our root-directory and create it if necessary
final File rootDir = new File(FSProjectDAOImpl.ROOT_DIRECTORY);
if (!rootDir.exists()) {
final boolean result = rootDir.mkdir();
if (!result) {
throw new IOException("Could not create root directory.");
}
// Check for the necessary directories and create them if necessary
this.checkDir(FSProjectDAOImpl.ROOT_DIRECTORY);
this.checkDir(FSProjectDAOImpl.TEMP_DIRECTORY);
}
@PreDestroy
public void destroy() throws IOException {
// Try to clear the temporary directory
FileSystemUtils.deleteRecursively(new File(FSProjectDAOImpl.TEMP_DIRECTORY));
}
private void checkDir(final String dirName) throws IOException {
final File dir = new File(dirName);
if (!dir.exists() && !dir.mkdir()) {
// Try to create the directory
throw new IOException("Could not create directory '" + dirName + "'.");
}
}
......@@ -366,18 +380,20 @@ public class FSProjectDAOImpl implements IProjectDAO, ReleaseListener {
throw new ProjectNotExistingException("A project with the name '" + projectName + "' does not exist.");
}
// Create a new temporary directory
final File tempDir = this.createTemporaryDirectory();
final List<URL> libs = new ArrayList<URL>();
// Collect all libraries of the project
// Run through the libs and put them into our list.
// Copy and collect all libraries of the project
final File libDir = new File(FSProjectDAOImpl.ROOT_DIRECTORY + File.separator + projectName + File.separator + FSProjectDAOImpl.LIB_DIRECTORY);
final File[] files = libDir.listFiles();
if (files != null) {
for (final File file : files) {
if (file.getName().endsWith("." + FSProjectDAOImpl.LIB_EXTENSION)) {
final File newLibFile = new File(tempDir, file.getName());
FileCopyUtils.copy(file, newLibFile);
try {
libs.add(file.toURI().toURL());
libs.add(newLibFile.toURI().toURL());
} catch (final MalformedURLException ex) {
ex.printStackTrace();
}
......@@ -393,12 +409,25 @@ public class FSProjectDAOImpl implements IProjectDAO, ReleaseListener {
final CloseableURLClassLoader classLoader = AccessController.doPrivileged(action);
// Remember the requester
this.classLoaders.put(classLoader, new WeakReference<Object>(requester));
final WeakReference<Object> ref = new WeakReference<Object>(requester);
this.classLoaders.put(classLoader, ref);
this.tempDirs.put(tempDir, ref);
WeakReferenceMonitor.monitor(requester, this);
return classLoader;
}
private File createTemporaryDirectory() {
int counter = 0;
File tempDir;
do {
tempDir = new File(FSProjectDAOImpl.TEMP_DIRECTORY, "temp" + counter);
counter++;
} while (!tempDir.mkdir());
return tempDir;
}
/*
* (non-Javadoc)
*
......@@ -614,16 +643,24 @@ public class FSProjectDAOImpl implements IProjectDAO, ReleaseListener {
synchronized (this.classLoaders) {
int open = 0;
final List<CloseableURLClassLoader> toBeRemoved = new ArrayList<CloseableURLClassLoader>();
final List<CloseableURLClassLoader> toBeClosed = new ArrayList<CloseableURLClassLoader>();
final List<File> toBeRemoved = new ArrayList<File>();
// Run through the class loaders and check which of them can be closed
for (final Entry<CloseableURLClassLoader, WeakReference<Object>> entry : this.classLoaders.entrySet()) {
if (entry.getValue().get() == null) {
toBeRemoved.add(entry.getKey());
toBeClosed.add(entry.getKey());
} else {
open++;
}
}
for (final CloseableURLClassLoader classLoader : toBeRemoved) {
for (final Entry<File, WeakReference<Object>> entry : this.tempDirs.entrySet()) {
if (entry.getValue().get() == null) {
toBeRemoved.add(entry.getKey());
}
}
for (final CloseableURLClassLoader classLoader : toBeClosed) {
try {
classLoader.close();
this.classLoaders.remove(classLoader);
......@@ -632,6 +669,15 @@ public class FSProjectDAOImpl implements IProjectDAO, ReleaseListener {
FSProjectDAOImpl.LOG.error("Could not close classloader (" + classLoader + ")");
}
}
for (final File tempDir : toBeRemoved) {
final boolean result = FileSystemUtils.deleteRecursively(tempDir);
if (result) {
this.tempDirs.remove(tempDir);
FSProjectDAOImpl.LOG.info("Removed temporary directory (" + tempDir + ")");
} else {
FSProjectDAOImpl.LOG.error("Could not remove temporary directory (" + tempDir + ")");
}
}
FSProjectDAOImpl.LOG.info(open + " classloaders still open.");
}
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment