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