blob: f56405556630bdb5e3f2527692cf422f5500f733 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.netbeans.modules.editor.indent;
import java.io.IOException;
import java.io.Reader;
import java.util.Collections;
import java.util.List;
import javax.script.AbstractScriptEngine;
import javax.script.Bindings;
import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineFactory;
import javax.script.ScriptException;
import javax.script.SimpleBindings;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.PlainDocument;
import javax.swing.text.Position;
import org.netbeans.api.editor.document.AtomicLockDocument;
import org.netbeans.api.editor.document.LineDocumentUtils;
import org.netbeans.modules.editor.indent.api.Reformat;
import org.openide.util.Exceptions;
import org.openide.util.NbBundle;
import org.openide.util.lookup.ServiceProvider;
/**
* The class implements a ScriptEngine, which is just a hacky way how to provide identation
* to api.templates without introducing a new SPI.
*
* @author sdedic
*/
public class IndentScriptEngineHack extends AbstractScriptEngine {
private static final String ID_INDENT_ENGINE = "org.netbeans.api.templates.IndentEngine"; // NOI18N
private IndentScriptEngineHack() {}
@Override
public Object eval(final String text, ScriptContext context) throws ScriptException {
Document doc;
String mime = (String)context.getAttribute("mimeType"); // NOI18N
try {
doc = LineDocumentUtils.createDocument(mime);
} catch (IllegalArgumentException ex) {
// for testing: create a stupid document with a mimeType property
doc = new PlainDocument();
doc.putProperty("mimeType", mime); // NOI18N
}
final Reformat reformat = Reformat.get(doc);
reformat.lock();
try {
final Document d = doc;
final ScriptException err[] = new ScriptException[1];
Runnable op = new Runnable() {
@Override
public void run() {
if (text.length() > 0) {
try {
d.insertString(0, text, null);
Position endPos = d.createPosition(d.getLength());
reformat.reformat(0, endPos.getOffset());
int len = endPos.getOffset();
String reformattedText = d.getText(0, len);
getContext().getWriter().write(reformattedText);
} catch (BadLocationException e) {
Exceptions.printStackTrace(e);
} catch (IOException ex) {
err[0] = new ScriptException(ex);
return;
}
}
}
};
AtomicLockDocument ald = LineDocumentUtils.as(doc, AtomicLockDocument.class);
if (ald != null) {
ald.runAtomic(op);
} else {
op.run();
}
if (err[0] != null) {
throw err[0];
}
} finally {
reformat.unlock();
}
return Boolean.TRUE;
}
@Override
public Object eval(Reader reader, ScriptContext context) throws ScriptException {
StringBuilder sb = new StringBuilder();
char[] buf = new char[1024];
int read;
try {
while ((read = reader.read(buf)) >= 0) {
sb.append(buf, 0, read);
}
} catch (IOException ex) {
throw new ScriptException(ex);
}
return eval(sb.toString());
}
@Override
public Bindings createBindings() {
return new SimpleBindings();
}
@Override
public ScriptEngineFactory getFactory() {
if (f == null) {
f = new Factory();
}
return f;
}
private Factory f;
@NbBundle.Messages({
"NAME_IndentScriptEngine=NetBeans indentation"
})
@ServiceProvider(service = ScriptEngineFactory.class)
public static class Factory implements ScriptEngineFactory {
@Override
public String getEngineName() {
return Bundle.NAME_IndentScriptEngine();
}
@Override
public String getEngineVersion() {
return "1.0"; // NOI18N
}
@Override
public List<String> getExtensions() {
return Collections.emptyList();
}
@Override
public List<String> getMimeTypes() {
return Collections.emptyList();
}
@Override
public List<String> getNames() {
return Collections.singletonList(ID_INDENT_ENGINE);
}
@Override
public String getLanguageName() {
return ""; // NOI18N
}
@Override
public String getLanguageVersion() {
return "-1"; // NOI18N
}
@Override
public Object getParameter(String key) {
switch (key) {
case ScriptEngine.ENGINE:
return getEngineName();
case ScriptEngine.ENGINE_VERSION:
return getEngineVersion();
case ScriptEngine.LANGUAGE:
return getLanguageName();
case ScriptEngine.LANGUAGE_VERSION:
return getLanguageVersion();
case ScriptEngine.NAME:
return getNames().get(0);
}
return null;
}
@Override
public String getMethodCallSyntax(String obj, String m, String... args) {
return null;
}
@Override
public String getOutputStatement(String toDisplay) {
return toDisplay;
}
@Override
public String getProgram(String... statements) {
StringBuilder sb = new StringBuilder();
for (String s : statements) {
sb.append(s);
}
return sb.toString();
}
@Override
public ScriptEngine getScriptEngine() {
return new IndentScriptEngineHack();
}
}
}