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