Support multiple versions of the EPP Fee Extension

We want to support multiple versions of the fee extension, to allow new features while maintaining backward compatibility. This CL extends the framework and adds one new version, 0.11 (spec version 7), to the existing version 0.6 (spec version 3). A follow-on CL will add version 0.12 (spec version 8).

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=127849044
This commit is contained in:
Brian Mountford 2016-07-19 10:54:56 -07:00 committed by Justine Tunney
parent f75bb65fd3
commit 8443da5c5c
170 changed files with 4376 additions and 586 deletions

View file

@ -18,6 +18,8 @@ import static com.google.common.base.MoreObjects.firstNonNull;
import static com.google.common.base.Strings.nullToEmpty;
import static com.google.common.io.Resources.getResource;
import static com.google.common.net.HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN;
import static google.registry.model.domain.fee.Fee.FEE_EXTENSION_URIS;
import static google.registry.model.eppcommon.ProtocolDefinition.ServiceExtension.FEE_0_11;
import static google.registry.model.eppcommon.ProtocolDefinition.ServiceExtension.FEE_0_6;
import static google.registry.model.registry.Registries.findTldForNameOrThrow;
import static google.registry.util.DomainNameUtils.canonicalizeDomainName;
@ -25,7 +27,7 @@ import static java.nio.charset.StandardCharsets.UTF_8;
import static org.json.simple.JSONValue.toJSONString;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.net.InternetDomainName;
import com.google.common.net.MediaType;
import com.google.template.soy.SoyFileSet;
@ -35,7 +37,6 @@ import dagger.Provides;
import google.registry.config.RegistryConfig;
import google.registry.flows.soy.DomainCheckFeeEppSoyInfo;
import google.registry.model.domain.fee.FeeCheckResponseExtension;
import google.registry.model.domain.fee.FeeCheckResponseExtension.FeeCheck;
import google.registry.model.eppoutput.CheckData.DomainCheck;
import google.registry.model.eppoutput.CheckData.DomainCheckData;
import google.registry.model.eppoutput.EppResponse;
@ -96,7 +97,7 @@ public class CheckApiAction implements Runnable {
.getBytes(UTF_8);
SessionMetadata sessionMetadata = new StatelessRequestSessionMetadata(
config.getCheckApiServletRegistrarClientId(),
ImmutableSet.of(FEE_0_6.getUri()));
FEE_EXTENSION_URIS);
EppResponse response = eppController
.handleEppCommand(
sessionMetadata,
@ -117,10 +118,16 @@ public class CheckApiAction implements Runnable {
.put("status", "success")
.put("available", available);
if (available) {
FeeCheckResponseExtension feeCheckResponse =
(FeeCheckResponseExtension) response.getExtensions().get(0);
FeeCheck feeCheck = feeCheckResponse.getChecks().get(0);
builder.put("tier", firstNonNull(feeCheck.getFeeClass(), "standard"));
FeeCheckResponseExtension<?> feeCheckResponseExtension =
(FeeCheckResponseExtension<?>) response.getFirstExtensionOfType(
FEE_0_11.getResponseExtensionClass(),
FEE_0_6.getResponseExtensionClass());
if (feeCheckResponseExtension != null) {
builder.put("tier",
firstNonNull(
Iterables.getOnlyElement(feeCheckResponseExtension.getItems()).getFeeClass(),
"standard"));
}
} else {
builder.put("reason", check.getReason());
}

View file

@ -55,7 +55,8 @@ public class EppXmlTransformer {
"domain.xsd",
"rgp.xsd",
"secdns.xsd",
"fee.xsd",
"fee06.xsd",
"fee11.xsd",
"metadata.xsd",
"mark.xsd",
"dsig.xsd",

View file

@ -26,6 +26,7 @@ import google.registry.model.eppoutput.EppResponse.ResponseExtension;
import google.registry.model.eppoutput.Result;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.annotation.Nullable;
import org.joda.time.DateTime;
@ -123,6 +124,11 @@ public abstract class Flow {
Collections.addAll(validExtensions, extensions);
}
protected final <E extends CommandExtension>
void registerExtensions(List<Class<? extends E>> extensions) {
validExtensions.addAll(extensions);
}
/** Get the legal command extension types for this flow. */
protected final Set<Class<? extends CommandExtension>> getValidRequestExtensions() {
return ImmutableSet.copyOf(validExtensions);

View file

@ -44,7 +44,9 @@ public abstract class LoggedInFlow extends Flow {
* declared on login.
*/
private static final ImmutableSet<String> UNDECLARED_URIS_BLACKLIST =
ImmutableSet.of(ServiceExtension.FEE_0_6.getUri());
ImmutableSet.of(
ServiceExtension.FEE_0_6.getUri(),
ServiceExtension.FEE_0_11.getUri());
/**
* The TLDs on which the logged-in registrar is allowed access domains.

View file

@ -33,6 +33,7 @@ import static google.registry.flows.domain.DomainFlowUtils.verifySignedMarks;
import static google.registry.flows.domain.DomainFlowUtils.verifyUnitIsYears;
import static google.registry.model.EppResourceUtils.createDomainRoid;
import static google.registry.model.EppResourceUtils.loadByUniqueId;
import static google.registry.model.domain.fee.Fee.FEE_CREATE_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.registry.Registries.findTldForName;
import static google.registry.model.registry.label.ReservedList.matchesAnchorTenantReservation;
@ -52,7 +53,7 @@ import google.registry.model.domain.DomainBase;
import google.registry.model.domain.DomainBase.Builder;
import google.registry.model.domain.DomainCommand.Create;
import google.registry.model.domain.DomainResource;
import google.registry.model.domain.fee.FeeCreateExtension;
import google.registry.model.domain.fee.FeeTransformCommandExtension;
import google.registry.model.domain.launch.LaunchCreateExtension;
import google.registry.model.domain.launch.LaunchNotice;
import google.registry.model.domain.launch.LaunchNotice.InvalidChecksumException;
@ -83,7 +84,7 @@ public abstract class BaseDomainCreateFlow<R extends DomainBase, B extends Build
protected String domainLabel;
protected InternetDomainName domainName;
protected String idnTableName;
protected FeeCreateExtension feeCreate;
protected FeeTransformCommandExtension feeCreate;
protected EppCommandOperations commandOperations;
protected boolean hasSignedMarks;
protected SignedMark signedMark;
@ -96,7 +97,8 @@ public abstract class BaseDomainCreateFlow<R extends DomainBase, B extends Build
registerExtensions(SecDnsCreateExtension.class);
secDnsCreate = eppInput.getSingleExtension(SecDnsCreateExtension.class);
launchCreate = eppInput.getSingleExtension(LaunchCreateExtension.class);
feeCreate = eppInput.getSingleExtension(FeeCreateExtension.class);
feeCreate =
eppInput.getFirstExtensionOfClasses(FEE_CREATE_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER);
hasSignedMarks = launchCreate != null && !launchCreate.getSignedMarks().isEmpty();
initDomainCreateFlow();
}

View file

@ -16,6 +16,7 @@ package google.registry.flows.domain;
import static google.registry.flows.domain.DomainFlowUtils.DISALLOWED_TLD_STATES_FOR_LAUNCH_FLOWS;
import static google.registry.flows.domain.DomainFlowUtils.validateFeeChallenge;
import static google.registry.model.domain.fee.Fee.FEE_CREATE_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER;
import static google.registry.model.eppoutput.Result.Code.Success;
import static google.registry.model.index.DomainApplicationIndex.loadActiveApplicationsByDomainName;
import static google.registry.model.index.ForeignKeyIndex.loadAndGetReference;
@ -32,8 +33,6 @@ import google.registry.model.domain.DomainApplication;
import google.registry.model.domain.DomainApplication.Builder;
import google.registry.model.domain.DomainResource;
import google.registry.model.domain.Period;
import google.registry.model.domain.fee.FeeCreateExtension;
import google.registry.model.domain.fee.FeeCreateResponseExtension;
import google.registry.model.domain.launch.ApplicationStatus;
import google.registry.model.domain.launch.LaunchCreateExtension;
import google.registry.model.domain.launch.LaunchCreateResponseExtension;
@ -117,7 +116,8 @@ public class DomainApplicationCreateFlow extends BaseDomainCreateFlow<DomainAppl
@Override
protected void initDomainCreateFlow() {
registerExtensions(FeeCreateExtension.class, LaunchCreateExtension.class);
registerExtensions(LaunchCreateExtension.class);
registerExtensions(FEE_CREATE_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER);
}
@Override
@ -211,9 +211,9 @@ public class DomainApplicationCreateFlow extends BaseDomainCreateFlow<DomainAppl
.setApplicationId(newResource.getForeignKey())
.build());
if (feeCreate != null) {
responseExtensionsBuilder.add(new FeeCreateResponseExtension.Builder()
responseExtensionsBuilder.add(feeCreate.createResponseBuilder()
.setCurrency(commandOperations.getCurrency())
.setFee(commandOperations.getFees())
.setFees(commandOperations.getFees())
.build());
}

View file

@ -17,6 +17,8 @@ package google.registry.flows.domain;
import static google.registry.flows.domain.DomainFlowUtils.getReservationType;
import static google.registry.flows.domain.DomainFlowUtils.handleFeeRequest;
import static google.registry.model.EppResourceUtils.checkResourcesExist;
import static google.registry.model.domain.fee.Fee.FEE_CHECK_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER;
import static google.registry.model.domain.fee.Fee.FEE_EXTENSION_URIS;
import static google.registry.model.index.DomainApplicationIndex.loadActiveApplicationsByDomainName;
import static google.registry.model.registry.label.ReservationType.UNRESERVED;
import static google.registry.pricing.PricingEngineProxy.getPricesForDomainName;
@ -26,16 +28,17 @@ import static google.registry.util.DomainNameUtils.getTldFromDomainName;
import com.google.common.base.Predicate;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import com.google.common.net.InternetDomainName;
import google.registry.flows.EppException;
import google.registry.flows.EppException.ParameterValuePolicyErrorException;
import google.registry.model.domain.DomainApplication;
import google.registry.model.domain.fee.FeeCheckExtension;
import google.registry.model.domain.fee.FeeCheckCommandExtension;
import google.registry.model.domain.fee.FeeCheckCommandExtensionItem;
import google.registry.model.domain.fee.FeeCheckResponseExtension;
import google.registry.model.domain.fee.FeeCheckResponseExtension.FeeCheck;
import google.registry.model.domain.fee.FeeCheckResponseExtensionItem;
import google.registry.model.domain.launch.LaunchCheckExtension;
import google.registry.model.eppcommon.ProtocolDefinition.ServiceExtension;
import google.registry.model.eppoutput.CheckData;
import google.registry.model.eppoutput.CheckData.DomainCheck;
import google.registry.model.eppoutput.CheckData.DomainCheckData;
@ -43,8 +46,10 @@ import google.registry.model.eppoutput.EppResponse.ResponseExtension;
import google.registry.model.registry.Registry;
import google.registry.model.registry.Registry.TldState;
import google.registry.model.registry.label.ReservationType;
import java.util.Collections;
import java.util.Set;
import javax.inject.Inject;
import org.joda.money.CurrencyUnit;
/**
* An EPP flow that checks whether a domain can be provisioned.
@ -81,7 +86,8 @@ public class DomainCheckFlow extends BaseDomainCheckFlow {
@Override
protected void initDomainCheckFlow() throws EppException {
registerExtensions(LaunchCheckExtension.class, FeeCheckExtension.class);
registerExtensions(LaunchCheckExtension.class);
registerExtensions(FEE_CHECK_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER);
}
private String getMessageForCheck(String targetId, Set<String> existingIds) {
@ -103,8 +109,9 @@ public class DomainCheckFlow extends BaseDomainCheckFlow {
if (reservationType == UNRESERVED
&& getPricesForDomainName(domainName.toString(), now).isPremium()
&& registry.getPremiumPriceAckRequired()
&& !nullToEmpty(sessionMetadata.getServiceExtensionUris()).contains(
ServiceExtension.FEE_0_6.getUri())) {
&& Collections.disjoint(
nullToEmpty(sessionMetadata.getServiceExtensionUris()),
FEE_EXTENSION_URIS)) {
return "Premium names require EPP ext.";
}
return reservationType.getMessageForCheck();
@ -121,30 +128,59 @@ public class DomainCheckFlow extends BaseDomainCheckFlow {
return DomainCheckData.create(checks.build());
}
/** Handle the fee check extension. */
@Override
protected ImmutableList<? extends ResponseExtension> getResponseExtensions() throws EppException {
FeeCheckExtension feeCheck = eppInput.getSingleExtension(FeeCheckExtension.class);
if (feeCheck == null) {
return null; // No fee checks were requested.
}
ImmutableList.Builder<FeeCheck> feeChecksBuilder = new ImmutableList.Builder<>();
for (FeeCheckExtension.DomainCheck domainCheck : feeCheck.getDomains()) {
String domainName = domainCheck.getName();
if (!domainNames.containsKey(domainName)) {
/**
* Return the domains to be checked for a particular fee check item. Some versions of the fee
* extension specify the domain name in the extension item, while others use the list of domain
* names from the regular check domain availability list.
*/
private Set<String> getDomainNamesToCheck(FeeCheckCommandExtensionItem feeCheckItem)
throws OnlyCheckedNamesCanBeFeeCheckedException {
if (feeCheckItem.isDomainNameSupported()) {
String domainNameInExtension = feeCheckItem.getDomainName();
if (!domainNames.containsKey(domainNameInExtension)) {
// Although the fee extension explicitly says it's ok to fee check a domain name that you
// aren't also availability checking, we forbid it. This makes the experience simpler and
// also means we can assume any domain names in the fee checks have been validated.
throw new OnlyCheckedNamesCanBeFeeCheckedException();
}
FeeCheck.Builder builder = new FeeCheck.Builder();
handleFeeRequest(
domainCheck, builder, domainName, getTldFromDomainName(domainName), now);
feeChecksBuilder.add(builder.setName(domainName).build());
return ImmutableSet.of(domainNameInExtension);
} else {
// If this version of the fee extension is nameless, use the full list of domains.
return domainNames.keySet();
}
return ImmutableList.of(FeeCheckResponseExtension.create(feeChecksBuilder.build()));
}
}
/** Handle the fee check extension. */
@Override
protected ImmutableList<ResponseExtension> getResponseExtensions() throws EppException {
FeeCheckCommandExtension<
? extends FeeCheckCommandExtensionItem, ? extends FeeCheckResponseExtension<?>>
feeCheck = eppInput.getFirstExtensionOfClasses(
FEE_CHECK_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER);
if (feeCheck == null) {
return null; // No fee checks were requested.
}
CurrencyUnit topLevelCurrency = feeCheck.isCurrencySupported() ? feeCheck.getCurrency() : null;
ImmutableList.Builder<FeeCheckResponseExtensionItem> feeCheckResponseItemsBuilder =
new ImmutableList.Builder<>();
for (FeeCheckCommandExtensionItem feeCheckItem : feeCheck.getItems()) {
for (String domainName : getDomainNamesToCheck(feeCheckItem)) {
FeeCheckResponseExtensionItem.Builder builder = feeCheckItem.createResponseBuilder();
handleFeeRequest(
feeCheckItem,
builder,
domainName,
getTldFromDomainName(domainName),
topLevelCurrency,
now);
feeCheckResponseItemsBuilder
.add(builder.setDomainNameIfSupported(domainName).build());
}
}
return ImmutableList.<ResponseExtension>of(
feeCheck.createResponse(feeCheckResponseItemsBuilder.build()));
}
/** By server policy, fee check names must be listed in the availability check. */
static class OnlyCheckedNamesCanBeFeeCheckedException extends ParameterValuePolicyErrorException {
OnlyCheckedNamesCanBeFeeCheckedException() {

View file

@ -15,6 +15,7 @@
package google.registry.flows.domain;
import static google.registry.flows.domain.DomainFlowUtils.validateFeeChallenge;
import static google.registry.model.domain.fee.Fee.FEE_CREATE_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER;
import static google.registry.model.index.DomainApplicationIndex.loadActiveApplicationsByDomainName;
import static google.registry.model.ofy.ObjectifyService.ofy;
@ -28,7 +29,6 @@ import google.registry.model.billing.BillingEvent.Reason;
import google.registry.model.domain.DomainApplication;
import google.registry.model.domain.DomainResource.Builder;
import google.registry.model.domain.GracePeriod;
import google.registry.model.domain.fee.FeeCreateExtension;
import google.registry.model.domain.launch.LaunchCreateExtension;
import google.registry.model.domain.rgp.GracePeriodStatus;
import google.registry.model.registry.Registry;
@ -124,7 +124,8 @@ public class DomainCreateFlow extends DomainCreateOrAllocateFlow {
@Override
protected final void initDomainCreateOrAllocateFlow() {
registerExtensions(FeeCreateExtension.class, LaunchCreateExtension.class);
registerExtensions(LaunchCreateExtension.class);
registerExtensions(FEE_CREATE_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER);
}
@Override

View file

@ -29,7 +29,6 @@ import google.registry.model.billing.BillingEvent.Reason;
import google.registry.model.domain.DomainResource;
import google.registry.model.domain.DomainResource.Builder;
import google.registry.model.domain.Period;
import google.registry.model.domain.fee.FeeCreateResponseExtension;
import google.registry.model.eppoutput.CreateData.DomainCreateData;
import google.registry.model.eppoutput.EppOutput;
import google.registry.model.eppoutput.Result;
@ -108,9 +107,9 @@ public abstract class DomainCreateOrAllocateFlow
now,
newResource.getRegistrationExpirationTime()),
(feeCreate == null) ? null : ImmutableList.of(
new FeeCreateResponseExtension.Builder()
feeCreate.createResponseBuilder()
.setCurrency(commandOperations.getCurrency())
.setFee(commandOperations.getFees())
.setFees(commandOperations.getFees())
.build()));
}
}

View file

@ -37,7 +37,9 @@ import google.registry.model.domain.DomainResource;
import google.registry.model.domain.DomainResource.Builder;
import google.registry.model.domain.GracePeriod;
import google.registry.model.domain.fee.Credit;
import google.registry.model.domain.fee.FeeDeleteResponseExtension;
import google.registry.model.domain.fee.FeeTransformResponseExtension;
import google.registry.model.domain.fee06.FeeDeleteResponseExtensionV06;
import google.registry.model.domain.fee11.FeeDeleteResponseExtensionV11;
import google.registry.model.domain.rgp.GracePeriodStatus;
import google.registry.model.domain.secdns.SecDnsUpdateExtension;
import google.registry.model.eppcommon.ProtocolDefinition.ServiceExtension;
@ -48,6 +50,8 @@ import google.registry.model.poll.PendingActionNotificationResponse.DomainPendin
import google.registry.model.poll.PollMessage;
import google.registry.model.registry.Registry;
import google.registry.model.reporting.HistoryEntry;
import java.util.Set;
import javax.annotation.Nullable;
import javax.inject.Inject;
import org.joda.money.CurrencyUnit;
import org.joda.money.Money;
@ -169,18 +173,32 @@ public class DomainDeleteFlow extends ResourceSyncDeleteFlow<DomainResource, Bui
? SuccessWithActionPending : Success;
}
@Nullable
private FeeTransformResponseExtension.Builder getDeleteResponseBuilder() {
Set<String> uris = nullToEmpty(sessionMetadata.getServiceExtensionUris());
if (uris.contains(ServiceExtension.FEE_0_11.getUri())) {
return new FeeDeleteResponseExtensionV11.Builder();
}
if (uris.contains(ServiceExtension.FEE_0_6.getUri())) {
return new FeeDeleteResponseExtensionV06.Builder();
}
return null;
}
@Override
@Nullable
protected final ImmutableList<? extends ResponseExtension> getDeleteResponseExtensions() {
if (!credits.isEmpty()
&& nullToEmpty(sessionMetadata.getServiceExtensionUris()).contains(
ServiceExtension.FEE_0_6.getUri())) {
return ImmutableList.of(new FeeDeleteResponseExtension.Builder()
.setCurrency(checkNotNull(creditsCurrencyUnit))
.setCredits(credits)
.build());
} else {
if (credits.isEmpty()) {
return null;
}
FeeTransformResponseExtension.Builder feeResponseBuilder = getDeleteResponseBuilder();
if (feeResponseBuilder == null) {
return null;
}
return ImmutableList.of(feeResponseBuilder
.setCurrency(checkNotNull(creditsCurrencyUnit))
.setCredits(credits)
.build());
}
@Override

View file

@ -62,11 +62,12 @@ import google.registry.model.domain.DomainCommand.CreateOrUpdate;
import google.registry.model.domain.DomainCommand.InvalidReferencesException;
import google.registry.model.domain.DomainResource;
import google.registry.model.domain.Period;
import google.registry.model.domain.fee.BaseFeeCommand;
import google.registry.model.domain.fee.BaseFeeRequest;
import google.registry.model.domain.fee.BaseFeeResponse;
import google.registry.model.domain.fee.Fee;
import google.registry.model.domain.fee.FeeCommandDescriptor;
import google.registry.model.domain.fee.FeeCheckCommandExtensionItem;
import google.registry.model.domain.fee.FeeCheckResponseExtensionItem;
import google.registry.model.domain.fee.FeeQueryCommandExtensionItem;
import google.registry.model.domain.fee.FeeQueryResponseExtensionItem;
import google.registry.model.domain.fee.FeeTransformCommandExtension;
import google.registry.model.domain.launch.LaunchExtension;
import google.registry.model.domain.launch.LaunchPhase;
import google.registry.model.domain.secdns.DelegationSignerData;
@ -101,9 +102,11 @@ import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import javax.annotation.Nullable;
import javax.xml.crypto.MarshalException;
import javax.xml.crypto.dsig.XMLSignatureException;
import javax.xml.parsers.ParserConfigurationException;
import org.joda.money.CurrencyUnit;
import org.joda.money.Money;
import org.joda.time.DateTime;
import org.xml.sax.SAXException;
@ -555,42 +558,47 @@ public class DomainFlowUtils {
}
/**
* Validates a {@link BaseFeeRequest} and sets the appropriate fields on a {@link BaseFeeResponse}
* builder.
* Validates a {@link FeeCheckCommandExtensionItem} and sets the appropriate fields on a
* {@link FeeCheckResponseExtensionItem} builder.
*/
static void handleFeeRequest(
BaseFeeRequest feeRequest,
BaseFeeResponse.Builder<?, ?> builder,
FeeQueryCommandExtensionItem feeRequest,
FeeQueryResponseExtensionItem.Builder builder,
String domainName,
String tld,
@Nullable CurrencyUnit topLevelCurrency,
DateTime now) throws EppException {
InternetDomainName domain = InternetDomainName.from(domainName);
FeeCommandDescriptor feeCommand = feeRequest.getCommand();
Registry registry = Registry.get(tld);
int years = verifyUnitIsYears(feeRequest.getPeriod()).getValue();
boolean isSunrise = registry.getTldState(now).equals(TldState.SUNRISE);
if (feeCommand.getPhase() != null || feeCommand.getSubphase() != null) {
if (feeRequest.getPhase() != null || feeRequest.getSubphase() != null) {
throw new FeeChecksDontSupportPhasesException();
}
if (feeRequest.getCurrency() != null
&& !feeRequest.getCurrency().equals(registry.getCurrency())) {
CurrencyUnit currency =
feeRequest.isCurrencySupported() ? feeRequest.getCurrency() : topLevelCurrency;
if ((currency != null) && !currency.equals(registry.getCurrency())) {
throw new CurrencyUnitMismatchException();
}
builder
.setCommand(feeCommand)
.setCurrency(registry.getCurrency())
.setCommand(feeRequest.getCommandName(), feeRequest.getPhase(), feeRequest.getSubphase())
.setCurrencyIfSupported(registry.getCurrency())
.setPeriod(feeRequest.getPeriod())
.setClass(TldSpecificLogicProxy.getFeeClass(domainName, now).orNull());
switch (feeCommand.getCommand()) {
switch (feeRequest.getCommandName()) {
case UNKNOWN:
throw new UnknownFeeCommandException(feeCommand.getUnparsedCommandName());
throw new UnknownFeeCommandException(feeRequest.getUnparsedCommandName());
case CREATE:
if (isReserved(domain, isSunrise)) { // Don't return a create price for reserved names.
builder.setClass("reserved"); // Override whatever class we've set above.
builder.setAvailIfSupported(false);
builder.setReasonIfSupported("reserved");
} else {
builder.setAvailIfSupported(true);
builder.setFees(
TldSpecificLogicProxy.getCreatePrice(registry, domainName, now, years).getFees());
}
@ -599,11 +607,14 @@ public class DomainFlowUtils {
if (years != 1) {
throw new RestoresAreAlwaysForOneYearException();
}
builder.setAvailIfSupported(true);
builder.setFees(
TldSpecificLogicProxy.getRestorePrice(registry, domainName, now, years).getFees());
break;
// TODO(mountford): handle UPDATE
default:
// Anything else (transfer|renew) will have a "renew" fee.
builder.setAvailIfSupported(true);
builder.setFees(
TldSpecificLogicProxy.getRenewPrice(registry, domainName, now, years).getFees());
}
@ -613,7 +624,7 @@ public class DomainFlowUtils {
String domainName,
String tld,
DateTime priceTime,
final BaseFeeCommand feeCommand,
final FeeTransformCommandExtension feeCommand,
Money cost,
Money... otherCosts)
throws EppException {
@ -1014,3 +1025,4 @@ public class DomainFlowUtils {
}
}

View file

@ -21,8 +21,8 @@ import com.google.common.collect.ImmutableSet;
import google.registry.flows.EppException;
import google.registry.model.domain.DomainResource;
import google.registry.model.domain.DomainResource.Builder;
import google.registry.model.domain.fee.FeeInfoExtension;
import google.registry.model.domain.fee.FeeInfoResponseExtension;
import google.registry.model.domain.fee06.FeeInfoCommandExtensionV06;
import google.registry.model.domain.fee06.FeeInfoResponseExtensionV06;
import google.registry.model.domain.rgp.GracePeriodStatus;
import google.registry.model.domain.rgp.RgpInfoExtension;
import google.registry.model.eppoutput.EppResponse.ResponseExtension;
@ -44,7 +44,7 @@ public class DomainInfoFlow extends BaseDomainInfoFlow<DomainResource, Builder>
@Override
protected void initSingleResourceFlow() throws EppException {
registerExtensions(FeeInfoExtension.class);
registerExtensions(FeeInfoCommandExtensionV06.class);
}
@Override
@ -87,11 +87,17 @@ public class DomainInfoFlow extends BaseDomainInfoFlow<DomainResource, Builder>
if (!gracePeriodStatuses.isEmpty()) {
extensions.add(RgpInfoExtension.create(gracePeriodStatuses));
}
FeeInfoExtension feeInfo = eppInput.getSingleExtension(FeeInfoExtension.class);
FeeInfoCommandExtensionV06 feeInfo =
eppInput.getSingleExtension(FeeInfoCommandExtensionV06.class);
if (feeInfo != null) { // Fee check was requested.
FeeInfoResponseExtension.Builder builder = new FeeInfoResponseExtension.Builder();
FeeInfoResponseExtensionV06.Builder builder = new FeeInfoResponseExtensionV06.Builder();
handleFeeRequest(
feeInfo, builder, getTargetId(), existingResource.getTld(), now);
feeInfo,
builder,
getTargetId(),
existingResource.getTld(),
null,
now);
extensions.add(builder.build());
}
return extensions.build();

View file

@ -22,6 +22,7 @@ import static google.registry.flows.domain.DomainFlowUtils.updateAutorenewRecurr
import static google.registry.flows.domain.DomainFlowUtils.validateFeeChallenge;
import static google.registry.flows.domain.DomainFlowUtils.verifyUnitIsYears;
import static google.registry.model.domain.DomainResource.MAX_REGISTRATION_YEARS;
import static google.registry.model.domain.fee.Fee.FEE_RENEW_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER;
import static google.registry.model.eppoutput.Result.Code.Success;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.pricing.PricingEngineProxy.getDomainRenewCost;
@ -42,8 +43,7 @@ import google.registry.model.domain.DomainResource;
import google.registry.model.domain.GracePeriod;
import google.registry.model.domain.Period;
import google.registry.model.domain.fee.Fee;
import google.registry.model.domain.fee.FeeRenewExtension;
import google.registry.model.domain.fee.FeeRenewResponseExtension;
import google.registry.model.domain.fee.FeeTransformCommandExtension;
import google.registry.model.domain.rgp.GracePeriodStatus;
import google.registry.model.eppcommon.StatusValue;
import google.registry.model.eppoutput.EppOutput;
@ -80,7 +80,7 @@ public class DomainRenewFlow extends OwnedResourceMutateFlow<DomainResource, Ren
StatusValue.PENDING_DELETE,
StatusValue.SERVER_RENEW_PROHIBITED);
protected FeeRenewExtension feeRenew;
protected FeeTransformCommandExtension feeRenew;
protected Money renewCost;
@Inject DomainRenewFlow() {}
@ -92,8 +92,9 @@ public class DomainRenewFlow extends OwnedResourceMutateFlow<DomainResource, Ren
@Override
public final void initResourceCreateOrMutateFlow() throws EppException {
registerExtensions(FeeRenewExtension.class);
feeRenew = eppInput.getSingleExtension(FeeRenewExtension.class);
registerExtensions(FEE_RENEW_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER);
feeRenew =
eppInput.getFirstExtensionOfClasses(FEE_RENEW_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER);
}
@Override
@ -176,9 +177,9 @@ public class DomainRenewFlow extends OwnedResourceMutateFlow<DomainResource, Ren
newResource.getFullyQualifiedDomainName(),
newResource.getRegistrationExpirationTime()),
(feeRenew == null) ? null : ImmutableList.of(
new FeeRenewResponseExtension.Builder()
feeRenew.createResponseBuilder()
.setCurrency(renewCost.getCurrencyUnit())
.setFee(ImmutableList.of(Fee.create(renewCost.getAmount(), "renew")))
.setFees(ImmutableList.of(Fee.create(renewCost.getAmount(), "renew")))
.build()));
}

View file

@ -20,6 +20,7 @@ import static google.registry.flows.domain.DomainFlowUtils.newAutorenewPollMessa
import static google.registry.flows.domain.DomainFlowUtils.validateFeeChallenge;
import static google.registry.flows.domain.DomainFlowUtils.verifyNotReserved;
import static google.registry.flows.domain.DomainFlowUtils.verifyPremiumNameIsNotBlocked;
import static google.registry.model.domain.fee.Fee.FEE_UPDATE_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER;
import static google.registry.model.eppoutput.Result.Code.Success;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.pricing.PricingEngineProxy.getDomainRenewCost;
@ -38,8 +39,7 @@ import google.registry.model.billing.BillingEvent.Reason;
import google.registry.model.domain.DomainCommand.Update;
import google.registry.model.domain.DomainResource;
import google.registry.model.domain.fee.Fee;
import google.registry.model.domain.fee.FeeUpdateExtension;
import google.registry.model.domain.fee.FeeUpdateResponseExtension;
import google.registry.model.domain.fee.FeeTransformCommandExtension;
import google.registry.model.domain.rgp.GracePeriodStatus;
import google.registry.model.domain.rgp.RgpUpdateExtension;
import google.registry.model.eppcommon.StatusValue;
@ -71,7 +71,7 @@ import org.joda.time.DateTime;
*/
public class DomainRestoreRequestFlow extends OwnedResourceMutateFlow<DomainResource, Update> {
protected FeeUpdateExtension feeUpdate;
protected FeeTransformCommandExtension feeUpdate;
protected Money restoreCost;
protected Money renewCost;
@ -79,7 +79,8 @@ public class DomainRestoreRequestFlow extends OwnedResourceMutateFlow<DomainReso
@Override
protected final void initResourceCreateOrMutateFlow() throws EppException {
registerExtensions(FeeUpdateExtension.class, RgpUpdateExtension.class);
registerExtensions(RgpUpdateExtension.class);
registerExtensions(FEE_UPDATE_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER);
}
@Override
@ -101,7 +102,8 @@ public class DomainRestoreRequestFlow extends OwnedResourceMutateFlow<DomainReso
verifyNotReserved(InternetDomainName.from(targetId), false);
verifyPremiumNameIsNotBlocked(targetId, now, getClientId());
}
feeUpdate = eppInput.getSingleExtension(FeeUpdateExtension.class);
feeUpdate = eppInput.getFirstExtensionOfClasses(
FEE_UPDATE_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER);
restoreCost = Registry.get(tld).getStandardRestoreCost();
renewCost = getDomainRenewCost(targetId, now, 1);
validateFeeChallenge(targetId, tld, now, feeUpdate, restoreCost, renewCost);
@ -186,9 +188,9 @@ public class DomainRestoreRequestFlow extends OwnedResourceMutateFlow<DomainReso
Success,
null,
(feeUpdate == null) ? null : ImmutableList.of(
new FeeUpdateResponseExtension.Builder()
feeUpdate.createResponseBuilder()
.setCurrency(restoreCost.getCurrencyUnit())
.setFee(ImmutableList.of(
.setFees(ImmutableList.of(
Fee.create(restoreCost.getAmount(), "restore"),
Fee.create(renewCost.getAmount(), "renew")))
.build()));

View file

@ -14,13 +14,13 @@
package google.registry.flows.domain;
import static google.registry.flows.domain.DomainFlowUtils.checkAllowedAccessToTld;
import static google.registry.flows.domain.DomainFlowUtils.updateAutorenewRecurrenceEndTime;
import static google.registry.flows.domain.DomainFlowUtils.validateFeeChallenge;
import static google.registry.flows.domain.DomainFlowUtils.verifyPremiumNameIsNotBlocked;
import static google.registry.flows.domain.DomainFlowUtils.verifyUnitIsYears;
import static google.registry.model.domain.DomainResource.extendRegistrationWithCap;
import static google.registry.model.domain.fee.Fee.FEE_TRANSFER_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.pricing.PricingEngineProxy.getDomainRenewCost;
import static google.registry.util.DateTimeUtils.END_OF_TIME;
@ -38,8 +38,7 @@ import google.registry.model.domain.DomainCommand.Transfer;
import google.registry.model.domain.DomainResource;
import google.registry.model.domain.Period;
import google.registry.model.domain.fee.Fee;
import google.registry.model.domain.fee.FeeTransferExtension;
import google.registry.model.domain.fee.FeeTransferResponseExtension;
import google.registry.model.domain.fee.FeeTransformCommandExtension;
import google.registry.model.eppoutput.EppResponse.ResponseExtension;
import google.registry.model.poll.PollMessage;
import google.registry.model.registry.Registry;
@ -92,7 +91,7 @@ public class DomainTransferRequestFlow
/**
* An optional extension from the client specifying how much they think the transfer should cost.
*/
private FeeTransferExtension feeTransfer;
private FeeTransformCommandExtension feeTransfer;
@Inject DomainTransferRequestFlow() {}
@ -103,8 +102,9 @@ public class DomainTransferRequestFlow
@Override
protected final void initResourceTransferRequestFlow() {
registerExtensions(FeeTransferExtension.class);
feeTransfer = eppInput.getSingleExtension(FeeTransferExtension.class);
registerExtensions(FEE_TRANSFER_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER);
feeTransfer = eppInput.getFirstExtensionOfClasses(
FEE_TRANSFER_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER);
// The "existingResource" field is loaded before this function is called, but it may be null if
// the domain name specified is invalid or doesn't exist. If that's the case, simply exit
// early, and ResourceMutateFlow will later throw ResourceToMutateDoesNotExistException.
@ -162,9 +162,9 @@ public class DomainTransferRequestFlow
@Override
protected ImmutableList<? extends ResponseExtension> getTransferResponseExtensions() {
if (feeTransfer != null) {
return ImmutableList.of(new FeeTransferResponseExtension.Builder()
return ImmutableList.of(feeTransfer.createResponseBuilder()
.setCurrency(renewCost.getCurrencyUnit())
.setFee(ImmutableList.of(Fee.create(renewCost.getAmount(), "renew")))
.setFees(ImmutableList.of(Fee.create(renewCost.getAmount(), "renew")))
.build());
} else {
return null;

View file

@ -13,6 +13,8 @@ FIELD_EXPOSERS = [
"domain/FieldExposer.java",
"domain/allocate/FieldExposer.java",
"domain/fee/FieldExposer.java",
"domain/fee06/FieldExposer.java",
"domain/fee11/FieldExposer.java",
"domain/launch/FieldExposer.java",
"domain/rgp/FieldExposer.java",
"domain/secdns/FieldExposer.java",

View file

@ -0,0 +1,35 @@
// Copyright 2016 The Domain Registry Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.model.domain;
import google.registry.model.ImmutableObject;
/**
* Specification of a domain by name, as used in version 0.11 fee check response items and version
* 0.12 fee check commands. This class is used by JAXB, although it turns out that no JAXB-specific
* annotations are necessary.
*/
public class DomainObjectSpec extends ImmutableObject {
final String name;
public String getName() {
return name;
}
public DomainObjectSpec(String name) {
this.name = name;
}
}

View file

@ -16,6 +16,19 @@ package google.registry.model.domain.fee;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import google.registry.model.domain.fee06.FeeCheckCommandExtensionV06;
import google.registry.model.domain.fee06.FeeCreateCommandExtensionV06;
import google.registry.model.domain.fee06.FeeRenewCommandExtensionV06;
import google.registry.model.domain.fee06.FeeTransferCommandExtensionV06;
import google.registry.model.domain.fee06.FeeUpdateCommandExtensionV06;
import google.registry.model.domain.fee11.FeeCheckCommandExtensionV11;
import google.registry.model.domain.fee11.FeeCreateCommandExtensionV11;
import google.registry.model.domain.fee11.FeeRenewCommandExtensionV11;
import google.registry.model.domain.fee11.FeeTransferCommandExtensionV11;
import google.registry.model.domain.fee11.FeeUpdateCommandExtensionV11;
import google.registry.model.eppcommon.ProtocolDefinition.ServiceExtension;
import java.math.BigDecimal;
/** A fee, in currency units specified elsewhere in the xml, and with an optional description. */
@ -26,4 +39,45 @@ public class Fee extends BaseFee {
instance.description = description;
return instance;
}
public static final ImmutableList<
Class<? extends FeeCheckCommandExtension<
? extends FeeCheckCommandExtensionItem, ? extends FeeCheckResponseExtension<?>>>>
FEE_CHECK_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER =
ImmutableList.<
Class<? extends FeeCheckCommandExtension<
? extends FeeCheckCommandExtensionItem,
? extends FeeCheckResponseExtension<?>>>>of(
FeeCheckCommandExtensionV11.class,
FeeCheckCommandExtensionV06.class);
public static final ImmutableList<Class<? extends FeeTransformCommandExtension>>
FEE_CREATE_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER =
ImmutableList.<Class<? extends FeeTransformCommandExtension>>of(
FeeCreateCommandExtensionV11.class,
FeeCreateCommandExtensionV06.class);
public static final ImmutableList<Class<? extends FeeTransformCommandExtension>>
FEE_RENEW_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER =
ImmutableList.<Class<? extends FeeTransformCommandExtension>>of(
FeeRenewCommandExtensionV11.class,
FeeRenewCommandExtensionV06.class);
public static final ImmutableList<Class<? extends FeeTransformCommandExtension>>
FEE_TRANSFER_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER =
ImmutableList.<Class<? extends FeeTransformCommandExtension>>of(
FeeTransferCommandExtensionV11.class,
FeeTransferCommandExtensionV06.class);
public static final ImmutableList<Class<? extends FeeTransformCommandExtension>>
FEE_UPDATE_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER =
ImmutableList.<Class<? extends FeeTransformCommandExtension>>of(
FeeUpdateCommandExtensionV11.class,
FeeUpdateCommandExtensionV06.class);
public static final ImmutableSet<String>
FEE_EXTENSION_URIS =
ImmutableSet.<String>of(
ServiceExtension.FEE_0_11.getUri(),
ServiceExtension.FEE_0_6.getUri());
}

View file

@ -0,0 +1,45 @@
// Copyright 2016 The Domain Registry Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.model.domain.fee;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import google.registry.model.eppinput.EppInput.CommandExtension;
import org.joda.money.CurrencyUnit;
/**
* Interface for domain check command fee extensions. The check extension will contain some number
* of items requesting the fees for particular commands and domains. For some versions of the fee
* extension, the currency is also specified here; for other versions it is contained in the
* individual items.
*
* @type C the type of extension item used by this command (e.g. v6 items for a v6 extension)
* @type R the type of response returned for for this command (e.g. v6 responses for a v6 extension)
*/
public interface FeeCheckCommandExtension<
C extends FeeCheckCommandExtensionItem,
R extends FeeCheckResponseExtension<?>>
extends CommandExtension {
/** True if this version of the fee extension specifies the currency at the top level. */
public boolean isCurrencySupported();
/** Three-character currency code; throws an exception if currency is not supported. */
public CurrencyUnit getCurrency() throws UnsupportedOperationException;
public ImmutableSet<C> getItems();
public R createResponse(ImmutableList<? extends FeeCheckResponseExtensionItem> items);
}

View file

@ -0,0 +1,32 @@
// Copyright 2016 The Domain Registry Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.model.domain.fee;
/**
* Interface for individual fee extension items in Check commands. These are derived from the more
* general query items (which cover Info commands as well), but may also contain a domain name,
* depending on the version of the fee extension.
*/
public interface FeeCheckCommandExtensionItem extends FeeQueryCommandExtensionItem {
/** True if this version of the fee extension supports domain names in Check items. */
public boolean isDomainNameSupported();
/** The domain name being checked; throws an exception if domain names are not supported. */
public String getDomainName() throws UnsupportedOperationException;
/** Create a builder for a matching fee check response item. */
public FeeCheckResponseExtensionItem.Builder createResponseBuilder();
}

View file

@ -1,52 +0,0 @@
// Copyright 2016 The Domain Registry Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.model.domain.fee;
import static google.registry.util.CollectionUtils.nullToEmptyImmutableCopy;
import com.google.common.collect.ImmutableSet;
import google.registry.model.ImmutableObject;
import google.registry.model.domain.Period;
import google.registry.model.eppinput.EppInput.CommandExtension;
import java.util.Set;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
/** A fee extension that may be present on domain check commands. */
@XmlRootElement(name = "check")
public class FeeCheckExtension extends ImmutableObject implements CommandExtension {
/** The default validity period (if not specified) is 1 year for all operations. */
static final Period DEFAULT_PERIOD = Period.create(1, Period.Unit.YEARS);
@XmlElement(name = "domain")
Set<DomainCheck> domains;
public ImmutableSet<DomainCheck> getDomains() {
return nullToEmptyImmutableCopy(domains);
}
/** A check request for the fee to perform a given command on a given domain. */
@XmlType(propOrder = {"name", "currency", "command", "period"})
public static class DomainCheck extends BaseFeeRequest {
/** The fully qualified domain name being checked. */
String name;
public String getName() {
return name;
}
}
}

View file

@ -14,48 +14,24 @@
package google.registry.model.domain.fee;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import google.registry.model.ImmutableObject;
import google.registry.model.eppoutput.EppResponse.ResponseExtension;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
import org.joda.money.CurrencyUnit;
/**
* An XML data object that represents a fee extension that may be present on the response to EPP
* domain check commands.
* Interface for domain check response fee extensions. The check extension will contain some number
* of items requesting the fees for particular commands and domains. For some versions of the fee
* extension, the currency is also specified here; for other versions it is contained in the
* individual items.
*/
@XmlRootElement(name = "chkData")
public class FeeCheckResponseExtension extends ImmutableObject implements ResponseExtension {
public interface FeeCheckResponseExtension<F extends FeeCheckResponseExtensionItem>
extends ResponseExtension {
/** Check responses. */
@XmlElement(name = "cd")
ImmutableList<FeeCheck> feeChecks;
@VisibleForTesting
public ImmutableList<FeeCheck> getChecks() {
return feeChecks;
}
public static FeeCheckResponseExtension create(ImmutableList<FeeCheck> feeChecks) {
FeeCheckResponseExtension instance = new FeeCheckResponseExtension();
instance.feeChecks = feeChecks;
return instance;
}
/** The response for a check on a single resource. */
@XmlType(propOrder = {"name", "currency", "command", "period", "fee", "feeClass"})
public static class FeeCheck extends BaseFeeResponse {
/** The name of the domain that was checked, with an attribute indicating if it is premium. */
String name;
/** A builder for {@link FeeCheck}. */
public static class Builder extends BaseFeeResponse.Builder<FeeCheck, Builder> {
public Builder setName(String name) {
getInstance().name = name;
return this;
}
}
}
/**
* If currency is not supported at the top level of Check responses for this version of the fee
* extension, this function has not effect.
*/
public void setCurrencyIfSupported(CurrencyUnit currency);
public ImmutableList<F> getItems();
}

View file

@ -0,0 +1,33 @@
// Copyright 2016 The Domain Registry Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.model.domain.fee;
/**
* Interface for individual fee extension items in Check responses. These are derived from the more
* general query items (which cover Info responses as well), but may also contain a domain name,
* depending on the version of the fee extension.
*/
public interface FeeCheckResponseExtensionItem extends FeeQueryResponseExtensionItem {
/** Builder for {@link FeeCheckResponseExtensionItem}. */
public interface Builder extends FeeQueryResponseExtensionItem.Builder {
/** The name associated with the item. Has no effect if domain names are not supported. */
public Builder setDomainNameIfSupported(String name);
public FeeCheckResponseExtensionItem build();
}
}

View file

@ -1,56 +0,0 @@
// Copyright 2016 The Domain Registry Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.model.domain.fee;
import com.google.common.collect.ImmutableList;
import google.registry.model.Buildable.GenericBuilder;
import google.registry.model.ImmutableObject;
import google.registry.model.eppoutput.EppResponse.ResponseExtension;
import java.util.List;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import org.joda.money.CurrencyUnit;
/**
* An XML data object that represents a fee extension that may be present on the response to EPP
* domain create commands.
*/
@XmlRootElement(name = "delData")
public class FeeDeleteResponseExtension extends ImmutableObject implements ResponseExtension {
/** The currency of the credit(s). */
CurrencyUnit currency;
/**
* The magnitude of the credit(s), in the specified units, with an optional description.
*
* <p>This is a list because a single delete can receive multiple credits.
*/
@XmlElement(name = "credit")
List<Credit> credits;
/** Builder for {@link FeeDeleteResponseExtension}. */
public static class Builder extends GenericBuilder<FeeDeleteResponseExtension, Builder> {
public Builder setCurrency(CurrencyUnit currency) {
getInstance().currency = currency;
return thisCastToDerived();
}
public Builder setCredits(ImmutableList<Credit> credits) {
getInstance().credits = credits;
return thisCastToDerived();
}
}
}

View file

@ -17,20 +17,12 @@ package google.registry.model.domain.fee;
import com.google.common.base.Ascii;
import com.google.common.base.CharMatcher;
import google.registry.model.ImmutableObject;
import google.registry.model.domain.fee.FeeQueryCommandExtensionItem.CommandName;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlValue;
/** A command name along with the launch phase and subphase it is to be executed in. */
public class FeeCommandDescriptor extends ImmutableObject {
/** The name of a command that might have an associated fee. */
public enum CommandName {
CREATE,
RENEW,
TRANSFER,
RESTORE,
UNKNOWN
}
public class FeeExtensionCommandDescriptor extends ImmutableObject {
@XmlAttribute
String phase;
@ -64,4 +56,13 @@ public class FeeCommandDescriptor extends ImmutableObject {
}
return CommandName.UNKNOWN;
}
public static FeeExtensionCommandDescriptor
create(CommandName commandName, String phase, String subphase) {
FeeExtensionCommandDescriptor commandDescriptor = new FeeExtensionCommandDescriptor();
commandDescriptor.command = Ascii.toLowerCase(commandName.name());
commandDescriptor.phase = phase;
commandDescriptor.subphase = subphase;
return commandDescriptor;
}
}

View file

@ -0,0 +1,58 @@
// Copyright 2016 The Domain Registry Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.model.domain.fee;
import google.registry.model.domain.Period;
import org.joda.money.CurrencyUnit;
/**
* Interface for individual query items in Check and Info commands. Each item indicates the command
* to be checked, and the number of years for which the prices is requested. It may also contain the
* currency, but some versions of the fee extension specify the currency at the top level of the
* extension.
*/
public interface FeeQueryCommandExtensionItem {
/** The name of a command that might have an associated fee. */
public enum CommandName {
UNKNOWN,
CREATE,
RENEW,
TRANSFER,
RESTORE,
UPDATE
}
/** True if this version of fee extension includes a currency in this type of query item. */
public boolean isCurrencySupported();
/** A three-character ISO4217 currency code; throws an exception if currency is not supported. */
public CurrencyUnit getCurrency() throws UnsupportedOperationException;
/** The name of the command being checked. */
public CommandName getCommandName();
/** The unparse name of the command being checked, for use in error strings. */
public String getUnparsedCommandName();
/** The phase of the command being checked. */
public String getPhase();
/** The subphase of the command being checked. */
public String getSubphase();
/** The period for the command being checked. */
public Period getPeriod();
}

View file

@ -18,32 +18,50 @@ import com.google.common.base.Optional;
import google.registry.model.ImmutableObject;
import google.registry.model.domain.Period;
import javax.xml.bind.annotation.XmlTransient;
import org.joda.money.CurrencyUnit;
/** Base class for the fee requests on check and info. */
/**
* Abstract base class for the fee request query items used in Check and Info commands. It handles
* command and period, which are always present. Derived classes must handle currency, which may or
* may not be present, depending on the version of the extension being used.
*/
@XmlTransient
public class BaseFeeRequest extends ImmutableObject {
public abstract class FeeQueryCommandExtensionItemImpl
extends ImmutableObject implements FeeQueryCommandExtensionItem {
/** The default validity period (if not specified) is 1 year for all operations. */
static final Period DEFAULT_PERIOD = Period.create(1, Period.Unit.YEARS);
/** A three-character ISO4217 currency code. */
CurrencyUnit currency;
/** The command being checked. */
FeeCommandDescriptor command;
FeeExtensionCommandDescriptor command;
/** The period for the command being checked. */
Period period;
public CurrencyUnit getCurrency() {
return currency;
/** The name of the command being checked. */
@Override
public CommandName getCommandName() {
return command.getCommand();
}
/** The command name before being parsed into an enum, for use in error strings. */
@Override
public String getUnparsedCommandName() {
return command.getUnparsedCommandName();
}
/** The phase of the command being checked. */
@Override
public String getPhase() {
return command.getPhase();
}
public FeeCommandDescriptor getCommand() {
return command;
/** The subphase of the command being checked. */
@Override
public String getSubphase() {
return command.getSubphase();
}
@Override
public Period getPeriod() {
return Optional.fromNullable(period).or(DEFAULT_PERIOD);
}

View file

@ -0,0 +1,62 @@
// Copyright 2016 The Domain Registry Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.model.domain.fee;
import google.registry.model.domain.Period;
import google.registry.model.domain.fee.FeeQueryCommandExtensionItem.CommandName;
import java.util.List;
import org.joda.money.CurrencyUnit;
/**
* Interface for individual query items in Check and Info response. Each item indicates the fees and
* class associated with a particular command and period. The currency may also be listed, but some
* versions of the fee extension specify the currency at the top level of the extension.
*/
public interface FeeQueryResponseExtensionItem {
/**
* The type of the fee. We will use "premium" for fees on premium names, and omit the field
* otherwise.
*/
public String getFeeClass();
/** Builder for {@link FeeCheckResponseExtensionItem}. */
public interface Builder {
/**
* If currency is not supported in this type of query response item for this version of the fee
* extension, this function has no effect.
*/
public Builder setCurrencyIfSupported(CurrencyUnit currency);
/** Whether this check item can be calculated. If so, reason should be null. If not, fees
* should not be set.
*/
public Builder setAvailIfSupported(boolean avail);
/** The reason that the check item cannot be calculated. */
public Builder setReasonIfSupported(String reason);
public Builder setCommand(CommandName commandName, String phase, String subphase);
public Builder setPeriod(Period period);
public Builder setFees(List<Fee> fees);
public Builder setClass(String feeClass);
}
}

View file

@ -20,19 +20,22 @@ import com.google.common.collect.ImmutableList;
import google.registry.model.Buildable.GenericBuilder;
import google.registry.model.ImmutableObject;
import google.registry.model.domain.Period;
import google.registry.model.domain.fee.FeeQueryCommandExtensionItem.CommandName;
import java.util.List;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlTransient;
import org.joda.money.CurrencyUnit;
/** Base class for the fee responses on check and info. */
/**
* Abstract base class for the fee request query items used in Check and Info responses. It handles
* command, period, fees and class, which are always present. Derived classes must handle currency,
* which may or may not be present, depending on the version of the extension being used.
*/
@XmlTransient
public class BaseFeeResponse extends ImmutableObject {
/** The currency of the fee. */
CurrencyUnit currency;
public class FeeQueryResponseExtensionItemImpl
extends ImmutableObject implements FeeQueryResponseExtensionItem {
/** The command that was checked. */
FeeCommandDescriptor command;
FeeExtensionCommandDescriptor command;
/** The period that was checked. */
Period period;
@ -52,38 +55,44 @@ public class BaseFeeResponse extends ImmutableObject {
@XmlElement(name = "class")
String feeClass;
@Override
public String getFeeClass() {
return feeClass;
}
/** Abstract builder for {@link BaseFeeResponse}. */
public abstract static class Builder<T extends BaseFeeResponse, B extends Builder<?, ?>>
extends GenericBuilder<T, B> {
public B setCurrency(CurrencyUnit currency) {
getInstance().currency = currency;
return thisCastToDerived();
}
public B setCommand(FeeCommandDescriptor command) {
getInstance().command = command;
/** Abstract builder for {@link FeeQueryResponseExtensionItemImpl}. */
public abstract static class
Builder<T extends FeeQueryResponseExtensionItemImpl, B extends Builder<?, ?>>
extends GenericBuilder<T, B> implements FeeQueryResponseExtensionItem.Builder {
@Override
public B setCommand(CommandName commandName, String phase, String subphase) {
getInstance().command = FeeExtensionCommandDescriptor.create(commandName, phase, subphase);
return thisCastToDerived();
}
@Override
public B setPeriod(Period period) {
getInstance().period = period;
return thisCastToDerived();
}
@Override
public B setFees(List<Fee> fees) {
// If there are no fees, set the field to null to suppress the 'fee' section in the xml.
getInstance().fee = forceEmptyToNull(ImmutableList.copyOf(fees));
return thisCastToDerived();
}
public B setFee(List<Fee> fees) {
getInstance().fee = forceEmptyToNull(ImmutableList.copyOf(fees));
return thisCastToDerived();
}
@Override
public B setClass(String feeClass) {
getInstance().feeClass = feeClass;
return thisCastToDerived();
}
}
}

View file

@ -15,10 +15,13 @@
package google.registry.model.domain.fee;
import google.registry.model.eppinput.EppInput.CommandExtension;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
import java.util.List;
import org.joda.money.CurrencyUnit;
/** A fee extension that may be present on domain transfer requests. */
@XmlRootElement(name = "transfer")
@XmlType(propOrder = {"currency", "fees"})
public class FeeTransferExtension extends BaseFeeCommand implements CommandExtension {}
/** Interface for fee extensions in Create, Renew, Transfer and Update commands. */
public interface FeeTransformCommandExtension extends CommandExtension {
CurrencyUnit getCurrency();
List<Fee> getFees();
List<Credit> getCredits();
FeeTransformResponseExtension.Builder createResponseBuilder();
}

View file

@ -22,7 +22,8 @@ import org.joda.money.CurrencyUnit;
/** Base class for general transform commands with fees (create, renew, update, transfer). */
@XmlTransient
public class BaseFeeCommand extends ImmutableObject {
public abstract class FeeTransformCommandExtensionImpl
extends ImmutableObject implements FeeTransformCommandExtension {
/** The currency of the fee. */
CurrencyUnit currency;
@ -35,11 +36,21 @@ public class BaseFeeCommand extends ImmutableObject {
@XmlElement(name = "fee")
List<Fee> fees;
@XmlElement(name = "credit")
List<Credit> credits;
@Override
public CurrencyUnit getCurrency() {
return currency;
}
@Override
public List<Fee> getFees() {
return fees;
}
@Override
public List<Credit> getCredits() {
return credits;
}
}

View file

@ -0,0 +1,58 @@
// Copyright 2016 The Domain Registry Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.model.domain.fee;
import com.google.common.collect.ImmutableList;
import google.registry.model.ImmutableObject;
import java.util.List;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlTransient;
import org.joda.money.CurrencyUnit;
/**
* Base class for general transform commands with fees (create, renew, update, transfer). This
* version of the class is for fee extensions that do not support credits (certain older versions
* allow credits only for some commands).
*/
@XmlTransient
public abstract class FeeTransformCommandExtensionImplNoCredits
extends ImmutableObject implements FeeTransformCommandExtension {
/** The currency of the fee. */
CurrencyUnit currency;
/**
* The magnitude of the fee, in the specified units, with an optional description.
*
* <p>This is a list because a single operation can involve multiple fees.
*/
@XmlElement(name = "fee")
List<Fee> fees;
@Override
public CurrencyUnit getCurrency() {
return currency;
}
@Override
public List<Fee> getFees() {
return fees;
}
@Override
public List<Credit> getCredits() {
return ImmutableList.of();
}
}

View file

@ -0,0 +1,31 @@
// Copyright 2016 The Domain Registry Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.model.domain.fee;
import com.google.common.collect.ImmutableList;
import google.registry.model.eppoutput.EppResponse.ResponseExtension;
import org.joda.money.CurrencyUnit;
/** Interface for fee extensions in Create, Renew, Transfer and Update responses. */
public interface FeeTransformResponseExtension extends ResponseExtension {
/** Builder for {@link FeeTransformResponseExtension}. */
public interface Builder {
Builder setCurrency(CurrencyUnit currency);
Builder setFees(ImmutableList<Fee> fees);
Builder setCredits(ImmutableList<Credit> credits);
FeeTransformResponseExtension build();
}
}

View file

@ -18,12 +18,14 @@ import com.google.common.collect.ImmutableList;
import google.registry.model.Buildable.GenericBuilder;
import google.registry.model.ImmutableObject;
import java.util.List;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlTransient;
import org.joda.money.CurrencyUnit;
/** Base class for fee responses on general transform commands (create, update, renew, transfer). */
@XmlTransient
public class BaseFeeCommandResponse extends ImmutableObject {
public class FeeTransformResponseExtensionImpl extends ImmutableObject
implements FeeTransformResponseExtension {
/** The currency of the fee. */
CurrencyUnit currency;
@ -33,18 +35,32 @@ public class BaseFeeCommandResponse extends ImmutableObject {
*
* <p>This is a list because a single operation can involve multiple fees.
*/
List<Fee> fee;
@XmlElement(name = "fee")
List<Fee> fees;
@XmlElement(name = "credit")
List<Credit> credits;
/** Abstract builder for {@link BaseFeeCommandResponse}. */
public abstract static class Builder<T extends BaseFeeCommandResponse, B extends Builder<?, ?>>
extends GenericBuilder<T, B> {
/** Abstract builder for {@link FeeTransformResponseExtensionImpl}. */
public abstract static class
Builder<T extends FeeTransformResponseExtensionImpl, B extends Builder<?, ?>>
extends GenericBuilder<T, B> implements FeeTransformResponseExtension.Builder {
@Override
public B setCurrency(CurrencyUnit currency) {
getInstance().currency = currency;
return thisCastToDerived();
}
public B setFee(ImmutableList<Fee> fee) {
getInstance().fee = fee;
@Override
public B setFees(ImmutableList<Fee> fees) {
getInstance().fees = fees;
return thisCastToDerived();
}
@Override
public B setCredits(ImmutableList<Credit> credits) {
getInstance().credits = credits;
return thisCastToDerived();
}
}

View file

@ -0,0 +1,67 @@
// Copyright 2016 The Domain Registry Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.model.domain.fee;
import com.google.common.collect.ImmutableList;
import google.registry.model.Buildable.GenericBuilder;
import google.registry.model.ImmutableObject;
import java.util.List;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlTransient;
import org.joda.money.CurrencyUnit;
/**
* Base class for fee responses on general transform commands (create, update, renew, transfer).
* This version of the class is for fee extensions that do not support credits (certain older
* versions allow credits only for some commands).
*/
@XmlTransient
public class FeeTransformResponseExtensionImplNoCredits extends ImmutableObject
implements FeeTransformResponseExtension {
/** The currency of the fee. */
CurrencyUnit currency;
/**
* The magnitude of the fee, in the specified units, with an optional description.
*
* <p>This is a list because a single operation can involve multiple fees.
*/
@XmlElement(name = "fee")
List<Fee> fees;
/** Abstract builder for {@link FeeTransformResponseExtensionImplNoCredits}. */
public abstract static class
Builder<T extends FeeTransformResponseExtensionImplNoCredits, B extends Builder<?, ?>>
extends GenericBuilder<T, B> implements FeeTransformResponseExtension.Builder {
@Override
public B setCurrency(CurrencyUnit currency) {
getInstance().currency = currency;
return thisCastToDerived();
}
@Override
public B setFees(ImmutableList<Fee> fees) {
getInstance().fees = fees;
return thisCastToDerived();
}
@Override
public B setCredits(ImmutableList<Credit> credits) {
return thisCastToDerived();
}
}
}

View file

@ -0,0 +1,57 @@
// Copyright 2016 The Domain Registry Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.model.domain.fee06;
import google.registry.model.domain.fee.FeeCheckCommandExtensionItem;
import google.registry.model.domain.fee.FeeCheckResponseExtensionItem;
import google.registry.model.domain.fee.FeeQueryCommandExtensionItemImpl;
import javax.xml.bind.annotation.XmlType;
import org.joda.money.CurrencyUnit;
/** An individual price check item in version 0.6 of the fee extension on Check commands. */
@XmlType(propOrder = {"name", "currency", "command", "period"})
public class FeeCheckCommandExtensionItemV06
extends FeeQueryCommandExtensionItemImpl implements FeeCheckCommandExtensionItem {
/** The fully qualified domain name being checked. */
String name;
CurrencyUnit currency;
@Override
public boolean isDomainNameSupported() {
return true;
}
@Override
public String getDomainName() {
return name;
}
@Override
public boolean isCurrencySupported() {
return true;
}
@Override
public CurrencyUnit getCurrency() {
return currency;
}
@Override
public FeeCheckResponseExtensionItem.Builder createResponseBuilder() {
return new FeeCheckResponseExtensionItemV06.Builder();
}
}

View file

@ -0,0 +1,65 @@
// Copyright 2016 The Domain Registry Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.model.domain.fee06;
import static google.registry.util.CollectionUtils.nullToEmptyImmutableCopy;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import google.registry.model.ImmutableObject;
import google.registry.model.domain.fee.FeeCheckCommandExtension;
import google.registry.model.domain.fee.FeeCheckResponseExtensionItem;
import java.util.Set;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import org.joda.money.CurrencyUnit;
/** Version 0.6 of the fee extension that may be present on domain check commands. */
@XmlRootElement(name = "check")
public class FeeCheckCommandExtensionV06 extends ImmutableObject
implements FeeCheckCommandExtension<
FeeCheckCommandExtensionItemV06,
FeeCheckResponseExtensionV06> {
@XmlElement(name = "domain")
Set<FeeCheckCommandExtensionItemV06> items;
@Override
public boolean isCurrencySupported() {
return false;
}
@Override
public CurrencyUnit getCurrency() {
throw new UnsupportedOperationException("Currency not supported");
}
@Override
public ImmutableSet<FeeCheckCommandExtensionItemV06> getItems() {
return nullToEmptyImmutableCopy(items);
}
@Override
public FeeCheckResponseExtensionV06 createResponse(
ImmutableList<? extends FeeCheckResponseExtensionItem> items) {
ImmutableList.Builder<FeeCheckResponseExtensionItemV06> builder = new ImmutableList.Builder<>();
for (FeeCheckResponseExtensionItem item : items) {
if (item instanceof FeeCheckResponseExtensionItemV06) {
builder.add((FeeCheckResponseExtensionItemV06) item);
}
}
return FeeCheckResponseExtensionV06.create(builder.build());
}
}

View file

@ -0,0 +1,58 @@
// Copyright 2016 The Domain Registry Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.model.domain.fee06;
import google.registry.model.domain.fee.FeeCheckResponseExtensionItem;
import google.registry.model.domain.fee.FeeQueryResponseExtensionItemImpl;
import javax.xml.bind.annotation.XmlType;
import org.joda.money.CurrencyUnit;
/** The version 0.6 response for a domain check on a single resource. */
@XmlType(propOrder = {"name", "currency", "command", "period", "fee", "feeClass"})
public class FeeCheckResponseExtensionItemV06
extends FeeQueryResponseExtensionItemImpl implements FeeCheckResponseExtensionItem {
/** The name of the domain that was checked, with an attribute indicating if it is premium. */
String name;
CurrencyUnit currency;
/** Builder for {@link FeeCheckResponseExtensionItemV06}. */
public static class Builder
extends FeeQueryResponseExtensionItemImpl.Builder<FeeCheckResponseExtensionItemV06, Builder>
implements FeeCheckResponseExtensionItem.Builder {
@Override
public Builder setDomainNameIfSupported(String name) {
getInstance().name = name;
return this;
}
@Override
public Builder setCurrencyIfSupported(CurrencyUnit currency) {
getInstance().currency = currency;
return this;
}
@Override
public Builder setAvailIfSupported(boolean avail) {
return this;
}
@Override
public Builder setReasonIfSupported(String reason) {
return this;
}
}
}

View file

@ -0,0 +1,53 @@
// Copyright 2016 The Domain Registry Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.model.domain.fee06;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import google.registry.model.ImmutableObject;
import google.registry.model.domain.fee.FeeCheckResponseExtension;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import org.joda.money.CurrencyUnit;
/**
* An XML data object that represents version 0.6 of the fee extension that may be present on the
* response to EPP domain check commands.
*/
@XmlRootElement(name = "chkData")
public class FeeCheckResponseExtensionV06
extends ImmutableObject implements FeeCheckResponseExtension<FeeCheckResponseExtensionItemV06> {
/** Check responses. */
@XmlElement(name = "cd")
ImmutableList<FeeCheckResponseExtensionItemV06> items;
@Override
public void setCurrencyIfSupported(CurrencyUnit currency) {
}
@VisibleForTesting
@Override
public ImmutableList<FeeCheckResponseExtensionItemV06> getItems() {
return items;
}
static FeeCheckResponseExtensionV06
create(ImmutableList<FeeCheckResponseExtensionItemV06> items) {
FeeCheckResponseExtensionV06 instance = new FeeCheckResponseExtensionV06();
instance.items = items;
return instance;
}
}

View file

@ -12,13 +12,22 @@
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.model.domain.fee;
package google.registry.model.domain.fee06;
import google.registry.model.eppinput.EppInput.CommandExtension;
import google.registry.model.domain.fee.FeeTransformCommandExtension;
import google.registry.model.domain.fee.FeeTransformCommandExtensionImplNoCredits;
import google.registry.model.domain.fee.FeeTransformResponseExtension;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
/** A fee extension that may be present on domain create commands. */
@XmlRootElement(name = "create")
@XmlType(propOrder = {"currency", "fees"})
public class FeeCreateExtension extends BaseFeeCommand implements CommandExtension {}
public class FeeCreateCommandExtensionV06
extends FeeTransformCommandExtensionImplNoCredits implements FeeTransformCommandExtension {
@Override
public FeeTransformResponseExtension.Builder createResponseBuilder() {
return new FeeCreateResponseExtensionV06.Builder();
}
}

View file

@ -0,0 +1,31 @@
// Copyright 2016 The Domain Registry Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.model.domain.fee06;
import google.registry.model.domain.fee.FeeTransformResponseExtensionImplNoCredits;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
/**
* An XML data object that represents a fee extension that may be present on the response to EPP
* domain create commands.
*/
@XmlRootElement(name = "creData")
@XmlType(propOrder = {"currency", "fees"})
public class FeeCreateResponseExtensionV06 extends FeeTransformResponseExtensionImplNoCredits {
/** A builder for {@link FeeCreateResponseExtensionV06}. */
public static class Builder extends
FeeTransformResponseExtensionImplNoCredits.Builder<FeeCreateResponseExtensionV06, Builder> {}
}

View file

@ -0,0 +1,32 @@
// Copyright 2016 The Domain Registry Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.model.domain.fee06;
import google.registry.model.domain.fee.FeeTransformResponseExtensionImpl;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
/**
* An XML data object that represents a fee extension that may be present on the response to EPP
* domain create commands.
*/
@XmlRootElement(name = "delData")
@XmlType(propOrder = {"currency", "fees", "credits"})
public class FeeDeleteResponseExtensionV06 extends FeeTransformResponseExtensionImpl {
/** Builder for {@link FeeDeleteResponseExtensionV06}. */
public static class Builder
extends FeeTransformResponseExtensionImpl.Builder<FeeDeleteResponseExtensionV06, Builder> {}
}

View file

@ -12,13 +12,31 @@
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.model.domain.fee;
package google.registry.model.domain.fee06;
import google.registry.model.domain.fee.FeeQueryCommandExtensionItemImpl;
import google.registry.model.eppinput.EppInput.CommandExtension;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
import org.joda.money.CurrencyUnit;
/** A fee extension that may be present on domain info commands. */
@XmlRootElement(name = "info")
@XmlType(propOrder = {"currency", "command", "period"})
public class FeeInfoExtension extends BaseFeeRequest implements CommandExtension {}
public class FeeInfoCommandExtensionV06
extends FeeQueryCommandExtensionItemImpl implements CommandExtension {
/** A three-character ISO4217 currency code. */
CurrencyUnit currency;
@Override
public boolean isCurrencySupported() {
return true;
}
@Override
public CurrencyUnit getCurrency() {
return currency;
}
}

View file

@ -0,0 +1,56 @@
// Copyright 2016 The Domain Registry Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.model.domain.fee06;
import google.registry.model.domain.fee.FeeQueryResponseExtensionItem;
import google.registry.model.domain.fee.FeeQueryResponseExtensionItemImpl;
import google.registry.model.eppoutput.EppResponse.ResponseExtension;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
import org.joda.money.CurrencyUnit;
/**
* An XML data object that represents a fee extension that may be present on the response to EPP
* domain info commands.
*/
@XmlRootElement(name = "infData")
@XmlType(propOrder = {"currency", "command", "period", "fee", "feeClass"})
public class FeeInfoResponseExtensionV06
extends FeeQueryResponseExtensionItemImpl implements ResponseExtension {
CurrencyUnit currency;
/** Builder for {@link FeeInfoResponseExtensionV06}. */
public static class Builder
extends FeeQueryResponseExtensionItemImpl.Builder<FeeInfoResponseExtensionV06, Builder> {
@Override
public Builder setAvailIfSupported(boolean avail) {
return this;
}
@Override
public Builder setReasonIfSupported(String reason) {
return this;
}
@Override
public FeeQueryResponseExtensionItem.Builder
setCurrencyIfSupported(CurrencyUnit currency) {
getInstance().currency = currency;
return this;
}
}
}

View file

@ -12,13 +12,22 @@
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.model.domain.fee;
package google.registry.model.domain.fee06;
import google.registry.model.eppinput.EppInput.CommandExtension;
import google.registry.model.domain.fee.FeeTransformCommandExtension;
import google.registry.model.domain.fee.FeeTransformCommandExtensionImplNoCredits;
import google.registry.model.domain.fee.FeeTransformResponseExtension;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
/** A fee extension that may be present on domain renew commands. */
@XmlRootElement(name = "renew")
@XmlType(propOrder = {"currency", "fees"})
public class FeeRenewExtension extends BaseFeeCommand implements CommandExtension {}
public class FeeRenewCommandExtensionV06
extends FeeTransformCommandExtensionImplNoCredits implements FeeTransformCommandExtension {
@Override
public FeeTransformResponseExtension.Builder createResponseBuilder() {
return new FeeRenewResponseExtensionV06.Builder();
}
}

View file

@ -12,19 +12,20 @@
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.model.domain.fee;
package google.registry.model.domain.fee06;
import google.registry.model.eppoutput.EppResponse.ResponseExtension;
import google.registry.model.domain.fee.FeeTransformResponseExtensionImplNoCredits;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
/**
* An XML data object that represents a fee extension that may be present on the response to EPP
* domain info commands.
* domain renew commands.
*/
@XmlRootElement(name = "infData")
@XmlType(propOrder = {"currency", "command", "period", "fee", "feeClass"})
public class FeeInfoResponseExtension extends BaseFeeResponse implements ResponseExtension {
/** A builder for {@link FeeInfoResponseExtension}. */
public static class Builder extends BaseFeeResponse.Builder<FeeInfoResponseExtension, Builder> {}
@XmlRootElement(name = "renData")
@XmlType(propOrder = {"currency", "fees"})
public class FeeRenewResponseExtensionV06 extends FeeTransformResponseExtensionImplNoCredits {
/** A builder for {@link FeeRenewResponseExtensionV06}. */
public static class Builder extends
FeeTransformResponseExtensionImplNoCredits.Builder<FeeRenewResponseExtensionV06, Builder> {}
}

View file

@ -0,0 +1,33 @@
// Copyright 2016 The Domain Registry Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.model.domain.fee06;
import google.registry.model.domain.fee.FeeTransformCommandExtension;
import google.registry.model.domain.fee.FeeTransformCommandExtensionImplNoCredits;
import google.registry.model.domain.fee.FeeTransformResponseExtension;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
/** A fee extension that may be present on domain transfer requests. */
@XmlRootElement(name = "transfer")
@XmlType(propOrder = {"currency", "fees"})
public class FeeTransferCommandExtensionV06
extends FeeTransformCommandExtensionImplNoCredits implements FeeTransformCommandExtension {
@Override
public FeeTransformResponseExtension.Builder createResponseBuilder() {
return new FeeTransferResponseExtensionV06.Builder();
}
}

View file

@ -0,0 +1,32 @@
// Copyright 2016 The Domain Registry Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.model.domain.fee06;
import google.registry.model.domain.fee.FeeTransformResponseExtensionImplNoCredits;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
/**
* An XML data object that represents a fee extension that may be present on the response to EPP
* domain transfer requests.
*/
@XmlRootElement(name = "trnData")
@XmlType(propOrder = {"currency", "fees"})
public class FeeTransferResponseExtensionV06 extends FeeTransformResponseExtensionImplNoCredits {
/** A builder for {@link FeeTransferResponseExtensionV06}. */
public static class Builder
extends FeeTransformResponseExtensionImplNoCredits
.Builder<FeeTransferResponseExtensionV06, Builder> {}
}

View file

@ -12,13 +12,22 @@
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.model.domain.fee;
package google.registry.model.domain.fee06;
import google.registry.model.eppinput.EppInput.CommandExtension;
import google.registry.model.domain.fee.FeeTransformCommandExtension;
import google.registry.model.domain.fee.FeeTransformCommandExtensionImplNoCredits;
import google.registry.model.domain.fee.FeeTransformResponseExtension;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
/** A fee extension that may be present on domain update commands. */
@XmlRootElement(name = "update")
@XmlType(propOrder = {"currency", "fees"})
public class FeeUpdateExtension extends BaseFeeCommand implements CommandExtension {}
public class FeeUpdateCommandExtensionV06
extends FeeTransformCommandExtensionImplNoCredits implements FeeTransformCommandExtension {
@Override
public FeeTransformResponseExtension.Builder createResponseBuilder() {
return new FeeUpdateResponseExtensionV06.Builder();
}
}

View file

@ -0,0 +1,32 @@
// Copyright 2016 The Domain Registry Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.model.domain.fee06;
import google.registry.model.domain.fee.FeeTransformResponseExtensionImplNoCredits;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
/**
* An XML data object that represents a fee extension that may be present on the response to EPP
* domain update commands.
*/
@XmlRootElement(name = "updData")
@XmlType(propOrder = {"currency", "fees"})
public class FeeUpdateResponseExtensionV06 extends FeeTransformResponseExtensionImplNoCredits {
/** A builder for {@link FeeUpdateResponseExtensionV06}. */
public static class Builder
extends FeeTransformResponseExtensionImplNoCredits
.Builder<FeeUpdateResponseExtensionV06, Builder> {}
}

View file

@ -18,7 +18,7 @@
elementFormDefault = XmlNsForm.QUALIFIED)
@XmlAccessorType(XmlAccessType.FIELD)
@XmlJavaTypeAdapter(CurrencyUnitAdapter.class)
package google.registry.model.domain.fee;
package google.registry.model.domain.fee06;
import google.registry.model.translators.CurrencyUnitAdapter;
import javax.xml.bind.annotation.XmlAccessType;

View file

@ -0,0 +1,148 @@
// Copyright 2016 The Domain Registry Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.model.domain.fee11;
import static com.google.common.base.Preconditions.checkState;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import google.registry.model.ImmutableObject;
import google.registry.model.domain.Period;
import google.registry.model.domain.fee.FeeCheckCommandExtension;
import google.registry.model.domain.fee.FeeCheckCommandExtensionItem;
import google.registry.model.domain.fee.FeeCheckResponseExtensionItem;
import google.registry.model.domain.fee.FeeCheckResponseExtensionItem.Builder;
import google.registry.model.domain.fee.FeeExtensionCommandDescriptor;
import google.registry.model.domain.fee11.FeeCheckCommandExtensionV11.FeeCheckCommandExtensionItemV11;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
import org.joda.money.CurrencyUnit;
/**
* Version 0.11 of the fee extension that may be present on domain check commands. Unlike other
* versions, there is only one check item; things are nested one level less. However, the response
* will have multiple items, one for each domain in the check command.
*/
@XmlRootElement(name = "check")
@XmlType(propOrder = {"command", "currency", "period", "feeClass"})
public class FeeCheckCommandExtensionV11 extends ImmutableObject
implements FeeCheckCommandExtension<
FeeCheckCommandExtensionItemV11,
FeeCheckResponseExtensionV11> {
/** The default validity period (if not specified) is 1 year for all operations. */
static final Period DEFAULT_PERIOD = Period.create(1, Period.Unit.YEARS);
/** The command to check. */
FeeExtensionCommandDescriptor command;
/** Three-letter currency code in which results should be returned. */
CurrencyUnit currency;
/** The period to check. */
Period period;
/** The class to check. */
@XmlElement(name = "class")
String feeClass;
@Override
public boolean isCurrencySupported() {
return false;
}
@Override
public CurrencyUnit getCurrency() {
throw new UnsupportedOperationException("Currency not supported");
}
@Override
public ImmutableSet<FeeCheckCommandExtensionItemV11> getItems() {
return ImmutableSet.of(new FeeCheckCommandExtensionItemV11());
}
@Override
public FeeCheckResponseExtensionV11 createResponse(
ImmutableList<? extends FeeCheckResponseExtensionItem> items) {
ImmutableList.Builder<FeeCheckResponseExtensionItemV11> builder = new ImmutableList.Builder<>();
for (FeeCheckResponseExtensionItem item : items) {
checkState(
item instanceof FeeCheckResponseExtensionItemV11,
"Fee extension response item is not V11");
builder.add((FeeCheckResponseExtensionItemV11) item);
}
return FeeCheckResponseExtensionV11.create(builder.build());
}
/** Implementation of the item interface, returning values of the single "item". */
class FeeCheckCommandExtensionItemV11 implements FeeCheckCommandExtensionItem {
/** The name of the command being checked. */
@Override
public CommandName getCommandName() {
return command.getCommand();
}
/** The command name before being parsed into an enum, for use in error strings. */
@Override
public String getUnparsedCommandName() {
return command.getUnparsedCommandName();
}
/** The phase of the command being checked. */
@Override
public String getPhase() {
return command.getPhase();
}
/** The subphase of the command being checked. */
@Override
public String getSubphase() {
return command.getSubphase();
}
@Override
public Period getPeriod() {
return Optional.fromNullable(period).or(DEFAULT_PERIOD);
}
@Override
public boolean isDomainNameSupported() {
return false;
}
@Override
public String getDomainName() {
throw new UnsupportedOperationException("Domain not supported");
}
@Override
public boolean isCurrencySupported() {
return true;
}
@Override
public CurrencyUnit getCurrency() {
return currency;
}
@Override
public Builder createResponseBuilder() {
return new FeeCheckResponseExtensionItemV11.Builder();
}
}
}

View file

@ -0,0 +1,70 @@
// Copyright 2016 The Domain Registry Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.model.domain.fee11;
import google.registry.model.domain.DomainObjectSpec;
import google.registry.model.domain.fee.FeeCheckResponseExtensionItem;
import google.registry.model.domain.fee.FeeQueryResponseExtensionItemImpl;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlType;
import org.joda.money.CurrencyUnit;
/** The version 0.11 response for a domain check on a single resource. */
@XmlType(propOrder = {"object", "command", "currency", "period", "fee", "feeClass", "reason"})
public class FeeCheckResponseExtensionItemV11
extends FeeQueryResponseExtensionItemImpl implements FeeCheckResponseExtensionItem {
/** Whether the domain is available. */
@XmlAttribute
boolean avail;
/** The domain that was checked. */
DomainObjectSpec object;
CurrencyUnit currency;
/** The reason that the check item cannot be calculated. */
String reason;
/** Builder for {@link FeeCheckResponseExtensionItemV11}. */
public static class Builder
extends FeeQueryResponseExtensionItemImpl.Builder<FeeCheckResponseExtensionItemV11, Builder>
implements FeeCheckResponseExtensionItem.Builder {
@Override
public Builder setDomainNameIfSupported(String name) {
getInstance().object = new DomainObjectSpec(name);
return this;
}
@Override
public Builder setCurrencyIfSupported(CurrencyUnit currency) {
getInstance().currency = currency;
return this;
}
@Override
public Builder setAvailIfSupported(boolean avail) {
getInstance().avail = avail;
return this;
}
@Override
public Builder setReasonIfSupported(String reason) {
getInstance().reason = reason;
return this;
}
}
}

View file

@ -0,0 +1,53 @@
// Copyright 2016 The Domain Registry Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.model.domain.fee11;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import google.registry.model.ImmutableObject;
import google.registry.model.domain.fee.FeeCheckResponseExtension;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import org.joda.money.CurrencyUnit;
/**
* An XML data object that represents version 0.11 of the fee extension that may be present on the
* response to EPP domain check commands.
*/
@XmlRootElement(name = "chkData")
public class FeeCheckResponseExtensionV11
extends ImmutableObject implements FeeCheckResponseExtension<FeeCheckResponseExtensionItemV11> {
/** Check responses. */
@XmlElement(name = "cd")
ImmutableList<FeeCheckResponseExtensionItemV11> items;
@Override
public void setCurrencyIfSupported(CurrencyUnit currency) {}
@VisibleForTesting
@Override
public ImmutableList<FeeCheckResponseExtensionItemV11> getItems() {
return items;
}
static FeeCheckResponseExtensionV11
create(ImmutableList<FeeCheckResponseExtensionItemV11> items) {
FeeCheckResponseExtensionV11 instance = new FeeCheckResponseExtensionV11();
instance.items = items;
return instance;
}
}

View file

@ -0,0 +1,33 @@
// Copyright 2016 The Domain Registry Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.model.domain.fee11;
import google.registry.model.domain.fee.FeeTransformCommandExtension;
import google.registry.model.domain.fee.FeeTransformCommandExtensionImpl;
import google.registry.model.domain.fee.FeeTransformResponseExtension;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
/** A fee extension that may be present on domain create commands. */
@XmlRootElement(name = "create")
@XmlType(propOrder = {"currency", "fees", "credits"})
public class FeeCreateCommandExtensionV11
extends FeeTransformCommandExtensionImpl implements FeeTransformCommandExtension {
@Override
public FeeTransformResponseExtension.Builder createResponseBuilder() {
return new FeeCreateResponseExtensionV11.Builder();
}
}

View file

@ -12,9 +12,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.model.domain.fee;
package google.registry.model.domain.fee11;
import google.registry.model.eppoutput.EppResponse.ResponseExtension;
import google.registry.model.domain.fee.FeeTransformResponseExtensionImpl;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
@ -23,10 +23,9 @@ import javax.xml.bind.annotation.XmlType;
* domain create commands.
*/
@XmlRootElement(name = "creData")
@XmlType(propOrder = {"currency", "fee"})
public class FeeCreateResponseExtension extends BaseFeeCommandResponse
implements ResponseExtension {
/** A builder for {@link FeeCreateResponseExtension}. */
@XmlType(propOrder = {"currency", "fees", "credits"})
public class FeeCreateResponseExtensionV11 extends FeeTransformResponseExtensionImpl {
/** A builder for {@link FeeCreateResponseExtensionV11}. */
public static class Builder
extends BaseFeeCommandResponse.Builder<FeeCreateResponseExtension, Builder> {}
extends FeeTransformResponseExtensionImpl.Builder<FeeCreateResponseExtensionV11, Builder> {}
}

View file

@ -0,0 +1,32 @@
// Copyright 2016 The Domain Registry Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.model.domain.fee11;
import google.registry.model.domain.fee.FeeTransformResponseExtensionImpl;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
/**
* An XML data object that represents a fee extension that may be present on the response to EPP
* domain create commands.
*/
@XmlRootElement(name = "delData")
@XmlType(propOrder = {"currency", "fees", "credits"})
public class FeeDeleteResponseExtensionV11 extends FeeTransformResponseExtensionImpl {
/** Builder for {@link FeeDeleteResponseExtensionV11}. */
public static class Builder
extends FeeTransformResponseExtensionImpl.Builder<FeeDeleteResponseExtensionV11, Builder> {}
}

View file

@ -0,0 +1,33 @@
// Copyright 2016 The Domain Registry Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.model.domain.fee11;
import google.registry.model.domain.fee.FeeTransformCommandExtension;
import google.registry.model.domain.fee.FeeTransformCommandExtensionImpl;
import google.registry.model.domain.fee.FeeTransformResponseExtension;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
/** A fee extension that may be present on domain renew commands. */
@XmlRootElement(name = "renew")
@XmlType(propOrder = {"currency", "fees", "credits"})
public class FeeRenewCommandExtensionV11
extends FeeTransformCommandExtensionImpl implements FeeTransformCommandExtension {
@Override
public FeeTransformResponseExtension.Builder createResponseBuilder() {
return new FeeRenewResponseExtensionV11.Builder();
}
}

View file

@ -12,21 +12,20 @@
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.model.domain.fee;
package google.registry.model.domain.fee11;
import google.registry.model.eppoutput.EppResponse.ResponseExtension;
import google.registry.model.domain.fee.FeeTransformResponseExtensionImpl;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
/**
* An XML data object that represents a fee extension that may be present on the response to EPP
* domain create commands.
* domain renew commands.
*/
@XmlRootElement(name = "renData")
@XmlType(propOrder = {"currency", "fee"})
public class FeeRenewResponseExtension extends BaseFeeCommandResponse
implements ResponseExtension {
/** A builder for {@link FeeRenewResponseExtension}. */
@XmlType(propOrder = {"currency", "fees", "credits"})
public class FeeRenewResponseExtensionV11 extends FeeTransformResponseExtensionImpl {
/** A builder for {@link FeeRenewResponseExtensionV11}. */
public static class Builder
extends BaseFeeCommandResponse.Builder<FeeRenewResponseExtension, Builder> {}
extends FeeTransformResponseExtensionImpl.Builder<FeeRenewResponseExtensionV11, Builder> {}
}

View file

@ -0,0 +1,33 @@
// Copyright 2016 The Domain Registry Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.model.domain.fee11;
import google.registry.model.domain.fee.FeeTransformCommandExtension;
import google.registry.model.domain.fee.FeeTransformCommandExtensionImpl;
import google.registry.model.domain.fee.FeeTransformResponseExtension;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
/** A fee extension that may be present on domain transfer requests. */
@XmlRootElement(name = "transfer")
@XmlType(propOrder = {"currency", "fees", "credits"})
public class FeeTransferCommandExtensionV11
extends FeeTransformCommandExtensionImpl implements FeeTransformCommandExtension {
@Override
public FeeTransformResponseExtension.Builder createResponseBuilder() {
return new FeeTransferResponseExtensionV11.Builder();
}
}

View file

@ -12,9 +12,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.model.domain.fee;
package google.registry.model.domain.fee11;
import google.registry.model.eppoutput.EppResponse.ResponseExtension;
import google.registry.model.domain.fee.FeeTransformResponseExtensionImpl;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
@ -23,10 +23,9 @@ import javax.xml.bind.annotation.XmlType;
* domain transfer requests.
*/
@XmlRootElement(name = "trnData")
@XmlType(propOrder = {"currency", "fee"})
public class FeeTransferResponseExtension extends BaseFeeCommandResponse
implements ResponseExtension {
/** A builder for {@link FeeTransferResponseExtension}. */
@XmlType(propOrder = {"currency", "fees", "credits"})
public class FeeTransferResponseExtensionV11 extends FeeTransformResponseExtensionImpl {
/** A builder for {@link FeeTransferResponseExtensionV11}. */
public static class Builder
extends BaseFeeCommandResponse.Builder<FeeTransferResponseExtension, Builder> {}
extends FeeTransformResponseExtensionImpl.Builder<FeeTransferResponseExtensionV11, Builder> {}
}

View file

@ -0,0 +1,33 @@
// Copyright 2016 The Domain Registry Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.model.domain.fee11;
import google.registry.model.domain.fee.FeeTransformCommandExtension;
import google.registry.model.domain.fee.FeeTransformCommandExtensionImpl;
import google.registry.model.domain.fee.FeeTransformResponseExtension;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
/** A fee extension that may be present on domain update commands. */
@XmlRootElement(name = "update")
@XmlType(propOrder = {"currency", "fees", "credits"})
public class FeeUpdateCommandExtensionV11
extends FeeTransformCommandExtensionImpl implements FeeTransformCommandExtension {
@Override
public FeeTransformResponseExtension.Builder createResponseBuilder() {
return new FeeUpdateResponseExtensionV11.Builder();
}
}

View file

@ -12,9 +12,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.model.domain.fee;
package google.registry.model.domain.fee11;
import google.registry.model.eppoutput.EppResponse.ResponseExtension;
import google.registry.model.domain.fee.FeeTransformResponseExtensionImpl;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
@ -23,10 +23,9 @@ import javax.xml.bind.annotation.XmlType;
* domain update commands.
*/
@XmlRootElement(name = "updData")
@XmlType(propOrder = {"currency", "fee"})
public class FeeUpdateResponseExtension extends BaseFeeCommandResponse
implements ResponseExtension {
/** A builder for {@link FeeUpdateResponseExtension}. */
@XmlType(propOrder = {"currency", "fees", "credits"})
public class FeeUpdateResponseExtensionV11 extends FeeTransformResponseExtensionImpl {
/** A builder for {@link FeeUpdateResponseExtensionV11}. */
public static class Builder
extends BaseFeeCommandResponse.Builder<FeeUpdateResponseExtension, Builder> {}
extends FeeTransformResponseExtensionImpl.Builder<FeeUpdateResponseExtensionV11, Builder> {}
}

View file

@ -0,0 +1,30 @@
// Copyright 2016 The Domain Registry Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
@XmlSchema(
namespace = "urn:ietf:params:xml:ns:fee-0.11",
xmlns = @XmlNs(prefix = "fee11", namespaceURI = "urn:ietf:params:xml:ns:fee-0.11"),
elementFormDefault = XmlNsForm.QUALIFIED)
@XmlAccessorType(XmlAccessType.FIELD)
@XmlJavaTypeAdapter(CurrencyUnitAdapter.class)
package google.registry.model.domain.fee11;
import google.registry.model.translators.CurrencyUnitAdapter;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlNs;
import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

View file

@ -22,12 +22,16 @@ import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import google.registry.model.domain.allocate.AllocateCreateExtension;
import google.registry.model.domain.fee.FeeCheckExtension;
import google.registry.model.domain.fee06.FeeCheckCommandExtensionV06;
import google.registry.model.domain.fee06.FeeCheckResponseExtensionV06;
import google.registry.model.domain.fee11.FeeCheckCommandExtensionV11;
import google.registry.model.domain.fee11.FeeCheckResponseExtensionV11;
import google.registry.model.domain.launch.LaunchCreateExtension;
import google.registry.model.domain.metadata.MetadataExtension;
import google.registry.model.domain.rgp.RgpUpdateExtension;
import google.registry.model.domain.secdns.SecDnsCreateExtension;
import google.registry.model.eppinput.EppInput.CommandExtension;
import google.registry.model.eppoutput.EppResponse.ResponseExtension;
import java.util.EnumSet;
import java.util.Set;
import javax.xml.bind.annotation.XmlSchema;
@ -45,21 +49,37 @@ public class ProtocolDefinition {
/** Enums repesenting valid service extensions that are recognized by the server. */
public enum ServiceExtension {
LAUNCH_EXTENSION_1_0(LaunchCreateExtension.class, true),
REDEMPTION_GRACE_PERIOD_1_0(RgpUpdateExtension.class, true),
SECURE_DNS_1_1(SecDnsCreateExtension.class, true),
FEE_0_6(FeeCheckExtension.class, true),
ALLOCATE_1_0(AllocateCreateExtension.class, false),
METADATA_1_0(MetadataExtension.class, false);
LAUNCH_EXTENSION_1_0(LaunchCreateExtension.class, null, true),
REDEMPTION_GRACE_PERIOD_1_0(RgpUpdateExtension.class, null, true),
SECURE_DNS_1_1(SecDnsCreateExtension.class, null, true),
FEE_0_6(FeeCheckCommandExtensionV06.class, FeeCheckResponseExtensionV06.class, true),
FEE_0_11(FeeCheckCommandExtensionV11.class, FeeCheckResponseExtensionV11.class, true),
ALLOCATE_1_0(AllocateCreateExtension.class, null, false),
METADATA_1_0(MetadataExtension.class, null, false);
private final Class<? extends CommandExtension> commandExtensionClass;
private final Class<? extends ResponseExtension> responseExtensionClass;
private String uri;
private boolean visible;
ServiceExtension(Class<? extends CommandExtension> clazz, boolean visible) {
this.uri = getCommandExtensionUri(clazz);
ServiceExtension(
Class<? extends CommandExtension> commandExtensionClass,
Class<? extends ResponseExtension> responseExtensionClass,
boolean visible) {
this.commandExtensionClass = commandExtensionClass;
this.responseExtensionClass = responseExtensionClass;
this.uri = getCommandExtensionUri(commandExtensionClass);
this.visible = visible;
}
public Class<? extends CommandExtension> getCommandExtensionClass() {
return commandExtensionClass;
}
public Class<? extends ResponseExtension> getResponseExtensionClass() {
return responseExtensionClass;
}
public String getUri() {
return uri;
}

View file

@ -17,6 +17,7 @@ package google.registry.model.eppinput;
import static google.registry.util.CollectionUtils.nullSafeImmutableCopy;
import static google.registry.util.CollectionUtils.nullToEmptyImmutableCopy;
import com.google.common.base.Optional;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
@ -24,12 +25,17 @@ import google.registry.model.ImmutableObject;
import google.registry.model.contact.ContactCommand;
import google.registry.model.domain.DomainCommand;
import google.registry.model.domain.allocate.AllocateCreateExtension;
import google.registry.model.domain.fee.FeeCheckExtension;
import google.registry.model.domain.fee.FeeCreateExtension;
import google.registry.model.domain.fee.FeeInfoExtension;
import google.registry.model.domain.fee.FeeRenewExtension;
import google.registry.model.domain.fee.FeeTransferExtension;
import google.registry.model.domain.fee.FeeUpdateExtension;
import google.registry.model.domain.fee06.FeeCheckCommandExtensionV06;
import google.registry.model.domain.fee06.FeeCreateCommandExtensionV06;
import google.registry.model.domain.fee06.FeeInfoCommandExtensionV06;
import google.registry.model.domain.fee06.FeeRenewCommandExtensionV06;
import google.registry.model.domain.fee06.FeeTransferCommandExtensionV06;
import google.registry.model.domain.fee06.FeeUpdateCommandExtensionV06;
import google.registry.model.domain.fee11.FeeCheckCommandExtensionV11;
import google.registry.model.domain.fee11.FeeCreateCommandExtensionV11;
import google.registry.model.domain.fee11.FeeRenewCommandExtensionV11;
import google.registry.model.domain.fee11.FeeTransferCommandExtensionV11;
import google.registry.model.domain.fee11.FeeUpdateCommandExtensionV11;
import google.registry.model.domain.launch.LaunchCheckExtension;
import google.registry.model.domain.launch.LaunchCreateExtension;
import google.registry.model.domain.launch.LaunchDeleteExtension;
@ -44,6 +50,7 @@ import google.registry.model.eppinput.ResourceCommand.SingleResourceCommand;
import google.registry.model.host.HostCommand;
import java.util.List;
import java.util.Set;
import javax.annotation.Nullable;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementRef;
@ -90,10 +97,39 @@ public class EppInput extends ImmutableObject {
}
/** Get the extension based on type, or null. If there are multiple, it chooses the first. */
@Nullable
public <E extends CommandExtension> E getSingleExtension(Class<E> clazz) {
return FluentIterable.from(getCommandWrapper().getExtensions()).filter(clazz).first().orNull();
}
/** Get the extension based on type, or null, chosen from a list of possible extension classes.
* If there are extensions matching multiple classes, the first class listed is chosen. If there
* are multiple extensions of the same class, the first extension of that class is chosen
* (assuming that an extension matching a preceding class was not already chosen). This method is
* used to support multiple versions of an extension. Specify all supported versions, starting
* with the latest. The first-occurring extension of the latest version will be chosen, or failing
* that the first-occurring extension of the previous version, and so on.
*/
@Nullable
public <E extends CommandExtension>
E getFirstExtensionOfClasses(ImmutableList<Class<? extends E>> classes) {
for (Class<? extends E> clazz : classes) {
Optional<? extends E> extension = FluentIterable.from(
getCommandWrapper().getExtensions()).filter(clazz).first();
if (extension.isPresent()) {
return extension.get();
}
}
return null;
}
@SafeVarargs
@Nullable
public final <E extends CommandExtension>
E getFirstExtensionOfClasses(Class<? extends E>... classes) {
return getFirstExtensionOfClasses(ImmutableList.copyOf(classes));
}
/** A tag that goes inside of an EPP {@literal <command>}. */
public static class InnerCommand extends ImmutableObject {}
@ -260,13 +296,22 @@ public class EppInput extends ImmutableObject {
/** Zero or more command extensions. */
@XmlElementRefs({
// allocate create extension
@XmlElementRef(type = AllocateCreateExtension.class),
@XmlElementRef(type = FeeCheckExtension.class),
@XmlElementRef(type = FeeCreateExtension.class),
@XmlElementRef(type = FeeInfoExtension.class),
@XmlElementRef(type = FeeRenewExtension.class),
@XmlElementRef(type = FeeTransferExtension.class),
@XmlElementRef(type = FeeUpdateExtension.class),
// fee extension version 0.6
@XmlElementRef(type = FeeCheckCommandExtensionV06.class),
@XmlElementRef(type = FeeInfoCommandExtensionV06.class),
@XmlElementRef(type = FeeCreateCommandExtensionV06.class),
@XmlElementRef(type = FeeRenewCommandExtensionV06.class),
@XmlElementRef(type = FeeTransferCommandExtensionV06.class),
@XmlElementRef(type = FeeUpdateCommandExtensionV06.class),
// fee extension version 0.11
@XmlElementRef(type = FeeCheckCommandExtensionV11.class),
@XmlElementRef(type = FeeCreateCommandExtensionV11.class),
@XmlElementRef(type = FeeRenewCommandExtensionV11.class),
@XmlElementRef(type = FeeTransferCommandExtensionV11.class),
@XmlElementRef(type = FeeUpdateCommandExtensionV11.class),
// other extensions
@XmlElementRef(type = LaunchCheckExtension.class),
@XmlElementRef(type = LaunchCreateExtension.class),
@XmlElementRef(type = LaunchDeleteExtension.class),

View file

@ -14,6 +14,7 @@
package google.registry.model.eppoutput;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableList;
import google.registry.model.Buildable;
import google.registry.model.ImmutableObject;
@ -21,13 +22,19 @@ import google.registry.model.contact.ContactResource;
import google.registry.model.domain.DomainApplication;
import google.registry.model.domain.DomainRenewData;
import google.registry.model.domain.DomainResource;
import google.registry.model.domain.fee.FeeCheckResponseExtension;
import google.registry.model.domain.fee.FeeCreateResponseExtension;
import google.registry.model.domain.fee.FeeDeleteResponseExtension;
import google.registry.model.domain.fee.FeeInfoResponseExtension;
import google.registry.model.domain.fee.FeeRenewResponseExtension;
import google.registry.model.domain.fee.FeeTransferResponseExtension;
import google.registry.model.domain.fee.FeeUpdateResponseExtension;
import google.registry.model.domain.fee06.FeeCheckResponseExtensionV06;
import google.registry.model.domain.fee06.FeeCreateResponseExtensionV06;
import google.registry.model.domain.fee06.FeeDeleteResponseExtensionV06;
import google.registry.model.domain.fee06.FeeInfoResponseExtensionV06;
import google.registry.model.domain.fee06.FeeRenewResponseExtensionV06;
import google.registry.model.domain.fee06.FeeTransferResponseExtensionV06;
import google.registry.model.domain.fee06.FeeUpdateResponseExtensionV06;
import google.registry.model.domain.fee11.FeeCheckResponseExtensionV11;
import google.registry.model.domain.fee11.FeeCreateResponseExtensionV11;
import google.registry.model.domain.fee11.FeeDeleteResponseExtensionV11;
import google.registry.model.domain.fee11.FeeRenewResponseExtensionV11;
import google.registry.model.domain.fee11.FeeTransferResponseExtensionV11;
import google.registry.model.domain.fee11.FeeUpdateResponseExtensionV11;
import google.registry.model.domain.launch.LaunchCheckResponseExtension;
import google.registry.model.domain.launch.LaunchCreateResponseExtension;
import google.registry.model.domain.launch.LaunchInfoResponseExtension;
@ -120,13 +127,19 @@ public class EppResponse extends ImmutableObject implements ResponseOrGreeting {
/** Zero or more response extensions. */
@XmlElementRefs({
@XmlElementRef(type = FeeCheckResponseExtension.class),
@XmlElementRef(type = FeeCreateResponseExtension.class),
@XmlElementRef(type = FeeDeleteResponseExtension.class),
@XmlElementRef(type = FeeInfoResponseExtension.class),
@XmlElementRef(type = FeeRenewResponseExtension.class),
@XmlElementRef(type = FeeTransferResponseExtension.class),
@XmlElementRef(type = FeeUpdateResponseExtension.class),
@XmlElementRef(type = FeeCheckResponseExtensionV06.class),
@XmlElementRef(type = FeeInfoResponseExtensionV06.class),
@XmlElementRef(type = FeeCreateResponseExtensionV06.class),
@XmlElementRef(type = FeeDeleteResponseExtensionV06.class),
@XmlElementRef(type = FeeRenewResponseExtensionV06.class),
@XmlElementRef(type = FeeTransferResponseExtensionV06.class),
@XmlElementRef(type = FeeUpdateResponseExtensionV06.class),
@XmlElementRef(type = FeeCheckResponseExtensionV11.class),
@XmlElementRef(type = FeeCreateResponseExtensionV11.class),
@XmlElementRef(type = FeeDeleteResponseExtensionV11.class),
@XmlElementRef(type = FeeRenewResponseExtensionV11.class),
@XmlElementRef(type = FeeTransferResponseExtensionV11.class),
@XmlElementRef(type = FeeUpdateResponseExtensionV11.class),
@XmlElementRef(type = LaunchCheckResponseExtension.class),
@XmlElementRef(type = LaunchCreateResponseExtension.class),
@XmlElementRef(type = LaunchInfoResponseExtension.class),
@ -150,7 +163,31 @@ public class EppResponse extends ImmutableObject implements ResponseOrGreeting {
public ImmutableList<? extends ResponseExtension> getExtensions() {
return extensions;
}
@Nullable
public ResponseExtension getFirstExtensionOfType(Class<? extends ResponseExtension> clazz) {
return FluentIterable.from(extensions).filter(clazz).first().orNull();
}
@Nullable
public ResponseExtension
getFirstExtensionOfType(ImmutableList<Class<? extends ResponseExtension>> classes) {
for (Class<? extends ResponseExtension> clazz : classes) {
ResponseExtension extension = getFirstExtensionOfType(clazz);
if (extension != null) {
return extension;
}
}
return null;
}
@SafeVarargs
@Nullable
public final ResponseExtension
getFirstExtensionOfType(Class<? extends ResponseExtension>... classes) {
return getFirstExtensionOfType(ImmutableList.copyOf(classes));
}
public Result getResult() {
return result;
}

View file

@ -18,6 +18,7 @@ import static com.google.common.base.Predicates.not;
import static com.google.common.collect.Maps.toMap;
import static google.registry.flows.EppXmlTransformer.unmarshal;
import static google.registry.flows.picker.FlowPicker.getFlowClass;
import static google.registry.model.domain.fee.Fee.FEE_CREATE_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.util.CollectionUtils.isNullOrEmpty;
import static google.registry.util.DomainNameUtils.ACE_PREFIX;
@ -57,7 +58,6 @@ import google.registry.flows.host.HostCreateFlow;
import google.registry.flows.host.HostDeleteFlow;
import google.registry.flows.host.HostUpdateFlow;
import google.registry.model.domain.DomainCommand;
import google.registry.model.domain.fee.FeeCreateExtension;
import google.registry.model.domain.launch.LaunchCreateExtension;
import google.registry.model.domain.secdns.SecDnsCreateExtension;
import google.registry.model.domain.secdns.SecDnsUpdateExtension;
@ -143,7 +143,8 @@ public class VerifyOteAction implements Runnable, JsonAction {
private static final Predicate<EppInput> HAS_FEE = new Predicate<EppInput>() {
@Override
public boolean apply(@Nonnull EppInput eppInput) {
return eppInput.getSingleExtension(FeeCreateExtension.class) != null;
return eppInput.getFirstExtensionOfClasses(
FEE_CREATE_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER) != null;
}};
private static final Predicate<EppInput> HAS_SEC_DNS = new Predicate<EppInput>() {

View file

@ -42,6 +42,8 @@ public class XjcXmlTransformer {
.put("mark", "mark.xsd")
.put("dsig", "dsig.xsd")
.put("smd", "smd.xsd")
.put("fee06", "fee06.xsd")
.put("fee11", "fee11.xsd")
.put("launch", "launch.xsd")
.put("rde", "rde.xsd")
.put("rdeheader", "rde-header.xsd")

View file

@ -137,6 +137,24 @@
</nameXmlTransform>
</schemaBindings>
</bindings>
<bindings schemaLocation="fee06.xsd" node="/xsd:schema">
<schemaBindings>
<package name="google.registry.xjc.fee06"/>
<nameXmlTransform>
<elementName prefix="XjcFee06"/>
<typeName prefix="XjcFee06"/>
</nameXmlTransform>
</schemaBindings>
</bindings>
<bindings schemaLocation="fee11.xsd" node="/xsd:schema">
<schemaBindings>
<package name="google.registry.xjc.fee11"/>
<nameXmlTransform>
<elementName prefix="XjcFee11"/>
<typeName prefix="XjcFee11"/>
</nameXmlTransform>
</schemaBindings>
</bindings>
<bindings schemaLocation="launch.xsd" node="/xsd:schema">
<schemaBindings>
<package name="google.registry.xjc.launch"/>

View file

@ -1,4 +1,3 @@
# converted from extension //java/google/registry/xjc:generated_files
#
# .'``'. ...
# :o o `....'` ;
@ -15,7 +14,7 @@
# (bindings.xjb), you must regenerate this file with the following commands:
#
# bazel run java/google/registry/xjc:list_generated_files | tee /tmp/lol
# mv /tmp/lol java/google/registry/xjc/generated_files
# mv /tmp/lol java/google/registry/xjc/generated_files.bzl
#
pkginfo_generated_files = [
@ -24,6 +23,8 @@ pkginfo_generated_files = [
"dsig/package-info.java",
"epp/package-info.java",
"eppcom/package-info.java",
"fee06/package-info.java",
"fee11/package-info.java",
"host/package-info.java",
"iirdea/package-info.java",
"launch/package-info.java",
@ -168,6 +169,45 @@ xjc_generated_files = [
"eppcom/XjcEppcomPwAuthInfoType.java",
"eppcom/XjcEppcomReasonType.java",
"eppcom/XjcEppcomTrStatusType.java",
"fee06/ObjectFactory.java",
"fee06/XjcFee06Check.java",
"fee06/XjcFee06ChkData.java",
"fee06/XjcFee06CommandType.java",
"fee06/XjcFee06CreData.java",
"fee06/XjcFee06Create.java",
"fee06/XjcFee06CreditType.java",
"fee06/XjcFee06DelData.java",
"fee06/XjcFee06DomainCDType.java",
"fee06/XjcFee06DomainCheckType.java",
"fee06/XjcFee06FeeType.java",
"fee06/XjcFee06InfData.java",
"fee06/XjcFee06Info.java",
"fee06/XjcFee06RenData.java",
"fee06/XjcFee06Renew.java",
"fee06/XjcFee06Transfer.java",
"fee06/XjcFee06TransformCommandType.java",
"fee06/XjcFee06TransformResultType.java",
"fee06/XjcFee06TrnData.java",
"fee06/XjcFee06UpdData.java",
"fee06/XjcFee06Update.java",
"fee11/ObjectFactory.java",
"fee11/XjcFee11Check.java",
"fee11/XjcFee11ChkData.java",
"fee11/XjcFee11CommandType.java",
"fee11/XjcFee11CreData.java",
"fee11/XjcFee11Create.java",
"fee11/XjcFee11CreditType.java",
"fee11/XjcFee11DelData.java",
"fee11/XjcFee11FeeType.java",
"fee11/XjcFee11ObjectCDType.java",
"fee11/XjcFee11RenData.java",
"fee11/XjcFee11Renew.java",
"fee11/XjcFee11Transfer.java",
"fee11/XjcFee11TransformCommandType.java",
"fee11/XjcFee11TransformResultType.java",
"fee11/XjcFee11TrnData.java",
"fee11/XjcFee11UpdData.java",
"fee11/XjcFee11Update.java",
"host/ObjectFactory.java",
"host/XjcHostAddRemType.java",
"host/XjcHostAddrType.java",

View file

@ -33,6 +33,8 @@ create domain urn:ietf:params:xml:ns:domain-1.0
create dsig http://www.w3.org/2000/09/xmldsig#
create epp urn:ietf:params:xml:ns:epp-1.0
create eppcom urn:ietf:params:xml:ns:eppcom-1.0
create fee06 urn:ietf:params:xml:ns:fee-0.6
create fee11 urn:ietf:params:xml:ns:fee-0.11
create host urn:ietf:params:xml:ns:host-1.0
create iirdea urn:ietf:params:xml:ns:iirdea-1.0
create launch urn:ietf:params:xml:ns:launch-1.0

View file

@ -18,6 +18,12 @@
@javax.xml.bind.annotation.XmlNs(
prefix = "dsig",
namespaceURI = "http://www.w3.org/2000/09/xmldsig#"),
@javax.xml.bind.annotation.XmlNs(
prefix = "fee06",
namespaceURI = "urn:ietf:params:xml:ns:fee-0.6"),
@javax.xml.bind.annotation.XmlNs(
prefix = "fee11",
namespaceURI = "urn:ietf:params:xml:ns:fee-0.11"),
@javax.xml.bind.annotation.XmlNs(
prefix = "host",
namespaceURI = "urn:ietf:params:xml:ns:host-1.0"),

View file

@ -0,0 +1,211 @@
<?xml version="1.0" encoding="utf-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:fee="urn:ietf:params:xml:ns:fee-0.11"
xmlns:eppcom="urn:ietf:params:xml:ns:eppcom-1.0"
xmlns:domain="urn:ietf:params:xml:ns:domain-1.0"
targetNamespace="urn:ietf:params:xml:ns:fee-0.11"
elementFormDefault="qualified">
<import namespace="urn:ietf:params:xml:ns:eppcom-1.0" />
<import namespace="urn:ietf:params:xml:ns:domain-1.0" />
<annotation>
<documentation>Extensible Provisioning Protocol
v1.0 extension schema for fee
information.</documentation>
</annotation>
<!--
Child elements found in EPP commands and responses
-->
<element name="check" type="fee:checkType" />
<element name="chkData" type="fee:chkDataType" />
<element name="create" type="fee:transformCommandType" />
<element name="creData" type="fee:transformResultType" />
<element name="renew" type="fee:transformCommandType" />
<element name="renData" type="fee:transformResultType" />
<element name="transfer" type="fee:transformCommandType" />
<element name="trnData" type="fee:transferResultType" />
<element name="update" type="fee:transformCommandType" />
<element name="updData" type="fee:transformResultType" />
<element name="delData" type="fee:deleteDataType" />
<!--
client <check> command
-->
<complexType name="checkType">
<sequence>
<element name="command" type="fee:commandType" />
<element name="currency" type="fee:currencyType"
minOccurs="0" />
<element name="period" type="domain:periodType"
minOccurs="0" />
<element name="class" type="token"
minOccurs="0" />
</sequence>
</complexType>
<!--
server <check> result
-->
<complexType name="chkDataType">
<sequence>
<element name="cd" type="fee:objectCDType"
maxOccurs="unbounded" />
</sequence>
</complexType>
<complexType name="objectCDType">
<sequence>
<element name="object">
<complexType>
<sequence>
<any namespace="##other" processContents="lax"/>
</sequence>
</complexType>
</element>
<element name="command" type="fee:commandType" />
<element name="currency" type="fee:currencyType" />
<element name="period" type="domain:periodType"
minOccurs="0" maxOccurs="1" />
<element name="fee" type="fee:feeType"
minOccurs="0" maxOccurs="unbounded" />
<element name="credit" type="fee:creditType"
minOccurs="0" maxOccurs="unbounded" />
<element name="class" type="token" minOccurs="0" />
<element name="reason" type="token" minOccurs="0" />
</sequence>
<attribute name="avail" type="boolean" default="1" />
</complexType>
<!--
general transform (create, renew, update, transfer) command
-->
<complexType name="transformCommandType">
<sequence>
<element name="currency" type="fee:currencyType"
minOccurs="0" />
<element name="fee" type="fee:feeType"
maxOccurs="unbounded" />
<element name="credit" type="fee:creditType"
minOccurs="0" maxOccurs="unbounded" />
</sequence>
</complexType>
<!--
general transform (create, renew, update) result
-->
<complexType name="transformResultType">
<sequence>
<element name="currency" type="fee:currencyType" />
<element name="fee" type="fee:feeType"
minOccurs="0" maxOccurs="unbounded" />
<element name="credit" type="fee:creditType"
minOccurs="0" maxOccurs="unbounded" />
<element name="balance" type="fee:balanceType"
minOccurs="0" />
<element name="creditLimit" type="fee:creditLimitType"
minOccurs="0" />
</sequence>
</complexType>
<!--
transfer result
-->
<complexType name="transferResultType">
<sequence>
<element name="currency" type="fee:currencyType" />
<!-- only used op="query" responses -->
<element name="period" type="domain:periodType"
minOccurs="0" />
<element name="fee" type="fee:feeType"
maxOccurs="unbounded" />
<element name="credit" type="fee:creditType"
minOccurs="0" maxOccurs="unbounded" />
</sequence>
</complexType>
<!--
delete result
-->
<complexType name="deleteDataType">
<sequence>
<element name="currency" type="fee:currencyType" />
<element name="credit" type="fee:creditType"
minOccurs="0" maxOccurs="unbounded" />
<element name="balance" type="fee:balanceType"
minOccurs="0" />
<element name="creditLimit" type="fee:creditLimitType"
minOccurs="0" />
</sequence>
</complexType>
<!--
common types
-->
<simpleType name="currencyType">
<restriction base="string">
<pattern value="[A-Z]{3}" />
</restriction>
</simpleType>
<complexType name="commandType">
<simpleContent>
<extension base="fee:commandTypeValue">
<attribute name="phase" type="token" />
<attribute name="subphase" type="token" />
</extension>
</simpleContent>
</complexType>
<simpleType name="commandTypeValue">
<restriction base="token">
<minLength value="3"/>
<maxLength value="16"/>
</restriction>
</simpleType>
<simpleType name="nonNegativeDecimal">
<restriction base="decimal">
<minInclusive value="0" />
</restriction>
</simpleType>
<simpleType name="negativeDecimal">
<restriction base="decimal">
<maxInclusive value="0" />
</restriction>
</simpleType>
<complexType name="feeType">
<simpleContent>
<extension base="fee:nonNegativeDecimal">
<attribute name="description"/>
<attribute name="refundable" type="boolean" />
<attribute name="grace-period" type="duration" />
<attribute name="applied" default="immediate">
<simpleType>
<restriction base="token">
<enumeration value="immediate" />
<enumeration value="delayed" />
</restriction>
</simpleType>
</attribute>
</extension>
</simpleContent>
</complexType>
<complexType name="creditType">
<simpleContent>
<extension base="fee:negativeDecimal">
<attribute name="description"/>
</extension>
</simpleContent>
</complexType>
<simpleType name="balanceType">
<restriction base="decimal" />
</simpleType>
<simpleType name="creditLimitType">
<restriction base="decimal" />
</simpleType>
</schema>

View file

@ -50,6 +50,7 @@ import google.registry.testing.FakeClock;
import google.registry.testing.FakeHttpSession;
import google.registry.testing.InjectRule;
import google.registry.testing.ShardableTestCase;
import google.registry.testing.TestDataHelper;
import google.registry.util.TypeUtils.TypeInstantiator;
import google.registry.xml.ValidationMode;
import java.util.List;
@ -115,6 +116,10 @@ public abstract class FlowTestCase<F extends Flow> extends ShardableTestCase {
return readResourceUtf8(getClass(), "testdata/" + filename);
}
protected String readFile(String filename, Map<String, String> substitutions) {
return TestDataHelper.loadFileWithSubstitutions(getClass(), filename, substitutions);
}
protected String getClientTrid() throws Exception {
return eppLoader.getEpp().getCommandWrapper().getClTrid();
}

View file

@ -165,14 +165,36 @@ public class DomainApplicationCreateFlowTest
private void doSuccessfulTest(String responseXmlFile, boolean sunriseApplication)
throws Exception {
doSuccessfulTest(responseXmlFile, sunriseApplication, 1);
doSuccessfulTest(responseXmlFile, sunriseApplication, 1, null, null);
}
private void doSuccessfulTest(String responseXmlFile, boolean sunriseApplication, int years)
private void doSuccessfulTest(
String responseXmlFile, boolean sunriseApplication, int years)
throws Exception {
doSuccessfulTest(responseXmlFile, sunriseApplication, years, null, null);
}
private void doSuccessfulTest(
String responseXmlFile,
boolean sunriseApplication,
String feeExtensionVersion,
String feeExtensionNamespace) throws Exception {
doSuccessfulTest(
responseXmlFile, sunriseApplication, 1, feeExtensionVersion, feeExtensionNamespace);
}
private void doSuccessfulTest(
String responseXmlFile,
boolean sunriseApplication,
int years, String feeExtensionVersion,
String feeExtensionNamespace) throws Exception {
assertTransactionalFlow(true);
runFlowAssertResponse(
readFile(responseXmlFile),
(feeExtensionVersion == null)
? readFile(responseXmlFile)
: readFile(
responseXmlFile,
ImmutableMap.of("FEE_VERSION", feeExtensionVersion, "FEE_NS", feeExtensionNamespace)),
"epp.response.extension.creData.applicationID",
"epp.response.resData.creData.crDate");
// Check that the domain application was created and persisted with a history entry.
@ -440,50 +462,101 @@ public class DomainApplicationCreateFlowTest
}
@Test
public void testSuccess_landrushApplicationWithFee() throws Exception {
public void testSuccess_landrushApplicationWithFee_v06() throws Exception {
createTld("tld", TldState.LANDRUSH);
setEppInput("domain_create_landrush_fee.xml");
setEppInput("domain_create_landrush_fee.xml", ImmutableMap.of("FEE_VERSION", "0.6"));
persistContactsAndHosts();
clock.advanceOneMilli();
doSuccessfulTest("domain_create_landrush_fee_response.xml", false);
doSuccessfulTest("domain_create_landrush_fee_response.xml", false, "0.6", "fee");
}
@Test
public void testSuccess_landrushApplicationWithFee_withDefaultAttributes() throws Exception {
public void testSuccess_landrushApplicationWithFee_v11() throws Exception {
createTld("tld", TldState.LANDRUSH);
setEppInput("domain_create_landrush_fee_defaults.xml");
setEppInput("domain_create_landrush_fee.xml", ImmutableMap.of("FEE_VERSION", "0.11"));
persistContactsAndHosts();
clock.advanceOneMilli();
doSuccessfulTest("domain_create_landrush_fee_response.xml", false);
doSuccessfulTest("domain_create_landrush_fee_response.xml", false, "0.11", "fee11");
}
@Test
public void testFailure_landrushApplicationWithRefundableFee() throws Exception {
public void testSuccess_landrushApplicationWithFee_withDefaultAttributes_v06() throws Exception {
createTld("tld", TldState.LANDRUSH);
setEppInput("domain_create_landrush_fee_defaults.xml", ImmutableMap.of("FEE_VERSION", "0.6"));
persistContactsAndHosts();
clock.advanceOneMilli();
doSuccessfulTest("domain_create_landrush_fee_response.xml", false, "0.6", "fee");
}
@Test
public void testSuccess_landrushApplicationWithFee_withDefaultAttributes_v11() throws Exception {
createTld("tld", TldState.LANDRUSH);
setEppInput("domain_create_landrush_fee_defaults.xml", ImmutableMap.of("FEE_VERSION", "0.11"));
persistContactsAndHosts();
clock.advanceOneMilli();
doSuccessfulTest("domain_create_landrush_fee_response.xml", false, "0.11", "fee11");
}
@Test
public void testFailure_landrushApplicationWithRefundableFee_v06() throws Exception {
thrown.expect(UnsupportedFeeAttributeException.class);
createTld("tld", TldState.LANDRUSH);
persistContactsAndHosts();
clock.advanceOneMilli();
setEppInput("domain_create_landrush_fee_refundable.xml");
setEppInput("domain_create_landrush_fee_refundable.xml", ImmutableMap.of("FEE_VERSION", "0.6"));
runFlow();
}
@Test
public void testFailure_landrushApplicationWithGracePeriodFee() throws Exception {
public void testFailure_landrushApplicationWithRefundableFee_v11() throws Exception {
thrown.expect(UnsupportedFeeAttributeException.class);
createTld("tld", TldState.LANDRUSH);
persistContactsAndHosts();
clock.advanceOneMilli();
setEppInput("domain_create_landrush_fee_grace_period.xml");
setEppInput(
"domain_create_landrush_fee_refundable.xml", ImmutableMap.of("FEE_VERSION", "0.11"));
runFlow();
}
@Test
public void testFailure_landrushApplicationWithAppliedFee() throws Exception {
public void testFailure_landrushApplicationWithGracePeriodFee_v06() throws Exception {
thrown.expect(UnsupportedFeeAttributeException.class);
createTld("tld", TldState.LANDRUSH);
persistContactsAndHosts();
clock.advanceOneMilli();
setEppInput("domain_create_landrush_fee_applied.xml");
setEppInput(
"domain_create_landrush_fee_grace_period.xml", ImmutableMap.of("FEE_VERSION", "0.6"));
runFlow();
}
@Test
public void testFailure_landrushApplicationWithGracePeriodFee_v11() throws Exception {
thrown.expect(UnsupportedFeeAttributeException.class);
createTld("tld", TldState.LANDRUSH);
persistContactsAndHosts();
clock.advanceOneMilli();
setEppInput(
"domain_create_landrush_fee_grace_period.xml", ImmutableMap.of("FEE_VERSION", "0.11"));
runFlow();
}
@Test
public void testFailure_landrushApplicationWithAppliedFee_v06() throws Exception {
thrown.expect(UnsupportedFeeAttributeException.class);
createTld("tld", TldState.LANDRUSH);
persistContactsAndHosts();
clock.advanceOneMilli();
setEppInput("domain_create_landrush_fee_applied.xml", ImmutableMap.of("FEE_VERSION", "0.6"));
runFlow();
}
@Test
public void testFailure_landrushApplicationWithAppliedFee_v11() throws Exception {
thrown.expect(UnsupportedFeeAttributeException.class);
createTld("tld", TldState.LANDRUSH);
persistContactsAndHosts();
clock.advanceOneMilli();
setEppInput("domain_create_landrush_fee_applied.xml", ImmutableMap.of("FEE_VERSION", "0.11"));
runFlow();
}
@ -1115,10 +1188,10 @@ public class DomainApplicationCreateFlowTest
}
@Test
public void testFailure_wrongFeeLandrushApplication() throws Exception {
public void testFailure_wrongFeeLandrushApplication_v06() throws Exception {
thrown.expect(FeesMismatchException.class);
createTld("tld", TldState.LANDRUSH);
setEppInput("domain_create_landrush_fee.xml");
setEppInput("domain_create_landrush_fee.xml", ImmutableMap.of("FEE_VERSION", "0.6"));
persistResource(
Registry.get("tld").asBuilder().setCreateBillingCost(Money.of(USD, 20)).build());
persistContactsAndHosts();
@ -1127,10 +1200,22 @@ public class DomainApplicationCreateFlowTest
}
@Test
public void testFailure_wrongCurrency() throws Exception {
public void testFailure_wrongFeeLandrushApplication_v11() throws Exception {
thrown.expect(FeesMismatchException.class);
createTld("tld", TldState.LANDRUSH);
setEppInput("domain_create_landrush_fee.xml", ImmutableMap.of("FEE_VERSION", "0.11"));
persistResource(
Registry.get("tld").asBuilder().setCreateBillingCost(Money.of(USD, 20)).build());
persistContactsAndHosts();
clock.advanceOneMilli();
runFlow();
}
@Test
public void testFailure_wrongCurrency_v06() throws Exception {
thrown.expect(CurrencyUnitMismatchException.class);
createTld("tld", TldState.LANDRUSH);
setEppInput("domain_create_landrush_fee.xml");
setEppInput("domain_create_landrush_fee.xml", ImmutableMap.of("FEE_VERSION", "0.6"));
persistResource(Registry.get("tld").asBuilder()
.setCurrency(CurrencyUnit.EUR)
.setCreateBillingCost(Money.of(EUR, 13))
@ -1145,10 +1230,38 @@ public class DomainApplicationCreateFlowTest
}
@Test
public void testFailure_feeGivenInWrongScale() throws Exception {
public void testFailure_wrongCurrency_v11() throws Exception {
thrown.expect(CurrencyUnitMismatchException.class);
createTld("tld", TldState.LANDRUSH);
setEppInput("domain_create_landrush_fee.xml", ImmutableMap.of("FEE_VERSION", "0.11"));
persistResource(Registry.get("tld").asBuilder()
.setCurrency(CurrencyUnit.EUR)
.setCreateBillingCost(Money.of(EUR, 13))
.setRestoreBillingCost(Money.of(EUR, 11))
.setRenewBillingCostTransitions(ImmutableSortedMap.of(START_OF_TIME, Money.of(EUR, 7)))
.setEapFeeSchedule(ImmutableSortedMap.of(START_OF_TIME, Money.zero(EUR)))
.setServerStatusChangeBillingCost(Money.of(EUR, 19))
.build());
persistContactsAndHosts();
clock.advanceOneMilli();
runFlow();
}
@Test
public void testFailure_feeGivenInWrongScale_v06() throws Exception {
thrown.expect(CurrencyValueScaleException.class);
createTld("tld", TldState.LANDRUSH);
setEppInput("domain_create_landrush_fee_bad_scale.xml");
setEppInput("domain_create_landrush_fee_bad_scale.xml", ImmutableMap.of("FEE_VERSION", "0.6"));
persistContactsAndHosts();
clock.advanceOneMilli();
runFlow();
}
@Test
public void testFailure_feeGivenInWrongScale_v11() throws Exception {
thrown.expect(CurrencyValueScaleException.class);
createTld("tld", TldState.LANDRUSH);
setEppInput("domain_create_landrush_fee_bad_scale.xml", ImmutableMap.of("FEE_VERSION", "0.11"));
persistContactsAndHosts();
clock.advanceOneMilli();
runFlow();

View file

@ -381,28 +381,73 @@ public class DomainCheckFlowTest
doCheckTest(create(true, "rich.example", null));
}
/** Test multiyear periods and explicitly correct currency and that the avail extension is ok. */
@Test
public void testFeeExtension() throws Exception {
public void testFeeExtension_v06() throws Exception {
persistActiveDomain("example1.tld");
setEppInput("domain_check_fee.xml");
runFlowAssertResponse(readFile("domain_check_fee_response.xml"));
setEppInput("domain_check_fee_v06.xml");
runFlowAssertResponse(readFile("domain_check_fee_response_v06.xml"));
}
/** Test commands for create, renew, transfer and restore with implicit period and currency. */
@Test
public void testFeeExtension_multipleCommands() throws Exception {
setEppInput("domain_check_fee_multiple_commands.xml");
runFlowAssertResponse(readFile("domain_check_fee_multiple_commands_response.xml"));
public void testFeeExtension_v11() throws Exception {
persistActiveDomain("example1.tld");
setEppInput("domain_check_fee_v11.xml");
runFlowAssertResponse(readFile("domain_check_fee_response_v11.xml"));
}
/** Test the same as {@link #testFeeExtension_multipleCommands} with premium labels. */
/**
* Test commands for create, renew, transfer, restore and update with implicit period and
* currency. */
@Test
public void testFeeExtension_premiumLabels() throws Exception {
public void testFeeExtension_multipleCommands_v06() throws Exception {
setEppInput("domain_check_fee_multiple_commands_v06.xml");
runFlowAssertResponse(readFile("domain_check_fee_multiple_commands_response_v06.xml"));
}
// Version 11 cannot have multiple commands.
/** Test the same as {@link #testFeeExtension_multipleCommands_v06} with premium labels. */
@Test
public void testFeeExtension_premiumLabels_v06() throws Exception {
createTld("example");
setEppInput("domain_check_fee_premium.xml");
runFlowAssertResponse(readFile("domain_check_fee_premium_response.xml"));
setEppInput("domain_check_fee_premium_v06.xml");
runFlowAssertResponse(readFile("domain_check_fee_premium_response_v06.xml"));
}
@Test
public void testFeeExtension_premiumLabels_v11_create() throws Exception {
createTld("example");
setEppInput("domain_check_fee_premium_v11_create.xml");
runFlowAssertResponse(readFile("domain_check_fee_premium_response_v11_create.xml"));
}
@Test
public void testFeeExtension_premiumLabels_v11_renew() throws Exception {
createTld("example");
setEppInput("domain_check_fee_premium_v11_renew.xml");
runFlowAssertResponse(readFile("domain_check_fee_premium_response_v11_renew.xml"));
}
@Test
public void testFeeExtension_premiumLabels_v11_transfer() throws Exception {
createTld("example");
setEppInput("domain_check_fee_premium_v11_transfer.xml");
runFlowAssertResponse(readFile("domain_check_fee_premium_response_v11_transfer.xml"));
}
@Test
public void testFeeExtension_premiumLabels_v11_restore() throws Exception {
createTld("example");
setEppInput("domain_check_fee_premium_v11_restore.xml");
runFlowAssertResponse(readFile("domain_check_fee_premium_response_v11_restore.xml"));
}
@Test
public void testFeeExtension_premiumLabels_v11_update() throws Exception {
createTld("example");
setEppInput("domain_check_fee_premium_v11_update.xml");
runFlowAssertResponse(readFile("domain_check_fee_premium_response_v11_update.xml"));
}
@Test
@ -419,84 +464,222 @@ public class DomainCheckFlowTest
/** Test that create fees are properly omitted/classed on names on reserved lists. */
@Test
public void testFeeExtension_reservedName() throws Exception {
public void testFeeExtension_reservedName_v06() throws Exception {
persistResource(Registry.get("tld").asBuilder()
.setReservedLists(createReservedList())
.setPremiumList(persistPremiumList("tld", "premiumcollision,USD 70"))
.build());
setEppInput("domain_check_fee_reserved.xml");
runFlowAssertResponse(readFile("domain_check_fee_reserved_response.xml"));
setEppInput("domain_check_fee_reserved_v06.xml");
runFlowAssertResponse(readFile("domain_check_fee_reserved_response_v06.xml"));
}
/** The tests must be split up for version 11, which allows only one command at a time. */
@Test
public void testFeeExtension_reservedName_v11_create() throws Exception {
persistResource(Registry.get("tld").asBuilder()
.setReservedLists(createReservedList())
.setPremiumList(persistPremiumList("tld", "premiumcollision,USD 70"))
.build());
setEppInput("domain_check_fee_reserved_v11_create.xml");
runFlowAssertResponse(readFile("domain_check_fee_reserved_response_v11_create.xml"));
}
@Test
public void testFeeExtension_feesNotOmittedOnReservedNamesInSunrise() throws Exception {
public void testFeeExtension_reservedName_v11_renew() throws Exception {
persistResource(Registry.get("tld").asBuilder()
.setReservedLists(createReservedList())
.setPremiumList(persistPremiumList("tld", "premiumcollision,USD 70"))
.build());
setEppInput("domain_check_fee_reserved_v11_renew.xml");
runFlowAssertResponse(readFile("domain_check_fee_reserved_response_v11_renew.xml"));
}
@Test
public void testFeeExtension_reservedName_v11_transfer() throws Exception {
persistResource(Registry.get("tld").asBuilder()
.setReservedLists(createReservedList())
.setPremiumList(persistPremiumList("tld", "premiumcollision,USD 70"))
.build());
setEppInput("domain_check_fee_reserved_v11_transfer.xml");
runFlowAssertResponse(readFile("domain_check_fee_reserved_response_v11_transfer.xml"));
}
@Test
public void testFeeExtension_reservedName_v11_restore() throws Exception {
persistResource(Registry.get("tld").asBuilder()
.setReservedLists(createReservedList())
.setPremiumList(persistPremiumList("tld", "premiumcollision,USD 70"))
.build());
setEppInput("domain_check_fee_reserved_v11_restore.xml");
runFlowAssertResponse(readFile("domain_check_fee_reserved_response_v11_restore.xml"));
}
@Test
public void testFeeExtension_feesNotOmittedOnReservedNamesInSunrise_v06() throws Exception {
createTld("tld", TldState.SUNRISE);
persistResource(Registry.get("tld").asBuilder()
.setReservedLists(createReservedList())
.setPremiumList(persistPremiumList("tld", "premiumcollision,USD 70"))
.build());
setEppInput("domain_check_fee_reserved.xml");
runFlowAssertResponse(readFile("domain_check_fee_reserved_sunrise_response.xml"));
setEppInput("domain_check_fee_reserved_v06.xml");
runFlowAssertResponse(readFile("domain_check_fee_reserved_sunrise_response_v06.xml"));
}
@Test
public void testFeeExtension_wrongCurrency() throws Exception {
public void
testFeeExtension_feesNotOmittedOnReservedNamesInSunrise_v11_create() throws Exception {
createTld("tld", TldState.SUNRISE);
persistResource(Registry.get("tld").asBuilder()
.setReservedLists(createReservedList())
.setPremiumList(persistPremiumList("tld", "premiumcollision,USD 70"))
.build());
setEppInput("domain_check_fee_reserved_v11_create.xml");
runFlowAssertResponse(readFile("domain_check_fee_reserved_sunrise_response_v11_create.xml"));
}
@Test
public void
testFeeExtension_feesNotOmittedOnReservedNamesInSunrise_v11_renew() throws Exception {
createTld("tld", TldState.SUNRISE);
persistResource(Registry.get("tld").asBuilder()
.setReservedLists(createReservedList())
.setPremiumList(persistPremiumList("tld", "premiumcollision,USD 70"))
.build());
setEppInput("domain_check_fee_reserved_v11_renew.xml");
runFlowAssertResponse(readFile("domain_check_fee_reserved_sunrise_response_v11_renew.xml"));
}
@Test
public void
testFeeExtension_feesNotOmittedOnReservedNamesInSunrise_v11_transfer() throws Exception {
createTld("tld", TldState.SUNRISE);
persistResource(Registry.get("tld").asBuilder()
.setReservedLists(createReservedList())
.setPremiumList(persistPremiumList("tld", "premiumcollision,USD 70"))
.build());
setEppInput("domain_check_fee_reserved_v11_transfer.xml");
runFlowAssertResponse(readFile("domain_check_fee_reserved_sunrise_response_v11_transfer.xml"));
}
@Test
public void
testFeeExtension_feesNotOmittedOnReservedNamesInSunrise_v11_restore() throws Exception {
createTld("tld", TldState.SUNRISE);
persistResource(Registry.get("tld").asBuilder()
.setReservedLists(createReservedList())
.setPremiumList(persistPremiumList("tld", "premiumcollision,USD 70"))
.build());
setEppInput("domain_check_fee_reserved_v11_restore.xml");
runFlowAssertResponse(readFile("domain_check_fee_reserved_sunrise_response_v11_restore.xml"));
}
@Test
public void testFeeExtension_wrongCurrency_v06() throws Exception {
thrown.expect(CurrencyUnitMismatchException.class);
setEppInput("domain_check_fee_euro.xml");
setEppInput("domain_check_fee_euro_v06.xml");
runFlow();
}
@Test
public void testFeeExtension_periodNotInYears() throws Exception {
public void testFeeExtension_wrongCurrency_v11() throws Exception {
thrown.expect(CurrencyUnitMismatchException.class);
setEppInput("domain_check_fee_euro_v11.xml");
runFlow();
}
@Test
public void testFeeExtension_periodNotInYears_v06() throws Exception {
thrown.expect(BadPeriodUnitException.class);
setEppInput("domain_check_fee_bad_period.xml");
setEppInput("domain_check_fee_bad_period_v06.xml");
runFlow();
}
@Test
public void testFeeExtension_commandWithPhase() throws Exception {
thrown.expect(FeeChecksDontSupportPhasesException.class);
setEppInput("domain_check_fee_command_phase.xml");
public void testFeeExtension_periodNotInYears_v11() throws Exception {
thrown.expect(BadPeriodUnitException.class);
setEppInput("domain_check_fee_bad_period_v11.xml");
runFlow();
}
@Test
public void testFeeExtension_commandSubphase() throws Exception {
public void testFeeExtension_commandWithPhase_v06() throws Exception {
thrown.expect(FeeChecksDontSupportPhasesException.class);
setEppInput("domain_check_fee_command_subphase.xml");
setEppInput("domain_check_fee_command_phase_v06.xml");
runFlow();
}
@Test
public void testFeeExtension_commandWithPhase_v11() throws Exception {
thrown.expect(FeeChecksDontSupportPhasesException.class);
setEppInput("domain_check_fee_command_phase_v11.xml");
runFlow();
}
@Test
public void testFeeExtension_commandSubphase_v06() throws Exception {
thrown.expect(FeeChecksDontSupportPhasesException.class);
setEppInput("domain_check_fee_command_subphase_v06.xml");
runFlow();
}
@Test
public void testFeeExtension_commandSubphase_v11() throws Exception {
thrown.expect(FeeChecksDontSupportPhasesException.class);
setEppInput("domain_check_fee_command_subphase_v11.xml");
runFlow();
}
// This test is only relevant for v06, since domain names are not specified in v11 or v12.
@Test
public void testFeeExtension_feeCheckNotInAvailabilityCheck() throws Exception {
thrown.expect(OnlyCheckedNamesCanBeFeeCheckedException.class);
setEppInput("domain_check_fee_not_in_avail.xml");
runFlow();
}
@Test
public void testFeeExtension_multiyearRestore() throws Exception {
public void testFeeExtension_multiyearRestore_v06() throws Exception {
thrown.expect(RestoresAreAlwaysForOneYearException.class);
setEppInput("domain_check_fee_multiyear_restore.xml");
setEppInput("domain_check_fee_multiyear_restore_v06.xml");
runFlow();
}
@Test
public void testFeeExtension_unknownCommand() throws Exception {
public void testFeeExtension_multiyearRestore_v11() throws Exception {
thrown.expect(RestoresAreAlwaysForOneYearException.class);
setEppInput("domain_check_fee_multiyear_restore_v11.xml");
runFlow();
}
@Test
public void testFeeExtension_unknownCommand_v06() throws Exception {
thrown.expect(UnknownFeeCommandException.class);
setEppInput("domain_check_fee_unknown_command.xml");
setEppInput("domain_check_fee_unknown_command_v06.xml");
runFlow();
}
@Test
public void testFeeExtension_invalidCommand() throws Exception {
public void testFeeExtension_unknownCommand_v11() throws Exception {
thrown.expect(UnknownFeeCommandException.class);
setEppInput("domain_check_fee_invalid_command.xml");
setEppInput("domain_check_fee_unknown_command_v11.xml");
runFlow();
}
@Test
public void testSuccess_eapFeeCheck() throws Exception {
public void testFeeExtension_invalidCommand_v06() throws Exception {
thrown.expect(UnknownFeeCommandException.class);
setEppInput("domain_check_fee_invalid_command_v06.xml");
runFlow();
}
@Test
public void testFeeExtension_invalidCommand_v11() throws Exception {
thrown.expect(UnknownFeeCommandException.class);
setEppInput("domain_check_fee_invalid_command_v11.xml");
runFlow();
}
private void runEapFeeCheckTest(String inputFile, String outputFile) throws Exception {
clock.setTo(DateTime.parse("2010-01-01T10:00:00Z"));
persistActiveDomain("example1.tld");
persistResource(Registry.get("tld").asBuilder()
@ -505,7 +688,18 @@ public class DomainCheckFlowTest
clock.nowUtc().minusDays(1), Money.of(USD, 100),
clock.nowUtc().plusDays(1), Money.of(USD, 0)))
.build());
setEppInput("domain_check_fee.xml");
runFlowAssertResponse(readFile("domain_check_eap_fee_response.xml"));
setEppInput(inputFile);
runFlowAssertResponse(readFile(outputFile));
}
@Test
public void testSuccess_eapFeeCheck_v06() throws Exception {
runEapFeeCheckTest("domain_check_fee_v06.xml", "domain_check_eap_fee_response_v06.xml");
}
@Test
public void testSuccess_eapFeeCheck_v11() throws Exception {
runEapFeeCheckTest("domain_check_fee_v11.xml", "domain_check_eap_fee_response_v11.xml");
}
}

View file

@ -112,6 +112,7 @@ import google.registry.model.registry.Registry;
import google.registry.model.registry.Registry.TldState;
import google.registry.model.reporting.HistoryEntry;
import google.registry.testing.DatastoreHelper;
import java.util.Map;
import org.joda.money.CurrencyUnit;
import org.joda.money.Money;
import org.joda.time.DateTime;
@ -247,12 +248,28 @@ public class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow,
String domainTld,
String responseXmlFile,
UserPrivileges userPrivileges) throws Exception {
doSuccessfulTest(domainTld, responseXmlFile, userPrivileges, ImmutableMap.<String, String>of());
}
private void doSuccessfulTest(
String domainTld,
String responseXmlFile,
UserPrivileges userPrivileges,
Map<String, String> substitutions) throws Exception {
assertTransactionalFlow(true);
runFlowAssertResponse(CommitMode.LIVE, userPrivileges, readFile(responseXmlFile));
runFlowAssertResponse(
CommitMode.LIVE, userPrivileges, readFile(responseXmlFile, substitutions));
assertSuccessfulCreate(domainTld, false);
assertNoLordn();
}
private void doSuccessfulTest(
String domainTld,
String responseXmlFile,
Map<String, String> substitutions) throws Exception {
doSuccessfulTest(domainTld, responseXmlFile, UserPrivileges.NORMAL, substitutions);
}
private void doSuccessfulTest(String domainTld, String responseXmlFile) throws Exception {
doSuccessfulTest(domainTld, responseXmlFile, UserPrivileges.NORMAL);
}
@ -303,39 +320,81 @@ public class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow,
}
@Test
public void testSuccess_fee() throws Exception {
setEppInput("domain_create_fee.xml");
public void testSuccess_fee_v06() throws Exception {
setEppInput("domain_create_fee.xml", ImmutableMap.of("FEE_VERSION", "0.6"));
persistContactsAndHosts();
doSuccessfulTest("tld", "domain_create_response_fee.xml");
doSuccessfulTest(
"tld", "domain_create_response_fee.xml", ImmutableMap.of("FEE_VERSION", "0.6"));
}
@Test
public void testSuccess_fee_withDefaultAttributes() throws Exception {
setEppInput("domain_create_fee_defaults.xml");
public void testSuccess_fee_v11() throws Exception {
setEppInput("domain_create_fee.xml", ImmutableMap.of("FEE_VERSION", "0.11"));
persistContactsAndHosts();
doSuccessfulTest("tld", "domain_create_response_fee.xml");
doSuccessfulTest(
"tld", "domain_create_response_fee.xml", ImmutableMap.of("FEE_VERSION", "0.11"));
}
@Test
public void testFailure_refundableFee() throws Exception {
public void testSuccess_fee_withDefaultAttributes_v06() throws Exception {
setEppInput("domain_create_fee_defaults.xml", ImmutableMap.of("FEE_VERSION", "0.6"));
persistContactsAndHosts();
doSuccessfulTest(
"tld", "domain_create_response_fee.xml", ImmutableMap.of("FEE_VERSION", "0.6"));
}
@Test
public void testSuccess_fee_withDefaultAttributes_v11() throws Exception {
setEppInput("domain_create_fee_defaults.xml", ImmutableMap.of("FEE_VERSION", "0.11"));
persistContactsAndHosts();
doSuccessfulTest(
"tld", "domain_create_response_fee.xml", ImmutableMap.of("FEE_VERSION", "0.11"));
}
@Test
public void testFailure_refundableFee_v06() throws Exception {
thrown.expect(UnsupportedFeeAttributeException.class);
setEppInput("domain_create_fee_refundable.xml");
setEppInput("domain_create_fee_refundable.xml", ImmutableMap.of("FEE_VERSION", "0.6"));
persistContactsAndHosts();
runFlow();
}
@Test
public void testFailure_gracePeriodFee() throws Exception {
public void testFailure_refundableFee_v11() throws Exception {
thrown.expect(UnsupportedFeeAttributeException.class);
setEppInput("domain_create_fee_grace_period.xml");
setEppInput("domain_create_fee_refundable.xml", ImmutableMap.of("FEE_VERSION", "0.11"));
persistContactsAndHosts();
runFlow();
}
@Test
public void testFailure_appliedFee() throws Exception {
public void testFailure_gracePeriodFee_v06() throws Exception {
thrown.expect(UnsupportedFeeAttributeException.class);
setEppInput("domain_create_fee_applied.xml");
setEppInput("domain_create_fee_grace_period.xml", ImmutableMap.of("FEE_VERSION", "0.6"));
persistContactsAndHosts();
runFlow();
}
@Test
public void testFailure_gracePeriodFee_v11() throws Exception {
thrown.expect(UnsupportedFeeAttributeException.class);
setEppInput("domain_create_fee_grace_period.xml", ImmutableMap.of("FEE_VERSION", "0.11"));
persistContactsAndHosts();
runFlow();
}
@Test
public void testFailure_appliedFee_v06() throws Exception {
thrown.expect(UnsupportedFeeAttributeException.class);
setEppInput("domain_create_fee_applied.xml", ImmutableMap.of("FEE_VERSION", "0.6"));
persistContactsAndHosts();
runFlow();
}
@Test
public void testFailure_appliedFee_v11() throws Exception {
thrown.expect(UnsupportedFeeAttributeException.class);
setEppInput("domain_create_fee_applied.xml", ImmutableMap.of("FEE_VERSION", "0.11"));
persistContactsAndHosts();
runFlow();
}
@ -548,18 +607,43 @@ public class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow,
}
@Test
public void testFailure_wrongFeeAmount() throws Exception {
public void testFailure_wrongFeeAmount_v06() throws Exception {
thrown.expect(FeesMismatchException.class);
setEppInput("domain_create_fee.xml");
setEppInput("domain_create_fee.xml", ImmutableMap.of("FEE_VERSION", "0.6"));
persistResource(Registry.get("tld").asBuilder().setCreateBillingCost(Money.of(USD, 20)).build());
persistContactsAndHosts();
runFlow();
}
@Test
public void testFailure_wrongCurrency() throws Exception {
public void testFailure_wrongFeeAmount_v11() throws Exception {
thrown.expect(FeesMismatchException.class);
setEppInput("domain_create_fee.xml", ImmutableMap.of("FEE_VERSION", "0.11"));
persistResource(Registry.get("tld").asBuilder().setCreateBillingCost(Money.of(USD, 20)).build());
persistContactsAndHosts();
runFlow();
}
@Test
public void testFailure_wrongCurrency_v06() throws Exception {
thrown.expect(CurrencyUnitMismatchException.class);
setEppInput("domain_create_fee.xml");
setEppInput("domain_create_fee.xml", ImmutableMap.of("FEE_VERSION", "0.6"));
persistResource(Registry.get("tld").asBuilder()
.setCurrency(CurrencyUnit.EUR)
.setCreateBillingCost(Money.of(EUR, 13))
.setRestoreBillingCost(Money.of(EUR, 11))
.setRenewBillingCostTransitions(ImmutableSortedMap.of(START_OF_TIME, Money.of(EUR, 7)))
.setEapFeeSchedule(ImmutableSortedMap.of(START_OF_TIME, Money.zero(EUR)))
.setServerStatusChangeBillingCost(Money.of(EUR, 19))
.build());
persistContactsAndHosts();
runFlow();
}
@Test
public void testFailure_wrongCurrency_v11() throws Exception {
thrown.expect(CurrencyUnitMismatchException.class);
setEppInput("domain_create_fee.xml", ImmutableMap.of("FEE_VERSION", "0.11"));
persistResource(Registry.get("tld").asBuilder()
.setCurrency(CurrencyUnit.EUR)
.setCreateBillingCost(Money.of(EUR, 13))
@ -979,19 +1063,39 @@ public class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow,
}
@Test
public void testFailure_omitFeeExtensionOnLogin() throws Exception {
public void testFailure_omitFeeExtensionOnLogin_v06() throws Exception {
thrown.expect(UndeclaredServiceExtensionException.class);
removeServiceExtensionUri(ServiceExtension.FEE_0_6.getUri());
removeServiceExtensionUri(ServiceExtension.FEE_0_11.getUri());
createTld("net");
setEppInput("domain_create_fee.xml");
setEppInput("domain_create_fee.xml", ImmutableMap.of("FEE_VERSION", "0.6"));
persistContactsAndHosts();
runFlow();
}
@Test
public void testFailure_feeGivenInWrongScale() throws Exception {
public void testFailure_omitFeeExtensionOnLogin_v11() throws Exception {
thrown.expect(UndeclaredServiceExtensionException.class);
removeServiceExtensionUri(ServiceExtension.FEE_0_6.getUri());
removeServiceExtensionUri(ServiceExtension.FEE_0_11.getUri());
createTld("net");
setEppInput("domain_create_fee.xml", ImmutableMap.of("FEE_VERSION", "0.11"));
persistContactsAndHosts();
runFlow();
}
@Test
public void testFailure_feeGivenInWrongScale_v06() throws Exception {
thrown.expect(CurrencyValueScaleException.class);
setEppInput("domain_create_fee_bad_scale.xml");
setEppInput("domain_create_fee_bad_scale.xml", ImmutableMap.of("FEE_VERSION", "0.6"));
persistContactsAndHosts();
runFlow();
}
@Test
public void testFailure_feeGivenInWrongScale_v11() throws Exception {
thrown.expect(CurrencyValueScaleException.class);
setEppInput("domain_create_fee_bad_scale.xml", ImmutableMap.of("FEE_VERSION", "0.11"));
persistContactsAndHosts();
runFlow();
}
@ -1283,8 +1387,8 @@ public class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow,
}
@Test
public void testSuccess_eapFeeApplied() throws Exception {
setEppInput("domain_create_eap_fee.xml");
public void testSuccess_eapFeeApplied_v06() throws Exception {
setEppInput("domain_create_eap_fee.xml", ImmutableMap.of("FEE_VERSION", "0.6"));
persistContactsAndHosts();
persistResource(Registry.get("tld").asBuilder()
.setEapFeeSchedule(ImmutableSortedMap.of(
@ -1292,7 +1396,22 @@ public class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow,
clock.nowUtc().minusDays(1), Money.of(USD, 100),
clock.nowUtc().plusDays(1), Money.of(USD, 0)))
.build());
doSuccessfulTest("tld", "domain_create_response_eap_fee.xml");
doSuccessfulTest(
"tld", "domain_create_response_eap_fee.xml", ImmutableMap.of("FEE_VERSION", "0.6"));
}
@Test
public void testSuccess_eapFeeApplied_v11() throws Exception {
setEppInput("domain_create_eap_fee.xml", ImmutableMap.of("FEE_VERSION", "0.11"));
persistContactsAndHosts();
persistResource(Registry.get("tld").asBuilder()
.setEapFeeSchedule(ImmutableSortedMap.of(
START_OF_TIME, Money.of(USD, 0),
clock.nowUtc().minusDays(1), Money.of(USD, 100),
clock.nowUtc().plusDays(1), Money.of(USD, 0)))
.build());
doSuccessfulTest(
"tld", "domain_create_response_eap_fee.xml", ImmutableMap.of("FEE_VERSION", "0.11"));
}
@Test

View file

@ -37,6 +37,7 @@ import static google.registry.util.DateTimeUtils.START_OF_TIME;
import static org.joda.money.CurrencyUnit.USD;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedMap;
import com.google.common.collect.Iterables;
@ -57,6 +58,7 @@ import google.registry.model.contact.ContactResource;
import google.registry.model.domain.DomainResource;
import google.registry.model.domain.GracePeriod;
import google.registry.model.domain.rgp.GracePeriodStatus;
import google.registry.model.eppcommon.ProtocolDefinition.ServiceExtension;
import google.registry.model.eppcommon.StatusValue;
import google.registry.model.eppcommon.Trid;
import google.registry.model.host.HostResource;
@ -68,6 +70,7 @@ import google.registry.model.reporting.HistoryEntry;
import google.registry.model.transfer.TransferData;
import google.registry.model.transfer.TransferResponse;
import google.registry.model.transfer.TransferStatus;
import java.util.Map;
import org.joda.money.Money;
import org.joda.time.DateTime;
import org.joda.time.Duration;
@ -84,6 +87,11 @@ public class DomainDeleteFlowTest extends ResourceFlowTestCase<DomainDeleteFlow,
private static final DateTime A_MONTH_AGO = TIME_BEFORE_FLOW.minusMonths(1);
private static final DateTime A_MONTH_FROM_NOW = TIME_BEFORE_FLOW.plusMonths(1);
private static final ImmutableMap<String, String> FEE_06_MAP =
ImmutableMap.of("FEE_VERSION", "0.6", "FEE_NS", "fee");
private static final ImmutableMap<String, String> FEE_11_MAP =
ImmutableMap.of("FEE_VERSION", "0.11", "FEE_NS", "fee11");
public DomainDeleteFlowTest() {
setEppInput("domain_delete.xml");
clock.setTo(TIME_BEFORE_FLOW);
@ -226,6 +234,13 @@ public class DomainDeleteFlowTest extends ResourceFlowTestCase<DomainDeleteFlow,
private void doImmediateDeleteTest(GracePeriodStatus gracePeriodStatus, String responseFilename)
throws Exception {
doImmediateDeleteTest(gracePeriodStatus, responseFilename, ImmutableMap.<String, String>of());
}
private void doImmediateDeleteTest(
GracePeriodStatus gracePeriodStatus,
String responseFilename,
Map<String, String> substitutions) throws Exception {
// Persist the billing event so it can be retrieved for cancellation generation and checking.
setupSuccessfulTest();
BillingEvent.OneTime graceBillingEvent =
@ -234,7 +249,7 @@ public class DomainDeleteFlowTest extends ResourceFlowTestCase<DomainDeleteFlow,
// We should see exactly one poll message, which is for the autorenew 1 month in the future.
assertPollMessages(createAutorenewPollMessage("TheRegistrar").build());
clock.advanceOneMilli();
runFlowAssertResponse(readFile(responseFilename));
runFlowAssertResponse(readFile(responseFilename, substitutions));
// Check that the domain is fully deleted.
assertThat(reloadResourceByUniqueId()).isNull();
// The add grace period is for a billable action, so it should trigger a cancellation.
@ -253,8 +268,14 @@ public class DomainDeleteFlowTest extends ResourceFlowTestCase<DomainDeleteFlow,
}
@Test
public void testSuccess_addGracePeriodCredit() throws Exception {
doImmediateDeleteTest(GracePeriodStatus.ADD, "domain_delete_response_fee.xml");
public void testSuccess_addGracePeriodCredit_v06() throws Exception {
removeServiceExtensionUri(ServiceExtension.FEE_0_11.getUri());
doImmediateDeleteTest(GracePeriodStatus.ADD, "domain_delete_response_fee.xml", FEE_06_MAP);
}
@Test
public void testSuccess_addGracePeriodCredit_v11() throws Exception {
doImmediateDeleteTest(GracePeriodStatus.ADD, "domain_delete_response_fee.xml", FEE_11_MAP);
}
@Test
@ -264,6 +285,11 @@ public class DomainDeleteFlowTest extends ResourceFlowTestCase<DomainDeleteFlow,
}
private void doSuccessfulTest_noAddGracePeriod(String responseFilename) throws Exception {
doSuccessfulTest_noAddGracePeriod(responseFilename, ImmutableMap.<String, String>of());
}
private void doSuccessfulTest_noAddGracePeriod(
String responseFilename, Map<String, String> substitutions) throws Exception {
// Persist the billing event so it can be retrieved for cancellation generation and checking.
setupSuccessfulTest();
BillingEvent.OneTime renewBillingEvent =
@ -275,7 +301,7 @@ public class DomainDeleteFlowTest extends ResourceFlowTestCase<DomainDeleteFlow,
// We should see exactly one poll message, which is for the autorenew 1 month in the future.
assertPollMessages(createAutorenewPollMessage("TheRegistrar").build());
clock.advanceOneMilli();
runFlowAssertResponse(readFile(responseFilename));
runFlowAssertResponse(readFile(responseFilename, substitutions));
DomainResource resource = reloadResourceByUniqueId();
// Check that the domain is in the pending delete state.
assertAboutDomains().that(resource)
@ -315,8 +341,14 @@ public class DomainDeleteFlowTest extends ResourceFlowTestCase<DomainDeleteFlow,
}
@Test
public void testSuccess_renewGracePeriodCredit() throws Exception {
doSuccessfulTest_noAddGracePeriod("domain_delete_response_pending_fee.xml");
public void testSuccess_renewGracePeriodCredit_v06() throws Exception {
removeServiceExtensionUri(ServiceExtension.FEE_0_11.getUri());
doSuccessfulTest_noAddGracePeriod("domain_delete_response_pending_fee.xml", FEE_06_MAP);
}
@Test
public void testSuccess_renewGracePeriodCredit_v11() throws Exception {
doSuccessfulTest_noAddGracePeriod("domain_delete_response_pending_fee.xml", FEE_11_MAP);
}
@Test
@ -361,14 +393,23 @@ public class DomainDeleteFlowTest extends ResourceFlowTestCase<DomainDeleteFlow,
}
@Test
public void testSuccess_autoRenewGracePeriod() throws Exception {
public void testSuccess_autoRenewGracePeriod_v06() throws Exception {
removeServiceExtensionUri(ServiceExtension.FEE_0_11.getUri());
setupAutorenewGracePeriod();
clock.advanceOneMilli();
runFlowAssertResponse(readFile("domain_delete_response_autorenew_fee.xml"));
runFlowAssertResponse(readFile("domain_delete_response_autorenew_fee.xml", FEE_06_MAP));
}
@Test
public void testSuccess_autoRenewGracePeriod_priceChanges() throws Exception {
public void testSuccess_autoRenewGracePeriod_v11() throws Exception {
setupAutorenewGracePeriod();
clock.advanceOneMilli();
runFlowAssertResponse(readFile("domain_delete_response_autorenew_fee.xml", FEE_11_MAP));
}
@Test
public void testSuccess_autoRenewGracePeriod_priceChanges_v06() throws Exception {
removeServiceExtensionUri(ServiceExtension.FEE_0_11.getUri());
persistResource(
Registry.get("tld")
.asBuilder()
@ -377,7 +418,20 @@ public class DomainDeleteFlowTest extends ResourceFlowTestCase<DomainDeleteFlow,
.build());
setupAutorenewGracePeriod();
clock.advanceOneMilli();
runFlowAssertResponse(readFile("domain_delete_response_autorenew_fee.xml"));
runFlowAssertResponse(readFile("domain_delete_response_autorenew_fee.xml", FEE_06_MAP));
}
@Test
public void testSuccess_autoRenewGracePeriod_priceChanges_v11() throws Exception {
persistResource(
Registry.get("tld")
.asBuilder()
.setRenewBillingCostTransitions(ImmutableSortedMap.of(
START_OF_TIME, Money.of(USD, 11), TIME_BEFORE_FLOW.minusDays(5), Money.of(USD, 20)))
.build());
setupAutorenewGracePeriod();
clock.advanceOneMilli();
runFlowAssertResponse(readFile("domain_delete_response_autorenew_fee.xml", FEE_11_MAP));
}
@Test

View file

@ -498,7 +498,10 @@ public class DomainInfoFlowTest extends ResourceFlowTestCase<DomainInfoFlow, Dom
runFlow();
}
/** Test create command. */
/**
* Test create command. Fee extension version 6 is the only one which supports fee extensions
* on info commands and responses, so we don't need to test the other versions.
*/
@Test
public void testFeeExtension_createCommand() throws Exception {
setEppInput("domain_info_fee_create.xml");

View file

@ -58,6 +58,7 @@ import google.registry.model.poll.PollMessage;
import google.registry.model.registrar.Registrar;
import google.registry.model.registry.Registry;
import google.registry.model.reporting.HistoryEntry;
import java.util.Map;
import org.joda.money.Money;
import org.joda.time.DateTime;
import org.joda.time.Duration;
@ -67,6 +68,11 @@ import org.junit.Test;
/** Unit tests for {@link DomainRenewFlow}. */
public class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainResource> {
private static final ImmutableMap<String, String> FEE_06_MAP =
ImmutableMap.of("FEE_VERSION", "0.6", "FEE_NS", "fee");
private static final ImmutableMap<String, String> FEE_11_MAP =
ImmutableMap.of("FEE_VERSION", "0.11", "FEE_NS", "fee11");
final DateTime expirationTime = DateTime.parse("2000-04-03T22:00:00.0Z");
public DomainRenewFlowTest() {
@ -115,10 +121,16 @@ public class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, D
}
private void doSuccessfulTest(String responseFilename, int renewalYears) throws Exception {
doSuccessfulTest(responseFilename, renewalYears, ImmutableMap.<String, String>of());
}
private void doSuccessfulTest(
String responseFilename,
int renewalYears,
Map<String, String> substitutions) throws Exception {
assertTransactionalFlow(true);
DateTime currentExpiration = reloadResourceByUniqueId().getRegistrationExpirationTime();
DateTime newExpiration = currentExpiration.plusYears(renewalYears);
runFlowAssertResponse(readFile(responseFilename));
runFlowAssertResponse(readFile(responseFilename, substitutions));
DomainResource domain = reloadResourceByUniqueId();
HistoryEntry historyEntryDomainRenew =
getOnlyHistoryEntryOfType(domain, HistoryEntry.Type.DOMAIN_RENEW);
@ -195,39 +207,77 @@ public class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, D
}
@Test
public void testSuccess_fee() throws Exception {
setEppInput("domain_renew_fee.xml");
public void testSuccess_fee_v06() throws Exception {
setEppInput("domain_renew_fee.xml", FEE_06_MAP);
persistDomain();
doSuccessfulTest("domain_renew_response_fee.xml", 5);
doSuccessfulTest("domain_renew_response_fee.xml", 5, FEE_06_MAP);
}
@Test
public void testSuccess_fee_withDefaultAttributes() throws Exception {
setEppInput("domain_renew_fee_defaults.xml");
public void testSuccess_fee_v11() throws Exception {
setEppInput("domain_renew_fee.xml", FEE_11_MAP);
persistDomain();
doSuccessfulTest("domain_renew_response_fee.xml", 5);
doSuccessfulTest("domain_renew_response_fee.xml", 5, FEE_11_MAP);
}
@Test
public void testFailure_refundableFee() throws Exception {
public void testSuccess_fee_withDefaultAttributes_v06() throws Exception {
setEppInput("domain_renew_fee_defaults.xml", FEE_06_MAP);
persistDomain();
doSuccessfulTest("domain_renew_response_fee.xml", 5, FEE_06_MAP);
}
@Test
public void testSuccess_fee_withDefaultAttributes_v11() throws Exception {
setEppInput("domain_renew_fee_defaults.xml", FEE_11_MAP);
persistDomain();
doSuccessfulTest("domain_renew_response_fee.xml", 5, FEE_11_MAP);
}
@Test
public void testFailure_refundableFee_v06() throws Exception {
thrown.expect(UnsupportedFeeAttributeException.class);
setEppInput("domain_renew_fee_refundable.xml");
setEppInput("domain_renew_fee_refundable.xml", FEE_06_MAP);
persistDomain();
runFlow();
}
@Test
public void testFailure_gracePeriodFee() throws Exception {
public void testFailure_refundableFee_v11() throws Exception {
thrown.expect(UnsupportedFeeAttributeException.class);
setEppInput("domain_renew_fee_grace_period.xml");
setEppInput("domain_renew_fee_refundable.xml", FEE_11_MAP);
persistDomain();
runFlow();
}
@Test
public void testFailure_appliedFee() throws Exception {
public void testFailure_gracePeriodFee_v06() throws Exception {
thrown.expect(UnsupportedFeeAttributeException.class);
setEppInput("domain_renew_fee_applied.xml");
setEppInput("domain_renew_fee_grace_period.xml", FEE_06_MAP);
persistDomain();
runFlow();
}
@Test
public void testFailure_gracePeriodFee_v11() throws Exception {
thrown.expect(UnsupportedFeeAttributeException.class);
setEppInput("domain_renew_fee_grace_period.xml", FEE_11_MAP);
persistDomain();
runFlow();
}
@Test
public void testFailure_appliedFee_v06() throws Exception {
thrown.expect(UnsupportedFeeAttributeException.class);
setEppInput("domain_renew_fee_applied.xml", FEE_06_MAP);
persistDomain();
runFlow();
}
@Test
public void testFailure_appliedFee_v11() throws Exception {
thrown.expect(UnsupportedFeeAttributeException.class);
setEppInput("domain_renew_fee_applied.xml", FEE_11_MAP);
persistDomain();
runFlow();
}
@ -313,9 +363,9 @@ public class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, D
}
@Test
public void testFailure_wrongFeeAmount() throws Exception {
public void testFailure_wrongFeeAmount_v06() throws Exception {
thrown.expect(FeesMismatchException.class);
setEppInput("domain_renew_fee.xml");
setEppInput("domain_renew_fee.xml", FEE_06_MAP);
persistResource(
Registry.get("tld")
.asBuilder()
@ -326,9 +376,22 @@ public class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, D
}
@Test
public void testFailure_wrongCurrency() throws Exception {
public void testFailure_wrongFeeAmount_v11() throws Exception {
thrown.expect(FeesMismatchException.class);
setEppInput("domain_renew_fee.xml", FEE_11_MAP);
persistResource(
Registry.get("tld")
.asBuilder()
.setRenewBillingCostTransitions(ImmutableSortedMap.of(START_OF_TIME, Money.of(USD, 20)))
.build());
persistDomain();
runFlow();
}
@Test
public void testFailure_wrongCurrency_v06() throws Exception {
thrown.expect(CurrencyUnitMismatchException.class);
setEppInput("domain_renew_fee.xml");
setEppInput("domain_renew_fee.xml", FEE_06_MAP);
persistResource(
Registry.get("tld")
.asBuilder()
@ -344,9 +407,35 @@ public class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, D
}
@Test
public void testFailure_feeGivenInWrongScale() throws Exception {
public void testFailure_wrongCurrency_v11() throws Exception {
thrown.expect(CurrencyUnitMismatchException.class);
setEppInput("domain_renew_fee.xml", FEE_11_MAP);
persistResource(
Registry.get("tld")
.asBuilder()
.setCurrency(EUR)
.setCreateBillingCost(Money.of(EUR, 13))
.setRestoreBillingCost(Money.of(EUR, 11))
.setRenewBillingCostTransitions(ImmutableSortedMap.of(START_OF_TIME, Money.of(EUR, 7)))
.setEapFeeSchedule(ImmutableSortedMap.of(START_OF_TIME, Money.zero(EUR)))
.setServerStatusChangeBillingCost(Money.of(EUR, 19))
.build());
persistDomain();
runFlow();
}
@Test
public void testFailure_feeGivenInWrongScale_v06() throws Exception {
thrown.expect(CurrencyValueScaleException.class);
setEppInput("domain_renew_fee_bad_scale.xml");
setEppInput("domain_renew_fee_bad_scale.xml", FEE_06_MAP);
persistDomain();
runFlow();
}
@Test
public void testFailure_feeGivenInWrongScale_v11() throws Exception {
thrown.expect(CurrencyValueScaleException.class);
setEppInput("domain_renew_fee_bad_scale.xml", FEE_11_MAP);
persistDomain();
runFlow();
}

View file

@ -30,6 +30,7 @@ import static google.registry.util.DateTimeUtils.START_OF_TIME;
import static org.joda.money.CurrencyUnit.EUR;
import static org.joda.money.CurrencyUnit.USD;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedMap;
import com.googlecode.objectify.Key;
@ -58,6 +59,7 @@ import google.registry.model.poll.PollMessage;
import google.registry.model.registrar.Registrar;
import google.registry.model.registry.Registry;
import google.registry.model.reporting.HistoryEntry;
import java.util.Map;
import org.joda.money.Money;
import org.junit.Before;
import org.junit.Test;
@ -66,6 +68,11 @@ import org.junit.Test;
public class DomainRestoreRequestFlowTest extends
ResourceFlowTestCase<DomainRestoreRequestFlow, DomainResource> {
private static final ImmutableMap<String, String> FEE_06_MAP =
ImmutableMap.of("FEE_VERSION", "0.6", "FEE_NS", "fee");
private static final ImmutableMap<String, String> FEE_11_MAP =
ImmutableMap.of("FEE_VERSION", "0.11", "FEE_NS", "fee11");
public DomainRestoreRequestFlowTest() {
setEppInput("domain_update_restore_request.xml");
}
@ -175,39 +182,77 @@ public class DomainRestoreRequestFlowTest extends
}
@Test
public void testSuccess_fee() throws Exception {
setEppInput("domain_update_restore_request_fee.xml");
public void testSuccess_fee_v06() throws Exception {
setEppInput("domain_update_restore_request_fee.xml", FEE_06_MAP);
persistPendingDeleteDomain();
runFlowAssertResponse(readFile("domain_update_restore_request_response_fee.xml"));
runFlowAssertResponse(readFile("domain_update_restore_request_response_fee.xml", FEE_06_MAP));
}
@Test
public void testSuccess_fee_withDefaultAttributes() throws Exception {
setEppInput("domain_update_restore_request_fee_defaults.xml");
public void testSuccess_fee_v11() throws Exception {
setEppInput("domain_update_restore_request_fee.xml", FEE_11_MAP);
persistPendingDeleteDomain();
runFlowAssertResponse(readFile("domain_update_restore_request_response_fee.xml"));
runFlowAssertResponse(readFile("domain_update_restore_request_response_fee.xml", FEE_11_MAP));
}
@Test
public void testFailure_refundableFee() throws Exception {
public void testSuccess_fee_withDefaultAttributes_v06() throws Exception {
setEppInput("domain_update_restore_request_fee_defaults.xml", FEE_06_MAP);
persistPendingDeleteDomain();
runFlowAssertResponse(readFile("domain_update_restore_request_response_fee.xml", FEE_06_MAP));
}
@Test
public void testSuccess_fee_withDefaultAttributes_v11() throws Exception {
setEppInput("domain_update_restore_request_fee_defaults.xml", FEE_11_MAP);
persistPendingDeleteDomain();
runFlowAssertResponse(readFile("domain_update_restore_request_response_fee.xml", FEE_11_MAP));
}
@Test
public void testFailure_refundableFee_v06() throws Exception {
thrown.expect(UnsupportedFeeAttributeException.class);
setEppInput("domain_update_restore_request_fee_refundable.xml");
setEppInput("domain_update_restore_request_fee_refundable.xml", FEE_06_MAP);
persistPendingDeleteDomain();
runFlow();
}
@Test
public void testFailure_gracePeriodFee() throws Exception {
public void testFailure_refundableFee_v11() throws Exception {
thrown.expect(UnsupportedFeeAttributeException.class);
setEppInput("domain_update_restore_request_fee_grace_period.xml");
setEppInput("domain_update_restore_request_fee_refundable.xml", FEE_11_MAP);
persistPendingDeleteDomain();
runFlow();
}
@Test
public void testFailure_appliedFee() throws Exception {
public void testFailure_gracePeriodFee_v06() throws Exception {
thrown.expect(UnsupportedFeeAttributeException.class);
setEppInput("domain_update_restore_request_fee_applied.xml");
setEppInput("domain_update_restore_request_fee_grace_period.xml", FEE_06_MAP);
persistPendingDeleteDomain();
runFlow();
}
@Test
public void testFailure_gracePeriodFee_v11() throws Exception {
thrown.expect(UnsupportedFeeAttributeException.class);
setEppInput("domain_update_restore_request_fee_grace_period.xml", FEE_11_MAP);
persistPendingDeleteDomain();
runFlow();
}
@Test
public void testFailure_appliedFee_v06() throws Exception {
thrown.expect(UnsupportedFeeAttributeException.class);
setEppInput("domain_update_restore_request_fee_applied.xml", FEE_06_MAP);
persistPendingDeleteDomain();
runFlow();
}
@Test
public void testFailure_appliedFee_v11() throws Exception {
thrown.expect(UnsupportedFeeAttributeException.class);
setEppInput("domain_update_restore_request_fee_applied.xml", FEE_11_MAP);
persistPendingDeleteDomain();
runFlow();
}
@ -259,9 +304,9 @@ public class DomainRestoreRequestFlowTest extends
}
@Test
public void testFailure_wrongFeeAmount() throws Exception {
public void testFailure_wrongFeeAmount_v06() throws Exception {
thrown.expect(FeesMismatchException.class);
setEppInput("domain_update_restore_request_fee.xml");
setEppInput("domain_update_restore_request_fee.xml", FEE_06_MAP);
persistPendingDeleteDomain();
persistResource(
Registry.get("tld").asBuilder().setRestoreBillingCost(Money.of(USD, 100)).build());
@ -269,9 +314,18 @@ public class DomainRestoreRequestFlowTest extends
}
@Test
public void testFailure_wrongCurrency() throws Exception {
public void testFailure_wrongFeeAmount_v11() throws Exception {
thrown.expect(FeesMismatchException.class);
setEppInput("domain_update_restore_request_fee.xml", FEE_11_MAP);
persistPendingDeleteDomain();
persistResource(
Registry.get("tld").asBuilder().setRestoreBillingCost(Money.of(USD, 100)).build());
runFlow();
}
private void runWrongCurrencyTest(Map<String, String> substitutions) throws Exception {
thrown.expect(CurrencyUnitMismatchException.class);
setEppInput("domain_update_restore_request_fee.xml");
setEppInput("domain_update_restore_request_fee.xml", substitutions);
persistPendingDeleteDomain();
persistResource(
Registry.get("tld")
@ -283,13 +337,31 @@ public class DomainRestoreRequestFlowTest extends
.setEapFeeSchedule(ImmutableSortedMap.of(START_OF_TIME, Money.zero(EUR)))
.setServerStatusChangeBillingCost(Money.of(EUR, 19))
.build());
runFlow();
}
@Test
public void testFailure_wrongCurrency_v06() throws Exception {
runWrongCurrencyTest(FEE_06_MAP);
}
@Test
public void testFailure_wrongCurrency_v11() throws Exception {
runWrongCurrencyTest(FEE_11_MAP);
}
@Test
public void testFailure_feeGivenInWrongScale_v06() throws Exception {
thrown.expect(CurrencyValueScaleException.class);
setEppInput("domain_update_restore_request_fee_bad_scale.xml", FEE_06_MAP);
persistPendingDeleteDomain();
runFlow();
}
@Test
public void testFailure_feeGivenInWrongScale() throws Exception {
public void testFailure_feeGivenInWrongScale_v11() throws Exception {
thrown.expect(CurrencyValueScaleException.class);
setEppInput("domain_update_restore_request_fee_bad_scale.xml");
setEppInput("domain_update_restore_request_fee_bad_scale.xml", FEE_11_MAP);
persistPendingDeleteDomain();
runFlow();
}

View file

@ -70,6 +70,7 @@ import google.registry.model.registry.Registry;
import google.registry.model.reporting.HistoryEntry;
import google.registry.model.transfer.TransferResponse;
import google.registry.model.transfer.TransferStatus;
import java.util.Map;
import org.joda.money.Money;
import org.joda.time.DateTime;
import org.joda.time.Duration;
@ -80,6 +81,11 @@ import org.junit.Test;
public class DomainTransferRequestFlowTest
extends DomainTransferFlowTestCase<DomainTransferRequestFlow, DomainResource> {
private static final ImmutableMap<String, String> FEE_06_MAP =
ImmutableMap.of("FEE_VERSION", "0.6", "FEE_NS", "fee");
private static final ImmutableMap<String, String> FEE_11_MAP =
ImmutableMap.of("FEE_VERSION", "0.11", "FEE_NS", "fee11");
@Before
public void setUp() throws Exception {
setEppInput("domain_transfer_request.xml");
@ -118,8 +124,9 @@ public class DomainTransferRequestFlowTest
String commandFilename,
String expectedXmlFilename,
DateTime expectedExpirationTime,
Map<String, String> substitutions,
BillingEvent.Cancellation.Builder... extraExpectedBillingEvents) throws Exception {
setEppInput(commandFilename);
setEppInput(commandFilename, substitutions);
ImmutableSet<GracePeriod> originalGracePeriods = domain.getGracePeriods();
// Replace the ROID in the xml file with the one generated in our test.
eppLoader.replaceAll("JD1234-REP", contact.getRepoId());
@ -130,7 +137,7 @@ public class DomainTransferRequestFlowTest
clock.nowUtc().plus(Registry.get("tld").getAutomaticTransferLength());
// Setup done; run the test.
assertTransactionalFlow(true);
runFlowAssertResponse(readFile(expectedXmlFilename));
runFlowAssertResponse(readFile(expectedXmlFilename, substitutions));
// Transfer should have been requested. Verify correct fields were set.
domain = reloadResourceByUniqueId();
final HistoryEntry historyEntryTransferRequest =
@ -262,6 +269,31 @@ public class DomainTransferRequestFlowTest
assertThat(afterGracePeriod.getGracePeriods()).isEmpty();
}
private void doSuccessfulTest(
String commandFilename,
String expectedXmlFilename,
DateTime expectedExpirationTime,
BillingEvent.Cancellation.Builder... extraExpectedBillingEvents) throws Exception {
doSuccessfulTest(
commandFilename,
expectedXmlFilename,
expectedExpirationTime,
ImmutableMap.<String, String>of(),
extraExpectedBillingEvents);
}
private void doSuccessfulTest(
String commandFilename,
String expectedXmlFilename,
Map<String, String> substitutions) throws Exception {
clock.advanceOneMilli();
doSuccessfulTest(
commandFilename,
expectedXmlFilename,
domain.getRegistrationExpirationTime().plusYears(1),
substitutions);
}
private void doSuccessfulTest(String commandFilename, String expectedXmlFilename)
throws Exception {
clock.advanceOneMilli();
@ -269,17 +301,29 @@ public class DomainTransferRequestFlowTest
commandFilename, expectedXmlFilename, domain.getRegistrationExpirationTime().plusYears(1));
}
private void runTest(String commandFilename, UserPrivileges userPrivileges) throws Exception {
setEppInput(commandFilename);
private void runTest(
String commandFilename,
UserPrivileges userPrivileges,
Map<String, String> substitutions) throws Exception {
setEppInput(commandFilename, substitutions);
// Replace the ROID in the xml file with the one generated in our test.
eppLoader.replaceAll("JD1234-REP", contact.getRepoId());
// Setup done; run the test.
assertTransactionalFlow(true);
runFlow(CommitMode.LIVE, userPrivileges);
}
private void runTest(String commandFilename, UserPrivileges userPrivileges) throws Exception {
runTest(commandFilename, userPrivileges, ImmutableMap.<String, String>of());
}
private void doFailingTest(
String commandFilename, Map<String, String> substitutions) throws Exception {
runTest(commandFilename, UserPrivileges.NORMAL, substitutions);
}
private void doFailingTest(String commandFilename) throws Exception {
runTest(commandFilename, UserPrivileges.NORMAL);
runTest(commandFilename, UserPrivileges.NORMAL, ImmutableMap.<String, String> of());
}
@Test
@ -295,34 +339,69 @@ public class DomainTransferRequestFlowTest
}
@Test
public void testSuccess_fee() throws Exception {
doSuccessfulTest("domain_transfer_request_fee.xml", "domain_transfer_request_response_fee.xml");
}
@Test
public void testSuccess_fee_withDefaultAttributes() throws Exception {
public void testSuccess_fee_v06() throws Exception {
doSuccessfulTest(
"domain_transfer_request_fee_defaults.xml", "domain_transfer_request_response_fee.xml");
"domain_transfer_request_fee.xml", "domain_transfer_request_response_fee.xml", FEE_06_MAP);
}
@Test
public void testFailure_refundableFee() throws Exception {
public void testSuccess_fee_v11() throws Exception {
doSuccessfulTest(
"domain_transfer_request_fee.xml", "domain_transfer_request_response_fee.xml", FEE_11_MAP);
}
@Test
public void testSuccess_fee_withDefaultAttributes_v06() throws Exception {
doSuccessfulTest(
"domain_transfer_request_fee_defaults.xml",
"domain_transfer_request_response_fee.xml",
FEE_06_MAP);
}
@Test
public void testSuccess_fee_withDefaultAttributes_v11() throws Exception {
doSuccessfulTest(
"domain_transfer_request_fee_defaults.xml",
"domain_transfer_request_response_fee.xml",
FEE_11_MAP);
}
@Test
public void testFailure_refundableFee_v06() throws Exception {
thrown.expect(UnsupportedFeeAttributeException.class);
doFailingTest("domain_transfer_request_fee_refundable.xml");
doFailingTest("domain_transfer_request_fee_refundable.xml", FEE_06_MAP);
}
@Test
public void testFailure_gracePeriodFee() throws Exception {
public void testFailure_refundableFee_v11() throws Exception {
thrown.expect(UnsupportedFeeAttributeException.class);
doFailingTest("domain_transfer_request_fee_grace_period.xml");
doFailingTest("domain_transfer_request_fee_refundable.xml", FEE_11_MAP);
}
@Test
public void testFailure_appliedFee() throws Exception {
public void testFailure_gracePeriodFee_v06() throws Exception {
thrown.expect(UnsupportedFeeAttributeException.class);
doFailingTest("domain_transfer_request_fee_applied.xml");
doFailingTest("domain_transfer_request_fee_grace_period.xml", FEE_06_MAP);
}
@Test
public void testFailure_gracePeriodFee_v11() throws Exception {
thrown.expect(UnsupportedFeeAttributeException.class);
doFailingTest("domain_transfer_request_fee_grace_period.xml", FEE_11_MAP);
}
@Test
public void testFailure_appliedFee_v06() throws Exception {
thrown.expect(UnsupportedFeeAttributeException.class);
doFailingTest("domain_transfer_request_fee_applied.xml", FEE_06_MAP);
}
@Test
public void testFailure_appliedFee_v11() throws Exception {
thrown.expect(UnsupportedFeeAttributeException.class);
doFailingTest("domain_transfer_request_fee_applied.xml", FEE_11_MAP);
}
@Test
@ -428,8 +507,7 @@ public class DomainTransferRequestFlowTest
runTest("domain_transfer_request_premium.xml", UserPrivileges.SUPERUSER);
}
@Test
public void testFailure_wrongCurrency() throws Exception {
private void runWrongCurrencyTest(Map<String, String> substitutions) throws Exception {
thrown.expect(CurrencyUnitMismatchException.class);
persistResource(
Registry.get("tld")
@ -441,24 +519,49 @@ public class DomainTransferRequestFlowTest
.setEapFeeSchedule(ImmutableSortedMap.of(START_OF_TIME, Money.zero(EUR)))
.setServerStatusChangeBillingCost(Money.of(EUR, 19))
.build());
doFailingTest("domain_transfer_request_fee.xml");
doFailingTest("domain_transfer_request_fee.xml", substitutions);
}
@Test
public void testFailure_feeGivenInWrongScale() throws Exception {
public void testFailure_wrongCurrency_v06() throws Exception {
runWrongCurrencyTest(FEE_06_MAP);
}
@Test
public void testFailure_wrongCurrency_v11() throws Exception {
runWrongCurrencyTest(FEE_11_MAP);
}
@Test
public void testFailure_feeGivenInWrongScale_v06() throws Exception {
thrown.expect(CurrencyValueScaleException.class);
doFailingTest("domain_transfer_request_fee_bad_scale.xml");
doFailingTest("domain_transfer_request_fee_bad_scale.xml", FEE_06_MAP);
}
@Test
public void testFailure_wrongFeeAmount() throws Exception {
public void testFailure_feeGivenInWrongScale_v11() throws Exception {
thrown.expect(CurrencyValueScaleException.class);
doFailingTest("domain_transfer_request_fee_bad_scale.xml", FEE_11_MAP);
}
private void runWrongFeeAmountTest(Map<String, String> substitutions) throws Exception {
thrown.expect(FeesMismatchException.class);
persistResource(
Registry.get("tld")
.asBuilder()
.setRenewBillingCostTransitions(ImmutableSortedMap.of(START_OF_TIME, Money.of(USD, 20)))
.build());
doFailingTest("domain_transfer_request_fee.xml");
doFailingTest("domain_transfer_request_fee.xml", substitutions);
}
@Test
public void testFailure_wrongFeeAmount_v06() throws Exception {
runWrongFeeAmountTest(FEE_06_MAP);
}
@Test
public void testFailure_wrongFeeAmount_v11() throws Exception {
runWrongFeeAmountTest(FEE_11_MAP);
}
@Test
@ -471,7 +574,6 @@ public class DomainTransferRequestFlowTest
doFailingTest("domain_transfer_request_premium.xml");
}
@Test
public void testFailure_feeNotProvidedOnPremiumName() throws Exception {
thrown.expect(FeesRequiredForPremiumNameException.class);

View file

@ -0,0 +1,60 @@
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<response>
<result code="1000">
<msg>Command completed successfully</msg>
</result>
<resData>
<domain:chkData xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
<domain:cd>
<domain:name avail="0">example1.tld</domain:name>
<domain:reason>In use</domain:reason>
</domain:cd>
<domain:cd>
<domain:name avail="1">example2.tld</domain:name>
</domain:cd>
<domain:cd>
<domain:name avail="1">example3.tld</domain:name>
</domain:cd>
</domain:chkData>
</resData>
<extension>
<fee:chkData xmlns:fee="urn:ietf:params:xml:ns:fee-0.11"
xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
<fee:cd avail="1">
<fee:object>
<domain:name>example1.tld</domain:name>
</fee:object>
<fee:command>create</fee:command>
<fee:currency>USD</fee:currency>
<fee:period unit="y">1</fee:period>
<fee:fee description="create">13.00</fee:fee>
<fee:fee description="Early Access Period, fee expires: 2010-01-02T10:00:00.000Z">100.00</fee:fee>
</fee:cd>
<fee:cd avail="1">
<fee:object>
<domain:name>example2.tld</domain:name>
</fee:object>
<fee:command>create</fee:command>
<fee:currency>USD</fee:currency>
<fee:period unit="y">1</fee:period>
<fee:fee description="create">13.00</fee:fee>
<fee:fee description="Early Access Period, fee expires: 2010-01-02T10:00:00.000Z">100.00</fee:fee>
</fee:cd>
<fee:cd avail="1">
<fee:object>
<domain:name>example3.tld</domain:name>
</fee:object>
<fee:command>create</fee:command>
<fee:currency>USD</fee:currency>
<fee:period unit="y">1</fee:period>
<fee:fee description="create">13.00</fee:fee>
<fee:fee description="Early Access Period, fee expires: 2010-01-02T10:00:00.000Z">100.00</fee:fee>
</fee:cd>
</fee:chkData>
</extension>
<trID>
<clTRID>ABC-12345</clTRID>
<svTRID>server-trid</svTRID>
</trID>
</response>
</epp>

View file

@ -0,0 +1,16 @@
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<command>
<check>
<domain:check xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
<domain:name>example1.tld</domain:name>
</domain:check>
</check>
<extension>
<fee:check xmlns:fee="urn:ietf:params:xml:ns:fee-0.11">
<fee:command>create</fee:command>
<fee:period unit="m">1</fee:period>
</fee:check>
</extension>
<clTRID>ABC-12345</clTRID>
</command>
</epp>

View file

@ -0,0 +1,15 @@
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<command>
<check>
<domain:check xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
<domain:name>example1.tld</domain:name>
</domain:check>
</check>
<extension>
<fee:check xmlns:fee="urn:ietf:params:xml:ns:fee-0.11">
<fee:command phase="claims">create</fee:command>
</fee:check>
</extension>
<clTRID>ABC-12345</clTRID>
</command>
</epp>

View file

@ -0,0 +1,15 @@
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<command>
<check>
<domain:check xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
<domain:name>example1.tld</domain:name>
</domain:check>
</check>
<extension>
<fee:check xmlns:fee="urn:ietf:params:xml:ns:fee-0.11">
<fee:command subphase="landrush">create</fee:command>
</fee:check>
</extension>
<clTRID>ABC-12345</clTRID>
</command>
</epp>

View file

@ -0,0 +1,22 @@
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<command>
<check>
<domain:check xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
<domain:name>example1.tld</domain:name>
<domain:name>example2.tld</domain:name>
<domain:name>example3.tld</domain:name>
</domain:check>
</check>
<extension>
<launch:check xmlns:launch="urn:ietf:params:xml:ns:launch-1.0" type="avail">
<launch:phase name="foo">custom</launch:phase>
</launch:check>
<fee:check xmlns:fee="urn:ietf:params:xml:ns:fee-0.11">
<fee:command>create</fee:command>
<fee:currency>EUR</fee:currency>
<fee:period unit="y">1</fee:period>
</fee:check>
</extension>
<clTRID>ABC-12345</clTRID>
</command>
</epp>

View file

@ -0,0 +1,16 @@
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<command>
<check>
<domain:check xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
<domain:name>example1.tld</domain:name>
</domain:check>
</check>
<extension>
<fee:check xmlns:fee="urn:ietf:params:xml:ns:fee-0.11">
<fee:command>Create</fee:command>
<fee:period unit="y">1</fee:period>
</fee:check>
</extension>
<clTRID>ABC-12345</clTRID>
</command>
</epp>

View file

@ -41,6 +41,13 @@
<fee:fee description="renew">11.00</fee:fee>
<fee:fee description="restore">17.00</fee:fee>
</fee:cd>
<fee:cd xmlns:fee="urn:ietf:params:xml:ns:fee-0.6">
<fee:name>example1.tld</fee:name>
<fee:currency>USD</fee:currency>
<fee:command>update</fee:command>
<fee:period unit="y">1</fee:period>
<fee:fee description="renew">11.00</fee:fee>
</fee:cd>
</fee:chkData>
</extension>
<trID>

View file

@ -23,6 +23,10 @@
<fee:name>example1.tld</fee:name>
<fee:command>restore</fee:command>
</fee:domain>
<fee:domain>
<fee:name>example1.tld</fee:name>
<fee:command>update</fee:command>
</fee:domain>
</fee:check>
</extension>
<clTRID>ABC-12345</clTRID>

View file

@ -0,0 +1,19 @@
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<command>
<check>
<domain:check xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
<domain:name>example1.tld</domain:name>
</domain:check>
</check>
<extension>
<launch:check xmlns:launch="urn:ietf:params:xml:ns:launch-1.0" type="avail">
<launch:phase name="foo">custom</launch:phase>
</launch:check>
<fee:check xmlns:fee="urn:ietf:params:xml:ns:fee-0.11">
<fee:command>restore</fee:command>
<fee:period unit="y">2</fee:period>
</fee:check>
</extension>
<clTRID>ABC-12345</clTRID>
</command>
</epp>

Some files were not shown because too many files have changed in this diff Show more