/*
* (C) Copyright 2006-2011 Nuxeo SA (http://nuxeo.com/) and others.
*
* Licensed 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.
*
* Contributors:
* bstefanescu
*
* $Id$
*/
package org.nuxeo.osgi.application;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.jar.JarFile;
import org.nuxeo.osgi.BundleFile;
import org.nuxeo.osgi.DirectoryBundleFile;
import org.nuxeo.osgi.JarBundleFile;
import org.osgi.framework.BundleException;
/**
* @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
*/
public class ApplicationBundleLoader {
protected StandaloneBundleLoader bundleLoader;
protected final StandaloneApplication app;
protected boolean useCache = false;
protected boolean extractNestedJARs = true;
protected boolean scanForNestedJARs = true;
public ApplicationBundleLoader(StandaloneApplication app) {
this(app, false);
}
public ApplicationBundleLoader(StandaloneApplication app, boolean useCache) {
this.app = app;
bundleLoader = new StandaloneBundleLoader(app);
this.useCache = useCache;
}
public void setScanForNestedJARs(boolean scanForNestedJARs) {
this.scanForNestedJARs = scanForNestedJARs;
}
public boolean getScanForNestedJARs() {
return scanForNestedJARs;
}
public void setExtractNestedJARs(boolean extractNestedJARs) {
this.extractNestedJARs = extractNestedJARs;
}
public boolean getExtractNestedJARs() {
return extractNestedJARs;
}
public void setUseCache(boolean useCache) {
this.useCache = useCache;
}
public boolean getUseCache() {
return useCache;
}
public StandaloneBundleLoader getBundleLoader() {
return bundleLoader;
}
public File getCacheFile() {
return new File(app.getDataDir(), "bundles.cache");
}
public ClassLoader loadBundles(List<File> classPath) throws IOException, BundleException {
// create the standalone loader
bundleLoader = new StandaloneBundleLoader(app, app.getSharedClassLoader());
Thread.currentThread().setContextClassLoader(bundleLoader.getSharedClassLoader().getLoader());
aboutToStartRuntime();
boolean scan = true;
File file = getCacheFile();
if (useCache) {
if (file.isFile()) { // use the cache
scan = false;
try {
fastLoad(file);
} catch (IOException e) {
scan = true;
} catch (BundleException e) {
scan = true;
}
}
}
if (scan) {
List<BundleFile> bundles = new ArrayList<BundleFile>();
List<BundleFile> jars = new ArrayList<BundleFile>();
scanAndLoad(classPath, bundles, jars);
writeCache(file, bundles, jars);
app.installAll(bundles);
}
// that's all
runtimeStarted();
return bundleLoader.getSharedClassLoader().getLoader();
}
public void scanAndLoad(List<File> classPath, List<BundleFile> bundles, List<BundleFile> jars) {
bundleLoader.setScanForNestedJARs(scanForNestedJARs);
bundleLoader.setExtractNestedJARs(extractNestedJARs);
for (File file : classPath) {
if (file.isFile()) { // a JAR file
String name = file.getName();
if (!name.endsWith(".jar") || name.endsWith(".rar") || name.endsWith(".zip") || name.endsWith(".sar")) {
continue;
}
try {
JarFile jar = new JarFile(file);
JarBundleFile bf = new JarBundleFile(jar);
if (bf.getSymbolicName() != null) {
bundles.add(bf);
} else {
jars.add(bf);
}
} catch (IOException e) { // may be not a JAR
continue;
}
} else if (file.isDirectory()) { // a file directory
try {
DirectoryBundleFile bf = new DirectoryBundleFile(file);
if (bf.getSymbolicName() != null) {
bundles.add(bf);
} else {
jars.add(bf);
}
} catch (IOException e) {
continue;
}
}
}
}
public static void writeCache(File file, List<BundleFile> bundles, List<BundleFile> jars) throws IOException {
// write loaded bundles to the cache
BufferedWriter writer = null;
try {
writer = new BufferedWriter(new FileWriter(file));
for (BundleFile bf : bundles) {
writer.append(bf.getFile().getAbsolutePath());
writer.newLine();
}
writer.append("#");
writer.newLine();
for (BundleFile bf : jars) {
writer.append(bf.getFile().getAbsolutePath());
writer.newLine();
}
} finally {
if (writer != null) {
writer.close();
}
}
}
public void fastLoad(File file) throws IOException, BundleException {
BufferedReader reader = null;
List<BundleFile> bundles = new ArrayList<BundleFile>();
try {
reader = new BufferedReader(new FileReader(file));
List<BundleFile> list = bundles;
while (true) {
String line = reader.readLine();
if (line == null) {
break;
}
if (line.startsWith("#")) {
list = null;
continue;
}
BundleFile bf = null;
File f = new File(line.trim());
if (f.isDirectory()) {
bf = new DirectoryBundleFile(f);
} else {
bf = new JarBundleFile(f);
}
bundleLoader.loadJAR(bf);
if (list != null) {
list.add(bf);
}
}
} finally {
if (reader != null) {
reader.close();
}
}
// install found bundles
app.installAll(bundles);
}
protected void aboutToStartRuntime() {
// do nothing
}
protected void runtimeStarted() {
// do nothing
}
}