]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.scl.osgi/src/org/simantics/scl/osgi/internal/BundleModuleSourceRepository.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.scl.osgi / src / org / simantics / scl / osgi / internal / BundleModuleSourceRepository.java
diff --git a/bundles/org.simantics.scl.osgi/src/org/simantics/scl/osgi/internal/BundleModuleSourceRepository.java b/bundles/org.simantics.scl.osgi/src/org/simantics/scl/osgi/internal/BundleModuleSourceRepository.java
new file mode 100644 (file)
index 0000000..31d06b7
--- /dev/null
@@ -0,0 +1,197 @@
+package org.simantics.scl.osgi.internal;
+
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Enumeration;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleEvent;
+import org.osgi.service.component.ComponentContext;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Deactivate;
+import org.osgi.util.tracker.BundleTracker;
+import org.simantics.scl.compiler.module.repository.UpdateListener;
+import org.simantics.scl.compiler.source.ModuleSource;
+import org.simantics.scl.compiler.source.repository.AbstractModuleSourceRepository;
+import org.simantics.scl.compiler.source.repository.ModuleSourceRepository;
+
+import gnu.trove.map.hash.THashMap;
+import gnu.trove.procedure.TObjectObjectProcedure;
+import gnu.trove.procedure.TObjectProcedure;
+import gnu.trove.set.hash.THashSet;
+
+@Component
+public class BundleModuleSourceRepository extends AbstractModuleSourceRepository implements ModuleSourceRepository {
+    
+    Tracker tracker;
+    THashMap<String, BundleModuleSource> modules = new THashMap<String, BundleModuleSource>();
+    THashMap<Bundle, ArrayList<String>> modulesPerBundle = new THashMap<Bundle, ArrayList<String>>();
+    THashMap<String, BundleDocumentationSource> documentations = new THashMap<String, BundleDocumentationSource>();
+    THashMap<Bundle, ArrayList<String>> documentationsPerBundle = new THashMap<Bundle, ArrayList<String>>();
+            
+    class Tracker extends BundleTracker<Bundle> {
+        public Tracker(BundleContext context) {
+            super(context, 0xffffffff, null);
+        }
+        
+        @Override
+        public Bundle addingBundle(Bundle bundle, BundleEvent event) {
+            synchronized(BundleModuleSourceRepository.this) {
+                Enumeration<URL> moduleEntries = bundle.findEntries("scl", "*.scl", true);
+                if(moduleEntries != null) {
+                    ArrayList<String> modulesInThisBundle = new ArrayList<String>();
+                    while(moduleEntries.hasMoreElements()) {
+                        URL url = moduleEntries.nextElement();
+                        String path = url.getPath();
+                        String moduleName = path.substring(5, path.length()-4);
+                        modules.put(moduleName, new BundleModuleSource(moduleName, bundle, url));
+                        modulesInThisBundle.add(moduleName);
+                    }
+                    modulesPerBundle.put(bundle, modulesInThisBundle);
+                }
+                else
+                    modulesPerBundle.put(bundle, new ArrayList<String>(0));
+                
+                Enumeration<URL> documentationEntries = bundle.findEntries("scl", "*.md", true);
+                if(documentationEntries != null) {
+                    ArrayList<String> documentationsInThisBundle = new ArrayList<String>();
+                    while(documentationEntries.hasMoreElements()) {
+                        URL url = documentationEntries.nextElement();
+                        String path = url.getPath();
+                        String documentationName = path.substring(5, path.length()-3);
+                        documentations.put(documentationName, new BundleDocumentationSource(documentationName, bundle, url));
+                        documentationsInThisBundle.add(documentationName);
+                    }
+                    documentationsPerBundle.put(bundle, documentationsInThisBundle);
+                }
+                else
+                    documentationsPerBundle.put(bundle, new ArrayList<String>(0));
+                
+                return bundle;
+            }
+        }
+        
+        @Override
+        public void removedBundle(Bundle bundle, BundleEvent event,
+                Bundle object) {
+            synchronized(BundleModuleSourceRepository.this) {
+                ArrayList<String> moduleList = modulesPerBundle.get(bundle);
+                if(moduleList != null)
+                    for(String moduleName : moduleList)
+                        modules.remove(moduleName);
+                ArrayList<String> documentationsList = documentationsPerBundle.get(bundle);
+                if(documentationsList != null)
+                    for(String documentation : documentationsList)
+                        documentations.remove(documentation);
+            }
+        }
+    };
+    
+    @Activate
+    public void activate(ComponentContext context) {
+        tracker = new Tracker(context.getBundleContext());
+        tracker.open();
+    }
+    
+    @Deactivate
+    public void deactivate(ComponentContext context) {
+        tracker.close();
+    }
+
+    @Override
+    synchronized public ModuleSource getModuleSource(String moduleName,
+            UpdateListener listener) {
+        return modules.get(moduleName);
+    }
+
+    @Override
+    synchronized public void forAllModules(TObjectProcedure<String> procedure) {
+        modules.forEachKey(procedure);
+    }
+    
+    @Override
+    synchronized public String getDocumentation(String documentationName) {
+        BundleDocumentationSource source = documentations.get(documentationName);
+        if(source == null)
+            return null;
+        else
+            return source.getText();
+    }
+
+    @Override
+    synchronized public void forAllDocumentations(TObjectProcedure<String> procedure) {
+        documentations.forEachKey(procedure);
+    }
+
+    @Override
+    public void checkUpdates() {
+        synchronized(this) {
+            modulesPerBundle.forEachEntry(new TObjectObjectProcedure<Bundle, ArrayList<String>>() {
+                @Override
+                public boolean execute(Bundle bundle, ArrayList<String> oldModules) {
+                    Enumeration<URL> moduleEntries = bundle.findEntries("scl", "*.scl", true);
+                    if(moduleEntries != null) {
+                        THashSet<String> oldModuleSet = new THashSet<String>(oldModules);
+                        ArrayList<String> modulesInThisBundle = new ArrayList<String>();
+                        while(moduleEntries.hasMoreElements()) {
+                            URL url = moduleEntries.nextElement();
+                            String path = url.getPath();
+                            String moduleName = path.substring(5, path.length()-4);
+                            if(!oldModuleSet.remove(moduleName))
+                                modules.put(moduleName, new BundleModuleSource(moduleName, bundle, url));
+                            modulesInThisBundle.add(moduleName);
+                        }
+                        for(String oldModule : oldModuleSet)
+                            modules.remove(oldModule);
+                        modulesPerBundle.put(bundle, modulesInThisBundle);
+                    }
+                    else {
+                        for(String oldModule : oldModules)
+                            modules.remove(oldModule);
+                        modulesPerBundle.put(bundle, new ArrayList<String>(0));
+                    }
+                    return true;
+                }
+            });
+            documentationsPerBundle.forEachEntry(new TObjectObjectProcedure<Bundle, ArrayList<String>>() {
+                @Override
+                public boolean execute(Bundle bundle, ArrayList<String> oldDocumentations) {
+                    Enumeration<URL> documentationEntries = bundle.findEntries("scl", "*.md", true);
+                    if(documentationEntries != null) {
+                        THashSet<String> oldDocSet = new THashSet<String>(oldDocumentations);
+                        ArrayList<String> documentationsInThisBundle = new ArrayList<String>();
+                        while(documentationEntries.hasMoreElements()) {
+                            URL url = documentationEntries.nextElement();
+                            String path = url.getPath();
+                            String documentationName = path.substring(5, path.length()-3);
+                            if(!oldDocSet.remove(documentationName))
+                                documentations.put(documentationName, new BundleDocumentationSource(documentationName, bundle, url));
+                            documentationsInThisBundle.add(documentationName);
+                        }
+                        for(String oldDocumentation : oldDocSet)
+                            documentations.remove(oldDocumentation);
+                        documentationsPerBundle.put(bundle, documentationsInThisBundle);
+                    }
+                    else {
+                        for(String oldDocumentation : oldDocumentations)
+                            documentations.remove(oldDocumentation);
+                        documentationsPerBundle.put(bundle, new ArrayList<String>(0));
+                    }
+                    return true;
+                }
+            });
+        }
+        for(BundleModuleSource source : modules.values())
+            source.checkUpdates();
+    }
+
+    @Override
+    public void clear() {
+        for (BundleModuleSource source : modules.values()) {
+            source.clear();
+        }
+    }
+
+}