/*
* Rsync server -> client session creation
*
* Copyright (C) 1996-2011 by Andrew Tridgell, Wayne Davison, and others
* Copyright (C) 2013-2015 Per Lundqvist
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.perlundq.yajsync;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
import java.nio.charset.Charset;
import java.nio.charset.UnsupportedCharsetException;
import java.util.concurrent.ExecutorService;
import com.github.perlundq.yajsync.internal.session.FilterMode;
import com.github.perlundq.yajsync.internal.session.Generator;
import com.github.perlundq.yajsync.internal.session.Receiver;
import com.github.perlundq.yajsync.internal.session.RsyncTaskExecutor;
import com.github.perlundq.yajsync.internal.session.Sender;
import com.github.perlundq.yajsync.internal.session.ServerSessionConfig;
import com.github.perlundq.yajsync.internal.session.SessionStatus;
import com.github.perlundq.yajsync.internal.text.Text;
import com.github.perlundq.yajsync.internal.util.Util;
import com.github.perlundq.yajsync.server.module.Modules;
public class RsyncServer
{
public static final int DEFAULT_LISTEN_PORT = 873;
public static class Builder
{
private boolean _isDeferWrite;
private Charset _charset = Charset.forName(Text.UTF8_NAME);
private ExecutorService _executorService;
public Builder isDeferWrite(boolean isDeferWrite)
{
_isDeferWrite = isDeferWrite;
return this;
}
/**
*
* @throws UnsupportedCharsetException if charset is not supported
*/
public Builder charset(Charset charset)
{
assert charset != null;
Util.validateCharset(charset);
_charset = charset;
return this;
}
public RsyncServer build(ExecutorService executorService)
{
assert executorService != null;
_executorService = executorService;
return new RsyncServer(this);
}
}
private final boolean _isDeferWrite;
private final Charset _charset;
private final RsyncTaskExecutor _rsyncTaskExecutor;
private RsyncServer(Builder builder)
{
_isDeferWrite = builder._isDeferWrite;
_charset = builder._charset;
_rsyncTaskExecutor = new RsyncTaskExecutor(builder._executorService);
}
public boolean serve(Modules modules,
ReadableByteChannel in,
WritableByteChannel out,
boolean isChannelsInterruptible)
throws RsyncException, InterruptedException
{
assert modules != null;
assert in != null;
assert out != null;
ServerSessionConfig cfg = ServerSessionConfig.handshake(_charset, // throws IllegalArgumentException if _charset is not supported
in,
out,
modules);
if (cfg.status() == SessionStatus.ERROR) {
return false;
} else if (cfg.status() == SessionStatus.EXIT) {
return true;
}
if (cfg.isSender()) {
Sender sender = Sender.Builder.newServer(in, out,
cfg.sourceFiles(),
cfg.checksumSeed()).
filterMode(FilterMode.RECEIVE).
charset(cfg.charset()).
fileSelection(cfg.fileSelection()).
isPreserveDevices(cfg.isPreserveDevices()).
isPreserveSpecials(cfg.isPreserveSpecials()).
isPreserveLinks(cfg.isPreserveLinks()).
isPreserveUser(cfg.isPreserveUser()).
isPreserveGroup(cfg.isPreserveGroup()).
isNumericIds(cfg.isNumericIds()).
isInterruptible(isChannelsInterruptible).
isSafeFileList(cfg.isSafeFileList()).build();
return _rsyncTaskExecutor.exec(sender);
} else {
Generator generator = new Generator.Builder(out,
cfg.checksumSeed()).
charset(cfg.charset()).
fileSelection(cfg.fileSelection()).
isDelete(cfg.isDelete()).
isPreserveDevices(cfg.isPreserveDevices()).
isPreserveSpecials(cfg.isPreserveSpecials()).
isPreserveLinks(cfg.isPreserveLinks()).
isPreservePermissions(cfg.isPreservePermissions()).
isPreserveTimes(cfg.isPreserveTimes()).
isPreserveUser(cfg.isPreserveUser()).
isPreserveGroup(cfg.isPreserveGroup()).
isNumericIds(cfg.isNumericIds()).
isIgnoreTimes(cfg.isIgnoreTimes()).
isAlwaysItemize(cfg.verbosity() > 1).
isInterruptible(isChannelsInterruptible).build();
Receiver receiver = Receiver.Builder.newServer(generator,
in,
cfg.getReceiverDestination()).
filterMode(cfg.isDelete() ? FilterMode.RECEIVE
: FilterMode.NONE).
isDeferWrite(_isDeferWrite).
isSafeFileList(cfg.isSafeFileList()).build();
return _rsyncTaskExecutor.exec(generator, receiver);
}
}
}