001: /*
002: * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: *
023: * Free Software Foundation, Inc.
024: * 59 Temple Place, Suite 330
025: * Boston, MA 02111-1307 USA
026: *
027: * @author Scott Ferguson
028: */
029:
030: package com.caucho.jcr.svn;
031:
032: import com.caucho.util.L10N;
033: import com.caucho.vfs.Path;
034: import com.caucho.vfs.ReadStream;
035: import com.caucho.vfs.ReadWritePair;
036: import com.caucho.vfs.Vfs;
037: import com.caucho.vfs.WriteStream;
038:
039: import java.io.IOException;
040: import java.util.ArrayList;
041: import java.util.logging.Level;
042: import java.util.logging.Logger;
043:
044: /**
045: * Subversion Client class.
046: */
047: public class SubversionClient {
048: private final L10N L = new L10N(SubversionClient.class);
049: private final Logger log = Logger.getLogger(SubversionClient.class
050: .getName());;
051:
052: private Path _path;
053: private ReadStream _is;
054: private WriteStream _os;
055:
056: private SubversionInput _in;
057: private long _rev = 1;
058:
059: public SubversionClient(String host, int port) throws IOException {
060: _path = Vfs.lookup("tcp://" + host + ":" + port);
061:
062: ReadWritePair pair = _path.openReadWrite();
063:
064: _is = pair.getReadStream();
065: _os = pair.getWriteStream();
066:
067: _in = new SubversionInput(_is);
068:
069: readHello();
070:
071: // anonymous login (?)
072: String svnurl = "svn://" + host + ":" + port;
073: println("( 2 ( edit-pipeline ) " + svnurl.length() + ":"
074: + svnurl + " )");
075:
076: readLoginResponse();
077:
078: println("( ANONYMOUS ( 0: ) )");
079:
080: readSuccess();
081:
082: _in.expect('(');
083: expectSuccess();
084: _in.expect('(');
085:
086: String uuid = _in.readString();
087: String url = _in.readString();
088:
089: _in.expect(')');
090: _in.expect(')');
091: }
092:
093: /**
094: * Sends a get-latest-rev request to the client, returning the latest
095: * version.
096: */
097: public long getLatestRev() throws IOException {
098: println("( get-latest-rev ( ) )");
099:
100: readSuccess();
101:
102: _in.expect('(');
103: expectSuccess();
104: _in.expect('(');
105:
106: long value = _in.readLong();
107:
108: _rev = value;
109:
110: _in.expect(')');
111: _in.expect(')');
112:
113: return value;
114: }
115:
116: public String checkPath(String s) throws IOException {
117: println("( check-path ( " + s.length() + ":" + s + " ( ) ) )");
118:
119: readSuccess();
120:
121: _in.expect('(');
122: expectSuccess();
123: _in.expect('(');
124:
125: String type = _in.readLiteral();
126:
127: _in.expect(')');
128: _in.expect(')');
129:
130: return type;
131: }
132:
133: public Object getDir(String s) throws IOException {
134: // wantProps, wantContents
135: println("( get-dir ( " + s.length() + ":" + s + " ( " + _rev
136: + " ) false true ) )");
137:
138: readSuccess();
139:
140: _in.expect('(');
141: expectSuccess();
142:
143: _in.expect('(');
144:
145: long dirVersion = _in.readLong();
146:
147: Object props = _in.readSexp();
148:
149: ArrayList<SubversionNode> results = new ArrayList<SubversionNode>();
150:
151: _in.expect('(');
152:
153: while (true) {
154: _in.skipWhitespace();
155:
156: int ch = _in.read();
157:
158: if (ch == '(') {
159: String name = _in.readString();
160: String type = _in.readLiteral();
161: long length = _in.readLong();
162: boolean bValue = !"false".equals(_in.readLiteral());
163: long version = _in.readLong();
164:
165: _in.expect('(');
166: String modified = _in.readString();
167: _in.expect(')');
168:
169: _in.expect('(');
170: String user = _in.readString();
171: _in.expect(')');
172: _in.expect(')');
173:
174: SubversionNode node;
175:
176: if ("dir".equals(type))
177: node = new SubversionFolder(name);
178: else if ("file".equals(type)) {
179: SubversionFile file = new SubversionFile(name);
180: file.setLength(length);
181: node = file;
182: } else
183: node = new SubversionNode(name);
184:
185: node.setVersion(version);
186: node.setUser(user);
187:
188: results.add(node);
189: } else if (ch == ')')
190: break;
191: else {
192: throw error(L.l("Expected '(' at {0} (0x{1})", String
193: .valueOf(ch), Integer.toHexString(ch)));
194: }
195: }
196:
197: _in.expect(')');
198: _in.expect(')');
199:
200: return results;
201: }
202:
203: public Object update(long version, String s) throws IOException {
204: boolean recurse = true;
205:
206: println("( update ( " + " ( " + version + " ) " + s.length()
207: + ":" + s + " " + recurse + " ) )");
208:
209: readSuccess();
210:
211: boolean startEmpty = true;
212:
213: println("( set-path ( " + s.length() + ":" + s + " " + version
214: + " " + startEmpty + " ) )");
215:
216: println("( finish-report ( ) )");
217:
218: readSuccess();
219:
220: while (true) {
221: _in.expect('(');
222: String cmd = _in.readLiteral();
223:
224: Object arg = _in.readSexp();
225: _in.expect(')');
226:
227: System.out.println("CMD: " + cmd);
228:
229: if ("close-edit".equals(cmd))
230: break;
231: }
232:
233: return "ok";
234: }
235:
236: public Object setPath(long version, String s) throws IOException {
237: boolean startEmpty = true;
238:
239: println("( set-path ( " + s.length() + ":" + s + " " + version
240: + " " + startEmpty + " ) )");
241:
242: println("( finish-report ( ) )");
243:
244: readSuccess();
245:
246: return _in.readSexp();
247: }
248:
249: public Object finishReport() throws IOException {
250: println("( finish-report ( ) )");
251:
252: readSuccess();
253:
254: return _in.readSexp();
255: }
256:
257: public void doMore() throws IOException {
258: println("( check-path ( 0: ( ) ) )");
259:
260: readSuccess();
261:
262: System.out.println(_in.readSexp());
263:
264: println("( get-dir ( 0: ( 1 ) false true ) )");
265:
266: readSuccess();
267:
268: System.out.println(_in.readSexp());
269: }
270:
271: private void readHello() throws IOException {
272: _in.expect('(');
273: expectSuccess();
274: _in.expect('(');
275:
276: long major = _in.readLong();
277: long minor = _in.readLong();
278:
279: Object auth = _in.readSexp();
280: Object cap = _in.readSexp();
281:
282: _in.expect(')');
283: _in.expect(')');
284: }
285:
286: private void readLoginResponse() throws IOException {
287: _in.expect('(');
288: expectSuccess();
289: _in.expect('(');
290:
291: Object cap = _in.readSexp();
292:
293: String code = _in.readString();
294:
295: _in.expect(')');
296: _in.expect(')');
297: }
298:
299: public void readSuccess() throws IOException {
300: _in.expect('(');
301:
302: expectSuccess();
303:
304: _in.readSexp();
305:
306: _in.expect(')');
307: }
308:
309: public void expectSuccess() throws IOException {
310: String token = _in.readLiteral();
311:
312: if (!"success".equals(token))
313: throw error(L.l("Expected 'success' at {0}", token));
314: }
315:
316: private void println(String msg) throws IOException {
317: if (log.isLoggable(Level.FINER))
318: log.finer(msg);
319:
320: _os.println(msg);
321: }
322:
323: private IOException error(String msg) {
324: return new IOException(msg);
325: }
326:
327: public void close() {
328: ReadStream is = _is;
329: _is = null;
330:
331: WriteStream os = _os;
332: _os = null;
333:
334: _in.close();
335:
336: if (os != null) {
337: try {
338: os.close();
339: } catch (IOException e) {
340: }
341: }
342:
343: if (is != null) {
344: is.close();
345: }
346: }
347: }
|