Make EppInput.getSingleExtension() return Optional, not @Nullable

This makes it harder to use it incorrectly by accident.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=181795813
This commit is contained in:
mcilwain 2018-01-12 14:45:46 -08:00 committed by Ben McIlwain
parent fbdb148540
commit 315e6d57bf
21 changed files with 290 additions and 239 deletions

View file

@ -209,8 +209,12 @@ public class FlowModule {
@ApplicationId @ApplicationId
static String provideApplicationId(EppInput eppInput) { static String provideApplicationId(EppInput eppInput) {
// Treat a missing application id as empty so we can always inject a non-null value. // Treat a missing application id as empty so we can always inject a non-null value.
return nullToEmpty( Optional<ApplicationIdTargetExtension> extension =
eppInput.getSingleExtension(ApplicationIdTargetExtension.class).getApplicationId()); eppInput.getSingleExtension(ApplicationIdTargetExtension.class);
checkState(
extension.isPresent(),
"ApplicationIdTargetExtension must be used to provide the application ID");
return nullToEmpty(extension.get().getApplicationId());
} }
@Provides @Provides
@ -233,16 +237,18 @@ public class FlowModule {
@Superuser boolean isSuperuser, @Superuser boolean isSuperuser,
@ClientId String clientId, @ClientId String clientId,
EppInput eppInput) { EppInput eppInput) {
HistoryEntry.Builder historyBuilder = new HistoryEntry.Builder() HistoryEntry.Builder historyBuilder =
.setTrid(trid) new HistoryEntry.Builder()
.setXmlBytes(inputXmlBytes) .setTrid(trid)
.setBySuperuser(isSuperuser) .setXmlBytes(inputXmlBytes)
.setClientId(clientId); .setBySuperuser(isSuperuser)
MetadataExtension metadataExtension = eppInput.getSingleExtension(MetadataExtension.class); .setClientId(clientId);
if (metadataExtension != null) { Optional<MetadataExtension> metadataExtension =
eppInput.getSingleExtension(MetadataExtension.class);
if (metadataExtension.isPresent()) {
historyBuilder historyBuilder
.setReason(metadataExtension.getReason()) .setReason(metadataExtension.get().getReason())
.setRequestedByRegistrar(metadataExtension.getRequestedByRegistrar()); .setRequestedByRegistrar(metadataExtension.get().getRequestedByRegistrar());
} }
return historyBuilder; return historyBuilder;
} }

View file

