diff --git a/osgi.enroute.updater.provider/.classpath b/osgi.enroute.updater.provider/.classpath new file mode 100644 index 0000000..57c70f3 --- /dev/null +++ b/osgi.enroute.updater.provider/.classpath @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/osgi.enroute.updater.provider/.gitignore b/osgi.enroute.updater.provider/.gitignore new file mode 100644 index 0000000..11f90b6 --- /dev/null +++ b/osgi.enroute.updater.provider/.gitignore @@ -0,0 +1,3 @@ +/generated/ +/bin/ +/bin_test/ diff --git a/osgi.enroute.updater.provider/.project b/osgi.enroute.updater.provider/.project new file mode 100644 index 0000000..01ad476 --- /dev/null +++ b/osgi.enroute.updater.provider/.project @@ -0,0 +1,23 @@ + + + osgi.enroute.updater.provider + + + + + + org.eclipse.jdt.core.javabuilder + + + + + bndtools.core.bndbuilder + + + + + + org.eclipse.jdt.core.javanature + bndtools.core.bndnature + + diff --git a/osgi.enroute.updater.provider/.settings/org.eclipse.core.resources.prefs b/osgi.enroute.updater.provider/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 0000000..94dd240 --- /dev/null +++ b/osgi.enroute.updater.provider/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,10 @@ +eclipse.preferences.version=1 +encoding/.classpath=UTF-8 +encoding/.gitignore=UTF-8 +encoding/.project=UTF-8 +encoding//.settings/org.eclipse.jdt.core.prefs=UTF-8 +encoding//src/osgi/enroute/updater/provider/UpdaterImpl.java=UTF-8 +encoding//test/.gitignore=UTF-8 +encoding//test/osgi/enroute/updater/provider/UpdaterImplTest.java=UTF-8 +encoding/bnd.bnd=UTF-8 +encoding/readme.md=UTF-8 diff --git a/osgi.enroute.updater.provider/.settings/org.eclipse.jdt.core.prefs b/osgi.enroute.updater.provider/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..a698e59 --- /dev/null +++ b/osgi.enroute.updater.provider/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,12 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/osgi.enroute.updater.provider/bnd.bnd b/osgi.enroute.updater.provider/bnd.bnd new file mode 100644 index 0000000..83c80bc --- /dev/null +++ b/osgi.enroute.updater.provider/bnd.bnd @@ -0,0 +1,25 @@ +# +# OSGI ENROUTE UPDATER PROVIDER BUNDLE +# + + +Bundle-Description: \ + Updates bundles based on their location if they use a file: URL. + +Private-Package: \ + osgi.enroute.updater.provider + +-buildpath: \ + osgi.enroute.base.api;version=1.0 + +-testpath: \ + osgi.enroute.junit.wrapper;version=4.12 + +-includeresource: {readme.md} + + +-runrequires: \ + osgi.identity;filter:='(osgi.identity=osgi.enroute.updater.provider)' + +-runbundles: \ + ${error;Resolve first} diff --git a/osgi.enroute.updater.provider/readme.md b/osgi.enroute.updater.provider/readme.md new file mode 100644 index 0000000..5f08afd --- /dev/null +++ b/osgi.enroute.updater.provider/readme.md @@ -0,0 +1,15 @@ +# OSGI ENROUTE UPDATER PROVIDER + +${Bundle-Description} + +## Example + +## Configuration + + Pid: osgi.enroute.updater + + Field Type Description + + +## References + diff --git a/osgi.enroute.updater.provider/src/osgi/enroute/updater/provider/UpdaterImpl.java b/osgi.enroute.updater.provider/src/osgi/enroute/updater/provider/UpdaterImpl.java new file mode 100644 index 0000000..6cec903 --- /dev/null +++ b/osgi.enroute.updater.provider/src/osgi/enroute/updater/provider/UpdaterImpl.java @@ -0,0 +1,136 @@ +package osgi.enroute.updater.provider; + +import java.io.File; +import java.net.URI; +import java.nio.file.Paths; +import java.util.HashSet; +import java.util.Set; +import java.util.concurrent.atomic.AtomicBoolean; + +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; +import org.osgi.framework.BundleEvent; +import org.osgi.framework.wiring.FrameworkWiring; +import org.osgi.util.tracker.BundleTracker; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * A very simple bundle that tracks bundles that have a location + * that maps to a file. If so, it checks the lastModified times + * of the bundle and if necessary refreshes the bundles. + */ +public class UpdaterImpl extends Thread implements BundleActivator { + private static final String REFERENCE = "reference:"; + private static final int SYSTEM_BUNDLE = 0; + private static Logger logger = LoggerFactory + .getLogger(UpdaterImpl.class); + + static class BInfo { + File file; + Bundle bundle; + long lastPolled; + } + + private BundleTracker tracker; + private FrameworkWiring framework; + private AtomicBoolean inRefresh = new AtomicBoolean(false); + + public UpdaterImpl() { + super("OSGi Bundle Updater"); + } + + @Override + public void start(BundleContext context) throws Exception { + framework = context.getBundle(0).adapt(FrameworkWiring.class); + tracker = new BundleTracker(context, -1, null) { + @Override + public BInfo addingBundle(Bundle bundle, BundleEvent event) { + try { + + if (bundle.getBundleId() == SYSTEM_BUNDLE) + return null; + + String location = bundle.getLocation(); + if (location.startsWith(REFERENCE)) + location = location.substring(REFERENCE.length()); + + if (!location.startsWith("file:")) + return null; + + File f = Paths.get(new URI(location)).toFile(); + if (!f.exists()) + return null; + + BInfo b = new BInfo(); + b.bundle = bundle; + return b; + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + }; + tracker.open(); + start(); + } + + @Override + public void stop(BundleContext context) throws Exception { + interrupt(); + } + + public void run() { + logger.info("Starting"); + try { + while (!isInterrupted()) + try { + logger.info("Sleep"); + sleep(1000); + if (inRefresh.get()) + continue; + + Set bundles = new HashSet(); + + long recently = System.currentTimeMillis() - 1000; + for (BInfo b : tracker.getTracked().values()) { + long lastModified = b.file.lastModified(); + + if (lastModified > recently) + continue; + + if (lastModified > b.bundle.getLastModified()) { + bundles.add(b.bundle); + b.bundle.stop(); + } + } + + if (bundles.isEmpty()) + continue; + + logger.info("Update " + bundles); + for (Bundle b : bundles) try { + b.update(); + b.start(); + } catch(Exception e) { + logger.error("Unexpected error updating bundle "+b, e); + } + + logger.info("Refresh start"); + inRefresh.set(true); + framework.refreshBundles(bundles, event -> { + inRefresh.set(false); + logger.info("Refresh end"); + }); + + } catch (InterruptedException e) { + return; + } catch (Exception e) { + logger.error("Unexpected error", e); + } + } finally { + logger.info("Exiting"); + } + } +} diff --git a/osgi.enroute.updater.provider/test/.gitignore b/osgi.enroute.updater.provider/test/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/osgi.enroute.updater.provider/test/osgi/enroute/updater/provider/UpdaterImplTest.java b/osgi.enroute.updater.provider/test/osgi/enroute/updater/provider/UpdaterImplTest.java new file mode 100644 index 0000000..8bbba13 --- /dev/null +++ b/osgi.enroute.updater.provider/test/osgi/enroute/updater/provider/UpdaterImplTest.java @@ -0,0 +1,18 @@ +package osgi.enroute.updater.provider; + +import junit.framework.TestCase; + +/* + * + * + * + */ + +public class UpdaterImplTest extends TestCase { + + /* + * + * + * + */ +}