package org.simantics.scl.osgi.internal; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.BundleException; import org.osgi.framework.wiring.BundleWiring; import org.simantics.scl.compiler.common.exceptions.InternalCompilerError; import org.simantics.scl.compiler.internal.codegen.types.JavaReferenceValidator; import org.simantics.scl.compiler.internal.codegen.types.JavaReferenceValidatorFactory; import org.simantics.scl.compiler.internal.codegen.types.RuntimeJavaReferenceValidator; import org.simantics.scl.compiler.types.Type; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @SuppressWarnings("restriction") public class OsgiJavaReferenceValidatorFactory implements JavaReferenceValidatorFactory { private static final Logger LOGGER = LoggerFactory.getLogger(OsgiJavaReferenceValidatorFactory.class); private final Bundle bundle; public OsgiJavaReferenceValidatorFactory(Bundle bundle) { this.bundle = bundle; } private static ClassLoader getClassLoader(Bundle bundle) { if (bundle.getSymbolicName().equals("org.simantics.scl.runtime")) return Type.class.getClassLoader(); else { BundleWiring wiring = bundle.adapt(BundleWiring.class); if (wiring == null && bundle.getState() == Bundle.INSTALLED) { LOGGER.info("Starting bundle {} with state {}", bundle.getSymbolicName(), BundleUtils.resolveBundleState(bundle)); try { bundle.start(); } catch (BundleException e) { throw new InternalCompilerError("Couldn't activate bundle " + bundle.getSymbolicName() + ". Bundle state is " + BundleUtils.resolveBundleState(bundle)); } wiring = bundle.adapt(BundleWiring.class); } if (wiring != null) return wiring.getClassLoader(); else throw new InternalCompilerError("Cannot get the class loader for bundle " + bundle.getSymbolicName() + ". Bundle state is " + BundleUtils.resolveBundleState(bundle)); } } @SuppressWarnings("unchecked") private static JavaReferenceValidator getJavaReferenceValidator(Bundle bundle) { if(bundle == null) return null; return (JavaReferenceValidator) (JavaReferenceValidator)new RuntimeJavaReferenceValidator(getClassLoader(bundle)); } private static Bundle getBundle(BundleContext bundleContext, String symbolicName) { Bundle result = null; for (Bundle candidate : bundleContext.getBundles()) if (candidate.getSymbolicName().equals(symbolicName)) if (result == null || result.getVersion().compareTo(candidate.getVersion()) < 0) result = candidate; return result; } @Override public JavaReferenceValidator getJavaReferenceValidator(String bundleName) { LOGGER.info("getJavaReferenceValidator(" + bundleName + ")"); return getJavaReferenceValidator(getBundle(bundle.getBundleContext(), bundleName)); } @Override public JavaReferenceValidator getDefaultJavaReferenceValidator() { return getJavaReferenceValidator(bundle); } }