UploadPack: allow custom RequestValidator instances

Make the existing concrete implementations public as well so custom
implementations may delegate to them where appropriate. Treat all custom
implementations as providing allow-tip-sha1 in want.

Change-Id: If386fe25c0d3b4551a97c16a22350714453b03e9
This commit is contained in:
Dave Borowitz 2013-06-23 17:28:34 -07:00
parent 68ccc5d213
commit 360d8624ca
1 changed files with 90 additions and 33 deletions

View File

@ -141,8 +141,12 @@ public static enum RequestPolicy {
ANY;
}
/** Validator for client requests. */
private interface RequestValidator {
/**
* Validator for client requests.
*
* @since 3.1
*/
public interface RequestValidator {
/**
* Check a list of client wants against the request policy.
*
@ -155,6 +159,7 @@ private interface RequestValidator {
* if one or more wants is not valid.
* @throws IOException
* if a low-level exception occurred.
* @since 3.1
*/
void checkWants(UploadPack up, List<RevObject> wants)
throws PackProtocolException, IOException;
@ -297,7 +302,7 @@ public Set<String> getOptions() {
private final RevFlagSet SAVE;
private RequestPolicy requestPolicy;
private RequestValidator requestValidator = new AdvertisedRequestValidator();
private MultiAck multiAck = MultiAck.OFF;
@ -414,9 +419,22 @@ public void setBiDirectionalPipe(final boolean twoWay) {
biDirectionalPipe = twoWay;
}
/** @return policy used by the service to validate client requests. */
/**
* @return policy used by the service to validate client requests, or null for
* a custom request validator.
*/
public RequestPolicy getRequestPolicy() {
return requestPolicy;
if (requestValidator instanceof AdvertisedRequestValidator)
return RequestPolicy.ADVERTISED;
if (requestValidator instanceof ReachableCommitRequestValidator)
return RequestPolicy.REACHABLE_COMMIT;
if (requestValidator instanceof TipRequestValidator)
return RequestPolicy.TIP;
if (requestValidator instanceof ReachableCommitTipRequestValidator)
return RequestPolicy.REACHABLE_COMMIT_TIP;
if (requestValidator instanceof AnyRequestValidator)
return RequestPolicy.ANY;
return null;
}
/**
@ -431,7 +449,34 @@ public RequestPolicy getRequestPolicy() {
* Overrides any policy specified in a {@link TransferConfig}.
*/
public void setRequestPolicy(RequestPolicy policy) {
requestPolicy = policy;
switch (policy) {
case ADVERTISED:
default:
requestValidator = new AdvertisedRequestValidator();
break;
case REACHABLE_COMMIT:
requestValidator = new ReachableCommitRequestValidator();
break;
case TIP:
requestValidator = new TipRequestValidator();
break;
case REACHABLE_COMMIT_TIP:
requestValidator = new ReachableCommitTipRequestValidator();
break;
case ANY:
requestValidator = new AnyRequestValidator();
break;
}
}
/**
* @param validator
* custom validator for client want list.
* @since 3.1
*/
public void setRequestValidator(RequestValidator validator) {
requestValidator = validator != null ? validator
: new AdvertisedRequestValidator();
}
/** @return the hook used while advertising the refs to the client */
@ -509,8 +554,8 @@ public void setPackConfig(PackConfig pc) {
*/
public void setTransferConfig(TransferConfig tc) {
this.transferConfig = tc != null ? tc : new TransferConfig(db);
this.requestPolicy = transferConfig.isAllowTipSha1InWant()
? RequestPolicy.TIP : RequestPolicy.ADVERTISED;
setRequestPolicy(transferConfig.isAllowTipSha1InWant()
? RequestPolicy.TIP : RequestPolicy.ADVERTISED);
}
/** @return the configured logger. */
@ -619,7 +664,7 @@ private Map<String, Ref> getAdvertisedOrDefaultRefs() {
private void service() throws IOException {
if (biDirectionalPipe)
sendAdvertisedRefs(new PacketLineOutRefAdvertiser(pckOut));
else if (requestPolicy == RequestPolicy.ANY)
else if (requestValidator instanceof AnyRequestValidator)
advertised = Collections.emptySet();
else
advertised = refIdSet(getAdvertisedOrDefaultRefs().values());
@ -758,8 +803,10 @@ public void sendAdvertisedRefs(final RefAdvertiser adv) throws IOException,
adv.advertiseCapability(OPTION_SHALLOW);
if (!biDirectionalPipe)
adv.advertiseCapability(OPTION_NO_DONE);
if (requestPolicy == RequestPolicy.TIP
|| requestPolicy == RequestPolicy.REACHABLE_COMMIT_TIP)
RequestPolicy policy = getRequestPolicy();
if (policy == RequestPolicy.TIP
|| policy == RequestPolicy.REACHABLE_COMMIT_TIP
|| policy == null)
adv.advertiseCapability(OPTION_ALLOW_TIP_SHA1_IN_WANT);
adv.setDerefTags(true);
advertised = adv.send(getAdvertisedOrDefaultRefs());
@ -1008,7 +1055,7 @@ private void parseWants() throws IOException {
}
}
if (notAdvertisedWants != null)
getRequestValidator().checkWants(this, notAdvertisedWants);
requestValidator.checkWants(this, notAdvertisedWants);
wantIds.clear();
} catch (MissingObjectException notFound) {
ObjectId id = notFound.getObjectId();
@ -1026,23 +1073,13 @@ private void want(RevObject obj) {
}
}
private RequestValidator getRequestValidator() {
switch (requestPolicy) {
case ADVERTISED:
default:
return new AdvertisedRequestValidator();
case REACHABLE_COMMIT:
return new ReachableCommitRequestValidator();
case TIP:
return new TipRequestValidator();
case REACHABLE_COMMIT_TIP:
return new ReachableCommitTipRequestValidator();
case ANY:
return new AnyRequestValidator();
}
}
private static class AdvertisedRequestValidator implements RequestValidator {
/**
* Validator corresponding to {@link RequestPolicy#ADVERTISED}.
*
* @since 3.1
*/
public static final class AdvertisedRequestValidator
implements RequestValidator {
public void checkWants(UploadPack up, List<RevObject> wants)
throws PackProtocolException, IOException {
if (!up.isBiDirectionalPipe())
@ -1053,7 +1090,12 @@ else if (!wants.isEmpty())
}
}
private static class ReachableCommitRequestValidator
/**
* Validator corresponding to {@link RequestPolicy#REACHABLE_COMMIT}.
*
* @since 3.1
*/
public static final class ReachableCommitRequestValidator
implements RequestValidator {
public void checkWants(UploadPack up, List<RevObject> wants)
throws PackProtocolException, IOException {
@ -1062,7 +1104,12 @@ public void checkWants(UploadPack up, List<RevObject> wants)
}
}
private static class TipRequestValidator implements RequestValidator {
/**
* Validator corresponding to {@link RequestPolicy#TIP}.
*
* @since 3.1
*/
public static final class TipRequestValidator implements RequestValidator {
public void checkWants(UploadPack up, List<RevObject> wants)
throws PackProtocolException, IOException {
if (!up.isBiDirectionalPipe())
@ -1079,7 +1126,12 @@ else if (!wants.isEmpty()) {
}
}
private static class ReachableCommitTipRequestValidator
/**
* Validator corresponding to {@link RequestPolicy#REACHABLE_COMMIT_TIP}.
*
* @since 3.1
*/
public static final class ReachableCommitTipRequestValidator
implements RequestValidator {
public void checkWants(UploadPack up, List<RevObject> wants)
throws PackProtocolException, IOException {
@ -1088,7 +1140,12 @@ public void checkWants(UploadPack up, List<RevObject> wants)
}
}
private static class AnyRequestValidator implements RequestValidator {
/**
* Validator corresponding to {@link RequestPolicy#ANY}.
*
* @since 3.1
*/
public static final class AnyRequestValidator implements RequestValidator {
public void checkWants(UploadPack up, List<RevObject> wants)
throws PackProtocolException, IOException {
// All requests are valid.