001: /*
002: * ====================================================================
003: * Copyright (c) 2004-2008 TMate Software Ltd. All rights reserved.
004: *
005: * This software is licensed as described in the file COPYING, which
006: * you should have received as part of this distribution. The terms
007: * are also available at http://svnkit.com/license.html
008: * If newer versions of this license are posted there, you may use a
009: * newer version instead, at your option.
010: * ====================================================================
011: */
012:
013: package org.tmatesoft.svn.cli;
014:
015: import java.io.ByteArrayOutputStream;
016: import java.io.File;
017: import java.io.FileInputStream;
018: import java.io.IOException;
019: import java.io.InputStream;
020: import java.io.PrintStream;
021: import java.util.Arrays;
022: import java.util.HashMap;
023: import java.util.HashSet;
024: import java.util.Iterator;
025: import java.util.Map;
026: import java.util.Set;
027: import java.util.StringTokenizer;
028:
029: import org.tmatesoft.svn.core.SVNErrorCode;
030: import org.tmatesoft.svn.core.SVNErrorMessage;
031: import org.tmatesoft.svn.core.SVNException;
032: import org.tmatesoft.svn.core.SVNURL;
033: import org.tmatesoft.svn.core.auth.ISVNAuthenticationManager;
034: import org.tmatesoft.svn.core.wc.ISVNOptions;
035: import org.tmatesoft.svn.core.wc.SVNClientManager;
036: import org.tmatesoft.svn.core.wc.SVNRevision;
037: import org.tmatesoft.svn.core.wc.SVNWCUtil;
038: import org.tmatesoft.svn.util.SVNDebugLog;
039:
040: /**
041: * @version 1.1.1
042: * @author TMate Software Ltd.
043: */
044: public abstract class SVNCommand {
045:
046: private SVNCommandLine myCommandLine;
047: private String myUserName;
048: private String myPassword;
049:
050: private static Map ourCommands;
051: private static Set ourPegCommands;
052: private static HashSet ourForceLogCommands;
053:
054: private boolean myIsStoreCreds;
055: private SVNClientManager myClientManager;
056:
057: protected SVNCommandLine getCommandLine() {
058: return myCommandLine;
059: }
060:
061: public void setCommandLine(SVNCommandLine commandLine) {
062: myCommandLine = commandLine;
063: myUserName = (String) commandLine
064: .getArgumentValue(SVNArgument.USERNAME);
065: myPassword = (String) commandLine
066: .getArgumentValue(SVNArgument.PASSWORD);
067: myIsStoreCreds = !commandLine
068: .hasArgument(SVNArgument.NO_AUTH_CACHE);
069: }
070:
071: public abstract void run(PrintStream out, PrintStream err)
072: throws SVNException;
073:
074: public abstract void run(InputStream in, PrintStream out,
075: PrintStream err) throws SVNException;
076:
077: private ISVNOptions getOptions() {
078: String dir = (String) getCommandLine().getArgumentValue(
079: SVNArgument.CONFIG_DIR);
080: File dirFile = dir == null ? null : new File(dir);
081: ISVNOptions options = SVNWCUtil.createDefaultOptions(dirFile,
082: true);
083: options.setAuthStorageEnabled(myIsStoreCreds);
084: return options;
085: }
086:
087: protected SVNClientManager getClientManager() {
088: if (myClientManager == null) {
089: String dir = (String) getCommandLine().getArgumentValue(
090: SVNArgument.CONFIG_DIR);
091: File dirFile = dir == null ? null : new File(dir);
092: ISVNAuthenticationManager authManager = SVNWCUtil
093: .createDefaultAuthenticationManager(dirFile,
094: myUserName, myPassword, getOptions()
095: .isAuthStorageEnabled());
096: if (!myCommandLine.hasArgument(SVNArgument.NON_INTERACTIVE)) {
097: authManager
098: .setAuthenticationProvider(new SVNConsoleAuthenticationProvider());
099: }
100: myClientManager = SVNClientManager.newInstance(
101: getOptions(), authManager);
102: }
103: return myClientManager;
104: }
105:
106: protected String getCommitMessage() throws SVNException {
107: String fileName = (String) getCommandLine().getArgumentValue(
108: SVNArgument.FILE);
109: if (fileName != null) {
110: FileInputStream is = null;
111: ByteArrayOutputStream bos = new ByteArrayOutputStream();
112: try {
113: is = new FileInputStream(fileName);
114: while (true) {
115: int r = is.read();
116: if (r < 0) {
117: break;
118: }
119: if (r == 0) {
120: // invalid
121: SVNErrorMessage err = SVNErrorMessage
122: .create(
123: SVNErrorCode.CL_BAD_LOG_MESSAGE,
124: "error: commit message contains a zero byte");
125: throw new SVNException(err);
126: }
127: bos.write(r);
128: }
129: } catch (IOException e) {
130: SVNErrorMessage msg = SVNErrorMessage.create(
131: SVNErrorCode.CL_BAD_LOG_MESSAGE, e
132: .getLocalizedMessage());
133: throw new SVNException(msg, e);
134: } finally {
135: try {
136: if (is != null) {
137: is.close();
138: }
139: bos.close();
140: } catch (IOException e) {
141: SVNErrorMessage msg = SVNErrorMessage.create(
142: SVNErrorCode.CL_BAD_LOG_MESSAGE, e
143: .getLocalizedMessage());
144: throw new SVNException(msg, e);
145: }
146: }
147: return new String(bos.toByteArray());
148: }
149: return (String) getCommandLine().getArgumentValue(
150: SVNArgument.MESSAGE);
151: }
152:
153: public static String formatString(String str, int chars,
154: boolean left) {
155: if (str.length() > chars) {
156: return str.substring(0, chars);
157: }
158: StringBuffer formatted = new StringBuffer();
159: if (left) {
160: formatted.append(str);
161: }
162: for (int i = 0; i < chars - str.length(); i++) {
163: formatted.append(' ');
164: }
165: if (!left) {
166: formatted.append(str);
167: }
168: return formatted.toString();
169: }
170:
171: public static SVNCommand getCommand(String name) {
172: return getCommand(name, ourCommands);
173: }
174:
175: public static SVNCommand getCommand(String name, Map commands) {
176: if (name == null) {
177: return null;
178: }
179: String className = null;
180: for (Iterator keys = commands.keySet().iterator(); keys
181: .hasNext();) {
182: String[] names = (String[]) keys.next();
183: for (int i = 0; i < names.length; i++) {
184: if (name.equals(names[i])) {
185: className = (String) commands.get(names);
186: break;
187: }
188: }
189: if (className != null) {
190: break;
191: }
192: }
193: if (className == null) {
194: return null;
195: }
196: try {
197: Class clazz = Class.forName(className);
198: if (clazz != null) {
199: return (SVNCommand) clazz.newInstance();
200: }
201: } catch (Throwable th) {
202: SVNDebugLog.getDefaultLog().info(th);
203: //
204: }
205: return null;
206: }
207:
208: public static boolean hasPegRevision(String commandName) {
209: String fullName = getFullCommandName(commandName);
210: return fullName != null && ourPegCommands.contains(fullName);
211: }
212:
213: public static boolean isForceLogCommand(String commandName) {
214: String fullName = getFullCommandName(commandName);
215: return fullName != null
216: && ourForceLogCommands.contains(fullName);
217: }
218:
219: private static String getFullCommandName(String commandName) {
220: if (commandName == null) {
221: return null;
222: }
223: String fullName = null;
224: for (Iterator keys = ourCommands.keySet().iterator(); keys
225: .hasNext();) {
226: String[] names = (String[]) keys.next();
227: for (int i = 0; i < names.length; i++) {
228: if (commandName.equalsIgnoreCase(names[i])) {
229: fullName = names[0];
230: break;
231: }
232: }
233: if (fullName != null) {
234: break;
235: }
236: }
237: return fullName;
238: }
239:
240: protected static SVNRevision parseRevision(
241: SVNCommandLine commandLine) {
242: if (commandLine.hasArgument(SVNArgument.REVISION)) {
243: final String revStr = (String) commandLine
244: .getArgumentValue(SVNArgument.REVISION);
245: return SVNRevision.parse(revStr);
246: }
247: return SVNRevision.UNDEFINED;
248: }
249:
250: public static void println(PrintStream out, String line) {
251: out.println(line);
252: SVNDebugLog.getDefaultLog().info(line);
253: }
254:
255: public static void print(PrintStream out, String line) {
256: out.print(line);
257: }
258:
259: public static void println(PrintStream out) {
260: out.println();
261: }
262:
263: protected static boolean matchTabsInPath(String path,
264: PrintStream out) {
265: if (path != null && path.indexOf('\t') >= 0) {
266: out
267: .println("svn: Invalid control character '0x09' in path '"
268: + path + "'");
269: return true;
270: }
271: return false;
272: }
273:
274: protected static boolean matchTabsInURL(String url, PrintStream out) {
275: String path = null;
276: try {
277: path = SVNURL.parseURIEncoded(url).getURIEncodedPath();
278: } catch (SVNException e) {
279: }
280: if (path != null && path.indexOf("%09") >= 0) {
281: out
282: .println("svn: Invalid control character '0x09' in path '"
283: + url + "'");
284: return true;
285: }
286: return false;
287: }
288:
289: static {
290: // Locale.setDefault(Locale.ENGLISH);
291:
292: ourCommands = new HashMap();
293: ourCommands.put(new String[] { "status", "st", "stat" },
294: "org.tmatesoft.svn.cli.command.SVNStatusCommand");
295: ourCommands.put(new String[] { "import" },
296: "org.tmatesoft.svn.cli.command.SVNImportCommand");
297: ourCommands.put(new String[] { "checkout", "co" },
298: "org.tmatesoft.svn.cli.command.SVNCheckoutCommand");
299: ourCommands.put(new String[] { "add" },
300: "org.tmatesoft.svn.cli.command.SVNAddCommand");
301: ourCommands.put(new String[] { "commit", "ci" },
302: "org.tmatesoft.svn.cli.command.SVNCommitCommand");
303: ourCommands.put(new String[] { "update", "up" },
304: "org.tmatesoft.svn.cli.command.SVNUpdateCommand");
305: ourCommands.put(
306: new String[] { "delete", "rm", "remove", "del" },
307: "org.tmatesoft.svn.cli.command.SVNDeleteCommand");
308: ourCommands.put(new String[] { "move", "mv", "rename", "ren" },
309: "org.tmatesoft.svn.cli.command.SVNMoveCommand");
310: ourCommands.put(new String[] { "copy", "cp" },
311: "org.tmatesoft.svn.cli.command.SVNCopyCommand");
312: ourCommands.put(new String[] { "revert" },
313: "org.tmatesoft.svn.cli.command.SVNRevertCommand");
314: ourCommands.put(new String[] { "mkdir" },
315: "org.tmatesoft.svn.cli.command.SVNMkDirCommand");
316: ourCommands.put(new String[] { "propset", "pset", "ps" },
317: "org.tmatesoft.svn.cli.command.SVNPropsetCommand");
318: ourCommands.put(new String[] { "propdel", "pdel", "pd" },
319: "org.tmatesoft.svn.cli.command.SVNPropdelCommand");
320: ourCommands.put(new String[] { "propget", "pget", "pg" },
321: "org.tmatesoft.svn.cli.command.SVNPropgetCommand");
322: ourCommands.put(new String[] { "proplist", "plist", "pl" },
323: "org.tmatesoft.svn.cli.command.SVNProplistCommand");
324: ourCommands.put(new String[] { "info" },
325: "org.tmatesoft.svn.cli.command.SVNInfoCommand");
326: ourCommands.put(new String[] { "resolved" },
327: "org.tmatesoft.svn.cli.command.SVNResolvedCommand");
328: ourCommands.put(new String[] { "cat" },
329: "org.tmatesoft.svn.cli.command.SVNCatCommand");
330: ourCommands.put(new String[] { "ls", "list" },
331: "org.tmatesoft.svn.cli.command.SVNLsCommand");
332: ourCommands.put(new String[] { "log" },
333: "org.tmatesoft.svn.cli.command.SVNLogCommand");
334: ourCommands.put(new String[] { "switch", "sw" },
335: "org.tmatesoft.svn.cli.command.SVNSwitchCommand");
336: ourCommands.put(new String[] { "diff", "di" },
337: "org.tmatesoft.svn.cli.command.SVNDiffCommand");
338: ourCommands.put(new String[] { "merge" },
339: "org.tmatesoft.svn.cli.command.SVNMergeCommand");
340: ourCommands.put(new String[] { "export" },
341: "org.tmatesoft.svn.cli.command.SVNExportCommand");
342: ourCommands.put(new String[] { "cleanup" },
343: "org.tmatesoft.svn.cli.command.SVNCleanupCommand");
344: ourCommands.put(new String[] { "lock" },
345: "org.tmatesoft.svn.cli.command.SVNLockCommand");
346: ourCommands.put(new String[] { "unlock" },
347: "org.tmatesoft.svn.cli.command.SVNUnlockCommand");
348: ourCommands.put(new String[] { "annotate", "blame", "praise",
349: "ann" },
350: "org.tmatesoft.svn.cli.command.SVNAnnotateCommand");
351:
352: ourPegCommands = new HashSet();
353: ourPegCommands.addAll(Arrays.asList(new String[] { "cat",
354: "annotate", "checkout", "diff", "export", "info", "ls",
355: "merge", "propget", "proplist", "log" }));
356:
357: ourForceLogCommands = new HashSet();
358: ourForceLogCommands.addAll(Arrays.asList(new String[] {
359: "commit", "copy", "delete", "import", "mkdir", "move",
360: "lock" }));
361: }
362:
363: protected static int getLinesCount(String str) {
364: if ("".equals(str)) {
365: return 1;
366: }
367: int count = 0;
368: for (StringTokenizer lines = new StringTokenizer(str, "\r\n"); lines
369: .hasMoreTokens();) {
370: lines.nextToken();
371: count++;
372: }
373: return count;
374: }
375:
376: protected SVNRevision[] getStartEndRevisions() {
377: String revStr = (String) getCommandLine().getArgumentValue(
378: SVNArgument.REVISION);
379: SVNRevision startRevision = SVNRevision.UNDEFINED;
380: SVNRevision endRevision = SVNRevision.UNDEFINED;
381: if (revStr != null && revStr.indexOf("}:{") > 0) {
382: startRevision = SVNRevision.parse(revStr.substring(0,
383: revStr.indexOf("}:{") + 1));
384: endRevision = SVNRevision.parse(revStr.substring(revStr
385: .indexOf("}:{") + 2));
386: } else if (revStr != null && revStr.indexOf(':') > 0
387: && revStr.indexOf('{') < 0 && revStr.indexOf('}') < 0) {
388: startRevision = SVNRevision.parse(revStr.substring(0,
389: revStr.indexOf(':')));
390: endRevision = SVNRevision.parse(revStr.substring(revStr
391: .indexOf(':') + 1));
392: } else if (revStr != null) {
393: startRevision = SVNRevision.parse(revStr);
394: }
395: return new SVNRevision[] { startRevision, endRevision };
396: }
397:
398: }
|