/* * (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 */ package org.nuxeo.osgi.application.client; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.LinkedHashSet; import java.util.List; import java.util.StringTokenizer; import org.nuxeo.common.Environment; import org.nuxeo.osgi.BundleFile; import org.nuxeo.osgi.BundleImpl; import org.nuxeo.osgi.DirectoryBundleFile; import org.nuxeo.osgi.JarBundleFile; import org.nuxeo.osgi.OSGiAdapter; import org.nuxeo.osgi.SystemBundle; import org.nuxeo.osgi.SystemBundleFile; import org.osgi.framework.BundleException; import org.osgi.framework.FrameworkEvent; /** * Nuxeo Runtime launcher. * <p> * This launcher assumes all bundles are already on the classpath. * * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a> */ public class NuxeoApp { protected final ClassLoader loader; protected final Environment env; private OSGiAdapter osgi; public static ClassLoader getDefaultClassLoader() { ClassLoader cl = Thread.currentThread().getContextClassLoader(); return cl == null ? NuxeoApp.class.getClassLoader() : cl; } public NuxeoApp() { this(new File("."), getDefaultClassLoader()); } public NuxeoApp(File home) { this(home, getDefaultClassLoader()); } public NuxeoApp(File home, ClassLoader loader) { this.loader = loader; env = new Environment(home); Environment.setDefault(env); } public ClassLoader getLoader() { return loader; } public Environment getEnvironment() { return env; } public void deployBundles(String bundlePath) throws BundleException, IOException { deployBundles(getBundleFiles(new File("."), bundlePath, ":")); } public void deployBundles(File baseDir, String bundlePath) throws BundleException, IOException { deployBundles(getBundleFiles(baseDir, bundlePath, ":")); } public synchronized void deployBundles(Collection<File> files) throws BundleException, IOException { if (!isStarted()) { throw new IllegalStateException("Framework not started"); } for (File file : files) { deployBundle(file); } } public synchronized void deployBundle(File file) throws BundleException, IOException { if (!isStarted()) { throw new IllegalStateException("Framework not started"); } if (!file.getPath().endsWith(".jar")) { return; // not a valid bundle } BundleFile bf = file.isDirectory() ? new DirectoryBundleFile(file) : new JarBundleFile(file); try { BundleImpl bundle = new BundleImpl(osgi, bf, loader); if (bundle.getSymbolicName() != null) { osgi.install(bundle); } } catch (NullPointerException t) { // do nothing: may happen with non OSGi manifests // System.out.println("Ignore: "+file); } } public synchronized void start() { if (osgi != null) { throw new IllegalStateException("Nuxeo Runtime already started"); } osgi = new OSGiAdapter(env.getHome(), env.getData(), env.getProperties()); } public synchronized boolean isStarted() { return osgi != null; } public synchronized OSGiAdapter getOsgi() { return osgi; } public synchronized void shutdown() throws IOException { if (osgi == null) { throw new IllegalStateException("Nuxeo Runtime not started"); } osgi.shutdown(); osgi = null; } public static Collection<File> getBundleFiles(File baseDir, String bundles, String delim) throws IOException { Collection<File> result = new LinkedHashSet<File>(); StringTokenizer tokenizer = new StringTokenizer(bundles, delim == null ? " \t\n\r\f" : delim); while (tokenizer.hasMoreTokens()) { String tok = tokenizer.nextToken(); List<File> files = expandFiles(baseDir, tok); for (File file : files) { result.add(file.getCanonicalFile()); } } return result; } public static File makeFile(File baseDir, String path) { if (path.startsWith("/")) { return new File(path); } return new File(baseDir, path); } public static List<File> expandFiles(File baseDir, String line) { int p = line.lastIndexOf("/"); String fileName = null; if (p > -1) { fileName = line.substring(p + 1); baseDir = makeFile(baseDir, line.substring(0, p)); } else { fileName = line; } if (fileName.length() == 0) { return Arrays.asList(baseDir.listFiles()); } p = fileName.indexOf("*"); if (p == -1) { return Collections.singletonList(makeFile(baseDir, fileName)); } else if (p == 0) { String suffix = fileName.substring(p + 1); List<File> result = new ArrayList<File>(); String[] names = baseDir.list(); if (names != null) { for (String name : names) { if (name.endsWith(suffix)) { result.add(makeFile(baseDir, name)); } } } return result; } else if (p == fileName.length() - 1) { String prefix = fileName.substring(0, p); List<File> result = new ArrayList<File>(); String[] names = baseDir.list(); if (names != null) { for (String name : baseDir.list()) { if (name.startsWith(prefix)) { result.add(makeFile(baseDir, name)); } } } return result; } else { String prefix = fileName.substring(0, p); String suffix = fileName.substring(p + 1); List<File> result = new ArrayList<File>(); String[] names = baseDir.list(); if (names != null) { for (String name : names) { if (name.startsWith(prefix) && name.endsWith(suffix)) { result.add(makeFile(baseDir, name)); } } } return result; } } public void fireFrameworkStarted() throws BundleException { if (osgi.getSystemBundle() == null) { SystemBundleFile file; try { file = new SystemBundleFile(osgi.getWorkingDir()); } catch (IOException e) { throw new BundleException("Cannot create system bundle file", e); } osgi.setSystemBundle(new SystemBundle(osgi, file, loader)); } osgi.fireFrameworkEvent(new FrameworkEvent(FrameworkEvent.STARTED, osgi.getSystemBundle(), null)); } }