]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.scl.osgi/src/org/simantics/scl/osgi/internal/BundleModuleSource.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.scl.osgi / src / org / simantics / scl / osgi / internal / BundleModuleSource.java
diff --git a/bundles/org.simantics.scl.osgi/src/org/simantics/scl/osgi/internal/BundleModuleSource.java b/bundles/org.simantics.scl.osgi/src/org/simantics/scl/osgi/internal/BundleModuleSource.java
new file mode 100644 (file)
index 0000000..66431fe
--- /dev/null
@@ -0,0 +1,157 @@
+package org.simantics.scl.osgi.internal;\r
+\r
+import java.io.File;\r
+import java.io.IOException;\r
+import java.io.InputStream;\r
+import java.net.URISyntaxException;\r
+import java.net.URL;\r
+import java.nio.charset.Charset;\r
+import java.nio.file.Files;\r
+import java.nio.file.Path;\r
+import java.nio.file.Paths;\r
+import java.security.MessageDigest;\r
+import java.security.NoSuchAlgorithmException;\r
+import java.util.ArrayList;\r
+import java.util.Arrays;\r
+\r
+import org.eclipse.core.runtime.FileLocator;\r
+import org.osgi.framework.Bundle;\r
+import org.osgi.framework.wiring.BundleWiring;\r
+import org.simantics.scl.compiler.module.ImportDeclaration;\r
+import org.simantics.scl.compiler.module.repository.UpdateListener;\r
+import org.simantics.scl.compiler.source.EncodedTextualModuleSource;\r
+import org.simantics.scl.compiler.types.Type;\r
+\r
+public class BundleModuleSource extends EncodedTextualModuleSource {\r
+\r
+    public static final ImportDeclaration[] DEFAULT_IMPORTS = new ImportDeclaration[] {\r
+        new ImportDeclaration("Builtin", ""),\r
+        new ImportDeclaration("StandardLibrary", "")\r
+    };\r
+    \r
+    public static final ImportDeclaration[] DEFAULT_IMPORTS_FOR_STANDARD_LIBRARY = new ImportDeclaration[] {\r
+        new ImportDeclaration("Builtin", ""),\r
+    };\r
+    \r
+    public final Bundle bundle;\r
+    public final URL url;\r
+    \r
+    private byte[] digest;\r
+    private ArrayList<UpdateListener> listeners;\r
+    \r
+    public BundleModuleSource(String moduleName, Bundle bundle, URL url) {\r
+        super(moduleName);\r
+        this.bundle = bundle;\r
+        this.url = url;\r
+    }\r
+\r
+    @Override\r
+    protected ImportDeclaration[] getBuiltinImports(UpdateListener listener) {\r
+        if(bundle.getSymbolicName().equals("org.simantics.scl.runtime"))\r
+            return DEFAULT_IMPORTS_FOR_STANDARD_LIBRARY;\r
+        else\r
+            return DEFAULT_IMPORTS;\r
+    }\r
+    \r
+    private byte[] computeDigest() {\r
+        try {\r
+            InputStream stream = url.openStream();\r
+            try {\r
+                MessageDigest digest = MessageDigest.getInstance("SHA1");\r
+                byte[] buffer = new byte[1024];\r
+                while(true) {\r
+                    int count = stream.read(buffer);\r
+                    if(count <= 0)\r
+                        break;\r
+                    digest.update(buffer, 0, count);\r
+                }\r
+                return digest.digest();\r
+            } catch (NoSuchAlgorithmException e) {\r
+                e.printStackTrace();\r
+                return new byte[0];\r
+            } finally {\r
+                stream.close();\r
+            }\r
+        } catch(IOException e) {\r
+            e.printStackTrace();\r
+            return new byte[0];\r
+        }\r
+    }\r
+    \r
+    @Override\r
+    protected InputStream getSourceStream(UpdateListener listener)\r
+            throws IOException {\r
+        if(digest == null)\r
+            digest = computeDigest();\r
+        if(listener != null) {\r
+            if(listeners == null)\r
+                listeners = new ArrayList<UpdateListener>(2);\r
+            listeners.add(listener);\r
+        }\r
+        return url.openStream();\r
+    }\r
+    \r
+    @Override\r
+    public ClassLoader getClassLoader() {\r
+        if(bundle.getSymbolicName().equals("org.simantics.scl.runtime"))\r
+            return Type.class.getClassLoader();\r
+        else {\r
+            BundleWiring wiring = bundle.adapt(BundleWiring.class);\r
+            if(wiring != null)\r
+                return wiring.getClassLoader();\r
+            else\r
+                return getClass().getClassLoader();\r
+        }\r
+    }\r
+\r
+    public void checkUpdates() {\r
+        System.out.println(url + " checkUpdates");\r
+        if(digest != null && listeners != null) {\r
+            byte[] newDigest = computeDigest();\r
+            if(!Arrays.equals(digest, newDigest)) {\r
+                digest = newDigest;\r
+                ArrayList<UpdateListener> oldListeners = listeners;\r
+                listeners = null;\r
+                for(UpdateListener listener : oldListeners)\r
+                    listener.notifyAboutUpdate();\r
+            }\r
+        }\r
+    }\r
+    \r
+    private Path getPath() throws IOException {\r
+        try {\r
+            return Paths.get(FileLocator.toFileURL(url).toURI());\r
+        } catch (URISyntaxException e) {\r
+            throw new IOException(e);\r
+        }\r
+    }\r
+    \r
+    @Override\r
+    public boolean isUpdateable() {\r
+        try {\r
+            return Files.exists(getPath());\r
+        } catch (IOException e) {\r
+            return false;\r
+        }\r
+    }\r
+    \r
+    @Override\r
+    public void update(String newSourceText) {\r
+        System.out.println(url + " update");\r
+        try {\r
+            Path path = getPath();\r
+            Files.write(path, newSourceText.getBytes(Charset.forName("UTF-8")));\r
+        } catch(IOException e) {\r
+            e.printStackTrace();\r
+        }\r
+        checkUpdates();\r
+    }\r
+\r
+    public void clear() {\r
+        if (listeners != null) {\r
+            listeners.clear();\r
+            listeners = null;\r
+        }\r
+    }\r
+\r
+}\r