google-nomulus/java/google/registry/flows/FlowModule.java
cgoldfeder efd3424849 Change to FlowModule to support the new flat flows
This factors out a huge chunk of boilerplate that
would otherwise be in every single flow.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=133014837
2016-09-14 15:57:31 -04:00

241 lines
6.4 KiB
Java

// 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.flows;
import static com.google.common.base.Preconditions.checkState;
import dagger.Module;
import dagger.Provides;
import google.registry.flows.exceptions.OnlyToolCanPassMetadataException;
import google.registry.flows.picker.FlowPicker;
import google.registry.model.domain.metadata.MetadataExtension;
import google.registry.model.eppcommon.Trid;
import google.registry.model.eppinput.EppInput;
import google.registry.model.eppinput.EppInput.ResourceCommandWrapper;
import google.registry.model.eppinput.ResourceCommand;
import google.registry.model.reporting.HistoryEntry;
import java.lang.annotation.Documented;
import javax.annotation.Nullable;
import javax.inject.Qualifier;
/** Module to choose and instantiate an EPP flow. */
@Module
public class FlowModule {
private EppInput eppInput;
private byte[] inputXmlBytes;
private SessionMetadata sessionMetadata;
private TransportCredentials credentials;
private boolean isDryRun;
private EppRequestSource eppRequestSource;
private boolean isSuperuser;
private FlowModule() {}
/** Builder for {@link FlowModule}. */
static class Builder {
FlowModule module = new FlowModule();
Builder setEppInput(EppInput eppInput) {
module.eppInput = eppInput;
return this;
}
Builder setInputXmlBytes(byte[] inputXmlBytes) {
module.inputXmlBytes = inputXmlBytes;
return this;
}
Builder setSessionMetadata(SessionMetadata sessionMetadata) {
module.sessionMetadata = sessionMetadata;
return this;
}
Builder setIsDryRun(boolean isDryRun) {
module.isDryRun = isDryRun;
return this;
}
Builder setIsSuperuser(boolean isSuperuser) {
module.isSuperuser = isSuperuser;
return this;
}
Builder setEppRequestSource(EppRequestSource eppRequestSource) {
module.eppRequestSource = eppRequestSource;
return this;
}
Builder setCredentials(TransportCredentials credentials) {
module.credentials = credentials;
return this;
}
FlowModule build() {
try {
checkState(module != null, "Already built");
return module;
} finally {
module = null;
}
}
}
@Provides
@FlowScope
@InputXml
byte[] provideInputXml() {
return inputXmlBytes;
}
@Provides
@FlowScope
EppInput provideEppInput() {
return eppInput;
}
@Provides
@FlowScope
SessionMetadata provideSessionMetadata() {
return sessionMetadata;
}
@Provides
@FlowScope
@DryRun
boolean provideIsDryRun() {
return isDryRun;
}
@Provides
@FlowScope
@Transactional
boolean provideIsTransactional(Class<? extends Flow> flowClass) {
return TransactionalFlow.class.isAssignableFrom(flowClass);
}
@Provides
@FlowScope
@Superuser
boolean provideIsSuperuser() {
return isSuperuser;
}
@Provides
@FlowScope
EppRequestSource provideEppRequestSource() {
return eppRequestSource;
}
@Provides
@FlowScope
TransportCredentials provideTransportCredentials() {
return credentials;
}
@Provides
@FlowScope
@Nullable
@ClientId
static String provideClientId(SessionMetadata sessionMetadata) {
return sessionMetadata.getClientId();
}
@Provides
@FlowScope
static Trid provideTrid(EppInput eppInput) {
return Trid.create(eppInput.getCommandWrapper().getClTrid());
}
@Provides
@FlowScope
static Class<? extends Flow> provideFlowClass(EppInput eppInput) {
try {
return FlowPicker.getFlowClass(eppInput);
} catch (EppException e) {
throw new EppExceptionInProviderException(e);
}
}
@Provides
@FlowScope
static ResourceCommand provideResourceCommand(EppInput eppInput) {
return ((ResourceCommandWrapper) eppInput.getCommandWrapper().getCommand())
.getResourceCommand();
}
/**
* Provides a partially filled in {@link HistoryEntry} builder.
*
* <p>This is not marked with {@link FlowScope} so that each retry gets a fresh one. Otherwise,
* the fact that the builder is one-use would cause NPEs.
*/
@Provides
static HistoryEntry.Builder provideHistoryEntryBuilder(
Trid trid,
@InputXml byte[] inputXmlBytes,
@Superuser boolean isSuperuser,
@ClientId @Nullable String clientId,
EppRequestSource eppRequestSource,
EppInput eppInput) {
HistoryEntry.Builder historyBuilder = new HistoryEntry.Builder()
.setTrid(trid)
.setXmlBytes(inputXmlBytes)
.setBySuperuser(isSuperuser)
.setClientId(clientId);
MetadataExtension metadataExtension = eppInput.getSingleExtension(MetadataExtension.class);
if (metadataExtension != null) {
if (!eppRequestSource.equals(EppRequestSource.TOOL)) {
throw new EppExceptionInProviderException(new OnlyToolCanPassMetadataException());
}
historyBuilder
.setReason(metadataExtension.getReason())
.setRequestedByRegistrar(metadataExtension.getRequestedByRegistrar());
}
return historyBuilder;
}
/** Wrapper class to carry an {@link EppException} to the calling code. */
static class EppExceptionInProviderException extends RuntimeException {
EppExceptionInProviderException(EppException exception) {
super(exception);
}
}
/** Dagger qualifier for inputXml. */
@Qualifier
@Documented
public @interface InputXml {}
/** Dagger qualifier for registrar client id. */
@Qualifier
@Documented
public @interface ClientId {}
/** Dagger qualifier for whether a flow is in dry run mode. */
@Qualifier
@Documented
public @interface DryRun {}
/** Dagger qualifier for whether a flow is in superuser mode. */
@Qualifier
@Documented
public @interface Superuser {}
/** Dagger qualifier for whether a flow is transactional. */
@Qualifier
@Documented
public @interface Transactional {}
}