001/*
002 * (C) Copyright 2006-2010 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     bstefanescu
018 */
019package org.nuxeo.shell.equinox;
020
021import java.io.IOException;
022import java.io.InputStreamReader;
023import java.io.PrintWriter;
024import java.io.Reader;
025import java.net.Socket;
026import java.util.ArrayList;
027
028import org.nuxeo.shell.ShellException;
029import org.nuxeo.shell.cmds.Interactive;
030import org.nuxeo.shell.utils.StringUtils;
031
032/**
033 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
034 */
035public class Connector {
036
037    protected String[] commands;
038
039    protected Socket socket;
040
041    protected Reader in;
042
043    protected PrintWriter out;
044
045    public static Connector newConnector(String address) {
046        int p = address.indexOf(':');
047        if (p == -1) {
048            throw new ShellException("Illegal address '" + address + "'. Must be in format 'host:port'");
049        }
050        return new Connector(address.substring(0, p), Integer.parseInt(address.substring(p + 1)));
051    }
052
053    public Connector(String host, int port) {
054        try {
055            socket = new Socket(host, port);
056            socket.setReuseAddress(true);
057            in = new InputStreamReader(socket.getInputStream());
058            out = new PrintWriter(socket.getOutputStream());
059            initConnection();
060        } catch (Exception e) {
061            throw new ShellException("Failed to connect to " + host + ':' + port);
062        }
063    }
064
065    protected void initConnection() throws IOException {
066        readAll();
067        String r = send("help");
068        String[] lines = StringUtils.split(r, '\n', true);
069        ArrayList<String> cmds = new ArrayList<String>();
070        for (String line : lines) {
071            if (line.length() == 0 || line.startsWith("---")) {
072                continue;
073            }
074            int i = line.indexOf(' ');
075            cmds.add(line.substring(0, i));
076        }
077        commands = cmds.toArray(new String[cmds.size()]);
078    }
079
080    public String[] getBundles() {
081        String r = send("ss");
082        String[] lines = StringUtils.split(r, '\n', true);
083        ArrayList<String> bundles = new ArrayList<String>();
084        for (String line : lines) {
085            if (line.length() == 0 || line.startsWith("id")) {
086                continue;
087            }
088            String[] ar = line.split("\\s");
089            String b = ar[ar.length - 1];
090            int i = b.indexOf('_');
091            if (i > -1) {
092                b = b.substring(0, i);
093            }
094            bundles.add(b);
095        }
096        return bundles.toArray(new String[bundles.size()]);
097    }
098
099    public String[] getCommands() {
100        return commands;
101    }
102
103    public Reader getIn() {
104        return in;
105    }
106
107    public PrintWriter getOut() {
108        return out;
109    }
110
111    public void println(String text) {
112        out.println(text);
113        out.flush();
114    }
115
116    public void println() {
117        out.println();
118        out.flush();
119    }
120
121    public String sendCurrentCommand() {
122        return send(Interactive.getCurrentCmdLine());
123    }
124
125    public String send(String command) {
126        try {
127            println(command);
128            return readAll();
129        } catch (IOException e) {
130            throw new ShellException("Failed to read response", e);
131        }
132    }
133
134    /**
135     * Get the response and remove the ending "osgi>" if present - also trim the string before returning. (CRLF is not
136     * included at the end)
137     *
138     * @return
139     * @throws IOException
140     */
141    public String readAll() throws IOException {
142        StringBuilder result = new StringBuilder();
143        char[] cbuf = new char[4096];
144        int r = in.read(cbuf);
145        while (r > 0) {
146            result.append(new String(cbuf, 0, r));
147            if (result.lastIndexOf("osgi> ") == result.length() - "osgi> ".length()) {
148                break;
149            }
150            r = in.read(cbuf);
151        }
152        String str = result.toString().trim();
153        if (str.endsWith("osgi>")) {
154            str = str.substring(0, str.length() - "osgi>".length());
155            str = str.trim();
156        }
157        return str;
158    }
159
160    public void disconnect() {
161        try {
162            socket.close();
163        } catch (Exception e) {
164            throw new ShellException("Failed to disconnect", e);
165        }
166    }
167
168    public Socket getSocket() {
169        return socket;
170    }
171
172}