Index: assemblies/features/framework/src/main/filtered-resources/resources/etc/org.apache.karaf.editor.cfg IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- assemblies/features/framework/src/main/filtered-resources/resources/etc/org.apache.karaf.editor.cfg (revision ) +++ assemblies/features/framework/src/main/filtered-resources/resources/etc/org.apache.karaf.editor.cfg (revision ) @@ -0,0 +1,25 @@ +################################################################################ +# +# 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. +# +################################################################################ + +# +# These properties are used to configure Karaf's text editor. +# + +editor = vi + Index: util/src/main/java/org/apache/karaf/util/process/PumpStreamHandler.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- util/src/main/java/org/apache/karaf/util/process/PumpStreamHandler.java (revision 08715571e0fe23e10cd2d73f7f9b20ac8695637a) +++ util/src/main/java/org/apache/karaf/util/process/PumpStreamHandler.java (revision ) @@ -173,10 +173,14 @@ } try { + if (err != null) { - err.flush(); + err.flush(); + } } catch (IOException e) { } try { + if (out != null) { - out.flush(); + out.flush(); + } } catch (IOException e) { } } Index: shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/EditAction.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/EditAction.java (revision ) +++ shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/EditAction.java (revision ) @@ -0,0 +1,172 @@ +package org.apache.karaf.shell.commands.impl; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URL; +import java.net.URLConnection; +import java.util.UUID; +import java.util.regex.Pattern; +import jline.Terminal; +import org.apache.karaf.shell.commands.Argument; +import org.apache.karaf.shell.commands.Command; +import org.apache.karaf.shell.console.AbstractAction; +import org.apache.karaf.util.StreamUtils; +import org.apache.karaf.util.process.PumpStreamHandler; + +@Command(scope = "shell", name = "edit", description = "Calls a native editor.") +public class EditAction extends AbstractAction { + + @Argument(index = 0, name = "url", description = "The url of the resource to edit.", required = true, multiValued = false) + private String url; + + private String editor; + private final Pattern urlPattern = Pattern.compile("[^: ]+:[^ ]+"); + + @Override + protected Object doExecute() throws Exception { + URLConnection connection = null; + InputStream is = null; + OutputStream os = null; + String path = null; + boolean isLocal = true; + + //If no url format found, assume file url. + if (!urlPattern.matcher(url).matches()) { + File f = new File(url); + url = "file://" + f.getAbsolutePath(); + } + + URL u = new URL(url); + + //If its not a file url. + if (!u.getProtocol().equals("file")) { + isLocal = false; + + try { + connection = u.openConnection(); + is = connection.getInputStream(); + } catch (IOException ex) { + System.out.println("Failed to open " + url + " for reading."); + return null; + } + try { + os = connection.getOutputStream(); + } catch (IOException ex) { + System.out.println("Failed to open " + url + " for writing."); + return null; + } + + //Copy the resource to a tmp location. + FileOutputStream fos = null; + try { + path = System.getProperty("karaf.data") + "/editor/" + UUID.randomUUID(); + File f = new File(path); + if (!f.exists()) { + if (!f.getParentFile().exists()) { + f.getParentFile().mkdirs(); + } + } + + fos = new FileOutputStream(f); + copy(is, fos); + } catch (Exception ex) { + System.out.println("Failed to copy resource from url:" + url + " to tmp file: " + path + " for editing."); + } finally { + StreamUtils.close(fos); + } + } else { + path = u.getFile(); + } + + + File file = new File(path); + if (!file.exists()) { + if (!file.getParentFile().exists()) { + file.getParentFile().mkdirs(); + } + } + + Terminal terminal = getTerminal(); + ProcessBuilder builder = new ProcessBuilder(editor, file.getAbsolutePath()); + builder.environment().put("COLUMNS", String.valueOf(terminal.getWidth())); + builder.environment().put("LINES", String.valueOf(terminal.getHeight())); + Process p = builder.start(); + PumpStreamHandler handler = new PumpStreamHandler(session.getKeyboard(), System.out, null, "Editor"); + handler.attach(p); + handler.start(); + p.waitFor(); + handler.stop(); + + Object terminalObject = session.get(".jline.terminal"); + if (terminalObject instanceof Terminal) { + ((Terminal) terminalObject).reset(); + } + + System.out.print("\33[2J"); + System.out.print("\33[1;1H"); + System.out.flush(); + + //If resource is not local, copy the resource back. + if (!isLocal) { + FileInputStream fis = new FileInputStream(path); + try { + copy(fis, os); + } finally { + StreamUtils.close(fis); + } + } + + if (is != null) { + StreamUtils.close(is); + } + + if (os != null) { + StreamUtils.close(os); + } + return null; + } + + /** + * Gets the {@link Terminal} from the current {@link CommandSession}. + * + * @return + * @throws Exception + */ + private Terminal getTerminal() throws Exception { + Object terminalObject = session.get(".jline.terminal"); + if (terminalObject instanceof Terminal) { + return (Terminal) terminalObject; + + } + throw new IllegalStateException("Could not get Terminal from CommandSession."); + } + + /** + * Copies the content of {@link InputStream} to {@link OutputStream}. + * + * @param input + * @param output + * @throws IOException + */ + private void copy(final InputStream input, final OutputStream output) throws IOException { + byte[] buffer = new byte[1024 * 16]; + int n = 0; + while (-1 != (n = input.read(buffer))) { + output.write(buffer, 0, n); + output.flush(); + } + } + + + public String getEditor() { + return editor; + } + + public void setEditor(String editor) { + this.editor = editor; + } +} Index: shell/commands/src/main/resources/OSGI-INF/blueprint/shell-commands.xml IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- shell/commands/src/main/resources/OSGI-INF/blueprint/shell-commands.xml (revision 08715571e0fe23e10cd2d73f7f9b20ac8695637a) +++ shell/commands/src/main/resources/OSGI-INF/blueprint/shell-commands.xml (revision ) @@ -17,8 +17,17 @@ limitations under the License. --> - + + + + + + + @@ -96,6 +105,11 @@ + + + + +