// 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. * *
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 {} }