com.xebialabs.overthere.Overthere.java Source code

Java tutorial

Introduction

Here is the source code for com.xebialabs.overthere.Overthere.java

Source

/* License added by: GRADLE-LICENSE-PLUGIN
 *
 * Copyright 2008-2012 XebiaLabs
 * 
 * Licensed 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 com.xebialabs.overthere;

import static com.xebialabs.overthere.ConnectionOptions.JUMPSTATION;
import static com.xebialabs.overthere.ssh.SshConnectionBuilder.SSH_PROTOCOL;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;

import nl.javadude.scannit.Configuration;
import nl.javadude.scannit.Scannit;
import nl.javadude.scannit.scanner.TypeAnnotationScanner;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.io.Closeables;
import com.xebialabs.overthere.spi.AddressPortMapper;
import com.xebialabs.overthere.spi.OverthereConnectionBuilder;
import com.xebialabs.overthere.spi.Protocol;
import com.xebialabs.overthere.ssh.SshTunnelConnection;
import com.xebialabs.overthere.util.DefaultAddressPortMapper;

/**
 * Factory object to create {@link OverthereConnection connections}.
 */
@SuppressWarnings("unchecked")
public class Overthere {
    // The "logger" field has to be declared and defined at the top so that the static initializer below can access it
    private static final Logger logger = LoggerFactory.getLogger(Overthere.class);

    private static final AtomicReference<Map<String, Class<? extends OverthereConnectionBuilder>>> protocols = new AtomicReference<Map<String, Class<? extends OverthereConnectionBuilder>>>(
            new HashMap<String, Class<? extends OverthereConnectionBuilder>>());

    static {
        final Scannit scannit = new Scannit(
                Configuration.config().scan("com.xebialabs").with(new TypeAnnotationScanner()));
        final Set<Class<?>> protocolClasses = scannit.getTypesAnnotatedWith(Protocol.class);
        for (Class<?> protocol : protocolClasses) {
            if (OverthereConnectionBuilder.class.isAssignableFrom(protocol)) {
                final String name = protocol.getAnnotation(Protocol.class).name();
                Overthere.protocols.get().put(name, (Class<? extends OverthereConnectionBuilder>) protocol);
            } else {
                logger.warn("Skipping class {} because it is not a HostConnectionBuilder.", protocol);
            }
        }
    }

    private Overthere() {
        // should not instantiate
    }

    /**
    * Creates a connection.
    * 
    * @param protocol
    *            The protocol to use, e.g. "local".
    * @param options
    *            A set of options to use for the connection.
    * @return the connection.
    */
    public static OverthereConnection getConnection(String protocol, final ConnectionOptions options) {
        if (!protocols.get().containsKey(protocol)) {
            throw new IllegalArgumentException("Unknown connection protocol " + protocol);
        }

        logger.trace("Connection for protocol {} requested with the following connection options: {}", protocol,
                options);

        ConnectionOptions jumpstationOptions = options.get(JUMPSTATION, null);
        AddressPortMapper mapper = new DefaultAddressPortMapper();
        if (jumpstationOptions != null) {
            mapper = (SshTunnelConnection) Overthere.getConnection(SSH_PROTOCOL, jumpstationOptions);
        }
        try {
            return buildConnection(protocol, options, mapper);
        } catch (RuntimeException exc) {
            Closeables.closeQuietly(mapper);
            throw exc;
        }
    }

    private static OverthereConnection buildConnection(String protocol, ConnectionOptions options,
            AddressPortMapper mapper) {
        final Class<? extends OverthereConnectionBuilder> connectionBuilderClass = protocols.get().get(protocol);
        try {
            final Constructor<? extends OverthereConnectionBuilder> constructor = connectionBuilderClass
                    .getConstructor(String.class, ConnectionOptions.class, AddressPortMapper.class);
            OverthereConnectionBuilder connectionBuilder = constructor.newInstance(protocol, options, mapper);
            logger.info("Connecting to {}", connectionBuilder);
            OverthereConnection connection = connectionBuilder.connect();
            logger.trace("Connected to {}", connection);
            return connection;
        } catch (NoSuchMethodException exc) {
            throw new IllegalStateException(connectionBuilderClass
                    + " does not have a constructor that takes in a String and ConnectionOptions.", exc);
        } catch (IllegalArgumentException exc) {
            throw new IllegalStateException("Cannot instantiate " + connectionBuilderClass, exc);
        } catch (InstantiationException exc) {
            throw new IllegalStateException("Cannot instantiate " + connectionBuilderClass, exc);
        } catch (IllegalAccessException exc) {
            throw new IllegalStateException("Cannot instantiate " + connectionBuilderClass, exc);
        } catch (InvocationTargetException exc) {
            if (exc.getCause() instanceof RuntimeException) {
                throw (RuntimeException) exc.getCause();
            } else {
                throw new IllegalStateException("Cannot instantiate " + connectionBuilderClass, exc);
            }
        }
    }

}