]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.osgi/src/org/simantics/scl/osgi/internal/BundleModuleSourceRepository.java
31d06b72619399ffbb9d8f9b4666c2c468303bdd
[simantics/platform.git] / bundles / org.simantics.scl.osgi / src / org / simantics / scl / osgi / internal / BundleModuleSourceRepository.java
1 package org.simantics.scl.osgi.internal;
2
3 import java.net.URL;
4 import java.util.ArrayList;
5 import java.util.Enumeration;
6
7 import org.osgi.framework.Bundle;
8 import org.osgi.framework.BundleContext;
9 import org.osgi.framework.BundleEvent;
10 import org.osgi.service.component.ComponentContext;
11 import org.osgi.service.component.annotations.Activate;
12 import org.osgi.service.component.annotations.Component;
13 import org.osgi.service.component.annotations.Deactivate;
14 import org.osgi.util.tracker.BundleTracker;
15 import org.simantics.scl.compiler.module.repository.UpdateListener;
16 import org.simantics.scl.compiler.source.ModuleSource;
17 import org.simantics.scl.compiler.source.repository.AbstractModuleSourceRepository;
18 import org.simantics.scl.compiler.source.repository.ModuleSourceRepository;
19
20 import gnu.trove.map.hash.THashMap;
21 import gnu.trove.procedure.TObjectObjectProcedure;
22 import gnu.trove.procedure.TObjectProcedure;
23 import gnu.trove.set.hash.THashSet;
24
25 @Component
26 public class BundleModuleSourceRepository extends AbstractModuleSourceRepository implements ModuleSourceRepository {
27     
28     Tracker tracker;
29     THashMap<String, BundleModuleSource> modules = new THashMap<String, BundleModuleSource>();
30     THashMap<Bundle, ArrayList<String>> modulesPerBundle = new THashMap<Bundle, ArrayList<String>>();
31     THashMap<String, BundleDocumentationSource> documentations = new THashMap<String, BundleDocumentationSource>();
32     THashMap<Bundle, ArrayList<String>> documentationsPerBundle = new THashMap<Bundle, ArrayList<String>>();
33             
34     class Tracker extends BundleTracker<Bundle> {
35         public Tracker(BundleContext context) {
36             super(context, 0xffffffff, null);
37         }
38         
39         @Override
40         public Bundle addingBundle(Bundle bundle, BundleEvent event) {
41             synchronized(BundleModuleSourceRepository.this) {
42                 Enumeration<URL> moduleEntries = bundle.findEntries("scl", "*.scl", true);
43                 if(moduleEntries != null) {
44                     ArrayList<String> modulesInThisBundle = new ArrayList<String>();
45                     while(moduleEntries.hasMoreElements()) {
46                         URL url = moduleEntries.nextElement();
47                         String path = url.getPath();
48                         String moduleName = path.substring(5, path.length()-4);
49                         modules.put(moduleName, new BundleModuleSource(moduleName, bundle, url));
50                         modulesInThisBundle.add(moduleName);
51                     }
52                     modulesPerBundle.put(bundle, modulesInThisBundle);
53                 }
54                 else
55                     modulesPerBundle.put(bundle, new ArrayList<String>(0));
56                 
57                 Enumeration<URL> documentationEntries = bundle.findEntries("scl", "*.md", true);
58                 if(documentationEntries != null) {
59                     ArrayList<String> documentationsInThisBundle = new ArrayList<String>();
60                     while(documentationEntries.hasMoreElements()) {
61                         URL url = documentationEntries.nextElement();
62                         String path = url.getPath();
63                         String documentationName = path.substring(5, path.length()-3);
64                         documentations.put(documentationName, new BundleDocumentationSource(documentationName, bundle, url));
65                         documentationsInThisBundle.add(documentationName);
66                     }
67                     documentationsPerBundle.put(bundle, documentationsInThisBundle);
68                 }
69                 else
70                     documentationsPerBundle.put(bundle, new ArrayList<String>(0));
71                 
72                 return bundle;
73             }
74         }
75         
76         @Override
77         public void removedBundle(Bundle bundle, BundleEvent event,
78                 Bundle object) {
79             synchronized(BundleModuleSourceRepository.this) {
80                 ArrayList<String> moduleList = modulesPerBundle.get(bundle);
81                 if(moduleList != null)
82                     for(String moduleName : moduleList)
83                         modules.remove(moduleName);
84                 ArrayList<String> documentationsList = documentationsPerBundle.get(bundle);
85                 if(documentationsList != null)
86                     for(String documentation : documentationsList)
87                         documentations.remove(documentation);
88             }
89         }
90     };
91     
92     @Activate
93     public void activate(ComponentContext context) {
94         tracker = new Tracker(context.getBundleContext());
95         tracker.open();
96     }
97     
98     @Deactivate
99     public void deactivate(ComponentContext context) {
100         tracker.close();
101     }
102
103     @Override
104     synchronized public ModuleSource getModuleSource(String moduleName,
105             UpdateListener listener) {
106         return modules.get(moduleName);
107     }
108
109     @Override
110     synchronized public void forAllModules(TObjectProcedure<String> procedure) {
111         modules.forEachKey(procedure);
112     }
113     
114     @Override
115     synchronized public String getDocumentation(String documentationName) {
116         BundleDocumentationSource source = documentations.get(documentationName);
117         if(source == null)
118             return null;
119         else
120             return source.getText();
121     }
122
123     @Override
124     synchronized public void forAllDocumentations(TObjectProcedure<String> procedure) {
125         documentations.forEachKey(procedure);
126     }
127
128     @Override
129     public void checkUpdates() {
130         synchronized(this) {
131             modulesPerBundle.forEachEntry(new TObjectObjectProcedure<Bundle, ArrayList<String>>() {
132                 @Override
133                 public boolean execute(Bundle bundle, ArrayList<String> oldModules) {
134                     Enumeration<URL> moduleEntries = bundle.findEntries("scl", "*.scl", true);
135                     if(moduleEntries != null) {
136                         THashSet<String> oldModuleSet = new THashSet<String>(oldModules);
137                         ArrayList<String> modulesInThisBundle = new ArrayList<String>();
138                         while(moduleEntries.hasMoreElements()) {
139                             URL url = moduleEntries.nextElement();
140                             String path = url.getPath();
141                             String moduleName = path.substring(5, path.length()-4);
142                             if(!oldModuleSet.remove(moduleName))
143                                 modules.put(moduleName, new BundleModuleSource(moduleName, bundle, url));
144                             modulesInThisBundle.add(moduleName);
145                         }
146                         for(String oldModule : oldModuleSet)
147                             modules.remove(oldModule);
148                         modulesPerBundle.put(bundle, modulesInThisBundle);
149                     }
150                     else {
151                         for(String oldModule : oldModules)
152                             modules.remove(oldModule);
153                         modulesPerBundle.put(bundle, new ArrayList<String>(0));
154                     }
155                     return true;
156                 }
157             });
158             documentationsPerBundle.forEachEntry(new TObjectObjectProcedure<Bundle, ArrayList<String>>() {
159                 @Override
160                 public boolean execute(Bundle bundle, ArrayList<String> oldDocumentations) {
161                     Enumeration<URL> documentationEntries = bundle.findEntries("scl", "*.md", true);
162                     if(documentationEntries != null) {
163                         THashSet<String> oldDocSet = new THashSet<String>(oldDocumentations);
164                         ArrayList<String> documentationsInThisBundle = new ArrayList<String>();
165                         while(documentationEntries.hasMoreElements()) {
166                             URL url = documentationEntries.nextElement();
167                             String path = url.getPath();
168                             String documentationName = path.substring(5, path.length()-3);
169                             if(!oldDocSet.remove(documentationName))
170                                 documentations.put(documentationName, new BundleDocumentationSource(documentationName, bundle, url));
171                             documentationsInThisBundle.add(documentationName);
172                         }
173                         for(String oldDocumentation : oldDocSet)
174                             documentations.remove(oldDocumentation);
175                         documentationsPerBundle.put(bundle, documentationsInThisBundle);
176                     }
177                     else {
178                         for(String oldDocumentation : oldDocumentations)
179                             documentations.remove(oldDocumentation);
180                         documentationsPerBundle.put(bundle, new ArrayList<String>(0));
181                     }
182                     return true;
183                 }
184             });
185         }
186         for(BundleModuleSource source : modules.values())
187             source.checkUpdates();
188     }
189
190     @Override
191     public void clear() {
192         for (BundleModuleSource source : modules.values()) {
193             source.clear();
194         }
195     }
196
197 }