0
# Source Management
1
2
Source management provides representation and handling of source code for polyglot execution. Sources encapsulate executable code with metadata, support various input methods, and enable caching for optimal performance.
3
4
## Capabilities
5
6
### Source Creation
7
8
Create source objects from different input types.
9
10
```java { .api }
11
public final class Source {
12
// Quick creation shortcut
13
public static Source create(String language, CharSequence source);
14
15
// Builder pattern for various source types
16
public static Source.Builder newBuilder(String language, CharSequence characters, String name);
17
public static Source.Builder newBuilder(String language, ByteSequence bytes, String name);
18
public static Source.Builder newBuilder(String language, File file);
19
public static Source.Builder newBuilder(String language, URL url);
20
public static Source.Builder newBuilder(String language, Reader source, String name);
21
22
// Language and MIME type detection
23
public static String findLanguage(File file) throws IOException;
24
public static String findLanguage(URL url) throws IOException;
25
public static String findLanguage(String mimeType);
26
public static String findMimeType(File file) throws IOException;
27
public static String findMimeType(URL url) throws IOException;
28
}
29
```
30
31
**Usage:**
32
33
```java
34
// Quick creation from string
35
Source jsCode = Source.create("js", "console.log('Hello World')");
36
37
// Create from string with builder
38
Source namedCode = Source.newBuilder("js", "function add(a, b) { return a + b; }", "math.js")
39
.buildLiteral();
40
41
// Create from file
42
Source fileSource = Source.newBuilder("js", new File("/path/to/script.js"))
43
.build();
44
45
// Create from URL
46
URL scriptUrl = new URL("https://example.com/script.js");
47
Source urlSource = Source.newBuilder("js", scriptUrl)
48
.build();
49
50
// Create from Reader
51
StringReader reader = new StringReader("print('Hello from Python')");
52
Source readerSource = Source.newBuilder("python", reader, "inline.py")
53
.build();
54
55
// Create from bytes
56
ByteSequence scriptBytes = ByteSequence.create("console.log('From bytes')".getBytes(StandardCharsets.UTF_8));
57
Source bytesSource = Source.newBuilder("js", scriptBytes, "bytes.js")
58
.buildLiteral();
59
60
// Auto-detect language from file
61
String language = Source.findLanguage(new File("script.py")); // "python"
62
Source autoSource = Source.newBuilder(language, new File("script.py"))
63
.build();
64
```
65
66
### Source Builder
67
68
Configure sources with advanced options.
69
70
```java { .api }
71
public static final class Source.Builder {
72
public Source.Builder name(String newName);
73
public Source.Builder content(String code);
74
public Source.Builder content(CharSequence characters);
75
public Source.Builder content(ByteSequence bytes);
76
public Source.Builder mimeType(String mimeType);
77
public Source.Builder interactive(boolean interactive);
78
public Source.Builder internal(boolean internal);
79
public Source.Builder cached(boolean cached);
80
public Source.Builder uri(URI newUri);
81
public Source.Builder encoding(Charset encoding);
82
public Source.Builder option(String key, String value);
83
public Source.Builder options(Map<String, String> options);
84
public Source build() throws IOException;
85
public Source buildLiteral();
86
}
87
```
88
89
**Usage:**
90
91
```java
92
Source complexSource = Source.newBuilder("js", "const result = calculate(42);", "complex-script.js")
93
.cached(true)
94
.interactive(false)
95
.internal(false)
96
.encoding(StandardCharsets.UTF_8)
97
.uri(URI.create("file:///path/to/script.js"))
98
.buildLiteral();
99
```
100
101
### Source Properties
102
103
Access source metadata and content.
104
105
```java { .api }
106
public CharSequence getCharacters();
107
public String getName();
108
public String getPath();
109
public boolean isInteractive();
110
public String getLanguage();
111
public String getMimeType();
112
public URI getURI();
113
public boolean hasBytes();
114
public ByteSequence getBytes();
115
public boolean hasCharacters();
116
public int getLength();
117
public boolean isCached();
118
public boolean isInternal();
119
}
120
```
121
122
**Usage:**
123
124
```java
125
Source source = Source.newBuilder("js", "console.log('test')", "test.js").buildLiteral();
126
127
// Access content
128
CharSequence content = source.getCharacters();
129
System.out.println("Content: " + content);
130
131
// Access metadata
132
String name = source.getName(); // "test.js"
133
String language = source.getLanguage(); // "js"
134
int length = source.getLength(); // Content length
135
boolean cached = source.isCached(); // Caching enabled
136
137
// Check content type
138
boolean hasChars = source.hasCharacters(); // true for text sources
139
boolean hasBytes = source.hasBytes(); // true for binary sources
140
141
System.out.println("Source: " + name + " (" + language + ", " + length + " chars)");
142
```
143
144
### Source Sections
145
146
Work with specific sections of source code.
147
148
```java { .api }
149
public SourceSection createSection(int charIndex, int length);
150
public SourceSection createSection(int startLine, int startColumn, int endLine, int endColumn);
151
public SourceSection createUnavailableSection();
152
```
153
154
**Usage:**
155
156
```java
157
Source source = Source.create("js", "function add(a, b) {\n return a + b;\n}", "math.js");
158
159
// Create section by character index
160
SourceSection functionName = source.createSection(9, 3); // "add"
161
162
// Create section by line/column
163
SourceSection functionBody = source.createSection(1, 21, 2, 1); // "return a + b;"
164
165
// Create unavailable section (for error handling)
166
SourceSection unavailable = source.createUnavailableSection();
167
168
System.out.println("Function name: " + functionName.getCharacters());
169
System.out.println("Function body: " + functionBody.getCharacters());
170
```
171
172
## Advanced Usage
173
174
### MIME Type Detection
175
176
Sources can be created with automatic MIME type detection:
177
178
```java
179
// Explicit MIME type
180
Source explicitMime = Source.newBuilder("js")
181
.mimeType("application/javascript")
182
.content("console.log('test')")
183
.build();
184
185
// Auto-detected from file extension
186
String detectedLanguage = Source.findLanguage(new File("script.py")); // "python"
187
Source autoMime = Source.newBuilder(detectedLanguage, new File("script.py")).build();
188
189
System.out.println("MIME type: " + autoMime.getMimeType());
190
```
191
192
### Interactive Sources
193
194
Mark sources as interactive for REPL-style execution:
195
196
```java
197
Source interactiveSource = Source.newBuilder("js")
198
.content("2 + 2")
199
.interactive(true)
200
.build();
201
202
// Interactive sources may have different evaluation behavior
203
try (Context context = Context.create("js")) {
204
Value result = context.eval(interactiveSource);
205
System.out.println("Interactive result: " + result);
206
}
207
```
208
209
### Internal Sources
210
211
Mark sources as internal (not visible in stack traces):
212
213
```java
214
Source internalSource = Source.newBuilder("js")
215
.content("function internal() { throw new Error('internal error'); }")
216
.internal(true)
217
.build();
218
```
219
220
### Cached Sources
221
222
Enable caching for frequently used sources:
223
224
```java
225
Source cachedSource = Source.newBuilder("js")
226
.content("function expensive() { /* complex computation */ }")
227
.cached(true)
228
.build();
229
230
// Cached sources are stored in the engine's compilation cache
231
try (Engine engine = Engine.create()) {
232
Context context = Context.newBuilder("js").engine(engine).build();
233
234
// First execution - compiled and cached
235
context.eval(cachedSource);
236
237
// Subsequent executions use cached compilation
238
context.eval(cachedSource); // Faster
239
}
240
```
241
242
### Binary Sources
243
244
Work with binary source content:
245
246
```java
247
// Read binary file
248
byte[] binaryContent = Files.readAllBytes(Paths.get("script.wasm"));
249
ByteSequence byteSeq = ByteSequence.create(binaryContent);
250
Source binarySource = Source.newBuilder("wasm", byteSeq, "module.wasm").buildLiteral();
251
252
// Access binary content
253
if (binarySource.hasBytes()) {
254
ByteSequence bytes = binarySource.getBytes();
255
System.out.println("Binary size: " + bytes.length());
256
}
257
```
258
259
### URI-based Sources
260
261
Create sources with custom URIs for debugging and tooling:
262
263
```java
264
Source uriSource = Source.newBuilder("js")
265
.content("console.log('URI source')")
266
.uri(URI.create("custom-scheme://my-app/dynamic-script"))
267
.build();
268
269
// URI appears in stack traces and debugging tools
270
System.out.println("Source URI: " + uriSource.getURI());
271
```
272
273
### Source Validation
274
275
Validate sources before execution:
276
277
```java
278
try {
279
Source source = Source.create("js", "invalid javascript syntax +++");
280
281
try (Context context = Context.create("js")) {
282
// Parse without executing to check syntax
283
Value parsed = context.parse(source);
284
System.out.println("Source is valid");
285
}
286
} catch (PolyglotException e) {
287
if (e.isSyntaxError()) {
288
System.out.println("Syntax error: " + e.getMessage());
289
System.out.println("Location: " + e.getSourceLocation());
290
}
291
}
292
```
293
294
## Performance Considerations
295
296
- **Caching**: Enable caching for frequently executed sources to improve performance
297
- **Source Reuse**: Reuse Source objects instead of creating new ones for the same content
298
- **Content Size**: Large sources may impact memory usage; consider streaming for very large files
299
- **Binary vs Text**: Use appropriate content type (binary/text) for optimal handling
300
- **URI Overhead**: Custom URIs add minimal overhead but improve debugging experience
301
302
## Error Handling
303
304
Sources can produce various exceptions during creation and execution:
305
306
```java
307
try {
308
// File not found
309
Source fileSource = Source.newBuilder("js", new File("nonexistent.js")).build();
310
} catch (IOException e) {
311
System.out.println("File error: " + e.getMessage());
312
}
313
314
try {
315
// Invalid URL
316
Source urlSource = Source.newBuilder("js", new URL("invalid://url")).build();
317
} catch (IOException e) {
318
System.out.println("URL error: " + e.getMessage());
319
}
320
321
try (Context context = Context.create("js")) {
322
Source source = Source.create("js", "syntax error +++");
323
context.eval(source);
324
} catch (PolyglotException e) {
325
if (e.isSyntaxError()) {
326
System.out.println("Syntax error in source: " + e.getMessage());
327
}
328
}
329
```