]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.osgi/src/org/simantics/scl/osgi/internal/BundleModuleSource.java
Merge "Remove unused import in DeleteHandler"
[simantics/platform.git] / bundles / org.simantics.scl.osgi / src / org / simantics / scl / osgi / internal / BundleModuleSource.java
1 package org.simantics.scl.osgi.internal;\r
2 \r
3 import java.io.IOException;\r
4 import java.io.InputStream;\r
5 import java.net.URISyntaxException;\r
6 import java.net.URL;\r
7 import java.nio.charset.Charset;\r
8 import java.nio.file.Files;\r
9 import java.nio.file.Path;\r
10 import java.nio.file.Paths;\r
11 import java.security.MessageDigest;\r
12 import java.security.NoSuchAlgorithmException;\r
13 import java.util.ArrayList;\r
14 import java.util.Arrays;\r
15 \r
16 import org.eclipse.core.runtime.FileLocator;\r
17 import org.osgi.framework.Bundle;\r
18 import org.osgi.framework.wiring.BundleWiring;\r
19 import org.simantics.scl.compiler.module.ImportDeclaration;\r
20 import org.simantics.scl.compiler.module.repository.UpdateListener;\r
21 import org.simantics.scl.compiler.source.EncodedTextualModuleSource;\r
22 import org.simantics.scl.compiler.types.Type;\r
23 \r
24 public class BundleModuleSource extends EncodedTextualModuleSource {\r
25 \r
26     public static final ImportDeclaration[] DEFAULT_IMPORTS = new ImportDeclaration[] {\r
27         new ImportDeclaration("Builtin", ""),\r
28         new ImportDeclaration("StandardLibrary", "")\r
29     };\r
30     \r
31     public static final ImportDeclaration[] DEFAULT_IMPORTS_FOR_STANDARD_LIBRARY = new ImportDeclaration[] {\r
32         new ImportDeclaration("Builtin", ""),\r
33     };\r
34     \r
35     public final Bundle bundle;\r
36     public final URL url;\r
37     \r
38     private byte[] digest;\r
39     private ArrayList<UpdateListener> listeners;\r
40     \r
41     public BundleModuleSource(String moduleName, Bundle bundle, URL url) {\r
42         super(moduleName);\r
43         this.bundle = bundle;\r
44         this.url = url;\r
45     }\r
46 \r
47     @Override\r
48     protected ImportDeclaration[] getBuiltinImports(UpdateListener listener) {\r
49         if(bundle.getSymbolicName().equals("org.simantics.scl.runtime"))\r
50             return DEFAULT_IMPORTS_FOR_STANDARD_LIBRARY;\r
51         else\r
52             return DEFAULT_IMPORTS;\r
53     }\r
54     \r
55     private byte[] computeDigest() {\r
56         try {\r
57             InputStream stream = url.openStream();\r
58             try {\r
59                 MessageDigest digest = MessageDigest.getInstance("SHA1");\r
60                 byte[] buffer = new byte[1024];\r
61                 while(true) {\r
62                     int count = stream.read(buffer);\r
63                     if(count <= 0)\r
64                         break;\r
65                     digest.update(buffer, 0, count);\r
66                 }\r
67                 return digest.digest();\r
68             } catch (NoSuchAlgorithmException e) {\r
69                 e.printStackTrace();\r
70                 return new byte[0];\r
71             } finally {\r
72                 stream.close();\r
73             }\r
74         } catch(IOException e) {\r
75             e.printStackTrace();\r
76             return new byte[0];\r
77         }\r
78     }\r
79     \r
80     @Override\r
81     protected InputStream getSourceStream(UpdateListener listener)\r
82             throws IOException {\r
83         if(digest == null)\r
84             digest = computeDigest();\r
85         if(listener != null) {\r
86             if(listeners == null)\r
87                 listeners = new ArrayList<UpdateListener>(2);\r
88             listeners.add(listener);\r
89         }\r
90         return url.openStream();\r
91     }\r
92     \r
93     @Override\r
94     public ClassLoader getClassLoader() {\r
95         if(bundle.getSymbolicName().equals("org.simantics.scl.runtime"))\r
96             return Type.class.getClassLoader();\r
97         else {\r
98             BundleWiring wiring = bundle.adapt(BundleWiring.class);\r
99             if(wiring != null)\r
100                 return wiring.getClassLoader();\r
101             else\r
102                 return getClass().getClassLoader();\r
103         }\r
104     }\r
105 \r
106     public void checkUpdates() {\r
107         if(digest != null && listeners != null) {\r
108             byte[] newDigest = computeDigest();\r
109             if(!Arrays.equals(digest, newDigest)) {\r
110                 digest = newDigest;\r
111                 ArrayList<UpdateListener> oldListeners = listeners;\r
112                 listeners = null;\r
113                 for(UpdateListener listener : oldListeners)\r
114                     listener.notifyAboutUpdate();\r
115             }\r
116         }\r
117     }\r
118     \r
119     private Path getPath() throws IOException {\r
120         try {\r
121             return Paths.get(FileLocator.toFileURL(url).toURI());\r
122         } catch (URISyntaxException e) {\r
123             throw new IOException(e);\r
124         }\r
125     }\r
126     \r
127     @Override\r
128     public boolean isUpdateable() {\r
129         try {\r
130             return Files.exists(getPath());\r
131         } catch (IOException e) {\r
132             return false;\r
133         }\r
134     }\r
135     \r
136     @Override\r
137     public void update(String newSourceText) {\r
138         try {\r
139             Path path = getPath();\r
140             Files.write(path, newSourceText.getBytes(Charset.forName("UTF-8")));\r
141         } catch(IOException e) {\r
142             e.printStackTrace();\r
143         }\r
144         checkUpdates();\r
145     }\r
146 \r
147     public void clear() {\r
148         if (listeners != null) {\r
149             listeners.clear();\r
150             listeners = null;\r
151         }\r
152     }\r
153 \r
154 }\r