/*
* Copyright (c) 1998-2011 Caucho Technology -- all rights reserved
*
* This file is part of Resin(R) Open Source
*
* Each copy or derived work must preserve the copyright notice and this
* notice unmodified.
*
* Resin Open Source 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 2 of the License, or
* (at your option) any later version.
*
* Resin Open Source 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, or any warranty
* of NON-INFRINGEMENT. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with Resin Open Source; if not, write to the
*
* Free Software Foundation, Inc.
* 59 Temple Place, Suite 330
* Boston, MA 02111-1307 USA
*
* @author Scott Ferguson
*/
package com.caucho.jcr.svn;
import com.caucho.util.L10N;
import com.caucho.vfs.Path;
import com.caucho.vfs.ReadStream;
import com.caucho.vfs.ReadWritePair;
import com.caucho.vfs.Vfs;
import com.caucho.vfs.WriteStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Subversion Client class.
*/
public class SubversionClient {
private final L10N L = new L10N(SubversionClient.class);
private final Logger log
= Logger.getLogger(SubversionClient.class.getName());;
private Path _path;
private ReadStream _is;
private WriteStream _os;
private SubversionInput _in;
private long _rev = 1;
public SubversionClient(String host, int port)
throws IOException
{
_path = Vfs.lookup("tcp://" + host + ":" + port);
ReadWritePair pair = _path.openReadWrite();
_is = pair.getReadStream();
_os = pair.getWriteStream();
_in = new SubversionInput(_is);
readHello();
// anonymous login (?)
String svnurl = "svn://" + host + ":" + port;
println("( 2 ( edit-pipeline ) "+svnurl.length()+":"+svnurl+ " )");
readLoginResponse();
println("( ANONYMOUS ( 0: ) )");
readSuccess();
_in.expect('(');
expectSuccess();
_in.expect('(');
String uuid = _in.readString();
String url = _in.readString();
_in.expect(')');
_in.expect(')');
}
/**
* Sends a get-latest-rev request to the client, returning the latest
* version.
*/
public long getLatestRev()
throws IOException
{
println("( get-latest-rev ( ) )");
readSuccess();
_in.expect('(');
expectSuccess();
_in.expect('(');
long value = _in.readLong();
_rev = value;
_in.expect(')');
_in.expect(')');
return value;
}
public String checkPath(String s)
throws IOException
{
println("( check-path ( " + s.length() + ":" + s + " ( ) ) )");
readSuccess();
_in.expect('(');
expectSuccess();
_in.expect('(');
String type = _in.readLiteral();
_in.expect(')');
_in.expect(')');
return type;
}
public Object getDir(String s)
throws IOException
{
// wantProps, wantContents
println("( get-dir ( " + s.length() + ":" + s + " ( " + _rev + " ) false true ) )");
readSuccess();
_in.expect('(');
expectSuccess();
_in.expect('(');
long dirVersion = _in.readLong();
Object props = _in.readSexp();
ArrayList<SubversionNode> results = new ArrayList<SubversionNode>();
_in.expect('(');
while (true) {
_in.skipWhitespace();
int ch = _in.read();
if (ch == '(') {
String name = _in.readString();
String type = _in.readLiteral();
long length = _in.readLong();
boolean bValue = ! "false".equals(_in.readLiteral());
long version = _in.readLong();
_in.expect('(');
String modified = _in.readString();
_in.expect(')');
_in.expect('(');
String user = _in.readString();
_in.expect(')');
_in.expect(')');
SubversionNode node;
if ("dir".equals(type))
node = new SubversionFolder(name);
else if ("file".equals(type)) {
SubversionFile file = new SubversionFile(name);
file.setLength(length);
node = file;
}
else
node = new SubversionNode(name);
node.setVersion(version);
node.setUser(user);
results.add(node);
}
else if (ch == ')')
break;
else {
throw error(L.l("Expected '(' at {0} (0x{1})",
String.valueOf(ch),
Integer.toHexString(ch)));
}
}
_in.expect(')');
_in.expect(')');
return results;
}
public Object update(long version, String s)
throws IOException
{
boolean recurse = true;
println("( update ( " +
" ( " + version + " ) " +
s.length() + ":" + s + " " +
recurse + " ) )");
readSuccess();
boolean startEmpty = true;
println("( set-path ( " +
s.length() + ":" + s + " " +
version + " " +
startEmpty + " ) )");
println("( finish-report ( ) )");
readSuccess();
while (true) {
_in.expect('(');
String cmd = _in.readLiteral();
Object arg = _in.readSexp();
_in.expect(')');
System.out.println("CMD: " + cmd);
if ("close-edit".equals(cmd))
break;
}
return "ok";
}
public Object setPath(long version, String s)
throws IOException
{
boolean startEmpty = true;
println("( set-path ( " +
s.length() + ":" + s + " " +
version + " " +
startEmpty + " ) )");
println("( finish-report ( ) )");
readSuccess();
return _in.readSexp();
}
public Object finishReport()
throws IOException
{
println("( finish-report ( ) )");
readSuccess();
return _in.readSexp();
}
public void doMore()
throws IOException
{
println("( check-path ( 0: ( ) ) )");
readSuccess();
System.out.println(_in.readSexp());
println("( get-dir ( 0: ( 1 ) false true ) )");
readSuccess();
System.out.println(_in.readSexp());
}
private void readHello()
throws IOException
{
_in.expect('(');
expectSuccess();
_in.expect('(');
long major = _in.readLong();
long minor = _in.readLong();
Object auth = _in.readSexp();
Object cap = _in.readSexp();
_in.expect(')');
_in.expect(')');
}
private void readLoginResponse()
throws IOException
{
_in.expect('(');
expectSuccess();
_in.expect('(');
Object cap = _in.readSexp();
String code = _in.readString();
_in.expect(')');
_in.expect(')');
}
public void readSuccess()
throws IOException
{
_in.expect('(');
expectSuccess();
_in.readSexp();
_in.expect(')');
}
public void expectSuccess()
throws IOException
{
String token = _in.readLiteral();
if (! "success".equals(token))
throw error(L.l("Expected 'success' at {0}",
token));
}
private void println(String msg)
throws IOException
{
if (log.isLoggable(Level.FINER))
log.finer(msg);
_os.println(msg);
}
private IOException error(String msg)
{
return new IOException(msg);
}
public void close()
{
ReadStream is = _is;
_is = null;
WriteStream os = _os;
_os = null;
_in.close();
if (os != null) {
try {
os.close();
} catch (IOException e) {
}
}
if (is != null) {
is.close();
}
}
}