/**
* Copyright (c) 2015, Lucee Assosication Switzerland. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
*/
package lucee.loader.osgi;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
import java.util.List;
import lucee.commons.io.log.Log;
import lucee.commons.io.res.Resource;
import lucee.loader.engine.CFMLEngineFactory;
import lucee.loader.engine.CFMLEngineFactorySupport;
import lucee.loader.util.Util;
import lucee.runtime.util.ClassUtil;
import org.apache.felix.framework.Logger;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
import org.osgi.framework.Constants;
public class BundleUtil {
/*public static Bundle addBundlex(BundleContext context,File bundle, boolean start) throws IOException, BundleException {
return addBundle(context,bundle.getAbsolutePath(),bundle,start);
}*/
public static Bundle addBundle(final CFMLEngineFactory factory,
final BundleContext context, final File bundle, final Log log)
throws IOException, BundleException {
return addBundle(factory, context, bundle.getAbsolutePath(),
new FileInputStream(bundle), true, log);
}
public static Bundle addBundle(final CFMLEngineFactory factory,
final BundleContext context, final Resource bundle, final Log log)
throws IOException, BundleException {
return addBundle(factory, context, bundle.getAbsolutePath(),
bundle.getInputStream(), true, log);
}
public static Bundle addBundle(final CFMLEngineFactory factory,
final BundleContext context, final String path,
final InputStream is, final boolean closeIS, final Log log)
throws IOException, BundleException {
// if possible use that feature from core, it is smarter (can also load relations)
/* we no longer use this code, becaue it cause problem when the core is resatrted
ClassUtil cu = null;
try {
cu = CFMLEngineFactory.getInstance().getClassUtil();
}
catch (final Throwable t) {}
if (cu != null)
return cu.addBundle(context, is, closeIS, true);
*/
if (log != null)
log.info("OSGI", "add bundle:" + path);
else {
//factory.log(Log.LEVEL_INFO, "add_bundle:" + bundle);
}
try {
return installBundle(context, path, is);
} finally {
if (closeIS)
CFMLEngineFactorySupport.closeEL(is);
}
}
public static Bundle installBundle(final BundleContext context,
final String path, final InputStream is) throws BundleException {
return context.installBundle(path, is);
}
public static void start(final CFMLEngineFactory factory,
final List<Bundle> bundles) throws BundleException {
if (bundles == null || bundles.isEmpty())
return;
final Iterator<Bundle> it = bundles.iterator();
while (it.hasNext())
start(factory, it.next());
}
public static void start(final CFMLEngineFactory factory,
final Bundle bundle) throws BundleException {
/* we no longer use this code, becaue it cause problem when the core is resatrted
ClassUtil cu = null;
try {
cu = CFMLEngineFactory.getInstance().getClassUtil();
} catch (final Throwable t) {
}
if (cu != null) {
cu.start(bundle);
return;
}*/
final String fh = bundle.getHeaders().get("Fragment-Host");
if (!Util.isEmpty(fh)) {
factory.log(Logger.LOG_INFO,
"do not start [" + bundle.getSymbolicName()
+ "], because this is a fragment bundle for [" + fh
+ "]");
return;
}
factory.log(Logger.LOG_INFO, "start bundle:" + bundle.getSymbolicName()
+ ":" + bundle.getVersion().toString());
start(bundle,false);
}
@Deprecated
public static void start(final Bundle bundle) throws BundleException {start(bundle, false);}
public static void start(final Bundle bundle, boolean async) throws BundleException {
bundle.start();
if(!async)waitFor(bundle,Bundle.STARTING,Bundle.RESOLVED,Bundle.INSTALLED,60000L);
}
public static void stop(final Bundle bundle, boolean async) throws BundleException {
bundle.stop();
if(!async)waitFor(bundle,Bundle.STOPPING,Bundle.ACTIVE,Bundle.ACTIVE,60000L);
}
private static void waitFor(Bundle bundle, int action1, int action2, int action3, long timeout) throws BundleException {
// we poll because opening a new thread is an overhead
long start=System.currentTimeMillis();
while(bundle.getState()==action1 || bundle.getState()==action2 || bundle.getState()==action3) {
if((start+timeout)<System.currentTimeMillis())
throw new BundleException("timeout ["+timeout+"] reached for action ["+(action1==Bundle.STARTING?"starting":"stopping")+"], bundle is still in ["+bundle.getState()+"]");
try {Thread.sleep(1);} catch (InterruptedException e) {} // take a nap, before trying again
}
}
public static void startIfNecessary(final CFMLEngineFactory factory,
final Bundle bundle) throws BundleException {
if (bundle.getState() == Bundle.ACTIVE)
return;
start(factory, bundle);
}
public static String bundleState(final int state, final String defaultValue) {
switch (state) {
case Bundle.UNINSTALLED:
return "UNINSTALLED";
case Bundle.INSTALLED:
return "INSTALLED";
case Bundle.RESOLVED:
return "RESOLVED";
case Bundle.STARTING:
return "STARTING";
case Bundle.STOPPING:
return "STOPPING";
case Bundle.ACTIVE:
return "ACTIVE";
}
return defaultValue;
}
public static String toFrameworkBundleParent(String str)
throws BundleException {
if (str != null) {
str = str.trim();
if (Constants.FRAMEWORK_BUNDLE_PARENT_FRAMEWORK
.equalsIgnoreCase(str))
return Constants.FRAMEWORK_BUNDLE_PARENT_FRAMEWORK;
if (Constants.FRAMEWORK_BUNDLE_PARENT_APP.equalsIgnoreCase(str))
return Constants.FRAMEWORK_BUNDLE_PARENT_APP;
if (Constants.FRAMEWORK_BUNDLE_PARENT_BOOT.equalsIgnoreCase(str))
return Constants.FRAMEWORK_BUNDLE_PARENT_BOOT;
if (Constants.FRAMEWORK_BUNDLE_PARENT_EXT.equalsIgnoreCase(str))
return Constants.FRAMEWORK_BUNDLE_PARENT_EXT;
}
throw new BundleException("value [" + str + "] for ["
+ Constants.FRAMEWORK_BUNDLE_PARENT
+ "] defintion is invalid, " + "valid values are ["
+ Constants.FRAMEWORK_BUNDLE_PARENT_APP + ", "
+ Constants.FRAMEWORK_BUNDLE_PARENT_BOOT + ", "
+ Constants.FRAMEWORK_BUNDLE_PARENT_EXT + ", "
+ Constants.FRAMEWORK_BUNDLE_PARENT_FRAMEWORK + "]");
}
public static boolean isSystemBundle(final Bundle bundle) {
// TODO make a better implementation for this, independent of felix
return bundle.getSymbolicName().equals("org.apache.felix.framework");
}
}