1 package org.simantics.scl.osgi.internal;
3 import java.io.IOException;
4 import java.io.InputStream;
5 import java.net.URISyntaxException;
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;
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.internal.codegen.types.JavaReferenceValidatorFactory;
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;
24 import gnu.trove.set.hash.THashSet;
26 public class BundleModuleSource extends EncodedTextualModuleSource implements UpdateListener.Observable {
28 public static final ImportDeclaration[] DEFAULT_IMPORTS = new ImportDeclaration[] {
29 new ImportDeclaration("Builtin", ""),
30 new ImportDeclaration("StandardLibrary", "")
33 public static final ImportDeclaration[] DEFAULT_IMPORTS_FOR_STANDARD_LIBRARY = new ImportDeclaration[] {
34 new ImportDeclaration("Builtin", ""),
37 public final Bundle bundle;
40 private byte[] digest;
41 private THashSet<UpdateListener> listeners;
43 public BundleModuleSource(String moduleName, Bundle bundle, URL url) {
50 public void removeListener(UpdateListener listener) {
52 synchronized(listeners) {
53 listeners.remove(listener);
58 protected ImportDeclaration[] getBuiltinImports(UpdateListener listener) {
59 if(bundle.getSymbolicName().equals("org.simantics.scl.runtime"))
60 return DEFAULT_IMPORTS_FOR_STANDARD_LIBRARY;
62 return DEFAULT_IMPORTS;
65 private byte[] computeDigest() {
67 InputStream stream = url.openStream();
69 MessageDigest digest = MessageDigest.getInstance("SHA1");
70 byte[] buffer = new byte[1024];
72 int count = stream.read(buffer);
75 digest.update(buffer, 0, count);
77 return digest.digest();
78 } catch (NoSuchAlgorithmException e) {
84 } catch(IOException e) {
91 protected InputStream getSourceStream(UpdateListener listener)
94 digest = computeDigest();
95 if(listener != null) {
97 listeners = new THashSet<UpdateListener>(4);
98 listeners.add(listener);
99 listener.addObservable(this);
101 return url.openStream();
105 public ClassLoader getClassLoader() {
106 if(bundle.getSymbolicName().equals("org.simantics.scl.runtime"))
107 return Type.class.getClassLoader();
109 BundleWiring wiring = bundle.adapt(BundleWiring.class);
111 return wiring.getClassLoader();
113 return getClass().getClassLoader();
117 public void checkUpdates() {
118 if(digest != null && listeners != null) {
119 byte[] newDigest = computeDigest();
120 if(!Arrays.equals(digest, newDigest)) {
122 THashSet<UpdateListener> oldListeners = listeners;
124 for(UpdateListener listener : oldListeners)
125 listener.notifyAboutUpdate();
130 private Path getPath() throws IOException {
132 return Paths.get(FileLocator.toFileURL(url).toURI());
133 } catch (URISyntaxException e) {
134 throw new IOException(e);
139 public boolean isUpdateable() {
141 return Files.exists(getPath());
142 } catch (IOException e) {
148 public void update(String newSourceText) {
150 Path path = getPath();
151 Files.write(path, newSourceText.getBytes(Charset.forName("UTF-8")));
152 } catch(IOException e) {
158 public void clear() {
159 if (listeners != null) {
165 public JavaReferenceValidatorFactory getJavaReferenceValidatorFactory() {
166 return new OsgiJavaReferenceValidatorFactory(bundle);