3
* ====================================================================
4
* Licensed to the Apache Software Foundation (ASF) under one
5
* or more contributor license agreements. See the NOTICE file
6
* distributed with this work for additional information
7
* regarding copyright ownership. The ASF licenses this file
8
* to you under the Apache License, Version 2.0 (the
9
* "License"); you may not use this file except in compliance
10
* with the License. You may obtain a copy of the License at
12
* http://www.apache.org/licenses/LICENSE-2.0
14
* Unless required by applicable law or agreed to in writing,
15
* software distributed under the License is distributed on an
16
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17
* KIND, either express or implied. See the License for the
18
* specific language governing permissions and limitations
20
* ====================================================================
24
package org.apache.subversion.javahl;
26
import org.apache.subversion.javahl.callback.*;
27
import org.apache.subversion.javahl.types.*;
28
import org.apache.subversion.javahl.util.*;
30
import java.io.InputStream;
31
import java.io.OutputStream;
32
import java.util.Date;
33
import java.util.List;
39
// Global configuration
41
private static final ConfigLib configLib = new ConfigLib();
44
* Enable storing authentication credentials in Subversion's
45
* standard credentials store in the configuration directory and
46
* system-specific secure locations.
48
* The standard credentials store is enabled by default.
50
* This setting will be inherited by all ISVNClient and ISVNRemote
51
* objects. Changing the setting will not affect existing such
53
* @throws ClientException
55
public static void enableNativeCredentialsStore()
56
throws ClientException
58
configLib.enableNativeCredentialsStore();
62
* Disable storing authentication credentials in Subversion's
63
* standard credentials store in the configuration directory and
64
* system-specific secure locations. In this mode, the
65
* authentication (see {@link ISVNClient#setPrompt} and {@link
66
* remote.RemoteFactory#setPrompt}) will be called every time the
67
* underlying library needs access to the credentials.
69
* This mode is intented to support client implementations that
70
* use their own credentials store.
72
* The standard credentials store is enabled by default.
74
* This setting will be inherited by all ISVNClient and ISVNRemote
75
* objects. Changing the setting will not affect existing such
77
* @throws ClientException
79
public static void disableNativeCredentialsStore()
80
throws ClientException
82
configLib.disableNativeCredentialsStore();
86
* Find out if the standard credentials store is enabled.
88
public static boolean isNativeCredentialsStoreEnabled()
89
throws ClientException
91
return configLib.isNativeCredentialsStoreEnabled();
95
// Credentials management
99
* Exception used by calling the wrong accessor on Credential for
100
* the given credential type.
102
public static class CredentialTypeMismatch extends SubversionException
104
// Update the serialVersionUID when there is a incompatible change made to
105
// this class. See the java documentation for when a change is incompatible.
106
// http://java.sun.com/javase/7/docs/platform/serialization/spec/version.html#6678
107
private static final long serialVersionUID = 1L;
109
public CredentialTypeMismatch(Credential.Kind kind, String attribute)
111
super("Credential type '" + kind.toString()
112
+ "' does not have the attribute '" + attribute + "'");
117
* Generic credential description. Provides default accessors for
118
* concrete implementations.
120
public static class Credential implements java.io.Serializable
122
// Update the serialVersionUID when there is a incompatible change made to
123
// this class. See the java documentation for when a change is incompatible.
124
// http://java.sun.com/javase/7/docs/platform/serialization/spec/version.html#6678
125
private static final long serialVersionUID = 1L;
128
* Describes the kind of the credential.
130
public static enum Kind
132
/** The username for a realm. */
133
username ("svn.username"),
135
/** The username and password for a realm. */
136
simple ("svn.simple"),
138
/** The trusted SSL server certificate for a realm. */
139
sslServer ("svn.ssl.server"),
141
/** The client certificate passphrase for a realm. */
142
sslClientPassphrase ("svn.ssl.client-passphrase");
144
private String token;
151
/** @return the string representation of the enumeration. */
152
public String toString()
157
/* Factory used by the native implementation */
158
private static Kind fromString(String stringrep)
160
for (Kind kind : Kind.values()) {
161
if (kind.toString().equals(stringrep))
168
/** @return the kind of the credential. */
169
public Kind getKind()
174
/** @return the realm that the credential is valid for. */
175
public String getRealm()
181
* @return the type of the secure store used for the secret
182
* parts of this credential; may be <code>null</code> if the
183
* credential does not contain any secrets bits.
185
public String getSecureStore()
186
throws CredentialTypeMismatch
188
if (kind != Kind.simple && kind != Kind.sslClientPassphrase)
189
throw new CredentialTypeMismatch(kind, "secure store");
195
* @return the username associated with the credential, or
196
* <code>null</code>, if there is no username in the concrete
199
public String getUsername()
200
throws CredentialTypeMismatch
202
if (kind != Kind.username && kind != Kind.simple)
203
throw new CredentialTypeMismatch(kind, "username");
209
* @return the password associated with the credential, or
210
* <code>null</code>, if there is no password in the concrete
213
public String getPassword()
214
throws CredentialTypeMismatch
216
if (kind != Kind.simple && kind != Kind.sslClientPassphrase)
217
throw new CredentialTypeMismatch(kind, "password");
223
* @return the server certificate info associated with the
224
* credential, or <code>null</code>, if there is no server
225
* certificate in the concrete credential type.
227
public AuthnCallback.SSLServerCertInfo getServerCertInfo()
228
throws CredentialTypeMismatch
230
if (kind != Kind.sslServer)
231
throw new CredentialTypeMismatch(kind, "server cert info");
237
* @return the accepted server certificate failures associated
238
* with the credential, or <code>null</code>, if there is no
239
* server certificate in the concrete credential type.
241
public AuthnCallback.SSLServerCertFailures getServerCertFailures()
242
throws CredentialTypeMismatch
244
if (kind != Kind.sslServer)
245
throw new CredentialTypeMismatch(kind, "server cert failures");
251
* @return the client certificate passphrase associated with
252
* the credential, or <code>null</code>, if there is no client
253
* certificate in the concrete credential type.
255
public String getClientCertPassphrase()
256
throws CredentialTypeMismatch
258
if (kind != Kind.sslClientPassphrase)
259
throw new CredentialTypeMismatch(kind, "passphrase");
264
// ### TODO: There are currently no proper APIs in Subversion
265
// for adding credentials. These factory methods are
269
// * Creates an "svn.username" credential.
270
// * @param realm The realm string.
271
// * @param username The username for <code>realm</code>.
273
//public static Credential
274
// createUsername(String realm, String username)
276
// return new Credential(Kind.username, realm, null,
277
// username, null, null, null, null);
281
// * Creates an "svn.simple" credential.
282
// * @param realm The realm string.
283
// * @param username The username for <code>realm</code>.
284
// * @param password The password for <code>username</code>.
286
//public static Credential
287
// createSimple(String realm, String username, String password)
289
// return new Credential(Kind.simple, realm, null,
290
// username, password, null, null, null);
293
///** Creates an "svn.ssl.server" credential. */
294
//public static Credential
295
// createSSLServerCertTrust(String realm,
296
// AuthnCallback.SSLServerCertInfo info,
297
// AuthnCallback.SSLServerCertFailures failures)
299
// return new Credential(Kind.sslServer, realm, null,
300
// null, null, info, failures, null);
304
// * Creates an "svn.ssl.client-passphrase" credential.
305
// * @param realm The realm string.
306
// * @param passphrase The passphrase for for the client certificate
307
// * used for <code>realm</code>.
309
//public static Credential
310
// createSSLClientCertPassphrase(String realm, String passphrase)
312
// return new Credential(Kind.simple, realm, null,
313
// null, null, null, null, passphrase);
316
private Credential(Kind kind, String realm, String store,
317
String username, String password,
318
AuthnCallback.SSLServerCertInfo info,
319
AuthnCallback.SSLServerCertFailures failures,
322
assert(kind != null && realm != null);
325
assert(username != null && password == null
326
&& info == null && failures == null
327
&& passphrase == null);
330
assert(username != null && password != null
331
&& info == null && failures == null
332
&& passphrase == null);
335
assert(username == null && password == null
336
&& info != null && failures != null
337
&& passphrase == null);
339
case sslClientPassphrase:
340
assert(username == null && password == null
341
&& info == null && failures == null
342
&& passphrase != null);
345
assert(kind == Kind.username
346
|| kind == Kind.simple
347
|| kind == Kind.sslServer
348
|| kind == Kind.sslClientPassphrase);
354
this.username = username;
355
this.password = password;
357
this.failures = failures;
358
this.passphrase = passphrase;
362
private String realm;
363
private String store;
364
private String username;
365
private String password;
366
private AuthnCallback.SSLServerCertInfo info;
367
private AuthnCallback.SSLServerCertFailures failures;
368
private String passphrase;
372
* Find a stored credential.
373
* Unlike {@link #searchCredentials}, the the realm name is not
376
* <b>Note:</b> If the native credentials store is disabled, this
377
* method will always return <code>null</code>.
379
* @param configDir The path to the configuration directory; if
380
* <code>null</code>, the default (system-specific) user
381
* configuration path will be used.
382
* @param kind The kind of the credential; may not be <code>null</code>.
383
* @param realm The realm name; may not be <code>null</code>.
384
* @return the matching credential, or <code>null</code> if not found.
386
public static Credential getCredential(String configDir,
387
Credential.Kind kind,
389
throws ClientException, SubversionException
391
return configLib.getCredential(configDir, kind, realm);
395
* Remove a stored credential.
396
* Unlike {@link #deleteCredentials}, the the realm name is not
399
* <b>Note:</b> If the native credentials store is disabled, this
400
* method will always return <code>null</code>.
402
* @param configDir The path to the configuration directory; if
403
* <code>null</code>, the default (system-specific) user
404
* configuration path will be used.
405
* @param kind The kind of the credential; may not be <code>null</code>.
406
* @param realm The realm name; may not be <code>null</code>.
407
* @return the deleted credential, or <code>null</code> if not found.
409
public static Credential removeCredential(String configDir,
410
Credential.Kind kind,
412
throws ClientException, SubversionException
414
return configLib.removeCredential(configDir, kind, realm);
417
// ### TODO: There are currently no proper APIs in Subversion for
418
// adding credentials. This method is a placeholder.
421
// * Store a new credential, or replace an existing credential.
423
// * <b>Note:</b> If the native credentials store is disabled, this
424
// * method will always return <code>null</code>.
426
// * @param configDir The path to the configuration directory; if
427
// * <code>null</code>, the default (system-specific) user
428
// * configuration path will be used.
429
// * @param credential The credential to store.
430
// * @param replace If <code>true</code>, any existing matching
431
// * credential will be replaced.
433
// * @return the stored credential. If <code>replace</code> was
434
// * <code>false</code>, and a credential with the same kind and
435
// * for the same realm exists, it will be returned. If the given
436
// * credential was successfully added, the same object reference
437
// * will be returned (the calling code can compare reference values
438
// * to determine this). Will return <code>null</code> if the
439
// * credential could not be stored for any reason.
441
//public static Credential addCredential(String configDir,
442
// Credential credential,
444
// throws ClientException, SubversionException
446
// return configLib.addCredential(configDir, credential, replace);
450
* Find stored credentials that match the given search criteria.
452
* <b>Note:</b> If the native credentials store is disabled, this
453
* method will always return <code>null</code>.
455
* @param configDir The path to the configuration directory; if
456
* <code>null</code>, the default (system-specific) user
457
* configuration path will be used.
458
* @param kind The kind of the credential; if <code>null</code>,
459
* all matching credential types will be returned.
460
* @param realmPattern A glob pattern for the realm string;
461
* if <code>null</code>, all realms will be considered;
462
* otherwise, only those credentials whose realm matches
463
* the pattern will be returned.
464
* @param usernamePattern A glob pattern for the username;
465
* if <code>null</code>, all credentials will be considered;
466
* otherwise, only those credentials that have a username,
467
* and where the username matches the pattern, will be
469
* @param hostnamePattern A glob pattern for the hostnames of a
470
* server certificate; if <code>null</code>, all
471
* credntials will be considered; otherwise, only
472
* those credentials that have a server certificate
473
* with a hostname that matches the pattern will be
475
* @param textPattern A glob pattern that must match any textual
476
* information in a credential, for example, a realm,
477
* username, certificate details, etc; passwords, passphrases
478
* and other info considered secret will not be matched;
479
* @return the list of matching credentials.
481
public static List<Credential>
482
searchCredentials(String configDir,
483
Credential.Kind kind,
485
String usernamePattern,
486
String hostnamePattern,
488
throws ClientException, SubversionException
490
return configLib.searchCredentials(configDir, kind, realmPattern,
491
usernamePattern, hostnamePattern,
498
private static final DiffLib diffLib = new DiffLib();
501
* Options to control the behaviour of the file diff routines.
503
public static class DiffOptions
506
* To what extent whitespace should be ignored when comparing lines.
508
public enum IgnoreSpace
510
/** Do not ignore whitespace */
514
* Ignore changes in sequences of whitespace characters,
515
* treating each sequence of whitespace characters as a
520
/** Ignore all whitespace characters. */
525
* @param ignoreSpace Whether and how to ignore space differences
526
* in the files. The default is {@link IgnoreSpace#none}.
527
* @param ignoreEolStyle Whether to treat all end-of-line
528
* markers the same when comparing lines. The default
529
* is <code>false</code>.
530
* @param showCFunction Whether the "@@" lines of the unified
531
* diff output should include a prefix of the nearest
532
* preceding line that starts with a character that
533
* might be the initial character of a C language
534
* identifier. The default is <code>false</code>.
536
public DiffOptions(IgnoreSpace ignoreSpace,
537
boolean ignoreEolStyle,
538
boolean showCFunction)
540
this.ignoreSpace = ignoreSpace;
541
this.ignoreEolStyle = ignoreEolStyle;
542
this.showCFunction = showCFunction;
543
this.contextSize = -1;
547
* Like the {@see #DiffOptions(IgnoreSpace,boolean,boolean)},
548
* but with an additional parameter.
549
* @param contextSize If this is greater than 0, then this
550
* number of context lines will be used in the generated diff
551
* output. Otherwise the legacy compile time default will be
554
public DiffOptions(IgnoreSpace ignoreSpace,
555
boolean ignoreEolStyle,
556
boolean showCFunction,
559
this.ignoreSpace = ignoreSpace;
560
this.ignoreEolStyle = ignoreEolStyle;
561
this.showCFunction = showCFunction;
562
this.contextSize = contextSize;
565
public final IgnoreSpace ignoreSpace;
566
public final boolean ignoreEolStyle;
567
public final boolean showCFunction;
568
public final int contextSize;
571
/** Style for displaying conflicts in merge output. */
572
public enum ConflictDisplayStyle
574
/** Display modified and latest, with conflict markers. */
578
* Like <code>modified_latest</code>, but with an extra effort
579
* to identify common sequences between modified and latest.
581
resolved_modified_latest,
583
/** Display modified, original, and latest, with conflict markers. */
584
modified_original_latest,
586
/** Just display modified, with no markers. */
589
/** Just display latest, with no markers. */
593
* Like <code>modified_original_latest</code>, but
594
* <em>only<em> showing conflicts.
600
* Given two versions of a file, base (<code>originalFile</code>)
601
* and current (<code>modifiedFile</code>), show differences between
602
* them in unified diff format.
604
* @param originalFile The base file version (unmodified)
605
* @param modifiedFile The incoming file version (locally modified)
606
* @param diffOptions Options controlling how files are compared.
607
* May be <code>null</code>.
608
* @param originalHeader The header to display for the base file
609
* in the unidiff index block. If it is <code>null</code>,
610
* the <code>originalFile</code> path and its modification
611
* time will be used instead.
612
* @param modifiedHeader The header to display for the current
613
* file in the unidiff index block. If it is <code>null</code>,
614
* the <code>currentFile</code> path and its modification
615
* time will be used instead.
616
* @param headerEncoding The character encoding of the unidiff headers.
617
* @param relativeToDir If this parameter is not <null>, it must
618
* be the path of a (possibly non-immediate) parent of both
619
* <code>originalFile</code> and <code>modifiedFile</code>.
620
* This path will be stripped from the beginning of those
621
* file names if they are used in the unidiff index header.
622
* @param resultStream The stream that receives the merged output.
623
* @return <code>true</code> if there were differences between the files.
624
* @throws ClientException
626
public static boolean fileDiff(String originalFile,
628
SVNUtil.DiffOptions diffOptions,
630
String originalHeader,
631
String modifiedHeader,
632
String headerEncoding,
633
String relativeToDir,
635
OutputStream resultStream)
636
throws ClientException
638
// ### TODO: Support cancellation as in svn_diff_file_output_unified3.
639
return diffLib.fileDiff(originalFile, modifiedFile, diffOptions,
640
originalHeader, modifiedHeader,
642
relativeToDir, resultStream);
647
* Given three versions of a file, base (<code>originalFile</code>),
648
* incoming (<code>modifiedFile</code>) and current
649
* (<code>latestFile</code>, produce a merged result, possibly
650
* displaying conflict markers.
652
* @param originalFile The base file version (common ancestor)
653
* @param modifiedFile The incoming file version (modified elsewhere)
654
* @param latestFile The current file version (locally modified)
655
* @param diffOptions Options controlling how files are compared.
656
* May be <code>null</code>.
657
* @param conflictOriginal Optional custom conflict marker for
658
* the <code>originalFile</code> contents.
659
* @param conflictModified Optional custom conflict marker for
660
* the <code>modifiedFile</code> contents.
661
* @param conflictLatest Optional custom conflict marker for
662
* the <code>latestFile</code> contents.
663
* @param conflictSeparator Optional custom conflict separator.
664
* @param conflictStyle Determines how conflicts are displayed.
665
* @param resultStream The stream that receives the merged output.
666
* @return <code>true</code> if there were any conflicts.
667
* @throws ClientException
669
public static boolean fileMerge(String originalFile,
672
DiffOptions diffOptions,
674
String conflictOriginal,
675
String conflictModified,
676
String conflictLatest,
677
String conflictSeparator,
678
ConflictDisplayStyle conflictStyle,
680
OutputStream resultStream)
681
throws ClientException
683
return diffLib.fileMerge(originalFile, modifiedFile, latestFile,
685
conflictOriginal, conflictModified,
686
conflictLatest, conflictSeparator,
687
conflictStyle, resultStream);
691
// Property validation and parsing
693
private static final PropLib propLib = new PropLib();
696
* Validate the value of an <code>svn:</code> property on file or
697
* directory and return a canonical representation of its value.
698
* @param name The name of the property (must be a valid svn: property)
699
* @param value The property's value
700
* @param path The path or URL of the file or directory that
701
* owns the property; only used for error messages
702
* @param kind The node kind of the file or dir that owns the property
703
* @param mimeType If <code>kind</code> is {@link NodeKind.file}, this is
704
* tye file's mime-type, used for extra validation for the
705
* <code>svn:eol-style</code> property. If it is <code>null</code>,
706
* the extra validation will be skipped.
707
* @return a canonicalized representation of the property value
708
* @see http://subversion.apache.org/docs/api/latest/group__svn__wc__properties.html#ga83296313ec59cc825176224ac8282ec2
710
public static byte[] canonicalizeNodeProperty(
711
String name, byte[] value, String path, NodeKind kind,
713
throws ClientException
715
return propLib.canonicalizeNodeProperty(
716
name, value, path, kind, mimeType, null);
720
* Validate the value of an <code>svn:</code> property on file or
721
* directory and return a canonical representation of its value.
722
* @param name The name of the property (must be a valid svn: property)
723
* @param value The property's value
724
* @param path The path or URL of the file or directory that
725
* owns the property; only used for error messages
726
* @param kind The node kind of the file or dir that owns the property
727
* @param mimeType If <code>kind</code> is {@link NodeKind.file}, this is
728
* tye file's mime-type, used for extra validation for the
729
* <code>svn:eol-style</code> property. If it is <code>null</code>,
730
* the extra validation will be skipped.
731
* @param fileContents A stream with the file's contents. Only used
732
* to check for line-ending consistency when validating the
733
* <code>svn:eol-style</code> property, and only when
734
* <code>kind</code> is {@link NodeKind.file} and
735
* <code>mimeType</code> is not <code>null</code>.
736
* @return a canonicalized representation of the property value
737
* @see http://subversion.apache.org/docs/api/latest/group__svn__wc__properties.html#ga83296313ec59cc825176224ac8282ec2
739
public static byte[] canonicalizeNodeProperty(
740
String name, byte[] value, String path, NodeKind kind,
741
String mimeType, InputStream fileContents)
742
throws ClientException
744
return propLib.canonicalizeNodeProperty(
745
name, value, path, kind, mimeType, fileContents);
749
* Parse <code>description</code>, assuming it is an externals
750
* specification in the format required for the
751
* <code>svn:externals</code> property, and return a list of
752
* parsed external items.
753
* @param description The externals description.
754
* @param parentDirectory Used to construct error messages.
755
* @param canonicalizeUrl Whe <code>true</code>, canonicalize the
756
* <code>url</code> member of the returned objects. If the
757
* <code>url</code> member refers to an absolute URL, it will
758
* be canonicalized as URL consistent with the way URLs are
759
* canonicalized throughout the Subversion API. If, however,
760
* the <code>url</code> member makes use of the recognized
761
* (SVN-specific) relative URL syntax for
762
* <code>svn:externals</code>, "canonicalization" is an
763
* ill-defined concept which may even result in munging the
764
* relative URL syntax beyond recognition. You've been warned.
765
* @return a list of {@link ExternalItem}s
767
public static List<ExternalItem> parseExternals(byte[] description,
768
String parentDirectory,
769
boolean canonicalizeUrl)
770
throws ClientException
772
return propLib.parseExternals(description, parentDirectory,
777
* Unparse and list of external items into a format suitable for
778
* the value of the <code>svn:externals</code> property and
779
* validate the result.
780
* @param items The list of {@link ExternalItem}s
781
* @param parentDirectory Used to construct error messages.
782
* @param compatibleWithSvn1_5 When <code>true</code>, the format
783
* of the returned property value will be compatible with
784
* clients older than Subversion 1.5.
786
public static byte[] unparseExternals(List<ExternalItem> items,
787
String parentDirectory)
788
throws SubversionException
790
return propLib.unparseExternals(items, parentDirectory, false);
794
* Unparse and list of external items into a format suitable for
795
* the value of the <code>svn:externals</code> property compatible
796
* with Subversion clients older than release 1.5, and validate
798
* @param items The list of {@link ExternalItem}s
799
* @param parentDirectory Used to construct error messages.
801
public static byte[] unparseExternalsForAncientUnsupportedClients(
802
List<ExternalItem> items, String parentDirectory)
803
throws SubversionException
805
return propLib.unparseExternals(items, parentDirectory, true);
809
* If the URL in <code>external</code> is relative, resolve it to
810
* an absolute URL, using <code>reposRootUrl</code> and
811
* <code>parentDirUrl</code> to provide contest.
813
* Regardless if the URL is absolute or not, if there are no
814
* errors, the returned URL will be canonicalized.
816
* The following relative URL formats are supported:
818
* <dt><code>../</code></dt>
819
* <dd>relative to the parent directory of the external</dd>
820
* <dt><code>^/</code></dt>
821
* <dd>relative to the repository root</dd>
822
* <dt><code>//</code></dt>
823
* <dd>relative to the scheme</dd>
824
* <dt><code>/</code></dt>
825
* <dd>relative to the server's hostname</dd>
828
* The <code>../<code> and ^/ relative URLs may use <code>..</code>
829
* to remove path elements up to the server root.
831
* The external URL should not be canonicalized before calling
832
* this function, as otherwise the scheme relative URL
833
* '<code>//host/some/path</code>' would have been canonicalized
834
* to '<code>/host/some/path</code>' and we would not be able to
835
* match on the leading '<code>//</code>'.
837
public static String resolveExternalsUrl(ExternalItem external,
840
throws ClientException
842
return propLib.resolveExternalsUrl(
843
external, reposRootUrl, parentDirUrl);
847
// Newline translation and keyword expansion
849
private static final SubstLib substLib = new SubstLib();
852
* Use the linefeed code point ('<code>\x0a</code>')
853
* for the newline separator.
854
* @see translateStream
855
* @see untranslateStream
857
public static final byte[] EOL_LF = SubstLib.EOL_LF;
860
* Use the carraige-return code point ('<code>\x0d</code>')
861
* for the newline separator.
862
* @see translateStream
863
* @see untranslateStream
865
public static final byte[] EOL_CR = SubstLib.EOL_CR;
868
* Use carriage-return/linefeed sequence ('<code>\x0d\x0a</code>')
869
* for the newline separator.
870
* @see translateStream
871
* @see untranslateStream
873
public static final byte[] EOL_CRLF = SubstLib.EOL_CRLF;
877
* Build a dictionary of expanded keyword values, given the
878
* contents of a file's <code>svn:keywords</code> property, its
879
* revision, URL, the date it was committed on, the author of the
880
* commit and teh URL of the repository root.
882
* Custom keywords defined in <code>svn:keywords</code> properties
883
* are expanded using the provided parameters and in accordance
884
* with the following format substitutions in the
885
* <code>keywordsValue</code>:
887
* <dt><code>%a</dt></code>
888
* <dd>The author.</dd>
889
* <dt><code>%b</dt></code>
890
* <dd>The basename of the URL.</dd>
891
* <dt><code>%d</dt></code>
892
* <dd>Short format of the date.</dd>
893
* <dt><code>%D</dt></code>
894
* <dd>Long format of the date.</dd>
895
* <dt><code>%P</dt></code>
896
* <dd>The file's path, relative to the repository root URL.</dd>
897
* <dt><code>%r</dt></code>
898
* <dd>The revision.</dd>
899
* <dt><code>%R</dt></code>
900
* <dd>The URL to the root of the repository.</dd>
901
* <dt><code>%u</dt></code>
902
* <dd>The URL of the file.</dd>
903
* <dt><code>%_</dt></code>
904
* <dd>A space (keyword definitions cannot contain a literal space).</dd>
905
* <dt><code>%%</dt></code>
906
* <dd>A literal '%'.</dd>
907
* <dt><code>%H</dt></code>
908
* <dd>Equivalent to <code>%P%_%r%_%d%_%a</code>.</dd>
909
* <dt><code>%I</dt></code>
910
* <dd>Equivalent to <code>%b%_%r%_%d%_%a</code>.</dd>
913
* Custom keywords are defined by appending '=' to the keyword
914
* name, followed by a string containing any combination of the
915
* format substitutions.
917
* Any of the <code>revision</code>, <code>url</code>,
918
* <code>reposRootUrl</code>, <code>date</code> and
919
* <code>author</code> parameters may be <code>null</code>, or
920
* {@link Revision#SVN_INVALID_REVNUM} for <code>revision</code>,
921
* to indicate that the information is not present. Each piece of
922
* information that is not present expands to the empty string
923
* wherever it appears in an expanded keyword value. (This can
924
* result in multiple adjacent spaces in the expansion of a
925
* multi-valued keyword such as "<code>Id</code>".)
927
public static Map<String, byte[]> buildKeywords(byte[] keywordsValue,
933
throws SubversionException, ClientException
935
return substLib.buildKeywords(keywordsValue, revision,
936
url, reposRootUrl, date, author);
940
* Return a stream which performs end-of-line translation and
941
* keyword expansion when read from.
943
* <b>Important:</b> Make sure you close the returned stream to
944
* ensure all data are flushed and cleaned up (this will also
945
* close the provided stream and dispose the related netive
948
* If <code>eolMarker</code> is not <code>null</code>, replace
949
* whatever any end-of-line sequences in the input with
950
* <code>eolMarker</code>. If the input has an inconsistent line
951
* ending style, then:
953
* <li>if <code>repairEol</code> is <code>false</code>, then a
954
* subsequent read or other operation on the stream will
955
* generate an error when the inconsistency is detected;</li>
956
* <li>if <code>repaorEol</code> is <code>true</code>, convert any
957
* line ending to <code>eolMarker</code>.<br/>
958
* Recognized line endings are: "<code>\n</code>",
959
* "<code>\r</code>", and "<code>\r\n</code>".</li>
962
* Expand or contract keywords using the contents of
963
* <code>keywords</code> as the new values. If
964
* <code>expandKeywords</code> is <code>true</code>, expand
965
* contracted keywords and re-expand expanded keywords; otherwise,
966
* contract expanded keywords and ignore contracted ones.
967
* Keywords not found in the dictionary are ignored (not
968
* contracted or expanded). If the <code>keywords</code> itself
969
* is <code>null</code>, keyword substitution will be altogether
972
* Detect only keywords that are no longer than
973
* <code>SVN_KEYWORD_MAX_LEN</code> bytes (currently: 255),
974
* including the delimiters and the keyword itself.
976
* Recommendation: if <code>expandKeywords</code> is
977
* <code>false</code>, then you don't care about the keyword
978
* values, so just put <code>null</code> values into the
979
* <code>keywords</code> dictionary.
981
* If the inner stream implements marking and seeking via
982
* {@link InputStream#mark} and {@link InputStream#reset}, the
983
* translated stream will too.
985
* @param source the source (untranslated) stream.
986
* @param eolMarker the byte sequence to use as the end-of-line marker;
987
* must be one of {@link #EOL_LF}, {@link #EOL_CR}
988
* or {@link #EOL_CRLF}.
989
* @param repairEol flag to repair end-of-lines; see above
990
* @param keywords the keyword dictionary; see {@link buildKeywords}
991
* @param expandKeywords flag to expand keywords
993
public static InputStream translateStream(InputStream source,
996
Map<String, byte[]> keywords,
997
boolean expandKeywords)
998
throws SubversionException, ClientException
1000
return substLib.translateInputStream(
1001
source, eolMarker, repairEol,
1002
keywords, true, expandKeywords,
1003
null, Revision.SVN_INVALID_REVNUM,
1004
null, null, null, null);
1008
* Expand keywords and return a stream which performs end-of-line
1009
* translation and keyword expansion when read from.
1010
* @see buildKeywords
1011
* @see translateStream(InputStream,byte[],boolean,Map,boolean)
1013
public static InputStream translateStream(InputStream source,
1016
boolean expandKeywords,
1017
byte[] keywordsValue,
1020
String reposRootUrl,
1023
throws SubversionException, ClientException
1025
return substLib.translateInputStream(
1026
source, eolMarker, repairEol,
1027
null, false, expandKeywords,
1028
keywordsValue, revision,
1029
url, reposRootUrl, date, author);
1033
* Return a stream which performs end-of-line translation and
1034
* keyword expansion when written to. Behaves like
1035
* {@link #translateStream(InputStream,byte[],boolean,Map,boolean)},
1036
* except that it translates an <code>OutputStream</code> and never
1037
* supports marking and seeking.
1039
public static OutputStream translateStream(OutputStream destination,
1042
Map<String, byte[]> keywords,
1043
boolean expandKeywords)
1044
throws SubversionException, ClientException
1046
return substLib.translateOutputStream(
1047
destination, eolMarker, repairEol,
1048
keywords, true, expandKeywords,
1049
null, Revision.SVN_INVALID_REVNUM,
1050
null, null, null, null);
1054
* Expand keywords and return a stream which performs end-of-line
1055
* translation and keyword expansion when written to.
1056
* @see buildKeywords
1057
* @see translateStream(OutputStream,byte[],boolean,Map,boolean)
1059
public static OutputStream translateStream(OutputStream destination,
1062
boolean expandKeywords,
1063
byte[] keywordsValue,
1066
String reposRootUrl,
1069
throws SubversionException, ClientException
1071
return substLib.translateOutputStream(
1072
destination, eolMarker, repairEol,
1073
null, false, expandKeywords,
1074
keywordsValue, revision,
1075
url, reposRootUrl, date, author);