/*
* $Id: IWModuleLoader.java,v 1.11 2008/10/23 12:25:51 valdas Exp $ Created on
* 31.5.2005 in project com.idega.core
*
* Copyright (C) 2005 Idega Software hf. All Rights Reserved.
*
* This software is the proprietary information of Idega hf. Use is subject to
* license terms.
*/
package com.idega.idegaweb;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.jar.JarFile;
import java.util.logging.Logger;
import javax.servlet.ServletContext;
/**
* <p>
* This is the class responsible for loading the bundles (the new jar method)
* for the IWMainApplication instance.
* </p>
* Last modified: $Date: 2008/10/23 12:25:51 $ by $Author: valdas $
*
* @author <a href="mailto:tryggvil@idega.com">tryggvil</a>
* @version $Revision: 1.11 $
*/
public class IWModuleLoader {
private static final Logger LOGGER = Logger.getLogger(IWBundleLoader.class.getName());
IWMainApplication iwma;
//ServletContext _externalContext;
private List<JarLoader> jarLoaders;
public static final String DEFAULT_LIB_PATH = "/WEB-INF/lib/";
/**
* @deprecated
* There is no need to send ServletContext. Instead of it can be used iwma.getServletContext().
*/
public IWModuleLoader(IWMainApplication iwma, ServletContext sContext) {
this(iwma);
}
public IWModuleLoader(IWMainApplication iwma) {
this.iwma = iwma;
}
/**
* Tries to load a bundle from a jar, it assumes that the jar file-name begins with the bundleIdentifier
*/
public void tryBundleLoad(String bundleIdentifier){
Set jars = getJarSet();
if (jars != null) {
for (Iterator it = jars.iterator(); it.hasNext();) {
String path = (String) it.next();
String pathMinusPrefix = path.substring(DEFAULT_LIB_PATH.length(),path.length());
if (pathMinusPrefix.startsWith(bundleIdentifier)&&pathMinusPrefix.toLowerCase().endsWith(".jar")) {
loadJar(path);
}
}
}
}
public void loadBundlesFromJars() {
Set jars = getJarSet();
if (jars != null) {
for (Iterator it = jars.iterator(); it.hasNext();) {
String path = (String) it.next();
if (path.toLowerCase().endsWith(".jar")) {
loadJar(path);
}
}
}
}
protected Set getJarSet(){
// Set jars = getExternalContext().getResourcePaths(defaultLibPath);
Set jars = iwma.getResourcePaths(DEFAULT_LIB_PATH);
return jars;
}
/**
* <p>
* Loads jar file from path
* </p>
* @param path
*/
protected void loadJar(String path) {
// feedJarConfig(path);
try {
File file = getJarFile(path);
JarFile jarFile = new JarModule(file);
loadJar(file, jarFile, path);
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public boolean containerExpandsWebapp() {
// TODO: Implement this container portable
return true;
}
/**
* Loads jar file with each defined jarLoader
*
* @param bundleJarFile
* @param jarFile
* @param jarPath
*/
public void loadJar(File bundleJarFile, JarFile jarFile, String jarPath) {
List<JarLoader> loaders = getJarLoaders();
if (loaders.isEmpty()) {
LOGGER.warning("No Jar Loaders defined");
return;
}
for (Iterator<JarLoader> iter = loaders.iterator(); iter.hasNext();) {
iter.next().loadJar(bundleJarFile, jarFile, jarPath);
}
}
/**
* <p>
* Gets the jar file in a container portable way
* </p>
*
* @param jarPath
* @return
* @throws IOException
*/
private File getJarFile(String jarPath) throws IOException {
// try {
// not all containers expand archives, so we have to do it the
// generic way:
//1. If the container allows to read the jar file directly:
if (containerExpandsWebapp()) {
String webappDir = this.iwma.getApplicationRealPath();
//File webappDir = new File(iwma.getRealPath("/"));
File file = new File(webappDir,jarPath);
return file;
}
// 2. get the stream from external context
else {
// InputStream in = getExternalContext().getResourceAsStream(jarPath);
InputStream in = iwma.getResourceAsStream(jarPath);
if (in == null) {
if (jarPath.startsWith("/")) {
// in = getExternalContext().getResourceAsStream(jarPath.substring(1));
in = iwma.getResourceAsStream(jarPath.substring(1));
}
else {
// in = getExternalContext().getResourceAsStream("/" + jarPath);
in = iwma.getResourceAsStream("/" + jarPath);
}
}
if (in == null) {
LOGGER.warning("Resource " + jarPath + " not found in webapp archive");
return null;
}
// 2. search the jar stream for META-INF/faces-config.xml
// JarInputStream jar = new JarInputStream(in);
// JarEntry entry = jar.getNextJarEntry();
/*
* boolean found = false;
*
* while (entry != null) { if
* (entry.getName().equals("properties/bundle.pxml")) { if
* (log.isDebugEnabled()) log.debug("bundle.pxml found in " +
* jarPath); found = true; break; } entry =
* jar.getNextJarEntry(); } jar.close();
*/
File tmp = null;
// 3. if properties/bundle.pxml was found, extract the jar and
// copy it to a temp file; hand over the temp file
// to the parser and delete it afterwards
// if (found)
// {
tmp = File.createTempFile("idegaweb", ".jar");
FileOutputStream out = new FileOutputStream(tmp);
byte[] buffer = new byte[4096];
int r;
while ((r = in.read(buffer)) != -1) {
out.write(buffer, 0, r);
}
out.close();
/*
* JarFile jarFile = new JarFile(tmp); try {
* } finally { jarFile.close(); tmp.delete(); }
*/
// } else
// {
// if (log.isDebugEnabled()) log.debug("Jar " + jarPath + "
// contains no faces-config.xml");
// }
return tmp;
}
// }
// catch (Exception e) {
// throw new FacesException(e);
// }
}
/**
* @return Returns the jarLoaders.
*/
public List<JarLoader> getJarLoaders() {
if(this.jarLoaders==null){
this.jarLoaders = new ArrayList<JarLoader>();
}
return this.jarLoaders;
}
/**
* @param jarLoaders The jarLoaders to set.
*/
public void setJarLoaders(List<JarLoader> jarLoaders) {
this.jarLoaders = jarLoaders;
}
}