Package org.springframework.xd.integration.reactor.net

Source Code of org.springframework.xd.integration.reactor.net.NetServerSpecFactoryBean

/*
* Copyright 2013-2014 the original author or authors.
*
*  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 org.springframework.xd.integration.reactor.net;

import java.net.URI;
import java.util.HashMap;
import java.util.Map;

import org.springframework.beans.factory.FactoryBean;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import reactor.core.Environment;
import reactor.event.dispatch.Dispatcher;
import reactor.io.encoding.Codec;
import reactor.io.encoding.DelimitedCodec;
import reactor.io.encoding.LengthFieldCodec;
import reactor.io.encoding.StandardCodecs;
import reactor.net.encoding.syslog.SyslogCodec;
import reactor.net.netty.tcp.NettyTcpServer;
import reactor.net.netty.udp.NettyDatagramServer;
import reactor.net.spec.NetServerSpec;
import reactor.net.tcp.spec.TcpServers;
import reactor.net.udp.spec.DatagramServers;

/**
* @author Jon Brisbin
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public class NetServerSpecFactoryBean implements FactoryBean<NetServerSpec> {

  private static final Map<String, Codec> DEFAULT_CODECS = new HashMap<String, Codec>();

  static {
    DEFAULT_CODECS.put("bytes", StandardCodecs.BYTE_ARRAY_CODEC);
    DEFAULT_CODECS.put("string", StandardCodecs.STRING_CODEC);
    DEFAULT_CODECS.put("syslog", new SyslogCodec());
  }

  private final Map<String, Codec> codecs;

  private final NetServerSpec spec;

  private volatile String host;

  private volatile int port;

  private volatile String framing;

  private volatile int lengthFieldLength;

  private volatile Codec delegateCodec;

  public NetServerSpecFactoryBean(Environment env) {
    this(env, "tcp", null);
  }

  public NetServerSpecFactoryBean(Environment env, String transport) {
    this(env, transport, null);
  }

  public NetServerSpecFactoryBean(Environment env, Map<String, Codec> codecs) {
    this(env, "tcp", codecs);
  }

  public NetServerSpecFactoryBean(Environment env, String transport, Map<String, Codec> codecs) {
    this.codecs = (null == codecs ? DEFAULT_CODECS : codecs);
    if ("tcp".equals(transport)) {
      spec = TcpServers.create(env, NettyTcpServer.class);
    }
    else if ("udp".equals(transport)) {
      spec = DatagramServers.create(env, NettyDatagramServer.class);
    }
    else {
      throw new IllegalArgumentException(transport + " not a value transport type");
    }
  }

  public NetServerSpecFactoryBean configure(URI uri) {
    setHost(null != uri.getHost() ? uri.getHost() : "0.0.0.0");
    setPort(uri.getPort() > 0 ? uri.getPort() : 3000);
    setFraming(null != uri.getPath() ? uri.getPath().substring(1) : "linefeed");
    this.delegateCodec = StandardCodecs.STRING_CODEC;

    if (null != uri.getQuery()) {
      String[] params = StringUtils.split(uri.getQuery(), "&");
      if (null == params) {
        params = new String[] { uri.getQuery() };
      }
      for (String pair : params) {
        String[] parts = StringUtils.split(pair, "=");
        if (parts.length > 1) {
          if ("codec".equals(parts[0])) {
            setCodec(parts[1]);
          }
          else if ("dispatcher".equals(parts[0])) {
            setDispatcher(parts[1]);
          }
          else if ("lengthFieldLength".equals(parts[0])) {
            setLengthFieldLength(Integer.parseInt(parts[1]));
          }
        }
      }
    }
    return this;
  }

  /**
   * Set the name of the {@link reactor.event.dispatch.Dispatcher} to use, which will be pulled from the current
   * {@link reactor.core.Environment}.
   *
   * @param dispatcher dispatcher name
   *
   * @return {@literal this}
   */
  public NetServerSpecFactoryBean setDispatcher(String dispatcher) {
    spec.dispatcher(dispatcher);
    return this;
  }

  public NetServerSpecFactoryBean setDispatcher(Dispatcher dispatcher) {
    spec.dispatcher(dispatcher);
    return this;
  }

  /**
   * Set the host to which this server will bind.
   *
   * @param host the host to bind to (defaults to {@code 0.0.0.0})
   *
   * @return {@literal this}
   */
  public NetServerSpecFactoryBean setHost(String host) {
    Assert.notNull(host, "Host cannot be null.");
    this.host = host;
    return this;
  }

  /**
   * Set the port to which this server will bind.
   *
   * @param port the port to bind to (defaults to {@code 3000})
   *
   * @return {@literal this}
   */
  public NetServerSpecFactoryBean setPort(int port) {
    Assert.isTrue(port > 0, "Port must be greater than 0");
    this.port = port;
    return this;
  }

  /**
   * Set the type of {@link reactor.io.encoding.Codec} to use to managing encoding and decoding of the data.
   * <p>
   * The default options for codecs are:
   * <ul>
   * <li>{@code bytes} - Use the standard byte array codec.</li>
   * <li>{@code string} - Use the standard String codec.</li>
   * <li>{@code syslog} - Use the standard Syslog codec.</li>
   * </ul>
   * </p>
   *
   * @param codec the codec
   *
   * @return {@literal this}
   */
  public NetServerSpecFactoryBean setCodec(String codec) {
    this.delegateCodec = codecs.get(codec);
    Assert.notNull(delegateCodec, "No Codec found for type " + codec);
    return this;
  }

  /**
   * Set the type of framing to use.
   * <p>
   * The options for framing are:
   * <ul>
   * <li>{@code linefeed} - Means use an LF-delimited linefeed codec.</li>
   * <li>{@code length} - Means use a length-field based codec where the initial bytes of a message are the length of
   * the rest of the message.</li>
   * </ul>
   * </p>
   *
   * @param framing type of framing
   *
   * @return {@literal this}
   */
  public NetServerSpecFactoryBean setFraming(String framing) {
    Assert.isTrue("linefeed".equals(framing) || "length".equals(framing));
    this.framing = framing;
    return this;
  }

  /**
   * Set the length of the length field if using length-field framing.
   *
   * @param lengthFieldLength {@code 2} for a {@code short}, {@code 4} for an {@code int} (the default), or {@code 8}
   *        for a {@code long}
   *
   * @return {@literal this}
   */
  public NetServerSpecFactoryBean setLengthFieldLength(int lengthFieldLength) {
    this.lengthFieldLength = lengthFieldLength;
    return this;
  }


  @Override
  public NetServerSpec getObject() throws Exception {
    spec.listen(host, port);

    if (null != framing) {
      if ("linefeed".equals(framing)) {
        spec.codec(new DelimitedCodec(delegateCodec));
      }
      else if ("length".equals(framing)) {
        spec.codec(new LengthFieldCodec(lengthFieldLength, delegateCodec));
      }
    }

    return spec;
  }

  @Override
  public Class<?> getObjectType() {
    return NetServerSpec.class;
  }

  @Override
  public boolean isSingleton() {
    return true;
  }

}
TOP

Related Classes of org.springframework.xd.integration.reactor.net.NetServerSpecFactoryBean

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.