/*
* (c) Copyright 2010-2011 AgileBirds
*
* This file is part of OpenFlexo.
*
* OpenFlexo is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* OpenFlexo is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenFlexo. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.openflexo.foundation.dm;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.openflexo.foundation.FlexoException;
import org.openflexo.foundation.rm.FlexoJarResource;
import org.openflexo.foundation.rm.FlexoProject;
import org.openflexo.foundation.rm.FlexoResource;
import org.openflexo.foundation.rm.ImportedResourceData;
import org.openflexo.foundation.rm.RMNotification;
import org.openflexo.foundation.rm.SaveResourceException;
import org.openflexo.foundation.utils.FlexoProgress;
import org.openflexo.localization.FlexoLocalization;
import com.google.common.base.Predicate;
import com.google.common.collect.Maps;
/**
* Please comment this class
*
* @author sguerin
*
*/
public class JarLoader implements ImportedResourceData {
static final Logger logger = Logger.getLogger(JarLoader.class.getPackage().getName());
JarFile jarFile;
private Manifest manifest;
Set<String> classNames = new HashSet<String>();
private JarClassLoader classLoader;
private FlexoJarResource _jarResource;
private final FlexoProject project;
ExternalRepository getJarRepository() {
if (_jarResource != null) {
return _jarResource.getJarRepository();
}
return null;
}
public JarLoader(File aJarFile, FlexoJarResource jarResource, FlexoProject project) {
this(aJarFile, jarResource != null ? jarResource.getJarRepository() : null, jarResource, project, null);
}
public JarLoader(File aJarFile, ExternalRepository jarRepository, FlexoProject project) {
this(aJarFile, jarRepository, jarRepository != null ? jarRepository.getJarResource() : null, project, null);
}
public JarLoader(File aJarFile, FlexoJarResource jarResource, FlexoProject project, FlexoProgress progress) {
this(aJarFile, jarResource != null ? jarResource.getJarRepository() : null, jarResource, project, progress);
}
public JarLoader(File aJarFile, ExternalRepository jarRepository, FlexoProject project, FlexoProgress progress) {
this(aJarFile, jarRepository, jarRepository != null ? jarRepository.getJarResource() : null, project, progress);
}
private JarLoader(File aJarFile, ExternalRepository jarRepository, FlexoJarResource jarResource, FlexoProject project,
FlexoProgress progress) {
super();
_jarResource = jarResource;
this.project = project;
classLoader = getProject().getJarClassLoader();
try {
jarFile = new JarFile(aJarFile);
if (logger.isLoggable(Level.INFO)) {
logger.info("Loading jar file " + aJarFile.getAbsolutePath());
}
manifest = jarFile.getManifest();
loadJarFile(progress);
} catch (IOException e) {
if (logger.isLoggable(Level.WARNING)) {
logger.warning("Could not open file " + aJarFile.getAbsolutePath());
}
}
}
public void delete() {
if (classLoader != null) {
// Actually I don't think this is needed as the deletion of the LoadableDMEntities should already do that
// But let's just be sure.
classLoader.unloadClasses(new ArrayList<String>(classNames));
}
classNames = null;
_jarResource = null;
classLoader = null;
jarFile = null;
manifest = null;
}
public boolean contains(String className) {
return getContainedClasses().containsKey(className);
}
public Map<String, Class<?>> getContainedClasses() {
return Maps.filterKeys(classLoader.getClassForClassName(), new Predicate<String>() {
@Override
public boolean apply(String input) {
return classNames.contains(input);
}
});
}
public Class<?> getClassForName(String aName) {
return getContainedClasses().get(aName);
}
private void loadJarFile(FlexoProgress progress) {
logger.info("**************** load JAR file " + jarFile.getName());
if (logger.isLoggable(Level.FINE)) {
logger.fine("Manifest: " + manifest + "\n" + manifest.getEntries());
}
if (progress != null) {
progress.setProgress(FlexoLocalization.localizedForKey("loading_class_definitions"));
progress.resetSecondaryProgress(jarFile.size());
}
List<JarEntry> jarEntries = new ArrayList<JarEntry>();
for (Enumeration<JarEntry> en = jarFile.entries(); en.hasMoreElements();) {
JarEntry entry = en.nextElement();
if (progress != null) {
progress.setSecondaryProgress(FlexoLocalization.localizedForKey("loading_and_parsing") + " " + entry.getName());
}
if (isClassFile(entry.getName())) {
jarEntries.add(entry);
} else {
if (logger.isLoggable(Level.FINE)) {
logger.fine("Entry " + entry.getName());
}
}
}
int i = 0;
for (JarEntry entry : jarEntries) {
Class<?> loadedClass = classLoader.findClass(jarFile, entry);
if (loadedClass != null) {
classNames.add(loadedClass.getName());
i++;
if (logger.isLoggable(Level.FINE)) {
logger.fine("Loaded " + loadedClass.getName());
}
}
}
if (logger.isLoggable(Level.INFO)) {
logger.info("Loaded " + i + " classes.");
}
}
boolean isClassFile(String jarentryname) {
return jarentryname.endsWith(".class") && !jarentryname.startsWith("WebServerResources/");
}
public FlexoJarResource getJarResource() {
return _jarResource;
}
@Override
public FlexoJarResource getFlexoResource() {
return getJarResource();
}
@Override
public void setFlexoResource(FlexoResource resource) {
_jarResource = (FlexoJarResource) resource;
}
@Override
public FlexoProject getProject() {
return project;
}
// Degager tout ce qu'il y a en dessous
public void save() throws SaveResourceException {
// TODO Auto-generated method stub
}
public void setIsModified() {
// TODO Auto-generated method stub
}
public void clearIsModified() {
// TODO Auto-generated method stub
}
public boolean isModified() {
// TODO Auto-generated method stub
return false;
}
public Date lastMemoryUpdate() {
// TODO Auto-generated method stub
return null;
}
public void notifyRM(RMNotification notification) throws FlexoException {
// TODO Auto-generated method stub
}
public void receiveRMNotification(RMNotification notification) throws FlexoException {
// TODO Auto-generated method stub
}
/*public ExternalRepository getJarRepository() {
return _jarRepository;
}*/
}