All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.echocat.jomon.net.ssh.SshRemote Maven / Gradle / Ivy

/*****************************************************************************************
 * *** BEGIN LICENSE BLOCK *****
 *
 * Version: MPL 2.0
 *
 * echocat Jomon, Copyright (c) 2012-2013 echocat
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * *** END LICENSE BLOCK *****
 ****************************************************************************************/

package org.echocat.jomon.net.ssh;

import org.echocat.jomon.net.ssh.SshRemote.SerializerImpl;
import org.echocat.jomon.runtime.io.ChunkAwareSerializer;
import org.echocat.jomon.runtime.io.SerializableBy;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.io.*;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.nio.charset.Charset;

import static java.lang.Integer.parseInt;
import static java.lang.System.getProperty;
import static java.net.InetSocketAddress.createUnresolved;
import static org.apache.commons.lang3.StringUtils.isEmpty;
import static org.echocat.jomon.runtime.io.ByteUtils.*;
import static org.echocat.jomon.runtime.io.StreamUtils.*;

@SerializableBy(SerializerImpl.class)
public interface SshRemote extends SshContext {

    public static final int DEFAULT_PORT = 22;

    @Nonnull
    public InetSocketAddress getAddress();

    @Nonnull
    public String getUser();

    @Nullable
    public String getPassword();


    public static class Impl implements SshRemote {

        @Nonnull
        public static Impl remote(@Nonnull InetSocketAddress address, @Nullable String user, @Nullable String password) {
            return new Impl(address, user, password);
        }

        @Nonnull
        public static Impl remote(@Nonnull InetSocketAddress address, @Nullable String user) {
            return remote(address, user, null);
        }

        @Nonnull
        public static Impl remote(@Nonnull InetSocketAddress address) {
            return remote(address, null);
        }

        @Nonnull
        public static Impl remote(@Nonnull String remoteAsString) {
            final int lastAt = remoteAsString.lastIndexOf('@');
            final boolean hasUserPart = lastAt >= 0 && lastAt + 1 < remoteAsString.length();
            final String user = hasUserPart ? remoteAsString.substring(0, lastAt) : null;
            final String hostAndPort = hasUserPart ? remoteAsString.substring(lastAt + 1) : remoteAsString;
            final int lastDoubleDot = hostAndPort.lastIndexOf(':');
            final boolean hasPortPart = lastDoubleDot >= 0 && lastDoubleDot + 1 < hostAndPort.length();
            String host = hasPortPart ? hostAndPort.substring(0, lastDoubleDot) : hostAndPort;
            int port;
            try {
                port = hasPortPart ? parseInt(hostAndPort.substring(lastDoubleDot + 1)) : DEFAULT_PORT;
            } catch (NumberFormatException ignored) {
                host = hostAndPort;
                port = DEFAULT_PORT;
            }
            if (port <= 0) {
                throw new IllegalArgumentException("Illegal remote provided - containing illegal port: " + remoteAsString);
            }
            try {
                return remote(new InetSocketAddress(InetAddress.getByName(host), port), user);
            } catch (UnknownHostException e) {
                throw new IllegalArgumentException("Illegal remote provided - illegal host: " + remoteAsString, e);
            }
        }

        @Nonnull
        private final InetSocketAddress _address;
        @Nullable
        private final String _user;
        @Nullable
        private final String _password;

        public Impl(@Nonnull InetSocketAddress address, @Nullable String user, @Nullable String password) {
            _address = address;
            _user = user;
            _password = password;
        }

        @Nonnull
        @Override
        public InetSocketAddress getAddress() {
            return _address;
        }

        @Nonnull
        @Override
        public String getUser() {
            String user = getGivenUser();
            if (isEmpty(user)) {
                user = getProperty("user.name");
                if (isEmpty(user)) {
                    throw new RuntimeException("Could not determinate the current username.");
                }
            }
            return user;
        }

        @Nullable
        protected String getGivenUser() {
            return _user;
        }

        @Nullable
        @Override
        public String getPassword() {
            return _password;
        }

        @Override
        public String toString() {
            final InetSocketAddress address = getAddress();
            final String user = getGivenUser();
            final StringBuilder sb = new StringBuilder();
            if (!isEmpty(user)) {
                sb.append(user).append('@');
            }
            sb.append(address.getHostName());
            final int port = address.getPort();
            if (port != DEFAULT_PORT) {
                sb.append(':').append(port);
            }
            return sb.toString();
        }

        @Override
        public void close() throws IOException {}
    }

    public static class SerializerImpl implements ChunkAwareSerializer {

        public static final byte REGULAR_TYPE = (Byte.MIN_VALUE + 1);
        public static final byte NULL_TYPE = (Byte.MIN_VALUE + 0);
        public static final int STRING_BUFFER_SIZE = DEFAULT_STRING_BUFFER_SIZE;
        public static final Charset CHARSET = DEFAULT_CHARSET;
        public static final int CHUNK_SIZE = 1 // type
            + DEFAULT_STRING_CHUNK_SIZE // hostname
            + INTEGER_CHUNK_SIZE // port
            + DEFAULT_STRING_CHUNK_SIZE // username
            + DEFAULT_STRING_CHUNK_SIZE // password
            ;

        @Override
        public int getChunkSize() {
            return CHUNK_SIZE;
        }

        @Override
        public void write(@Nullable SshRemote value, @Nonnull DataOutput to) throws IOException {
            if (value != null) {
                writeByte(REGULAR_TYPE, to);
                final InetSocketAddress address = value.getAddress();
                writeString(STRING_BUFFER_SIZE, address.getHostString(), CHARSET, to);
                writeInteger(address.getPort(), to);
                writeString(STRING_BUFFER_SIZE, value.getUser(), CHARSET, to);
                writeString(STRING_BUFFER_SIZE, value.getPassword(), CHARSET, to);
            } else {
                writeByte(NULL_TYPE, to);
                writeZeros(CHUNK_SIZE - 1, to);
            }
        }

        @Nullable
        @Override
        public SshRemote read(@Nonnull DataInput from) throws IOException {
            final short type = readByte(from);
            final SshRemote result;
            if (type == NULL_TYPE) {
                readZeros(from, CHUNK_SIZE - 1);
                result = null;
            } else if (type == REGULAR_TYPE) {
                final String hostString = readString(from, STRING_BUFFER_SIZE, CHARSET);
                final int port = readInteger(from);
                final String user = readString(from, STRING_BUFFER_SIZE, CHARSET);
                final String password = readString(from, STRING_BUFFER_SIZE, CHARSET);
                result = new Impl(createUnresolved(hostString, port), user, password);
            } else {
                throw new IOException("Found no valid type marker.");
            }
            return result;
        }
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy