From 8d60995e2ff936c9a360c7fdb69cc4ed44666bc5 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Hannu=20Niemist=C3=B6?= Date: Fri, 23 Dec 2016 16:09:58 +0200 Subject: [PATCH] Fixing a deadlock. Some improvements to ModuleSourceRepository API refs #6851 Change-Id: I4328ab825ae1bb9f9ab529c947f6b02a8d90be83 --- .gitattributes | 10 + .../scl/GraphModuleSourceRepository.java | 414 +++++++++--------- .../scl/OntologyModuleSourceRepository.java | 137 +++--- .../AbstractModuleSourceRepository.java | 19 - .../ClassModuleSourceRepository.java | 13 +- .../CompositeModuleSourceRepository.java | 25 ++ .../FileModuleSourceRepository.java | 13 +- .../repository/MapModuleSourceRepository.java | 20 +- .../repository/ModuleSourceRepository.java | 67 ++- .../BundleModuleSourceRepository.java | 21 +- .../FileSystemModuleSourceRepository.java | 19 +- .../ServiceBasedModuleSourceRepository.java | 51 ++- 12 files changed, 441 insertions(+), 368 deletions(-) create mode 100644 .gitattributes delete mode 100644 bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/source/repository/AbstractModuleSourceRepository.java diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000..146504cda --- /dev/null +++ b/.gitattributes @@ -0,0 +1,10 @@ +*.java text +*.pgraph text +*.scl text +*.xml text +*.svg text +MANIFEST.MF text + +*.tg binary +*.png binary +*.gif binary \ No newline at end of file diff --git a/bundles/org.simantics.modeling/src/org/simantics/modeling/scl/GraphModuleSourceRepository.java b/bundles/org.simantics.modeling/src/org/simantics/modeling/scl/GraphModuleSourceRepository.java index 3edc7bfea..10a217b9d 100644 --- a/bundles/org.simantics.modeling/src/org/simantics/modeling/scl/GraphModuleSourceRepository.java +++ b/bundles/org.simantics.modeling/src/org/simantics/modeling/scl/GraphModuleSourceRepository.java @@ -1,210 +1,204 @@ -package org.simantics.modeling.scl; - -import java.util.Collection; - -import org.simantics.Simantics; -import org.simantics.db.ReadGraph; -import org.simantics.db.RequestProcessorSpecific; -import org.simantics.db.Resource; -import org.simantics.db.WriteGraph; -import org.simantics.db.common.request.UnaryRead; -import org.simantics.db.common.request.WriteRequest; -import org.simantics.db.exception.DatabaseException; -import org.simantics.db.procedure.SyncListener; -import org.simantics.db.request.Read; -import org.simantics.layer0.Layer0; -import org.simantics.modeling.ModelingUtils; -import org.simantics.scl.compiler.module.repository.UpdateListener; -import org.simantics.scl.compiler.source.ModuleSource; -import org.simantics.scl.compiler.source.StringModuleSource; -import org.simantics.scl.compiler.source.repository.ModuleSourceRepository; -import org.simantics.scl.runtime.SCLContext; -import org.simantics.structural2.utils.StructuralUtils; -import org.simantics.scl.runtime.tuple.Tuple0; - -import gnu.trove.procedure.TObjectProcedure; -import gnu.trove.set.hash.THashSet; - -public enum GraphModuleSourceRepository implements ModuleSourceRepository { - INSTANCE; - - @Override - public ModuleSource getModuleSource(final String moduleName, UpdateListener listener) { - if(!moduleName.startsWith("http://")) - return null; - - Object graph = SCLContext.getCurrent().get("graph"); - RequestProcessorSpecific requestProcessor; - if(graph instanceof ReadGraph) - requestProcessor = (ReadGraph)graph; - else - requestProcessor = Simantics.getSession(); - - Read request = new ReadModuleSource(moduleName); - - try { - if(listener != null) - return requestProcessor.syncRequest(request, new ModuleListener(listener, moduleName)); - else - return requestProcessor.syncRequest(request); - } catch (DatabaseException e) { - e.printStackTrace(); - return null; - } - } - - static class ModuleListener implements SyncListener { - UpdateListener listener; - boolean alreadyExecutedOnce; - final String moduleName; - public ModuleListener(UpdateListener listener, String moduleName) { - this.listener = listener; - this.moduleName = moduleName; - } - @Override - public boolean isDisposed() { - return listener == null; - } - private void fireUpdate(ReadGraph graph) { - if(listener != null) { - SCLContext context = SCLContext.getCurrent(); - Object oldGraph = context.put("graph", graph); - try { - listener.notifyAboutUpdate(); - } finally { - listener = null; - context.put("graph", oldGraph); - } - } - } - @Override - public void execute(ReadGraph graph, ModuleSource result) - throws DatabaseException { - if(alreadyExecutedOnce) - fireUpdate(graph); - else - alreadyExecutedOnce = true; - } - @Override - public void exception(ReadGraph graph, Throwable t) - throws DatabaseException { - t.printStackTrace(); - if(alreadyExecutedOnce && listener != null) - fireUpdate(graph); - } - }; - - public static class GraphModuleSource extends StringModuleSource { - - private final boolean immutable; - - public GraphModuleSource(String moduleName, ClassLoader classLoader, String moduleText, boolean immutable) { - super(moduleName, classLoader, moduleText); - this.immutable = immutable; - } - - @Override - public boolean isUpdateable() { - return !immutable; - } - - @Override - public void update(String newSourceText) { - try { - Simantics.getSession().syncRequest(new WriteModuleSource(getModuleName(), newSourceText)); - } catch (DatabaseException e) { - e.printStackTrace(); - } - } - } - - static class ReadModuleSource extends UnaryRead { - public ReadModuleSource(String moduleName) { - super(moduleName); - } - - @Override - public ModuleSource perform(ReadGraph graph) throws DatabaseException { - Resource moduleResource = graph.getPossibleResource(parameter); - if(moduleResource == null) - return null; - Layer0 L0 = Layer0.getInstance(graph); - if(!graph.isInstanceOf(moduleResource, L0.SCLModule)) - return null; - String text = graph.getRelatedValue(moduleResource, L0.SCLModule_definition); - boolean immutable = StructuralUtils.isImmutable(graph, moduleResource); - return new GraphModuleSource(parameter, getClass().getClassLoader(), text, immutable); - } - } - - static class WriteModuleSource extends WriteRequest { - private final String moduleURI; - private final String sourceText; - - public WriteModuleSource(String moduleURI, String sourceText) { - this.moduleURI = moduleURI; - this.sourceText = sourceText; - } - - @Override - public void perform(WriteGraph graph) throws DatabaseException { - Resource moduleResource = graph.getPossibleResource(moduleURI); - if(moduleResource == null) - return; - Layer0 L0 = Layer0.getInstance(graph); - if(!graph.isInstanceOf(moduleResource, L0.SCLModule)) - return; - graph.claimLiteral(moduleResource, L0.SCLModule_definition, sourceText); - } - } - - @Override - public void forAllModules(TObjectProcedure procedure) { - THashSet moduleURIs; - try { - moduleURIs = Simantics.getSession().syncRequest(new Read>() { - @Override - public THashSet perform(ReadGraph graph) - throws DatabaseException { - THashSet result = new THashSet(); - Resource projectResource = Simantics.getProjectResource(); - Layer0 L0 = Layer0.getInstance(graph); - for(Resource model : graph.getObjects(projectResource, L0.ConsistsOf)) { - if(graph.isInstanceOf(model, L0.IndexRoot)) { - for(Resource module : ModelingUtils.searchByType(graph, model, L0.SCLModule)) - result.add(graph.getURI(module)); - } - } - - Collection ontologies = Simantics.applySCL("Simantics/SharedOntologies", "getSharedOntologies", graph, Tuple0.INSTANCE); - for (Resource ontology : ontologies) { - for(Resource module : ModelingUtils.searchByType(graph, ontology, L0.SCLModule)) - result.add(graph.getURI(module)); - } - - return result; - } - }); - moduleURIs.forEach(procedure); - } catch (DatabaseException e) { - e.printStackTrace(); - } - } - - @Override - public void checkUpdates() { - } - - @Override - public String getDocumentation(String documentationName) { - return null; - } - - @Override - public void forAllDocumentations(TObjectProcedure procedure) { - } - - @Override - public void clear() { - } -} +package org.simantics.modeling.scl; + +import java.util.ArrayList; +import java.util.Collection; + +import org.simantics.Simantics; +import org.simantics.db.ReadGraph; +import org.simantics.db.RequestProcessorSpecific; +import org.simantics.db.Resource; +import org.simantics.db.WriteGraph; +import org.simantics.db.common.request.UnaryRead; +import org.simantics.db.common.request.WriteRequest; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.procedure.SyncListener; +import org.simantics.db.request.Read; +import org.simantics.layer0.Layer0; +import org.simantics.modeling.ModelingUtils; +import org.simantics.scl.compiler.module.repository.UpdateListener; +import org.simantics.scl.compiler.source.ModuleSource; +import org.simantics.scl.compiler.source.StringModuleSource; +import org.simantics.scl.compiler.source.repository.ModuleSourceRepository; +import org.simantics.scl.runtime.SCLContext; +import org.simantics.structural2.utils.StructuralUtils; +import org.simantics.scl.runtime.tuple.Tuple0; + +import gnu.trove.procedure.TObjectProcedure; +import gnu.trove.set.hash.THashSet; + +public enum GraphModuleSourceRepository implements ModuleSourceRepository { + INSTANCE; + + @Override + public ModuleSource getModuleSource(final String moduleName, UpdateListener listener) { + if(!moduleName.startsWith("http://")) + return null; + + Object graph = SCLContext.getCurrent().get("graph"); + RequestProcessorSpecific requestProcessor; + if(graph instanceof ReadGraph) + requestProcessor = (ReadGraph)graph; + else + requestProcessor = Simantics.getSession(); + + Read request = new ReadModuleSource(moduleName); + + try { + if(listener != null) + return requestProcessor.syncRequest(request, new ModuleListener(listener, moduleName)); + else + return requestProcessor.syncRequest(request); + } catch (DatabaseException e) { + e.printStackTrace(); + return null; + } + } + + static class ModuleListener implements SyncListener { + UpdateListener listener; + boolean alreadyExecutedOnce; + final String moduleName; + public ModuleListener(UpdateListener listener, String moduleName) { + this.listener = listener; + this.moduleName = moduleName; + } + @Override + public boolean isDisposed() { + return listener == null; + } + private void fireUpdate(ReadGraph graph) { + if(listener != null) { + SCLContext context = SCLContext.getCurrent(); + Object oldGraph = context.put("graph", graph); + try { + listener.notifyAboutUpdate(); + } finally { + listener = null; + context.put("graph", oldGraph); + } + } + } + @Override + public void execute(ReadGraph graph, ModuleSource result) + throws DatabaseException { + if(alreadyExecutedOnce) + fireUpdate(graph); + else + alreadyExecutedOnce = true; + } + @Override + public void exception(ReadGraph graph, Throwable t) + throws DatabaseException { + t.printStackTrace(); + if(alreadyExecutedOnce && listener != null) + fireUpdate(graph); + } + }; + + public static class GraphModuleSource extends StringModuleSource { + + private final boolean immutable; + + public GraphModuleSource(String moduleName, ClassLoader classLoader, String moduleText, boolean immutable) { + super(moduleName, classLoader, moduleText); + this.immutable = immutable; + } + + @Override + public boolean isUpdateable() { + return !immutable; + } + + @Override + public void update(String newSourceText) { + try { + Simantics.getSession().syncRequest(new WriteModuleSource(getModuleName(), newSourceText)); + } catch (DatabaseException e) { + e.printStackTrace(); + } + } + } + + static class ReadModuleSource extends UnaryRead { + public ReadModuleSource(String moduleName) { + super(moduleName); + } + + @Override + public ModuleSource perform(ReadGraph graph) throws DatabaseException { + Resource moduleResource = graph.getPossibleResource(parameter); + if(moduleResource == null) + return null; + Layer0 L0 = Layer0.getInstance(graph); + if(!graph.isInstanceOf(moduleResource, L0.SCLModule)) + return null; + String text = graph.getRelatedValue(moduleResource, L0.SCLModule_definition); + boolean immutable = StructuralUtils.isImmutable(graph, moduleResource); + return new GraphModuleSource(parameter, getClass().getClassLoader(), text, immutable); + } + } + + static class WriteModuleSource extends WriteRequest { + private final String moduleURI; + private final String sourceText; + + public WriteModuleSource(String moduleURI, String sourceText) { + this.moduleURI = moduleURI; + this.sourceText = sourceText; + } + + @Override + public void perform(WriteGraph graph) throws DatabaseException { + Resource moduleResource = graph.getPossibleResource(moduleURI); + if(moduleResource == null) + return; + Layer0 L0 = Layer0.getInstance(graph); + if(!graph.isInstanceOf(moduleResource, L0.SCLModule)) + return; + graph.claimLiteral(moduleResource, L0.SCLModule_definition, sourceText); + } + } + + @Override + public void forAllModules(TObjectProcedure procedure) { + THashSet moduleURIs; + try { + moduleURIs = Simantics.getSession().syncRequest(new Read>() { + @Override + public THashSet perform(ReadGraph graph) + throws DatabaseException { + THashSet result = new THashSet(); + Resource projectResource = Simantics.getProjectResource(); + Layer0 L0 = Layer0.getInstance(graph); + for(Resource model : graph.getObjects(projectResource, L0.ConsistsOf)) { + if(graph.isInstanceOf(model, L0.IndexRoot)) { + for(Resource module : ModelingUtils.searchByType(graph, model, L0.SCLModule)) + result.add(graph.getURI(module)); + } + } + + Collection ontologies = Simantics.applySCL("Simantics/SharedOntologies", "getSharedOntologies", graph, Tuple0.INSTANCE); + for (Resource ontology : ontologies) { + for(Resource module : ModelingUtils.searchByType(graph, ontology, L0.SCLModule)) + result.add(graph.getURI(module)); + } + + return result; + } + }); + moduleURIs.forEach(procedure); + } catch (DatabaseException e) { + e.printStackTrace(); + } + } + + @Override + public Collection getModuleNames() { + ArrayList result = new ArrayList<>(); + forAllModules((String name) -> { + result.add(name); + return true; + }); + return result; + } +} diff --git a/bundles/org.simantics.modeling/src/org/simantics/modeling/scl/OntologyModuleSourceRepository.java b/bundles/org.simantics.modeling/src/org/simantics/modeling/scl/OntologyModuleSourceRepository.java index a8cefb1fa..6fbcfd8e9 100644 --- a/bundles/org.simantics.modeling/src/org/simantics/modeling/scl/OntologyModuleSourceRepository.java +++ b/bundles/org.simantics.modeling/src/org/simantics/modeling/scl/OntologyModuleSourceRepository.java @@ -1,73 +1,64 @@ -package org.simantics.modeling.scl; - - -import org.simantics.Simantics; -import org.simantics.db.ReadGraph; -import org.simantics.db.common.request.UnaryRead; -import org.simantics.db.exception.DatabaseException; -import org.simantics.scl.compiler.module.repository.UpdateListener; -import org.simantics.scl.compiler.source.ModuleSource; -import org.simantics.scl.compiler.source.PrecompiledModuleSource; -import org.simantics.scl.compiler.source.repository.ModuleSourceRepository; -import org.simantics.scl.runtime.SCLContext; - -import gnu.trove.procedure.TObjectProcedure; - -public enum OntologyModuleSourceRepository implements ModuleSourceRepository { - INSTANCE; - - static class ModuleSourceRequest extends UnaryRead { - - public ModuleSourceRequest(String moduleName) { - super(moduleName); - } - - @Override - public ModuleSource perform(ReadGraph graph) throws DatabaseException { - return new PrecompiledModuleSource(new OntologyModule(graph, parameter), -1.0); - } - - }; - - @Override - public ModuleSource getModuleSource(final String moduleName, - UpdateListener listener) { - if(!moduleName.startsWith("http://")) - return null; // Don't do a graph request if this cannot be a resource - - ReadGraph graph = (ReadGraph)SCLContext.getCurrent().get("graph"); - - try { - if(graph != null) { - return new PrecompiledModuleSource(new OntologyModule(graph, moduleName), -1.0); - } - - return Simantics.getSession().syncRequest(new ModuleSourceRequest(moduleName)); - } catch(DatabaseException e) { - e.printStackTrace(); - return null; - } - } - - @Override - public void forAllModules(TObjectProcedure procedure) { - } - - @Override - public void checkUpdates() { - } - - @Override - public String getDocumentation(String documentationName) { - return null; - } - - @Override - public void forAllDocumentations(TObjectProcedure procedure) { - } - - @Override - public void clear() { - } - -} +package org.simantics.modeling.scl; + + +import java.util.Collection; +import java.util.Collections; + +import org.simantics.Simantics; +import org.simantics.db.ReadGraph; +import org.simantics.db.common.request.UnaryRead; +import org.simantics.db.exception.DatabaseException; +import org.simantics.scl.compiler.module.repository.UpdateListener; +import org.simantics.scl.compiler.source.ModuleSource; +import org.simantics.scl.compiler.source.PrecompiledModuleSource; +import org.simantics.scl.compiler.source.repository.ModuleSourceRepository; +import org.simantics.scl.runtime.SCLContext; + +import gnu.trove.procedure.TObjectProcedure; + +public enum OntologyModuleSourceRepository implements ModuleSourceRepository { + INSTANCE; + + static class ModuleSourceRequest extends UnaryRead { + + public ModuleSourceRequest(String moduleName) { + super(moduleName); + } + + @Override + public ModuleSource perform(ReadGraph graph) throws DatabaseException { + return new PrecompiledModuleSource(new OntologyModule(graph, parameter), -1.0); + } + + }; + + @Override + public ModuleSource getModuleSource(final String moduleName, + UpdateListener listener) { + if(!moduleName.startsWith("http://")) + return null; // Don't do a graph request if this cannot be a resource + + ReadGraph graph = (ReadGraph)SCLContext.getCurrent().get("graph"); + + try { + if(graph != null) { + return new PrecompiledModuleSource(new OntologyModule(graph, moduleName), -1.0); + } + + return Simantics.getSession().syncRequest(new ModuleSourceRequest(moduleName)); + } catch(DatabaseException e) { + e.printStackTrace(); + return null; + } + } + + @Override + public void forAllModules(TObjectProcedure procedure) { + } + + @Override + public Collection getModuleNames() { + return Collections.emptyList(); + } + +} diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/source/repository/AbstractModuleSourceRepository.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/source/repository/AbstractModuleSourceRepository.java deleted file mode 100644 index 1436310fe..000000000 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/source/repository/AbstractModuleSourceRepository.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.simantics.scl.compiler.source.repository; - -import gnu.trove.procedure.TObjectProcedure; - - -public abstract class AbstractModuleSourceRepository implements ModuleSourceRepository { - @Override - public String getDocumentation(String documentationName) { - return null; - } - - @Override - public void forAllDocumentations(TObjectProcedure procedure) { - } - - @Override - public void checkUpdates() { - } -} diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/source/repository/ClassModuleSourceRepository.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/source/repository/ClassModuleSourceRepository.java index 873859a2d..581f1db8a 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/source/repository/ClassModuleSourceRepository.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/source/repository/ClassModuleSourceRepository.java @@ -2,6 +2,7 @@ package org.simantics.scl.compiler.source.repository; import java.io.IOException; import java.net.URL; +import java.util.Collection; import org.simantics.scl.compiler.module.ImportDeclaration; import org.simantics.scl.compiler.module.repository.UpdateListener; @@ -11,7 +12,7 @@ import org.simantics.scl.compiler.source.ModuleSource; import gnu.trove.procedure.TObjectProcedure; import gnu.trove.set.hash.THashSet; -public class ClassModuleSourceRepository extends AbstractModuleSourceRepository { +public class ClassModuleSourceRepository implements ModuleSourceRepository { private final Class clazz; private final String path; @@ -36,6 +37,11 @@ public class ClassModuleSourceRepository extends AbstractModuleSourceRepository return new ClassModuleSource(moduleName, clazz, classLoader, path + "/" + moduleName + ".scl", getBuiltinImports()); } + @Override + public Collection getModuleNames() { + return modules; + } + @Override public void forAllModules(TObjectProcedure procedure) { modules.forEach(procedure); @@ -44,9 +50,4 @@ public class ClassModuleSourceRepository extends AbstractModuleSourceRepository protected ImportDeclaration[] getBuiltinImports() { return ClassModuleSource.DEFAULT_IMPORTS; } - - @Override - public void clear() { - - } } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/source/repository/CompositeModuleSourceRepository.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/source/repository/CompositeModuleSourceRepository.java index 82bb0bcf9..b55e3d285 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/source/repository/CompositeModuleSourceRepository.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/source/repository/CompositeModuleSourceRepository.java @@ -1,5 +1,8 @@ package org.simantics.scl.compiler.source.repository; +import java.util.ArrayList; +import java.util.Collection; + import org.simantics.scl.compiler.module.repository.UpdateListener; import org.simantics.scl.compiler.source.ModuleSource; @@ -50,14 +53,36 @@ public class CompositeModuleSourceRepository implements ModuleSourceRepository { sourceRepository.forAllModules(procedure); } + @Override + public Collection getModuleNames() { + ArrayList result = new ArrayList<>(); + forAllModules((String name) -> { + result.add(name); + return true; + }); + return result; + } + @Override public void forAllDocumentations(TObjectProcedure procedure) { for(ModuleSourceRepository sourceRepository : children) sourceRepository.forAllDocumentations(procedure); } + + @Override + public Collection getDocumentationNames() { + ArrayList result = new ArrayList<>(); + forAllDocumentations((String name) -> { + result.add(name); + return true; + }); + return result; + } @Override public void checkUpdates() { + for (ModuleSourceRepository child : children) + child.checkUpdates(); } @Override diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/source/repository/FileModuleSourceRepository.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/source/repository/FileModuleSourceRepository.java index 805dd77f4..d2caa3883 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/source/repository/FileModuleSourceRepository.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/source/repository/FileModuleSourceRepository.java @@ -2,6 +2,7 @@ package org.simantics.scl.compiler.source.repository; import java.io.File; import java.io.IOException; +import java.util.Collection; import org.simantics.scl.compiler.module.ImportDeclaration; import org.simantics.scl.compiler.module.repository.UpdateListener; @@ -12,7 +13,7 @@ import org.simantics.scl.compiler.source.ModuleSource; import gnu.trove.procedure.TObjectProcedure; import gnu.trove.set.hash.THashSet; -public class FileModuleSourceRepository extends AbstractModuleSourceRepository { +public class FileModuleSourceRepository implements ModuleSourceRepository { private final File path; private final ClassLoader classLoader; @@ -37,12 +38,12 @@ public class FileModuleSourceRepository extends AbstractModuleSourceRepository { modules.forEach(procedure); } + @Override + public Collection getModuleNames() { + return modules; + } + protected ImportDeclaration[] getBuiltinImports() { return ClassModuleSource.DEFAULT_IMPORTS; } - - @Override - public void clear() { - - } } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/source/repository/MapModuleSourceRepository.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/source/repository/MapModuleSourceRepository.java index 9872451c3..939010d40 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/source/repository/MapModuleSourceRepository.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/source/repository/MapModuleSourceRepository.java @@ -1,5 +1,7 @@ package org.simantics.scl.compiler.source.repository; +import java.util.Collection; + import org.simantics.scl.compiler.module.Module; import org.simantics.scl.compiler.module.repository.UpdateListener; import org.simantics.scl.compiler.source.ModuleSource; @@ -50,6 +52,11 @@ public class MapModuleSourceRepository implements ModuleSourceRepository { return modules.get(moduleName); } + @Override + public Collection getModuleNames() { + return modules.keySet(); + } + @Override public void forAllModules(TObjectProcedure procedure) { modules.forEachKey(procedure); @@ -61,16 +68,7 @@ public class MapModuleSourceRepository implements ModuleSourceRepository { } @Override - public void forAllDocumentations(TObjectProcedure procedure) { - for(String documentationName : documentations.keySet()) - procedure.execute(documentationName); - } - - @Override - public void checkUpdates() { - } - - @Override - public void clear() { + public Collection getDocumentationNames() { + return documentations.keySet(); } } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/source/repository/ModuleSourceRepository.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/source/repository/ModuleSourceRepository.java index 76698f5be..c335a8aa1 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/source/repository/ModuleSourceRepository.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/source/repository/ModuleSourceRepository.java @@ -1,5 +1,8 @@ package org.simantics.scl.compiler.source.repository; +import java.util.Collection; +import java.util.Collections; + import org.simantics.scl.compiler.module.repository.ModuleRepository; import org.simantics.scl.compiler.module.repository.UpdateListener; import org.simantics.scl.compiler.source.ModuleSource; @@ -13,10 +16,64 @@ import gnu.trove.procedure.TObjectProcedure; * @author Hannu Niemistö */ public interface ModuleSourceRepository { + /** + * Returns all module names governed by this repository. Some implementations + * may return empty collection, even if the contain modules, if it is hard + * to discover all modules (for example file system based module repository + * works like this). + */ + Collection getModuleNames(); + + /** + * Calls the given procedure with all module names returned by {@link #getModuleNames} + */ + default void forAllModules(TObjectProcedure procedure) { + for(String module : getModuleNames()) + if(!procedure.execute(module)) + return; + } + + /** + * Returns the module source of the given module name or null, if the module does not exists. + * If {@code listener} is not null, it is called when the module contents change. + */ ModuleSource getModuleSource(String moduleName, UpdateListener listener); - void forAllModules(TObjectProcedure procedure); - String getDocumentation(String documentationName); - void forAllDocumentations(TObjectProcedure procedure); - void checkUpdates(); - void clear(); + + /** + * Returns all documentation names governed by this repository. Some implementations + * may return empty collection, even if the contain documentation. + */ + default Collection getDocumentationNames() { + return Collections.emptyList(); + } + + /** + * Calls the given procedure with all documentation names eturned by {@link #getDocumentationNames} + */ + default void forAllDocumentations(TObjectProcedure procedure) { + for(String module : getDocumentationNames()) + if(!procedure.execute(module)) + return; + } + + /** + * Returns original markdown text for the given documentation name or null + * if the documentation does not exist. + */ + default String getDocumentation(String documentationName) { + return null; + } + + /** + * Triggers repository to check if module contents have been changed. Some repositories listen + * changes and report them to update listeners even without manual triggering. + */ + default void checkUpdates() { + } + + /** + * Resets the repository and removes listeners. This is only used during regression testing and shouldn't be called during normal operation. + */ + default void clear() { + } } 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 index 31d06b726..b3f5ac319 100644 --- 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 @@ -2,6 +2,7 @@ package org.simantics.scl.osgi.internal; import java.net.URL; import java.util.ArrayList; +import java.util.Collection; import java.util.Enumeration; import org.osgi.framework.Bundle; @@ -14,16 +15,14 @@ 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 { +public class BundleModuleSourceRepository implements ModuleSourceRepository { Tracker tracker; THashMap modules = new THashMap(); @@ -107,8 +106,13 @@ public class BundleModuleSourceRepository extends AbstractModuleSourceRepository } @Override - synchronized public void forAllModules(TObjectProcedure procedure) { - modules.forEachKey(procedure); + public synchronized Collection getModuleNames() { + return new ArrayList(modules.keySet()); + } + + @Override + public synchronized Collection getDocumentationNames() { + return new ArrayList(documentations.keySet()); } @Override @@ -119,12 +123,7 @@ public class BundleModuleSourceRepository extends AbstractModuleSourceRepository else return source.getText(); } - - @Override - synchronized public void forAllDocumentations(TObjectProcedure procedure) { - documentations.forEachKey(procedure); - } - + @Override public void checkUpdates() { synchronized(this) { diff --git a/bundles/org.simantics.scl.osgi/src/org/simantics/scl/osgi/internal/FileSystemModuleSourceRepository.java b/bundles/org.simantics.scl.osgi/src/org/simantics/scl/osgi/internal/FileSystemModuleSourceRepository.java index 0e26c1d27..68e6ac050 100644 --- a/bundles/org.simantics.scl.osgi/src/org/simantics/scl/osgi/internal/FileSystemModuleSourceRepository.java +++ b/bundles/org.simantics.scl.osgi/src/org/simantics/scl/osgi/internal/FileSystemModuleSourceRepository.java @@ -1,6 +1,8 @@ package org.simantics.scl.osgi.internal; import java.io.File; +import java.util.Collection; +import java.util.Collections; import org.osgi.service.component.annotations.Component; import org.simantics.scl.compiler.module.repository.UpdateListener; @@ -23,23 +25,12 @@ public class FileSystemModuleSourceRepository implements ModuleSourceRepository } @Override - synchronized public void forAllModules(TObjectProcedure procedure) { + public Collection getModuleNames() { + return Collections.emptyList(); } @Override - public String getDocumentation(String documentationName) { - return null; + public void forAllModules(TObjectProcedure procedure) { } - @Override - public void forAllDocumentations(TObjectProcedure procedure) { - } - - @Override - public void checkUpdates() { - } - - @Override - public void clear() { - } } diff --git a/bundles/org.simantics.scl.osgi/src/org/simantics/scl/osgi/internal/ServiceBasedModuleSourceRepository.java b/bundles/org.simantics.scl.osgi/src/org/simantics/scl/osgi/internal/ServiceBasedModuleSourceRepository.java index 9b173e48d..ac8384c24 100644 --- a/bundles/org.simantics.scl.osgi/src/org/simantics/scl/osgi/internal/ServiceBasedModuleSourceRepository.java +++ b/bundles/org.simantics.scl.osgi/src/org/simantics/scl/osgi/internal/ServiceBasedModuleSourceRepository.java @@ -1,6 +1,7 @@ package org.simantics.scl.osgi.internal; -import gnu.trove.procedure.TObjectProcedure; +import java.util.ArrayList; +import java.util.Collection; import org.osgi.framework.BundleContext; import org.osgi.util.tracker.ServiceTracker; @@ -8,6 +9,8 @@ import org.simantics.scl.compiler.module.repository.UpdateListener; import org.simantics.scl.compiler.source.ModuleSource; import org.simantics.scl.compiler.source.repository.ModuleSourceRepository; +import gnu.trove.procedure.TObjectProcedure; + public class ServiceBasedModuleSourceRepository implements ModuleSourceRepository { ServiceTracker sourceRepositories; @@ -45,6 +48,7 @@ public class ServiceBasedModuleSourceRepository implements ModuleSourceRepositor @Override public String getDocumentation(String documentationName) { + // getServices is internally synchronized, so no need to synchronize here Object[] services = sourceRepositories.getServices(); if(services != null) for(Object sourceRepository_ : services) { @@ -58,18 +62,43 @@ public class ServiceBasedModuleSourceRepository implements ModuleSourceRepositor @Override public void forAllModules(TObjectProcedure procedure) { - for(Object sourceRepository_ : sourceRepositories.getServices()) { - ModuleSourceRepository sourceLoader = (ModuleSourceRepository)sourceRepository_; - sourceLoader.forAllModules(procedure); - } + // getServices is internally synchronized, so no need to synchronize here + Object[] services = sourceRepositories.getServices(); + if(services != null) + for(Object sourceRepository_ : services) { + ModuleSourceRepository sourceLoader = (ModuleSourceRepository)sourceRepository_; + sourceLoader.forAllModules(procedure); + } + } + + @Override + public Collection getModuleNames() { + ArrayList result = new ArrayList<>(); + forAllModules((String name) -> { + result.add(name); + return true; + }); + return result; } @Override public void forAllDocumentations(TObjectProcedure procedure) { - for(Object sourceRepository_ : sourceRepositories.getServices()) { - ModuleSourceRepository sourceLoader = (ModuleSourceRepository)sourceRepository_; - sourceLoader.forAllDocumentations(procedure); - } + Object[] services = sourceRepositories.getServices(); + if(services != null) + for(Object sourceRepository_ : services) { + ModuleSourceRepository sourceLoader = (ModuleSourceRepository)sourceRepository_; + sourceLoader.forAllDocumentations(procedure); + } + } + + @Override + public Collection getDocumentationNames() { + ArrayList result = new ArrayList<>(); + forAllDocumentations((String name) -> { + result.add(name); + return true; + }); + return result; } @Override @@ -80,8 +109,4 @@ public class ServiceBasedModuleSourceRepository implements ModuleSourceRepositor } } - @Override - public void clear() { - } - } -- 2.47.1