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