@ -90,6 +90,7 @@ import google.registry.model.reporting.DomainTransactionRecord.TransactionReport
import google.registry.model.reporting.HistoryEntry; import google.registry.model.reporting.HistoryEntry;
import google.registry.model.reporting.IcannReportingTypes.ActivityReportField; import google.registry.model.reporting.IcannReportingTypes.ActivityReportField;
import google.registry.tmch.LordnTask; import google.registry.tmch.LordnTask;
import java.util.Optional;
import java.util.Set; import java.util.Set;
import javax.inject.Inject; import javax.inject.Inject;
import org.joda.time.DateTime; import org.joda.time.DateTime;
@ -150,11 +151,11 @@ public class DomainAllocateFlow implements TransactionalFlow {
int years = period.getValue(); int years = period.getValue();
validateRegistrationPeriod(years); validateRegistrationPeriod(years);
validateCreateCommandContactsAndNameservers(command, registry, domainName); validateCreateCommandContactsAndNameservers(command, registry, domainName);
SecDnsCreateExtension secDnsCreate = Optional<SecDnsCreateExtension> secDnsCreate =
validateSecDnsExtension(eppInput.getSingleExtension(SecDnsCreateExtension.class)); validateSecDnsExtension(eppInput.getSingleExtension(SecDnsCreateExtension.class));
boolean isSunrushAddGracePeriod = isNullOrEmpty(command.getNameservers()); boolean isSunrushAddGracePeriod = isNullOrEmpty(command.getNameservers());
AllocateCreateExtension allocateCreate = AllocateCreateExtension allocateCreate =
eppInput.getSingleExtension(AllocateCreateExtension.class); eppInput.getSingleExtension(AllocateCreateExtension.class).get();
DomainApplication application = DomainApplication application =
loadAndValidateApplication(allocateCreate.getApplicationRoid(), now); loadAndValidateApplication(allocateCreate.getApplicationRoid(), now);
String repoId = createDomainRepoId(ObjectifyService.allocateId(), registry.getTldStr()); String repoId = createDomainRepoId(ObjectifyService.allocateId(), registry.getTldStr());
@ -166,31 +167,37 @@ public class DomainAllocateFlow implements TransactionalFlow {
domainName, application, historyEntry, isSunrushAddGracePeriod, registry, now, years); domainName, application, historyEntry, isSunrushAddGracePeriod, registry, now, years);
entitiesToSave.addAll(billsAndPolls); entitiesToSave.addAll(billsAndPolls);
DateTime registrationExpirationTime = leapSafeAddYears(now, years); DateTime registrationExpirationTime = leapSafeAddYears(now, years);
DomainResource newDomain = new DomainResource.Builder() DomainResource newDomain =
.setCreationClientId(clientId) new DomainResource.Builder()
.setPersistedCurrentSponsorClientId(clientId) .setCreationClientId(clientId)
.setRepoId(repoId) .setPersistedCurrentSponsorClientId(clientId)
.setIdnTableName(validateDomainNameWithIdnTables(domainName)) .setRepoId(repoId)
.setRegistrationExpirationTime(registrationExpirationTime) .setIdnTableName(validateDomainNameWithIdnTables(domainName))
.setAutorenewBillingEvent(Key.create(getOnly(billsAndPolls, BillingEvent.Recurring.class))) .setRegistrationExpirationTime(registrationExpirationTime)
.setAutorenewPollMessage(Key.create(getOnly(billsAndPolls, PollMessage.Autorenew.class))) .setAutorenewBillingEvent(
.setApplicationTime(allocateCreate.getApplicationTime()) Key.create(getOnly(billsAndPolls, BillingEvent.Recurring.class)))
.setApplication(Key.create(application)) .setAutorenewPollMessage(
.setSmdId(allocateCreate.getSmdId()) Key.create(getOnly(billsAndPolls, PollMessage.Autorenew.class)))
.setLaunchNotice(allocateCreate.getNotice()) .setApplicationTime(allocateCreate.getApplicationTime())
.setDsData(secDnsCreate == null ? application.getDsData() : secDnsCreate.getDsData()) .setApplication(Key.create(application))
.addGracePeriod(createGracePeriod( .setSmdId(allocateCreate.getSmdId())
isSunrushAddGracePeriod, getOnly(billsAndPolls, BillingEvent.OneTime.class))) .setLaunchNotice(allocateCreate.getNotice())
// Names on the collision list will not be delegated. Set server hold. .setDsData(
.setStatusValues(getReservationTypes(domainName).contains(ReservationType.NAME_COLLISION) secDnsCreate.isPresent() ? secDnsCreate.get().getDsData() : application.getDsData())
? ImmutableSet.of(StatusValue.SERVER_HOLD) .addGracePeriod(
: ImmutableSet.of()) createGracePeriod(
.setRegistrant(command.getRegistrant()) isSunrushAddGracePeriod, getOnly(billsAndPolls, BillingEvent.OneTime.class)))
.setAuthInfo(command.getAuthInfo()) // Names on the collision list will not be delegated. Set server hold.
.setFullyQualifiedDomainName(targetId) .setStatusValues(
.setNameservers(command.getNameservers()) getReservationTypes(domainName).contains(ReservationType.NAME_COLLISION)
.setContacts(command.getContacts()) ? ImmutableSet.of(StatusValue.SERVER_HOLD)
.build(); : ImmutableSet.of())
.setRegistrant(command.getRegistrant())
.setAuthInfo(command.getAuthInfo())
.setFullyQualifiedDomainName(targetId)
.setNameservers(command.getNameservers())
.setContacts(command.getContacts())
.build();
entitiesToSave.add( entitiesToSave.add(
newDomain, newDomain,
buildApplicationHistory(application, now), buildApplicationHistory(application, now),
@ -402,11 +409,11 @@ public class DomainAllocateFlow implements TransactionalFlow {
private ImmutableList<FeeTransformResponseExtension> createResponseExtensions( private ImmutableList<FeeTransformResponseExtension> createResponseExtensions(
DateTime now, Registry registry, int years) throws EppException { DateTime now, Registry registry, int years) throws EppException {
FeesAndCredits feesAndCredits = pricingLogic.getCreatePrice(registry, targetId, now, years); FeesAndCredits feesAndCredits = pricingLogic.getCreatePrice(registry, targetId, now, years);
FeeCreateCommandExtension feeCreate = Optional<FeeCreateCommandExtension> feeCreate =
eppInput.getSingleExtension(FeeCreateCommandExtension.class); eppInput.getSingleExtension(FeeCreateCommandExtension.class);
return (feeCreate == null) return feeCreate.isPresent()
? ImmutableList.of() ? ImmutableList.of(createFeeCreateResponse(feeCreate.get(), feesAndCredits))
: ImmutableList.of(createFeeCreateResponse(feeCreate, feesAndCredits)); : ImmutableList.of();
} }
/** Domain application with specific ROID does not exist. */ /** Domain application with specific ROID does not exist. */

View file

@ -94,6 +94,7 @@ import google.registry.model.registry.Registry.TldState;
import google.registry.model.reporting.HistoryEntry; import google.registry.model.reporting.HistoryEntry;
import google.registry.model.reporting.IcannReportingTypes.ActivityReportField; import google.registry.model.reporting.IcannReportingTypes.ActivityReportField;
import google.registry.model.smd.EncodedSignedMark; import google.registry.model.smd.EncodedSignedMark;
import java.util.Optional;
import javax.inject.Inject; import javax.inject.Inject;
import org.joda.time.DateTime; import org.joda.time.DateTime;
@ -216,10 +217,9 @@ public final class DomainApplicationCreateFlow implements TransactionalFlow {
int years = command.getPeriod().getValue(); int years = command.getPeriod().getValue();
validateRegistrationPeriod(years); validateRegistrationPeriod(years);
validateCreateCommandContactsAndNameservers(command, registry, domainName); validateCreateCommandContactsAndNameservers(command, registry, domainName);
LaunchCreateExtension launchCreate = eppInput.getSingleExtension(LaunchCreateExtension.class); LaunchCreateExtension launchCreate =
if (launchCreate != null) { eppInput.getSingleExtension(LaunchCreateExtension.class).get();
validateLaunchCreateExtension(launchCreate, registry, domainName, now); validateLaunchCreateExtension(launchCreate, registry, domainName, now);
}
boolean isAnchorTenant = boolean isAnchorTenant =
matchesAnchorTenantReservation(domainName, authInfo.getPw().getValue()); matchesAnchorTenantReservation(domainName, authInfo.getPw().getValue());
// Superusers can create reserved domains, force creations on domains that require a claims // Superusers can create reserved domains, force creations on domains that require a claims
@ -232,10 +232,10 @@ public final class DomainApplicationCreateFlow implements TransactionalFlow {
verifyNotReserved(domainName, isSunriseApplication); verifyNotReserved(domainName, isSunriseApplication);
} }
} }
FeeCreateCommandExtension feeCreate = Optional<FeeCreateCommandExtension> feeCreate =
eppInput.getSingleExtension(FeeCreateCommandExtension.class); eppInput.getSingleExtension(FeeCreateCommandExtension.class);
validateFeeChallenge(targetId, tld, now, feeCreate, feesAndCredits); validateFeeChallenge(targetId, tld, now, feeCreate, feesAndCredits);
SecDnsCreateExtension secDnsCreate = Optional<SecDnsCreateExtension> secDnsCreate =
validateSecDnsExtension(eppInput.getSingleExtension(SecDnsCreateExtension.class)); validateSecDnsExtension(eppInput.getSingleExtension(SecDnsCreateExtension.class));
customLogic.afterValidation( customLogic.afterValidation(
AfterValidationParameters.newBuilder() AfterValidationParameters.newBuilder()
@ -254,7 +254,7 @@ public final class DomainApplicationCreateFlow implements TransactionalFlow {
.setPeriod(command.getPeriod()) .setPeriod(command.getPeriod())
.setApplicationStatus(ApplicationStatus.VALIDATED) .setApplicationStatus(ApplicationStatus.VALIDATED)
.addStatusValue(StatusValue.PENDING_CREATE) .addStatusValue(StatusValue.PENDING_CREATE)
.setDsData(secDnsCreate == null ? null : secDnsCreate.getDsData()) .setDsData(secDnsCreate.isPresent() ? secDnsCreate.get().getDsData() : null)
.setRegistrant(command.getRegistrant()) .setRegistrant(command.getRegistrant())
.setAuthInfo(command.getAuthInfo()) .setAuthInfo(command.getAuthInfo())
.setFullyQualifiedDomainName(targetId) .setFullyQualifiedDomainName(targetId)
@ -377,7 +377,7 @@ public final class DomainApplicationCreateFlow implements TransactionalFlow {
private static ImmutableList<ResponseExtension> createResponseExtensions( private static ImmutableList<ResponseExtension> createResponseExtensions(
String applicationId, String applicationId,
LaunchPhase launchPhase, LaunchPhase launchPhase,
FeeTransformCommandExtension feeCreate, Optional<? extends FeeTransformCommandExtension> feeCreate,
FeesAndCredits feesAndCredits) { FeesAndCredits feesAndCredits) {
ImmutableList.Builder<ResponseExtension> responseExtensionsBuilder = ImmutableList.Builder<ResponseExtension> responseExtensionsBuilder =
new ImmutableList.Builder<>(); new ImmutableList.Builder<>();
@ -385,8 +385,8 @@ public final class DomainApplicationCreateFlow implements TransactionalFlow {
.setPhase(launchPhase) .setPhase(launchPhase)
.setApplicationId(applicationId) .setApplicationId(applicationId)
.build()); .build());
if (feeCreate != null) { if (feeCreate.isPresent()) {
responseExtensionsBuilder.add(createFeeCreateResponse(feeCreate, feesAndCredits)); responseExtensionsBuilder.add(createFeeCreateResponse(feeCreate.get(), feesAndCredits));
} }
return responseExtensionsBuilder.build(); return responseExtensionsBuilder.build();
} }

View file

@ -93,7 +93,7 @@ public final class DomainApplicationDeleteFlow implements TransactionalFlow {
Registry registry = Registry.get(tld); Registry registry = Registry.get(tld);
verifyRegistryStateAllowsLaunchFlows(registry, now); verifyRegistryStateAllowsLaunchFlows(registry, now);
verifyLaunchPhaseMatchesRegistryPhase( verifyLaunchPhaseMatchesRegistryPhase(
registry, eppInput.getSingleExtension(LaunchDeleteExtension.class), now); registry, eppInput.getSingleExtension(LaunchDeleteExtension.class).get(), now);
verifyResourceOwnership(clientId, existingApplication); verifyResourceOwnership(clientId, existingApplication);
// Don't allow deleting a sunrise application during landrush. // Don't allow deleting a sunrise application during landrush.
if (existingApplication.getPhase().equals(LaunchPhase.SUNRISE) if (existingApplication.getPhase().equals(LaunchPhase.SUNRISE)

View file

@ -98,7 +98,7 @@ public final class DomainApplicationInfoFlow implements Flow {
: null); : null);
verifyApplicationDomainMatchesTargetId(application, targetId); verifyApplicationDomainMatchesTargetId(application, targetId);
verifyOptionalAuthInfo(authInfo, application); verifyOptionalAuthInfo(authInfo, application);
LaunchInfoExtension launchInfo = eppInput.getSingleExtension(LaunchInfoExtension.class); LaunchInfoExtension launchInfo = eppInput.getSingleExtension(LaunchInfoExtension.class).get();
if (!application.getPhase().equals(launchInfo.getPhase())) { if (!application.getPhase().equals(launchInfo.getPhase())) {
throw new ApplicationLaunchPhaseMismatchException(); throw new ApplicationLaunchPhaseMismatchException();
} }

View file

@ -189,12 +189,12 @@ public class DomainApplicationUpdateFlow implements TransactionalFlow {
Registry registry = Registry.get(tld); Registry registry = Registry.get(tld);
FeesAndCredits feesAndCredits = FeesAndCredits feesAndCredits =
pricingLogic.getApplicationUpdatePrice(registry, existingApplication, now); pricingLogic.getApplicationUpdatePrice(registry, existingApplication, now);
FeeUpdateCommandExtension feeUpdate = Optional<FeeUpdateCommandExtension> feeUpdate =
eppInput.getSingleExtension(FeeUpdateCommandExtension.class); eppInput.getSingleExtension(FeeUpdateCommandExtension.class);
// If the fee extension is present, validate it (even if the cost is zero, to check for price // If the fee extension is present, validate it (even if the cost is zero, to check for price
// mismatches). Don't rely on the the validateFeeChallenge check for feeUpdate nullness, because // mismatches). Don't rely on the the validateFeeChallenge check for feeUpdate nullness, because
// it throws an error if the name is premium, and we don't want to do that here. // it throws an error if the name is premium, and we don't want to do that here.
if (feeUpdate != null) { if (feeUpdate.isPresent()) {
validateFeeChallenge(targetId, tld, now, feeUpdate, feesAndCredits); validateFeeChallenge(targetId, tld, now, feeUpdate, feesAndCredits);
} else if (!feesAndCredits.getTotalCost().isZero()) { } else if (!feesAndCredits.getTotalCost().isZero()) {
// If it's not present but the cost is not zero, throw an exception. // If it's not present but the cost is not zero, throw an exception.
@ -231,11 +231,12 @@ public class DomainApplicationUpdateFlow implements TransactionalFlow {
checkSameValuesNotAddedAndRemoved(add.getContacts(), remove.getContacts()); checkSameValuesNotAddedAndRemoved(add.getContacts(), remove.getContacts());
checkSameValuesNotAddedAndRemoved(add.getStatusValues(), remove.getStatusValues()); checkSameValuesNotAddedAndRemoved(add.getStatusValues(), remove.getStatusValues());
Change change = command.getInnerChange(); Change change = command.getInnerChange();
SecDnsUpdateExtension secDnsUpdate = eppInput.getSingleExtension(SecDnsUpdateExtension.class); Optional<SecDnsUpdateExtension> secDnsUpdate =
eppInput.getSingleExtension(SecDnsUpdateExtension.class);
return application.asBuilder() return application.asBuilder()
// Handle the secDNS extension. // Handle the secDNS extension.
.setDsData(secDnsUpdate != null .setDsData(secDnsUpdate.isPresent()
? updateDsData(application.getDsData(), secDnsUpdate) ? updateDsData(application.getDsData(), secDnsUpdate.get())
: application.getDsData()) : application.getDsData())
.setLastEppUpdateTime(now) .setLastEppUpdateTime(now)
.setLastEppUpdateClientId(clientId) .setLastEppUpdateClientId(clientId)

View file

@ -151,13 +151,13 @@ public final class DomainCheckFlow implements Flow {
.setAsOfDate(now) .setAsOfDate(now)
.build()); .build());
Set<String> existingIds = checkResourcesExist(DomainResource.class, targetIds, now); Set<String> existingIds = checkResourcesExist(DomainResource.class, targetIds, now);
AllocationTokenExtension allocationTokenExtension = Optional<AllocationTokenExtension> allocationTokenExtension =
eppInput.getSingleExtension(AllocationTokenExtension.class); eppInput.getSingleExtension(AllocationTokenExtension.class);
ImmutableMap<String, String> tokenCheckResults = ImmutableMap<String, String> tokenCheckResults =
(allocationTokenExtension == null) allocationTokenExtension.isPresent()
? ImmutableMap.of() ? checkDomainsWithToken(
: checkDomainsWithToken( targetIds, allocationTokenExtension.get().getAllocationToken(), clientId)
targetIds, allocationTokenExtension.getAllocationToken(), clientId); : ImmutableMap.of();
ImmutableList.Builder<DomainCheck> checks = new ImmutableList.Builder<>(); ImmutableList.Builder<DomainCheck> checks = new ImmutableList.Builder<>();
for (String targetId : targetIds) { for (String targetId : targetIds) {
Optional<String> message = Optional<String> message =
@ -196,7 +196,7 @@ public final class DomainCheckFlow implements Flow {
if (reservationTypes.isEmpty() if (reservationTypes.isEmpty()
&& isDomainPremium(domainName.toString(), now) && isDomainPremium(domainName.toString(), now)
&& registry.getPremiumPriceAckRequired() && registry.getPremiumPriceAckRequired()
&& eppInput.getSingleExtension(FeeCheckCommandExtension.class) == null) { && !eppInput.getSingleExtension(FeeCheckCommandExtension.class).isPresent()) {
return Optional.of("Premium names require EPP ext."); return Optional.of("Premium names require EPP ext.");
} }
if (!reservationTypes.isEmpty()) { if (!reservationTypes.isEmpty()) {
@ -210,11 +210,12 @@ public final class DomainCheckFlow implements Flow {
/** Handle the fee check extension. */ /** Handle the fee check extension. */
private ImmutableList<? extends ResponseExtension> getResponseExtensions( private ImmutableList<? extends ResponseExtension> getResponseExtensions(
ImmutableMap<String, InternetDomainName> domainNames, DateTime now) throws EppException { ImmutableMap<String, InternetDomainName> domainNames, DateTime now) throws EppException {
FeeCheckCommandExtension<?, ?> feeCheck = Optional<FeeCheckCommandExtension> feeCheckOpt =
eppInput.getSingleExtension(FeeCheckCommandExtension.class); eppInput.getSingleExtension(FeeCheckCommandExtension.class);
if (feeCheck == null) { if (!feeCheckOpt.isPresent()) {
return ImmutableList.of(); // No fee checks were requested. return ImmutableList.of(); // No fee checks were requested.
} }
FeeCheckCommandExtension<?, ?> feeCheck = feeCheckOpt.get();
ImmutableList.Builder<FeeCheckResponseExtensionItem> responseItems = ImmutableList.Builder<FeeCheckResponseExtensionItem> responseItems =
new ImmutableList.Builder<>(); new ImmutableList.Builder<>();
for (FeeCheckCommandExtensionItem feeCheckItem : feeCheck.getItems()) { for (FeeCheckCommandExtensionItem feeCheckItem : feeCheck.getItems()) {

View file

@ -85,7 +85,7 @@ public final class DomainClaimsCheckFlow implements Flow {
extensionManager.register(LaunchCheckExtension.class, AllocationTokenExtension.class); extensionManager.register(LaunchCheckExtension.class, AllocationTokenExtension.class);
extensionManager.validate(); extensionManager.validate();
validateClientIsLoggedIn(clientId); validateClientIsLoggedIn(clientId);
if (eppInput.getSingleExtension(AllocationTokenExtension.class) != null) { if (eppInput.getSingleExtension(AllocationTokenExtension.class).isPresent()) {
throw new DomainClaimsCheckNotAllowedWithAllocationTokens(); throw new DomainClaimsCheckNotAllowedWithAllocationTokens();
} }
List<String> targetIds = ((Check) resourceCommand).getTargetIds(); List<String> targetIds = ((Check) resourceCommand).getTargetIds();

View file

@ -220,12 +220,14 @@ public class DomainCreateFlow implements TransactionalFlow {
} }
TldState tldState = registry.getTldState(now); TldState tldState = registry.getTldState(now);
boolean isAnchorTenant = isAnchorTenant(domainName); boolean isAnchorTenant = isAnchorTenant(domainName);
LaunchCreateExtension launchCreate = eppInput.getSingleExtension(LaunchCreateExtension.class); Optional<LaunchCreateExtension> launchCreate =
boolean hasSignedMarks = launchCreate != null && !launchCreate.getSignedMarks().isEmpty(); eppInput.getSingleExtension(LaunchCreateExtension.class);
boolean hasClaimsNotice = launchCreate != null && launchCreate.getNotice() != null; boolean hasSignedMarks =
if (launchCreate != null) { launchCreate.isPresent() && !launchCreate.get().getSignedMarks().isEmpty();
verifyNoCodeMarks(launchCreate); boolean hasClaimsNotice = launchCreate.isPresent() && launchCreate.get().getNotice() != null;
validateLaunchCreateNotice(launchCreate.getNotice(), domainLabel, isSuperuser, now); if (launchCreate.isPresent()) {
verifyNoCodeMarks(launchCreate.get());
validateLaunchCreateNotice(launchCreate.get().getNotice(), domainLabel, isSuperuser, now);
} }
boolean isSunriseCreate = hasSignedMarks && SUNRISE_STATES.contains(tldState); boolean isSunriseCreate = hasSignedMarks && SUNRISE_STATES.contains(tldState);
String signedMarkId = null; String signedMarkId = null;
@ -234,8 +236,8 @@ public class DomainCreateFlow implements TransactionalFlow {
// registering premium domains. // registering premium domains.
if (!isSuperuser) { if (!isSuperuser) {
checkAllowedAccessToTld(clientId, registry.getTldStr()); checkAllowedAccessToTld(clientId, registry.getTldStr());
if (launchCreate != null) { if (launchCreate.isPresent()) {
verifyLaunchPhaseMatchesRegistryPhase(registry, launchCreate, now); verifyLaunchPhaseMatchesRegistryPhase(registry, launchCreate.get(), now);
} }
if (!isAnchorTenant) { if (!isAnchorTenant) {
verifyNotReserved(domainName, isSunriseCreate); verifyNotReserved(domainName, isSunriseCreate);
@ -253,7 +255,9 @@ public class DomainCreateFlow implements TransactionalFlow {
// If a signed mark was provided, then it must match the desired domain label. Get the mark // If a signed mark was provided, then it must match the desired domain label. Get the mark
// at this point so that we can verify it before the "after validation" extension point. // at this point so that we can verify it before the "after validation" extension point.
signedMarkId = signedMarkId =
tmchUtils.verifySignedMarks(launchCreate.getSignedMarks(), domainLabel, now).getId(); tmchUtils
.verifySignedMarks(launchCreate.get().getSignedMarks(), domainLabel, now)
.getId();
} }
} }
Optional<AllocationToken> allocationToken = Optional<AllocationToken> allocationToken =
@ -264,11 +268,11 @@ public class DomainCreateFlow implements TransactionalFlow {
.setYears(years) .setYears(years)
.setSignedMarkId(Optional.ofNullable(signedMarkId)) .setSignedMarkId(Optional.ofNullable(signedMarkId))
.build()); .build());
FeeCreateCommandExtension feeCreate = Optional<FeeCreateCommandExtension> feeCreate =
eppInput.getSingleExtension(FeeCreateCommandExtension.class); eppInput.getSingleExtension(FeeCreateCommandExtension.class);
FeesAndCredits feesAndCredits = pricingLogic.getCreatePrice(registry, targetId, now, years); FeesAndCredits feesAndCredits = pricingLogic.getCreatePrice(registry, targetId, now, years);
validateFeeChallenge(targetId, registry.getTldStr(), now, feeCreate, feesAndCredits); validateFeeChallenge(targetId, registry.getTldStr(), now, feeCreate, feesAndCredits);
SecDnsCreateExtension secDnsCreate = Optional<SecDnsCreateExtension> secDnsCreate =
validateSecDnsExtension(eppInput.getSingleExtension(SecDnsCreateExtension.class)); validateSecDnsExtension(eppInput.getSingleExtension(SecDnsCreateExtension.class));
String repoId = createDomainRepoId(ObjectifyService.allocateId(), registry.getTldStr()); String repoId = createDomainRepoId(ObjectifyService.allocateId(), registry.getTldStr());
DateTime registrationExpirationTime = leapSafeAddYears(now, years); DateTime registrationExpirationTime = leapSafeAddYears(now, years);
@ -302,9 +306,9 @@ public class DomainCreateFlow implements TransactionalFlow {
.setRegistrationExpirationTime(registrationExpirationTime) .setRegistrationExpirationTime(registrationExpirationTime)
.setAutorenewBillingEvent(Key.create(autorenewBillingEvent)) .setAutorenewBillingEvent(Key.create(autorenewBillingEvent))
.setAutorenewPollMessage(Key.create(autorenewPollMessage)) .setAutorenewPollMessage(Key.create(autorenewPollMessage))
.setLaunchNotice(hasClaimsNotice ? launchCreate.getNotice() : null) .setLaunchNotice(hasClaimsNotice ? launchCreate.get().getNotice() : null)
.setSmdId(signedMarkId) .setSmdId(signedMarkId)
.setDsData(secDnsCreate == null ? null : secDnsCreate.getDsData()) .setDsData(secDnsCreate.isPresent() ? secDnsCreate.get().getDsData() : null)
.setRegistrant(command.getRegistrant()) .setRegistrant(command.getRegistrant())
.setAuthInfo(command.getAuthInfo()) .setAuthInfo(command.getAuthInfo())
.setFullyQualifiedDomainName(targetId) .setFullyQualifiedDomainName(targetId)
@ -354,9 +358,10 @@ public class DomainCreateFlow implements TransactionalFlow {
} }
private boolean isAnchorTenant(InternetDomainName domainName) { private boolean isAnchorTenant(InternetDomainName domainName) {
MetadataExtension metadataExtension = eppInput.getSingleExtension(MetadataExtension.class); Optional<MetadataExtension> metadataExtension =
eppInput.getSingleExtension(MetadataExtension.class);
return matchesAnchorTenantReservation(domainName, authInfo.getPw().getValue()) return matchesAnchorTenantReservation(domainName, authInfo.getPw().getValue())
|| (metadataExtension != null && metadataExtension.getIsAnchorTenant()); || (metadataExtension.isPresent() && metadataExtension.get().getIsAnchorTenant());
} }
/** Prohibit creating a domain if there is an open application for the same name. */ /** Prohibit creating a domain if there is an open application for the same name. */
@ -380,11 +385,12 @@ public class DomainCreateFlow implements TransactionalFlow {
private Optional<AllocationToken> verifyAllocationTokenIfPresent( private Optional<AllocationToken> verifyAllocationTokenIfPresent(
InternetDomainName domainName, Registry registry, String clientId) InternetDomainName domainName, Registry registry, String clientId)
throws EppException { throws EppException {
AllocationTokenExtension ext = eppInput.getSingleExtension(AllocationTokenExtension.class); Optional<AllocationTokenExtension> extension =
eppInput.getSingleExtension(AllocationTokenExtension.class);
return Optional.ofNullable( return Optional.ofNullable(
(ext == null) extension.isPresent()
? null ? verifyToken(domainName, extension.get().getAllocationToken(), registry, clientId)
: verifyToken(domainName, ext.getAllocationToken(), registry, clientId)); : null);
} }
private HistoryEntry buildHistoryEntry( private HistoryEntry buildHistoryEntry(
@ -488,10 +494,10 @@ public class DomainCreateFlow implements TransactionalFlow {
} }
private static ImmutableList<FeeTransformResponseExtension> createResponseExtensions( private static ImmutableList<FeeTransformResponseExtension> createResponseExtensions(
FeeCreateCommandExtension feeCreate, FeesAndCredits feesAndCredits) { Optional<FeeCreateCommandExtension> feeCreate, FeesAndCredits feesAndCredits) {
return (feeCreate == null) return feeCreate.isPresent()
? ImmutableList.of() ? ImmutableList.of(createFeeCreateResponse(feeCreate.get(), feesAndCredits))
: ImmutableList.of(createFeeCreateResponse(feeCreate, feesAndCredits)); : ImmutableList.of();
} }
/** There is an open application for this domain. */ /** There is an open application for this domain. */

View file

@ -155,13 +155,14 @@ public final class DomainDeleteFlow implements TransactionalFlow {
} }
Duration redemptionGracePeriodLength = registry.getRedemptionGracePeriodLength(); Duration redemptionGracePeriodLength = registry.getRedemptionGracePeriodLength();
Duration pendingDeleteLength = registry.getPendingDeleteLength(); Duration pendingDeleteLength = registry.getPendingDeleteLength();
DomainDeleteSuperuserExtension domainDeleteSuperuserExtension = Optional<DomainDeleteSuperuserExtension> domainDeleteSuperuserExtension =
eppInput.getSingleExtension(DomainDeleteSuperuserExtension.class); eppInput.getSingleExtension(DomainDeleteSuperuserExtension.class);
if (domainDeleteSuperuserExtension != null) { if (domainDeleteSuperuserExtension.isPresent()) {
redemptionGracePeriodLength = redemptionGracePeriodLength =
Duration.standardDays(domainDeleteSuperuserExtension.getRedemptionGracePeriodDays()); Duration.standardDays(
domainDeleteSuperuserExtension.get().getRedemptionGracePeriodDays());
pendingDeleteLength = pendingDeleteLength =
Duration.standardDays(domainDeleteSuperuserExtension.getPendingDeleteDays()); Duration.standardDays(domainDeleteSuperuserExtension.get().getPendingDeleteDays());
} }
boolean inAddGracePeriod = boolean inAddGracePeriod =
existingDomain.getGracePeriodStatuses().contains(GracePeriodStatus.ADD); existingDomain.getGracePeriodStatuses().contains(GracePeriodStatus.ADD);

View file

@ -617,20 +617,20 @@ public class DomainFlowUtils {
String domainName, String domainName,
String tld, String tld,
DateTime priceTime, DateTime priceTime,
final FeeTransformCommandExtension feeCommand, final Optional<? extends FeeTransformCommandExtension> feeCommand,
FeesAndCredits feesAndCredits) FeesAndCredits feesAndCredits)
throws EppException { throws EppException {
Registry registry = Registry.get(tld); Registry registry = Registry.get(tld);
if (registry.getPremiumPriceAckRequired() if (registry.getPremiumPriceAckRequired()
&& isDomainPremium(domainName, priceTime) && isDomainPremium(domainName, priceTime)
&& feeCommand == null) { && !feeCommand.isPresent()) {
throw new FeesRequiredForPremiumNameException(); throw new FeesRequiredForPremiumNameException();
} }
// Check for the case where a fee command extension was required but not provided. // Check for the case where a fee command extension was required but not provided.
// This only happens when the total fees are non-zero and include custom fees requiring the // This only happens when the total fees are non-zero and include custom fees requiring the
// extension. // extension.
if (feeCommand == null) { if (!feeCommand.isPresent()) {
if (!feesAndCredits.getEapCost().isZero()) { if (!feesAndCredits.getEapCost().isZero()) {
throw new FeesRequiredDuringEarlyAccessProgramException(feesAndCredits.getEapCost()); throw new FeesRequiredDuringEarlyAccessProgramException(feesAndCredits.getEapCost());
} }
@ -640,7 +640,7 @@ public class DomainFlowUtils {
throw new FeesRequiredForNonFreeOperationException(feesAndCredits.getTotalCost()); throw new FeesRequiredForNonFreeOperationException(feesAndCredits.getTotalCost());
} }
List<Fee> fees = feeCommand.getFees(); List<Fee> fees = feeCommand.get().getFees();
// The schema guarantees that at least one fee will be present. // The schema guarantees that at least one fee will be present.
checkState(!fees.isEmpty()); checkState(!fees.isEmpty());
BigDecimal total = BigDecimal.ZERO; BigDecimal total = BigDecimal.ZERO;
@ -650,7 +650,7 @@ public class DomainFlowUtils {
} }
total = total.add(fee.getCost()); total = total.add(fee.getCost());
} }
for (Credit credit : feeCommand.getCredits()) { for (Credit credit : feeCommand.get().getCredits()) {
if (!credit.hasDefaultAttributes()) { if (!credit.hasDefaultAttributes()) {
throw new UnsupportedFeeAttributeException(); throw new UnsupportedFeeAttributeException();
} }
@ -659,7 +659,7 @@ public class DomainFlowUtils {
Money feeTotal = null; Money feeTotal = null;
try { try {
feeTotal = Money.of(feeCommand.getCurrency(), total); feeTotal = Money.of(feeCommand.get().getCurrency(), total);
} catch (ArithmeticException e) { } catch (ArithmeticException e) {
throw new CurrencyValueScaleException(); throw new CurrencyValueScaleException();
} }
@ -801,18 +801,18 @@ public class DomainFlowUtils {
} }
/** Validate the secDNS extension, if present. */ /** Validate the secDNS extension, if present. */
static SecDnsCreateExtension validateSecDnsExtension(SecDnsCreateExtension secDnsCreate) static Optional<SecDnsCreateExtension> validateSecDnsExtension(
throws EppException { Optional<SecDnsCreateExtension> secDnsCreate) throws EppException {
if (secDnsCreate == null) { if (!secDnsCreate.isPresent()) {
return null; return Optional.empty();
} }
if (secDnsCreate.getDsData() == null) { if (secDnsCreate.get().getDsData() == null) {
throw new DsDataRequiredException(); throw new DsDataRequiredException();
} }
if (secDnsCreate.getMaxSigLife() != null) { if (secDnsCreate.get().getMaxSigLife() != null) {
throw new MaxSigLifeNotSupportedException(); throw new MaxSigLifeNotSupportedException();
} }
validateDsData(secDnsCreate.getDsData()); validateDsData(secDnsCreate.get().getDsData());
return secDnsCreate; return secDnsCreate;
} }

View file

@ -151,12 +151,12 @@ public final class DomainInfoFlow implements Flow {
if (!gracePeriodStatuses.isEmpty()) { if (!gracePeriodStatuses.isEmpty()) {
extensions.add(RgpInfoExtension.create(gracePeriodStatuses)); extensions.add(RgpInfoExtension.create(gracePeriodStatuses));
} }
FeeInfoCommandExtensionV06 feeInfo = Optional<FeeInfoCommandExtensionV06> feeInfo =
eppInput.getSingleExtension(FeeInfoCommandExtensionV06.class); eppInput.getSingleExtension(FeeInfoCommandExtensionV06.class);
if (feeInfo != null) { // Fee check was requested. if (feeInfo.isPresent()) { // Fee check was requested.
FeeInfoResponseExtensionV06.Builder builder = new FeeInfoResponseExtensionV06.Builder(); FeeInfoResponseExtensionV06.Builder builder = new FeeInfoResponseExtensionV06.Builder();
handleFeeRequest( handleFeeRequest(
feeInfo, feeInfo.get(),
builder, builder,
InternetDomainName.from(targetId), InternetDomainName.from(targetId),
null, null,

View file

@ -142,7 +142,7 @@ public final class DomainRenewFlow implements TransactionalFlow {
DateTime newExpirationTime = DateTime newExpirationTime =
leapSafeAddYears(existingDomain.getRegistrationExpirationTime(), years); // Uncapped leapSafeAddYears(existingDomain.getRegistrationExpirationTime(), years); // Uncapped
validateRegistrationPeriod(now, newExpirationTime); validateRegistrationPeriod(now, newExpirationTime);
FeeRenewCommandExtension feeRenew = Optional<FeeRenewCommandExtension> feeRenew =
eppInput.getSingleExtension(FeeRenewCommandExtension.class); eppInput.getSingleExtension(FeeRenewCommandExtension.class);
FeesAndCredits feesAndCredits = FeesAndCredits feesAndCredits =
pricingLogic.getRenewPrice(Registry.get(existingDomain.getTld()), targetId, now, years); pricingLogic.getRenewPrice(Registry.get(existingDomain.getTld()), targetId, now, years);
@ -261,13 +261,16 @@ public final class DomainRenewFlow implements TransactionalFlow {
} }
private ImmutableList<FeeTransformResponseExtension> createResponseExtensions( private ImmutableList<FeeTransformResponseExtension> createResponseExtensions(
Money renewCost, FeeRenewCommandExtension feeRenew) { Money renewCost, Optional<FeeRenewCommandExtension> feeRenew) {
return (feeRenew == null) return feeRenew.isPresent()
? ImmutableList.of() ? ImmutableList.of(
: ImmutableList.of(feeRenew.createResponseBuilder() feeRenew
.setCurrency(renewCost.getCurrencyUnit()) .get()
.setFees(ImmutableList.of(Fee.create(renewCost.getAmount(), FeeType.RENEW))) .createResponseBuilder()
.build()); .setCurrency(renewCost.getCurrencyUnit())
.setFees(ImmutableList.of(Fee.create(renewCost.getAmount(), FeeType.RENEW)))
.build())
: ImmutableList.of();
} }
/** The current expiration date is incorrect. */ /** The current expiration date is incorrect. */

View file

@ -134,7 +134,7 @@ public final class DomainRestoreRequestFlow implements TransactionalFlow {
DomainResource existingDomain = loadAndVerifyExistence(DomainResource.class, targetId, now); DomainResource existingDomain = loadAndVerifyExistence(DomainResource.class, targetId, now);
FeesAndCredits feesAndCredits = FeesAndCredits feesAndCredits =
pricingLogic.getRestorePrice(Registry.get(existingDomain.getTld()), targetId, now); pricingLogic.getRestorePrice(Registry.get(existingDomain.getTld()), targetId, now);
FeeUpdateCommandExtension feeUpdate = Optional<FeeUpdateCommandExtension> feeUpdate =
eppInput.getSingleExtension(FeeUpdateCommandExtension.class); eppInput.getSingleExtension(FeeUpdateCommandExtension.class);
verifyRestoreAllowed(command, existingDomain, feeUpdate, feesAndCredits, now); verifyRestoreAllowed(command, existingDomain, feeUpdate, feesAndCredits, now);
HistoryEntry historyEntry = buildHistoryEntry(existingDomain, now); HistoryEntry historyEntry = buildHistoryEntry(existingDomain, now);
@ -186,7 +186,7 @@ public final class DomainRestoreRequestFlow implements TransactionalFlow {
private void verifyRestoreAllowed( private void verifyRestoreAllowed(
Update command, Update command,
DomainResource existingDomain, DomainResource existingDomain,
FeeUpdateCommandExtension feeUpdate, Optional<FeeUpdateCommandExtension> feeUpdate,
FeesAndCredits feesAndCredits, FeesAndCredits feesAndCredits,
DateTime now) throws EppException { DateTime now) throws EppException {
verifyOptionalAuthInfo(authInfo, existingDomain); verifyOptionalAuthInfo(authInfo, existingDomain);
@ -261,15 +261,19 @@ public final class DomainRestoreRequestFlow implements TransactionalFlow {
} }
private static ImmutableList<FeeTransformResponseExtension> createResponseExtensions( private static ImmutableList<FeeTransformResponseExtension> createResponseExtensions(
Money restoreCost, Money renewCost, FeeUpdateCommandExtension feeUpdate) { Money restoreCost, Money renewCost, Optional<FeeUpdateCommandExtension> feeUpdate) {
return (feeUpdate == null) return feeUpdate.isPresent()
? ImmutableList.of() ? ImmutableList.of(
: ImmutableList.of(feeUpdate.createResponseBuilder() feeUpdate
.setCurrency(restoreCost.getCurrencyUnit()) .get()
.setFees(ImmutableList.of( .createResponseBuilder()
Fee.create(restoreCost.getAmount(), FeeType.RESTORE), .setCurrency(restoreCost.getCurrencyUnit())
Fee.create(renewCost.getAmount(), FeeType.RENEW))) .setFees(
.build()); ImmutableList.of(
Fee.create(restoreCost.getAmount(), FeeType.RESTORE),
Fee.create(renewCost.getAmount(), FeeType.RENEW)))
.build())
: ImmutableList.of();
} }
/** Restore command cannot have other changes specified. */ /** Restore command cannot have other changes specified. */

View file

@ -139,19 +139,19 @@ public final class DomainTransferRequestFlow implements TransactionalFlow {
validateClientIsLoggedIn(gainingClientId); validateClientIsLoggedIn(gainingClientId);
DateTime now = ofy().getTransactionTime(); DateTime now = ofy().getTransactionTime();
DomainResource existingDomain = loadAndVerifyExistence(DomainResource.class, targetId, now); DomainResource existingDomain = loadAndVerifyExistence(DomainResource.class, targetId, now);
DomainTransferRequestSuperuserExtension superuserExtension = Optional<DomainTransferRequestSuperuserExtension> superuserExtension =
eppInput.getSingleExtension(DomainTransferRequestSuperuserExtension.class); eppInput.getSingleExtension(DomainTransferRequestSuperuserExtension.class);
Period period = Period period =
(superuserExtension == null) superuserExtension.isPresent()
? ((Transfer) resourceCommand).getPeriod() ? superuserExtension.get().getRenewalPeriod()
: superuserExtension.getRenewalPeriod(); : ((Transfer) resourceCommand).getPeriod();
verifyTransferAllowed(existingDomain, period, now, superuserExtension); verifyTransferAllowed(existingDomain, period, now, superuserExtension);
String tld = existingDomain.getTld(); String tld = existingDomain.getTld();
Registry registry = Registry.get(tld); Registry registry = Registry.get(tld);
// An optional extension from the client specifying what they think the transfer should cost. // An optional extension from the client specifying what they think the transfer should cost.
FeeTransferCommandExtension feeTransfer = Optional<FeeTransferCommandExtension> feeTransfer =
eppInput.getSingleExtension(FeeTransferCommandExtension.class); eppInput.getSingleExtension(FeeTransferCommandExtension.class);
if (period.getValue() == 0 && feeTransfer != null) { if (period.getValue() == 0 && feeTransfer.isPresent()) {
// If the period is zero, then there is no transfer billing event, so using the fee transfer // If the period is zero, then there is no transfer billing event, so using the fee transfer
// extension does not make sense. // extension does not make sense.
throw new TransferPeriodZeroAndFeeTransferExtensionException(); throw new TransferPeriodZeroAndFeeTransferExtensionException();
@ -166,9 +166,9 @@ public final class DomainTransferRequestFlow implements TransactionalFlow {
} }
HistoryEntry historyEntry = buildHistoryEntry(existingDomain, registry, now, period); HistoryEntry historyEntry = buildHistoryEntry(existingDomain, registry, now, period);
DateTime automaticTransferTime = DateTime automaticTransferTime =
(superuserExtension == null) superuserExtension.isPresent()
? now.plus(registry.getAutomaticTransferLength()) ? now.plusDays(superuserExtension.get().getAutomaticTransferLength())
: now.plusDays(superuserExtension.getAutomaticTransferLength()); : now.plus(registry.getAutomaticTransferLength());
// If the domain will be in the auto-renew grace period at the moment of transfer, the transfer // If the domain will be in the auto-renew grace period at the moment of transfer, the transfer
// will subsume the autorenew, so we don't add the normal extra year from the transfer. // will subsume the autorenew, so we don't add the normal extra year from the transfer.
// The gaining registrar is still billed for the extra year; the losing registrar will get a // The gaining registrar is still billed for the extra year; the losing registrar will get a
@ -241,7 +241,7 @@ public final class DomainTransferRequestFlow implements TransactionalFlow {
DomainResource existingDomain, DomainResource existingDomain,
Period period, Period period,
DateTime now, DateTime now,
final DomainTransferRequestSuperuserExtension superuserExtension) Optional<DomainTransferRequestSuperuserExtension> superuserExtension)
throws EppException { throws EppException {
verifyNoDisallowedStatuses(existingDomain, DISALLOWED_STATUSES); verifyNoDisallowedStatuses(existingDomain, DISALLOWED_STATUSES);
verifyAuthInfoPresentForResourceTransfer(authInfo); verifyAuthInfoPresentForResourceTransfer(authInfo);
@ -283,19 +283,19 @@ public final class DomainTransferRequestFlow implements TransactionalFlow {
* will simply default to one year. * will simply default to one year.
*/ */
private static void verifyTransferPeriod( private static void verifyTransferPeriod(
Period period, DomainTransferRequestSuperuserExtension superuserExtension) Period period, Optional<DomainTransferRequestSuperuserExtension> superuserExtension)
throws EppException { throws EppException {
verifyUnitIsYears(period); verifyUnitIsYears(period);
if (superuserExtension == null) { if (superuserExtension.isPresent()) {
// If the superuser extension is not being used, then the period can only be one.
if (period.getValue() != 1) {
throw new TransferPeriodMustBeOneYearException();
}
} else {
// If the superuser extension is being used, then the period can be one or zero. // If the superuser extension is being used, then the period can be one or zero.
if (period.getValue() != 1 && period.getValue() != 0) { if (period.getValue() != 1 && period.getValue() != 0) {
throw new InvalidTransferPeriodValueException(); throw new InvalidTransferPeriodValueException();
} }
} else {
// If the superuser extension is not being used, then the period can only be one.
if (period.getValue() != 1) {
throw new TransferPeriodMustBeOneYearException();
}
} }
} }
@ -332,13 +332,16 @@ public final class DomainTransferRequestFlow implements TransactionalFlow {
} }
private static ImmutableList<FeeTransformResponseExtension> createResponseExtensions( private static ImmutableList<FeeTransformResponseExtension> createResponseExtensions(
Optional<FeesAndCredits> feesAndCredits, FeeTransferCommandExtension feeTransfer) { Optional<FeesAndCredits> feesAndCredits, Optional<FeeTransferCommandExtension> feeTransfer) {
return (feeTransfer == null || !feesAndCredits.isPresent()) return (feeTransfer.isPresent() && feesAndCredits.isPresent())
? ImmutableList.of() ? ImmutableList.of(
: ImmutableList.of(feeTransfer.createResponseBuilder() feeTransfer
.setFees(feesAndCredits.get().getFees()) .get()
.setCredits(feesAndCredits.get().getCredits()) .createResponseBuilder()
.setCurrency(feesAndCredits.get().getCurrency()) .setFees(feesAndCredits.get().getFees())
.build()); .setCredits(feesAndCredits.get().getCredits())
.setCurrency(feesAndCredits.get().getCurrency())
.build())
: ImmutableList.of();
} }
} }

View file

@ -68,7 +68,6 @@ import google.registry.model.domain.DomainCommand.Update.AddRemove;
import google.registry.model.domain.DomainCommand.Update.Change; import google.registry.model.domain.DomainCommand.Update.Change;
import google.registry.model.domain.DomainResource; import google.registry.model.domain.DomainResource;
import google.registry.model.domain.GracePeriod; import google.registry.model.domain.GracePeriod;
import google.registry.model.domain.fee.FeeTransformCommandExtension;
import google.registry.model.domain.fee.FeeUpdateCommandExtension; import google.registry.model.domain.fee.FeeUpdateCommandExtension;
import google.registry.model.domain.metadata.MetadataExtension; import google.registry.model.domain.metadata.MetadataExtension;
import google.registry.model.domain.rgp.GracePeriodStatus; import google.registry.model.domain.rgp.GracePeriodStatus;
@ -222,13 +221,13 @@ public final class DomainUpdateFlow implements TransactionalFlow {
checkAllowedAccessToTld(clientId, tld); checkAllowedAccessToTld(clientId, tld);
} }
Registry registry = Registry.get(tld); Registry registry = Registry.get(tld);
FeeTransformCommandExtension feeUpdate = Optional<FeeUpdateCommandExtension> feeUpdate =
eppInput.getSingleExtension(FeeUpdateCommandExtension.class); eppInput.getSingleExtension(FeeUpdateCommandExtension.class);
// If the fee extension is present, validate it (even if the cost is zero, to check for price // If the fee extension is present, validate it (even if the cost is zero, to check for price
// mismatches). Don't rely on the the validateFeeChallenge check for feeUpdate nullness, because // mismatches). Don't rely on the the validateFeeChallenge check for feeUpdate nullness, because
// it throws an error if the name is premium, and we don't want to do that here. // it throws an error if the name is premium, and we don't want to do that here.
FeesAndCredits feesAndCredits = pricingLogic.getUpdatePrice(registry, targetId, now); FeesAndCredits feesAndCredits = pricingLogic.getUpdatePrice(registry, targetId, now);
if (feeUpdate != null) { if (feeUpdate.isPresent()) {
validateFeeChallenge(targetId, existingDomain.getTld(), now, feeUpdate, feesAndCredits); validateFeeChallenge(targetId, existingDomain.getTld(), now, feeUpdate, feesAndCredits);
} else if (!feesAndCredits.getTotalCost().isZero()) { } else if (!feesAndCredits.getTotalCost().isZero()) {
// If it's not present but the cost is not zero, throw an exception. // If it's not present but the cost is not zero, throw an exception.
@ -268,14 +267,15 @@ public final class DomainUpdateFlow implements TransactionalFlow {
checkSameValuesNotAddedAndRemoved(add.getContacts(), remove.getContacts()); checkSameValuesNotAddedAndRemoved(add.getContacts(), remove.getContacts());
checkSameValuesNotAddedAndRemoved(add.getStatusValues(), remove.getStatusValues()); checkSameValuesNotAddedAndRemoved(add.getStatusValues(), remove.getStatusValues());
Change change = command.getInnerChange(); Change change = command.getInnerChange();
SecDnsUpdateExtension secDnsUpdate = eppInput.getSingleExtension(SecDnsUpdateExtension.class); Optional<SecDnsUpdateExtension> secDnsUpdate =
eppInput.getSingleExtension(SecDnsUpdateExtension.class);
DomainResource.Builder domainBuilder = DomainResource.Builder domainBuilder =
domain domain
.asBuilder() .asBuilder()
// Handle the secDNS extension. // Handle the secDNS extension.
.setDsData( .setDsData(
secDnsUpdate != null secDnsUpdate.isPresent()
? updateDsData(domain.getDsData(), secDnsUpdate) ? updateDsData(domain.getDsData(), secDnsUpdate.get())
: domain.getDsData()) : domain.getDsData())
.setLastEppUpdateTime(now) .setLastEppUpdateTime(now)
.setLastEppUpdateClientId(clientId) .setLastEppUpdateClientId(clientId)
@ -355,8 +355,9 @@ public final class DomainUpdateFlow implements TransactionalFlow {
DomainResource newDomain, DomainResource newDomain,
HistoryEntry historyEntry, HistoryEntry historyEntry,
DateTime now) { DateTime now) {
MetadataExtension metadataExtension = eppInput.getSingleExtension(MetadataExtension.class); Optional<MetadataExtension> metadataExtension =
if (metadataExtension != null && metadataExtension.getRequestedByRegistrar()) { eppInput.getSingleExtension(MetadataExtension.class);
if (metadataExtension.isPresent() && metadataExtension.get().getRequestedByRegistrar()) {
for (StatusValue statusValue for (StatusValue statusValue
: symmetricDifference(existingDomain.getStatusValues(), newDomain.getStatusValues())) { : symmetricDifference(existingDomain.getStatusValues(), newDomain.getStatusValues())) {
if (statusValue.isChargedStatus()) { if (statusValue.isChargedStatus()) {

View file

@ -85,6 +85,7 @@ import google.registry.model.eppinput.EppInput.Transfer.TransferOp;
import google.registry.model.eppinput.ResourceCommand; import google.registry.model.eppinput.ResourceCommand;
import google.registry.model.host.HostCommand; import google.registry.model.host.HostCommand;
import java.util.Map; import java.util.Map;
import java.util.Optional;
import java.util.Set; import java.util.Set;
/** Class that picks a flow to handle a given EPP command. */ /** Class that picks a flow to handle a given EPP command. */
@ -163,12 +164,13 @@ public class FlowPicker {
if (!(resourceCommand instanceof DomainCommand.Update)) { if (!(resourceCommand instanceof DomainCommand.Update)) {
return null; return null;
} }
RgpUpdateExtension rgpUpdateExtension = eppInput.getSingleExtension(RgpUpdateExtension.class); Optional<RgpUpdateExtension> rgpUpdateExtension =
if (rgpUpdateExtension == null) { eppInput.getSingleExtension(RgpUpdateExtension.class);
if (!rgpUpdateExtension.isPresent()) {
return null; return null;
} }
// Restore command with an op of "report" is not currently supported. // Restore command with an op of "report" is not currently supported.
return (rgpUpdateExtension.getRestoreCommand().getRestoreOp() == RestoreOp.REQUEST) return (rgpUpdateExtension.get().getRestoreCommand().getRestoreOp() == RestoreOp.REQUEST)
? DomainRestoreRequestFlow.class ? DomainRestoreRequestFlow.class
: UnimplementedFlow.class; : UnimplementedFlow.class;
}}; }};
@ -177,24 +179,29 @@ public class FlowPicker {
* The claims check flow is keyed on the type of the {@link ResourceCommand} and on having the * The claims check flow is keyed on the type of the {@link ResourceCommand} and on having the
* correct extension with a specific phase value. * correct extension with a specific phase value.
*/ */
private static final FlowProvider DOMAIN_CHECK_FLOW_PROVIDER = new FlowProvider() { private static final FlowProvider DOMAIN_CHECK_FLOW_PROVIDER =
@Override new FlowProvider() {
Class<? extends Flow> get( @Override
EppInput eppInput, InnerCommand innerCommand, ResourceCommand resourceCommand) { Class<? extends Flow> get(
if (!(resourceCommand instanceof DomainCommand.Check)) { EppInput eppInput, InnerCommand innerCommand, ResourceCommand resourceCommand) {
return null; if (!(resourceCommand instanceof DomainCommand.Check)) {
} return null;
LaunchCheckExtension extension = eppInput.getSingleExtension(LaunchCheckExtension.class); }
if (extension == null || CheckType.AVAILABILITY.equals(extension.getCheckType())) { Optional<LaunchCheckExtension> launchCheck =
// We don't distinguish between registry phases for "avail", so don't bother checking phase. eppInput.getSingleExtension(LaunchCheckExtension.class);
return DomainCheckFlow.class; if (!launchCheck.isPresent()
} || CheckType.AVAILABILITY.equals(launchCheck.get().getCheckType())) {
if (CheckType.CLAIMS.equals(extension.getCheckType()) // We don't distinguish between registry phases for "avail", so don't bother checking
&& LaunchPhase.CLAIMS.equals(extension.getPhase())) { // phase.
return DomainClaimsCheckFlow.class; return DomainCheckFlow.class;
} }
return null; if (CheckType.CLAIMS.equals(launchCheck.get().getCheckType())
}}; && LaunchPhase.CLAIMS.equals(launchCheck.get().getPhase())) {
return DomainClaimsCheckFlow.class;
}
return null;
}
};
/** General resource CRUD flows are keyed on the type of their {@link ResourceCommand}. */ /** General resource CRUD flows are keyed on the type of their {@link ResourceCommand}. */
private static final FlowProvider RESOURCE_CRUD_FLOW_PROVIDER = new FlowProvider() { private static final FlowProvider RESOURCE_CRUD_FLOW_PROVIDER = new FlowProvider() {
@ -224,50 +231,57 @@ public class FlowPicker {
}}; }};
/** The domain allocate flow has a specific extension. */ /** The domain allocate flow has a specific extension. */
private static final FlowProvider ALLOCATE_FLOW_PROVIDER = new FlowProvider() { private static final FlowProvider ALLOCATE_FLOW_PROVIDER =
@Override new FlowProvider() {
Class<? extends Flow> get( @Override
EppInput eppInput, InnerCommand innerCommand, ResourceCommand resourceCommand) { Class<? extends Flow> get(
return (resourceCommand instanceof DomainCommand.Create EppInput eppInput, InnerCommand innerCommand, ResourceCommand resourceCommand) {
&& eppInput.getSingleExtension(AllocateCreateExtension.class) != null) return (resourceCommand instanceof DomainCommand.Create
? DomainAllocateFlow.class : null; && eppInput.getSingleExtension(AllocateCreateExtension.class).isPresent())
}}; ? DomainAllocateFlow.class
: null;
}
};
/** /**
* Application CRUD flows have an extension and are keyed on the type of their * Application CRUD flows have an extension and are keyed on the type of their {@link
* {@link ResourceCommand}. * ResourceCommand}.
*/ */
private static final FlowProvider APPLICATION_CRUD_FLOW_PROVIDER = new FlowProvider() { private static final FlowProvider APPLICATION_CRUD_FLOW_PROVIDER =
new FlowProvider() {
private final Map<Class<? extends ResourceCommand>, Class<? extends Flow>> applicationFlows = private final Map<Class<? extends ResourceCommand>, Class<? extends Flow>>
ImmutableMap.of( applicationFlows =
DomainCommand.Create.class, DomainApplicationCreateFlow.class, ImmutableMap.of(
DomainCommand.Delete.class, DomainApplicationDeleteFlow.class, DomainCommand.Create.class, DomainApplicationCreateFlow.class,
DomainCommand.Info.class, DomainApplicationInfoFlow.class, DomainCommand.Delete.class, DomainApplicationDeleteFlow.class,
DomainCommand.Update.class, DomainApplicationUpdateFlow.class); DomainCommand.Info.class, DomainApplicationInfoFlow.class,
DomainCommand.Update.class, DomainApplicationUpdateFlow.class);
private final Set<LaunchPhase> launchPhases = ImmutableSet.of( private final Set<LaunchPhase> launchPhases =
LaunchPhase.SUNRISE, LaunchPhase.SUNRUSH, LaunchPhase.LANDRUSH); ImmutableSet.of(LaunchPhase.SUNRISE, LaunchPhase.SUNRUSH, LaunchPhase.LANDRUSH);
@Override @Override
Class<? extends Flow> get( Class<? extends Flow> get(
EppInput eppInput, InnerCommand innerCommand, ResourceCommand resourceCommand) { EppInput eppInput, InnerCommand innerCommand, ResourceCommand resourceCommand) {
if (eppInput.getSingleExtension(ApplicationIdTargetExtension.class) != null) { if (eppInput.getSingleExtension(ApplicationIdTargetExtension.class).isPresent()) {
return applicationFlows.get(resourceCommand.getClass()); return applicationFlows.get(resourceCommand.getClass());
} }
LaunchCreateExtension createExtension = Optional<LaunchCreateExtension> createExtension =
eppInput.getSingleExtension(LaunchCreateExtension.class); eppInput.getSingleExtension(LaunchCreateExtension.class);
// Return a flow if the type is APPLICATION, or if it's null and we are in a launch phase. // Return a flow if the type is APPLICATION, or if it's null and we are in a launch phase.
// If the type is specified as REGISTRATION, return null. // If the type is specified as REGISTRATION, return null.
if (createExtension != null) { if (createExtension.isPresent()) {
LaunchPhase launchPhase = createExtension.getPhase(); LaunchPhase launchPhase = createExtension.get().getPhase();
if (APPLICATION.equals(createExtension.getCreateType()) if (APPLICATION.equals(createExtension.get().getCreateType())
|| (createExtension.getCreateType() == null && launchPhases.contains(launchPhase))) { || (createExtension.get().getCreateType() == null
return applicationFlows.get(resourceCommand.getClass()); && launchPhases.contains(launchPhase))) {
return applicationFlows.get(resourceCommand.getClass());
}
}
return null;
} }
} };
return null;
}};
/** Transfer flows have an {@link InnerCommand} of type {@link Transfer}. */ /** Transfer flows have an {@link InnerCommand} of type {@link Transfer}. */
private static final FlowProvider TRANSFER_FLOW_PROVIDER = new FlowProvider() { private static final FlowProvider TRANSFER_FLOW_PROVIDER = new FlowProvider() {

View file

@ -151,15 +151,15 @@ public class EppInput extends ImmutableObject {
} }
/** Get the extension based on type, or null. If there are multiple, it chooses the first. */ /** Get the extension based on type, or null. If there are multiple, it chooses the first. */
@Nullable public <E extends CommandExtension> Optional<E> getSingleExtension(Class<E> clazz) {
public <E extends CommandExtension> E getSingleExtension(Class<E> clazz) { return Optional.ofNullable(
return getCommandWrapper() getCommandWrapper()
.getExtensions() .getExtensions()
.stream() .stream()
.filter(clazz::isInstance) .filter(clazz::isInstance)
.map(clazz::cast) .map(clazz::cast)
.findFirst() .findFirst()
.orElse(null); .orElse(null));
} }
/** A tag that goes inside of an EPP {@literal <command>}. */ /** A tag that goes inside of an EPP {@literal <command>}. */

View file

@ -105,20 +105,20 @@ public class VerifyOteAction implements Runnable, JsonAction {
private static final Predicate<EppInput> HAS_CLAIMS_NOTICE = private static final Predicate<EppInput> HAS_CLAIMS_NOTICE =
eppInput -> { eppInput -> {
LaunchCreateExtension launchCreate = Optional<LaunchCreateExtension> launchCreate =
eppInput.getSingleExtension(LaunchCreateExtension.class); eppInput.getSingleExtension(LaunchCreateExtension.class);
return launchCreate != null && launchCreate.getNotice() != null; return launchCreate.isPresent() && launchCreate.get().getNotice() != null;
}; };
private static final Predicate<EppInput> HAS_SEC_DNS = private static final Predicate<EppInput> HAS_SEC_DNS =
eppInput -> eppInput ->
(eppInput.getSingleExtension(SecDnsCreateExtension.class) != null) (eppInput.getSingleExtension(SecDnsCreateExtension.class).isPresent())
|| (eppInput.getSingleExtension(SecDnsUpdateExtension.class) != null); || (eppInput.getSingleExtension(SecDnsUpdateExtension.class).isPresent());
private static final Predicate<EppInput> IS_SUNRISE = private static final Predicate<EppInput> IS_SUNRISE =
eppInput -> { eppInput -> {
LaunchCreateExtension launchCreate = Optional<LaunchCreateExtension> launchCreate =
eppInput.getSingleExtension(LaunchCreateExtension.class); eppInput.getSingleExtension(LaunchCreateExtension.class);
return launchCreate != null && !isNullOrEmpty(launchCreate.getSignedMarks()); return launchCreate.isPresent() && !isNullOrEmpty(launchCreate.get().getSignedMarks());
}; };
private static final Predicate<EppInput> IS_IDN = private static final Predicate<EppInput> IS_IDN =
@ -158,7 +158,7 @@ public class VerifyOteAction implements Runnable, JsonAction {
DOMAIN_CREATES_WITH_FEE( DOMAIN_CREATES_WITH_FEE(
1, 1,
equalTo(Type.DOMAIN_CREATE), equalTo(Type.DOMAIN_CREATE),
eppInput -> eppInput.getSingleExtension(FeeCreateCommandExtension.class) != null), eppInput -> eppInput.getSingleExtension(FeeCreateCommandExtension.class).isPresent()),
DOMAIN_CREATES_WITH_SEC_DNS(1, equalTo(Type.DOMAIN_CREATE), HAS_SEC_DNS), DOMAIN_CREATES_WITH_SEC_DNS(1, equalTo(Type.DOMAIN_CREATE), HAS_SEC_DNS),
DOMAIN_CREATES_WITHOUT_SEC_DNS(0, equalTo(Type.DOMAIN_CREATE), HAS_SEC_DNS.negate()), DOMAIN_CREATES_WITHOUT_SEC_DNS(0, equalTo(Type.DOMAIN_CREATE), HAS_SEC_DNS.negate()),
DOMAIN_DELETES(2, equalTo(Type.DOMAIN_DELETE)), DOMAIN_DELETES(2, equalTo(Type.DOMAIN_DELETE)),

View file

@ -43,6 +43,7 @@ import google.registry.model.tmch.ClaimsListShard.ClaimsListRevision;
import google.registry.model.tmch.ClaimsListShard.ClaimsListSingleton; import google.registry.model.tmch.ClaimsListShard.ClaimsListSingleton;
import google.registry.testing.TaskQueueHelper.TaskMatcher; import google.registry.testing.TaskQueueHelper.TaskMatcher;
import google.registry.util.TypeUtils.TypeInstantiator; import google.registry.util.TypeUtils.TypeInstantiator;
import java.util.Optional;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import org.joda.time.DateTime; import org.joda.time.DateTime;
@ -106,9 +107,11 @@ public abstract class ResourceFlowTestCase<F extends Flow, R extends EppResource
* the test code rather than the production code. * the test code rather than the production code.
*/ */
protected String getUniqueIdFromCommand() throws Exception { protected String getUniqueIdFromCommand() throws Exception {
ApplicationIdTargetExtension extension = Optional<ApplicationIdTargetExtension> extension =
eppLoader.getEpp().getSingleExtension(ApplicationIdTargetExtension.class); eppLoader.getEpp().getSingleExtension(ApplicationIdTargetExtension.class);
return extension == null ? getResourceCommand().getTargetId() : extension.getApplicationId(); return extension.isPresent()
? extension.get().getApplicationId()
: getResourceCommand().getTargetId();
} }
protected Class<R> getResourceClass() { protected Class<R> getResourceClass() {

View file

@ -122,6 +122,7 @@ public class DomainApplicationInfoFlowTest
new EppLoader(this, "domain_create_sunrise_encoded_signed_mark.xml") new EppLoader(this, "domain_create_sunrise_encoded_signed_mark.xml")
.getEpp() .getEpp()
.getSingleExtension(LaunchCreateExtension.class) .getSingleExtension(LaunchCreateExtension.class)
.get()
.getSignedMarks() .getSignedMarks()
.get(0)) .get(0))
: null) : null)