mv com/google/domain/registry google/registry

This change renames directories in preparation for the great package
rename. The repository is now in a broken state because the code
itself hasn't been updated. However this should ensure that git
correctly preserves history for each file.
This commit is contained in:
Justine Tunney 2016-05-13 18:55:08 -04:00
parent a41677aea1
commit 5012893c1d
2396 changed files with 0 additions and 0 deletions

View file

@ -0,0 +1,73 @@
// 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 com.google.domain.registry.model.domain;
import com.google.common.annotations.VisibleForTesting;
import com.google.domain.registry.model.ImmutableObject;
import com.google.domain.registry.model.contact.ContactResource;
import com.googlecode.objectify.annotation.Embed;
import com.googlecode.objectify.annotation.Index;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlEnumValue;
import javax.xml.bind.annotation.XmlValue;
/**
* XML type for contact identifiers associated with a domain.
*
* @see "http://tools.ietf.org/html/rfc5731#section-2.2"
*/
@Embed
public class DesignatedContact extends ImmutableObject {
/**
* XML type for contact types. This can be either: {@code "admin"}, {@code "billing"}, or
* {@code "tech"} and corresponds to {@code contactAttrType} in {@code domain-1.0.xsd}.
*/
public enum Type {
@XmlEnumValue("admin")
ADMIN,
@XmlEnumValue("billing")
BILLING,
@XmlEnumValue("tech")
TECH,
/** The registrant type is not reflected in XML and exists only for internal use. */
REGISTRANT;
}
@VisibleForTesting
public static DesignatedContact create(Type type, ReferenceUnion<ContactResource> contact) {
DesignatedContact instance = new DesignatedContact();
instance.type = type;
instance.contactId = contact;
return instance;
}
@XmlAttribute(required = true)
Type type;
@Index
@XmlValue
ReferenceUnion<ContactResource> contactId;
public Type getType() {
return type;
}
public ReferenceUnion<ContactResource> getContactId() {
return contactId;
}
}

View file

@ -0,0 +1,173 @@
// 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 com.google.domain.registry.model.domain;
import static com.google.domain.registry.model.ofy.Ofy.RECOMMENDED_MEMCACHE_EXPIRATION;
import static com.google.domain.registry.util.CollectionUtils.nullToEmptyImmutableCopy;
import com.google.common.collect.ImmutableList;
import com.google.domain.registry.model.annotations.ExternalMessagingName;
import com.google.domain.registry.model.domain.launch.ApplicationStatus;
import com.google.domain.registry.model.domain.launch.LaunchPhase;
import com.google.domain.registry.model.eppcommon.Trid;
import com.google.domain.registry.model.smd.EncodedSignedMark;
import com.googlecode.objectify.annotation.Cache;
import com.googlecode.objectify.annotation.EntitySubclass;
import org.joda.money.Money;
import org.joda.time.DateTime;
import java.util.List;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
import javax.xml.bind.annotation.XmlType;
/** An application to create a domain. */
@XmlRootElement(name = "infData")
@XmlType(propOrder = {
"fullyQualifiedDomainName",
"repoId",
"status",
"registrant",
"contacts",
"nameservers",
"currentSponsorClientId",
"creationClientId",
"creationTime",
"lastEppUpdateClientId",
"lastEppUpdateTime",
"authInfo"})
@Cache(expirationSeconds = RECOMMENDED_MEMCACHE_EXPIRATION)
@EntitySubclass(index = true)
@ExternalMessagingName("application")
public class DomainApplication extends DomainBase {
/**
* The transaction id of the EPP command that created this application. This is saved off so that
* we can generate the poll message communicating the application result once it is rejected or
* allocated.
*
* <p>This field may be null for applications that were created before the field was added.
*/
@XmlTransient
Trid creationTrid;
/**
* The phase which this application is registered for. We store this only so we can return it back
* to the user on info commands.
*/
@XmlTransient
LaunchPhase phase;
/** The current status of this application. */
@XmlTransient
ApplicationStatus applicationStatus;
/** The encoded signed marks which were asserted when this application was created. */
@XmlTransient
List<EncodedSignedMark> encodedSignedMarks;
/** The amount paid at auction for the right to register the domain. Used only for reporting. */
@XmlTransient
Money auctionPrice;
@Override
public String getFullyQualifiedDomainName() {
return fullyQualifiedDomainName;
}
public Trid getCreationTrid() {
return creationTrid;
}
public LaunchPhase getPhase() {
return phase;
}
public ApplicationStatus getApplicationStatus() {
return applicationStatus;
}
public ImmutableList<EncodedSignedMark> getEncodedSignedMarks() {
return nullToEmptyImmutableCopy(encodedSignedMarks);
}
public Money getAuctionPrice() {
return auctionPrice;
}
/** Domain applications don't expose transfer time, so override this and mark it xml transient. */
@XmlTransient
@Override
public final DateTime getLastTransferTime() {
return super.getLastTransferTime();
}
/**
* The application id is the repoId.
*/
@Override
public String getForeignKey() {
return getRepoId();
}
@Override
public DomainApplication cloneProjectedAtTime(DateTime now) {
// Applications have no grace periods and can't be transferred, so there is nothing to project.
return this;
}
@Override
public Builder asBuilder() {
return new Builder(clone(this));
}
/** A builder for constructing {@link DomainApplication}, since it is immutable. */
public static class Builder extends DomainBase.Builder<DomainApplication, Builder> {
public Builder() {}
private Builder(DomainApplication instance) {
super(instance);
}
public Builder setCreationTrid(Trid creationTrid) {
getInstance().creationTrid = creationTrid;
return this;
}
public Builder setPhase(LaunchPhase phase) {
getInstance().phase = phase;
return this;
}
public Builder setApplicationStatus(ApplicationStatus applicationStatus) {
getInstance().applicationStatus = applicationStatus;
return this;
}
public Builder setEncodedSignedMarks(ImmutableList<EncodedSignedMark> encodedSignedMarks) {
getInstance().encodedSignedMarks = encodedSignedMarks;
return this;
}
public Builder setAuctionPrice(Money auctionPrice) {
getInstance().auctionPrice = auctionPrice;
return this;
}
}
}

View file

@ -0,0 +1,64 @@
// 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 com.google.domain.registry.model.domain;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.domain.registry.model.EppResource;
import com.google.domain.registry.model.contact.ContactResource;
import com.google.domain.registry.model.eppcommon.AuthInfo;
import com.googlecode.objectify.annotation.Embed;
/** A version of authInfo specifically for domains. */
@Embed
public class DomainAuthInfo extends AuthInfo {
public static DomainAuthInfo create(PasswordAuth pw) {
DomainAuthInfo instance = new DomainAuthInfo();
instance.pw = pw;
return instance;
}
@Override
public void verifyAuthorizedFor(EppResource eppResource) throws BadAuthInfoException {
DomainBase domain = (DomainBase) eppResource;
checkNotNull(getPw());
if (getRepoId() != null) {
// Make sure the repo id matches one of the contacts on the domain.
ReferenceUnion<ContactResource> foundContact = null;
for (ReferenceUnion<ContactResource> contact : domain.getReferencedContacts()) {
String contactRepoId = contact.getLinked().getKey().getName();
if (getRepoId().equals(contactRepoId)) {
foundContact = contact;
break;
}
}
if (foundContact == null) {
throw new BadAuthInfoException();
}
// Check if the password provided matches the password on the referenced contact.
if (!foundContact.getLinked().get().getAuthInfo().getPw().getValue().equals(
getPw().getValue())) {
throw new BadAuthInfoException();
}
} else {
// If not repository ID is specified, then check the password against the domain's password.
if (!domain.getAuthInfo().getPw().getValue().equals(getPw().getValue())) {
throw new BadAuthInfoException();
}
}
}
}

View file

@ -0,0 +1,294 @@
// 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 com.google.domain.registry.model.domain;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.base.Strings.isNullOrEmpty;
import static com.google.common.collect.Sets.difference;
import static com.google.common.collect.Sets.union;
import static com.google.domain.registry.model.domain.DesignatedContact.Type.REGISTRANT;
import static com.google.domain.registry.util.CollectionUtils.nullToEmptyImmutableCopy;
import static com.google.domain.registry.util.CollectionUtils.nullToEmptyImmutableSortedCopy;
import static com.google.domain.registry.util.CollectionUtils.union;
import static com.google.domain.registry.util.DomainNameUtils.getTldFromDomainName;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;
import com.google.domain.registry.model.EppResource;
import com.google.domain.registry.model.EppResourceUtils;
import com.google.domain.registry.model.contact.ContactResource;
import com.google.domain.registry.model.domain.launch.LaunchNotice;
import com.google.domain.registry.model.domain.secdns.DelegationSignerData;
import com.google.domain.registry.model.eppcommon.AuthInfo;
import com.google.domain.registry.model.host.HostResource;
import com.googlecode.objectify.annotation.Entity;
import com.googlecode.objectify.annotation.Ignore;
import com.googlecode.objectify.annotation.IgnoreSave;
import com.googlecode.objectify.annotation.Index;
import com.googlecode.objectify.annotation.OnLoad;
import com.googlecode.objectify.condition.IfNull;
import java.util.Set;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlTransient;
/** Shared base class for {@link DomainResource} and {@link DomainApplication}. */
@XmlTransient
@Entity
public abstract class DomainBase extends EppResource {
/**
* Fully qualified domain name (puny-coded), which serves as the foreign key for this domain.
* <p>
* This is only unique in the sense that for any given lifetime specified as the time range from
* (creationTime, deletionTime) there can only be one domain in the datastore with this name.
* However, there can be many domains with the same name and non-overlapping lifetimes.
*
* @invariant fullyQualifiedDomainName == fullyQualifiedDomainName.toLowerCase()
*/
@Index
@XmlElement(name = "name")
String fullyQualifiedDomainName;
/** The top level domain this is under, dernormalized from {@link #fullyQualifiedDomainName}. */
@Index
@XmlTransient
String tld;
/** References to hosts that are the nameservers for the domain. */
@XmlElementWrapper(name = "ns")
@XmlElement(name = "hostObj")
Set<ReferenceUnion<HostResource>> nameservers;
/**
* Associated contacts for the domain (other than registrant).
* <p>
* This field is marked with {@literal @}Ignore so that {@link DomainBase} subclasses won't
* persist it. Instead, the data in this field and in the {@link #registrant} are both stored in
* {@link DomainBase#allContacts} to allow for more efficient queries.
*/
@Ignore
@XmlElement(name = "contact")
Set<DesignatedContact> contacts;
/**
* The union of the contacts in {@link #contacts} and {@link #registrant}. This is so we can query
* across all contacts at once. It is maintained by the builder and by {@link #unpackageContacts}.
*/
@XmlTransient
Set<DesignatedContact> allContacts;
/**
* A reference to the registrant who registered this domain.
* <p>
* This field is marked with {@literal @}Ignore so that {@link DomainBase} subclasses won't
* persist it. Instead, the data in this field and in the {@link DomainBase#contacts} are
* both stored in {@link DomainBase#allContacts} to allow for more efficient queries.
*/
@Ignore
ReferenceUnion<ContactResource> registrant;
/** Authorization info (aka transfer secret) of the domain. */
DomainAuthInfo authInfo;
/**
* Data used to construct DS records for this domain.
* <p>
* This is {@literal @}XmlTransient because it needs to be returned under the "extension" tag
* of an info response rather than inside the "infData" tag.
*/
@XmlTransient
Set<DelegationSignerData> dsData;
/**
* The claims notice supplied when this application or domain was created, if there was one. It's
* {@literal @}XmlTransient because it's not returned in an info response.
*/
@IgnoreSave(IfNull.class)
@XmlTransient
LaunchNotice launchNotice;
/**
* Name of first IDN table associated with TLD that matched the characters in this domain label.
*
* @see com.google.domain.registry.tldconfig.idn.IdnLabelValidator#findValidIdnTableForTld
*/
@IgnoreSave(IfNull.class)
@XmlTransient
String idnTableName;
public String getFullyQualifiedDomainName() {
return fullyQualifiedDomainName;
}
public ImmutableSortedSet<DelegationSignerData> getDsData() {
return nullToEmptyImmutableSortedCopy(dsData);
}
public LaunchNotice getLaunchNotice() {
return launchNotice;
}
public String getIdnTableName() {
return idnTableName;
}
public ImmutableSet<ReferenceUnion<HostResource>> getNameservers() {
return nullToEmptyImmutableCopy(nameservers);
}
/** Loads and returns all linked nameservers. */
public ImmutableSet<HostResource> loadNameservers() {
return EppResourceUtils.loadReferencedNameservers(getNameservers());
}
public ReferenceUnion<ContactResource> getRegistrant() {
return registrant;
}
public ContactResource loadRegistrant() {
return registrant.getLinked().get();
}
public ImmutableSet<DesignatedContact> getContacts() {
return nullToEmptyImmutableCopy(contacts);
}
public AuthInfo getAuthInfo() {
return authInfo;
}
/** Returns all referenced contacts from this domain or application. */
public ImmutableSet<ReferenceUnion<ContactResource>> getReferencedContacts() {
ImmutableSet.Builder<ReferenceUnion<ContactResource>> contactsBuilder =
new ImmutableSet.Builder<>();
for (DesignatedContact designated : nullToEmptyImmutableCopy(allContacts)) {
contactsBuilder.add(designated.getContactId());
}
return contactsBuilder.build();
}
/** Loads and returns all referenced contacts from this domain or application. */
public ImmutableSet<ContactResource> loadReferencedContacts() {
return EppResourceUtils.loadReferencedContacts(getReferencedContacts());
}
public String getTld() {
return tld;
}
/**
* On load, unpackage the {@link #allContacts} field, placing the registrant into
* {@link #registrant} field and all other contacts into {@link #contacts}.
*/
@OnLoad
void unpackageContacts() {
ImmutableSet.Builder<DesignatedContact> contactsBuilder = new ImmutableSet.Builder<>();
for (DesignatedContact contact : nullToEmptyImmutableCopy(allContacts)) {
if (REGISTRANT.equals(contact.getType())){
registrant = contact.getContactId();
} else {
contactsBuilder.add(contact);
}
}
contacts = contactsBuilder.build();
}
/** An override of {@link EppResource#asBuilder} with tighter typing. */
@Override
public abstract Builder<?, ?> asBuilder();
/** A builder for constructing {@link DomainBase}, since it is immutable. */
public abstract static class Builder<T extends DomainBase, B extends Builder<?, ?>>
extends EppResource.Builder<T, B> {
protected Builder() {}
protected Builder(T instance) {
super(instance);
}
@Override
public T build() {
T instance = getInstance();
checkState(
!isNullOrEmpty(instance.fullyQualifiedDomainName), "Missing fullyQualifiedDomainName");
instance.tld = getTldFromDomainName(instance.fullyQualifiedDomainName);
instance.allContacts = instance.registrant == null ? instance.contacts : union(
instance.getContacts(), DesignatedContact.create(REGISTRANT, instance.registrant));
return super.build();
}
public B setFullyQualifiedDomainName(String fullyQualifiedDomainName) {
getInstance().fullyQualifiedDomainName = fullyQualifiedDomainName;
return thisCastToDerived();
}
public B setDsData(ImmutableSet<DelegationSignerData> dsData) {
getInstance().dsData = dsData;
return thisCastToDerived();
}
public B setRegistrant(ReferenceUnion<ContactResource> registrant) {
getInstance().registrant = registrant;
return thisCastToDerived();
}
public B setAuthInfo(DomainAuthInfo authInfo) {
getInstance().authInfo = authInfo;
return thisCastToDerived();
}
public B setNameservers(ImmutableSet<ReferenceUnion<HostResource>> nameservers) {
getInstance().nameservers = nameservers;
return thisCastToDerived();
}
public B addNameservers(ImmutableSet<ReferenceUnion<HostResource>> nameservers) {
return setNameservers(
ImmutableSet.copyOf(union(getInstance().getNameservers(), nameservers)));
}
public B removeNameservers(ImmutableSet<ReferenceUnion<HostResource>> nameservers) {
return setNameservers(
ImmutableSet.copyOf(difference(getInstance().getNameservers(), nameservers)));
}
public B setContacts(ImmutableSet<DesignatedContact> contacts) {
getInstance().contacts = contacts;
return thisCastToDerived();
}
public B addContacts(ImmutableSet<DesignatedContact> contacts) {
return setContacts(ImmutableSet.copyOf(union(getInstance().getContacts(), contacts)));
}
public B removeContacts(ImmutableSet<DesignatedContact> contacts) {
return setContacts(ImmutableSet.copyOf(difference(getInstance().getContacts(), contacts)));
}
public B setLaunchNotice(LaunchNotice launchNotice) {
getInstance().launchNotice = launchNotice;
return thisCastToDerived();
}
public B setIdnTableName(String idnTableName) {
getInstance().idnTableName = idnTableName;
return thisCastToDerived();
}
}
}

View file

@ -0,0 +1,462 @@
// 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 com.google.domain.registry.model.domain;
import static com.google.common.base.MoreObjects.firstNonNull;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Sets.intersection;
import static com.google.domain.registry.model.index.ForeignKeyIndex.loadAndGetReference;
import static com.google.domain.registry.model.ofy.ObjectifyService.ofy;
import static com.google.domain.registry.util.CollectionUtils.nullSafeImmutableCopy;
import static com.google.domain.registry.util.CollectionUtils.nullToEmptyImmutableCopy;
import com.google.common.base.MoreObjects;
import com.google.common.collect.ImmutableSet;
import com.google.domain.registry.model.EppResource;
import com.google.domain.registry.model.ImmutableObject;
import com.google.domain.registry.model.contact.ContactResource;
import com.google.domain.registry.model.eppcommon.AuthInfo;
import com.google.domain.registry.model.eppinput.ResourceCommand.AbstractSingleResourceCommand;
import com.google.domain.registry.model.eppinput.ResourceCommand.ResourceCheck;
import com.google.domain.registry.model.eppinput.ResourceCommand.ResourceCreateOrChange;
import com.google.domain.registry.model.eppinput.ResourceCommand.ResourceUpdate;
import com.google.domain.registry.model.eppinput.ResourceCommand.SingleResourceCommand;
import com.google.domain.registry.model.host.HostResource;
import com.googlecode.objectify.Ref;
import com.googlecode.objectify.Work;
import org.joda.time.DateTime;
import org.joda.time.LocalDate;
import java.util.Set;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlEnumValue;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
import javax.xml.bind.annotation.XmlType;
import javax.xml.bind.annotation.XmlValue;
/** A collection of {@link DomainResource} commands. */
public class DomainCommand {
/** 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 common interface for {@link Create} and {@link Update} to support linking resources.
*
* @param <T> the actual type (either {@link Create} or {@link Update})
*/
public interface CreateOrUpdate<T extends CreateOrUpdate<T>> extends SingleResourceCommand {
/** Creates a copy of this command with hard links to hosts and contacts. */
public T cloneAndLinkReferences(DateTime now) throws InvalidReferenceException;
}
/** The fields on "chgType" from {@link "http://tools.ietf.org/html/rfc5731"}. */
@XmlTransient
public static class DomainCreateOrChange<B extends DomainBase.Builder<?, ?>>
extends ImmutableObject implements ResourceCreateOrChange<B> {
/** A reference to the registrant who registered this domain. */
ReferenceUnion<ContactResource> registrant;
/** Authorization info (aka transfer secret) of the domain. */
DomainAuthInfo authInfo;
@Override
public void applyTo(B builder) {
if (registrant != null) {
builder.setRegistrant(registrant);
}
if (authInfo != null) {
builder.setAuthInfo(authInfo);
}
}
}
/**
* A create command for a {@link DomainBase}, mapping "createType" from
* {@link "http://tools.ietf.org/html/rfc5731"}.
*/
@XmlRootElement
@XmlType(propOrder = {
"fullyQualifiedDomainName", "period", "nameservers", "registrant", "contacts", "authInfo" })
public static class Create
extends DomainCreateOrChange<DomainBase.Builder<?, ?>>
implements CreateOrUpdate<Create> {
/** Fully qualified domain name, which serves as a unique identifier for this domain. */
@XmlElement(name = "name")
String fullyQualifiedDomainName;
/** References to hosts that are the nameservers for the domain. */
@XmlElementWrapper(name = "ns")
@XmlElement(name = "hostObj")
Set<ReferenceUnion<HostResource>> nameservers;
/** Associated contacts for the domain (other than registrant). */
@XmlElement(name = "contact")
Set<DesignatedContact> contacts;
/** The period that this domain's state was set to last for (e.g. 1-10 years). */
Period period;
public Period getPeriod() {
return firstNonNull(period, DEFAULT_PERIOD);
}
@Override
public String getTargetId() {
return fullyQualifiedDomainName;
}
public String getFullyQualifiedDomainName() {
return fullyQualifiedDomainName;
}
public ImmutableSet<ReferenceUnion<HostResource>> getNameservers() {
return nullSafeImmutableCopy(nameservers);
}
public ImmutableSet<DesignatedContact> getContacts() {
return nullSafeImmutableCopy(contacts);
}
public ReferenceUnion<ContactResource> getRegistrant() {
return registrant;
}
@Override
public AuthInfo getAuthInfo() {
return authInfo;
}
@Override
public void applyTo(DomainBase.Builder<?, ?> builder) {
super.applyTo(builder);
if (fullyQualifiedDomainName != null) {
builder.setFullyQualifiedDomainName(fullyQualifiedDomainName);
}
if (nameservers != null) {
builder.setNameservers(getNameservers());
}
if (contacts != null) {
builder.setContacts(getContacts());
}
}
/** Creates a copy of this {@link Create} with hard links to hosts and contacts. */
@Override
public Create cloneAndLinkReferences(DateTime now) throws InvalidReferenceException {
Create clone = clone(this);
clone.nameservers = linkHosts(clone.nameservers, now);
clone.contacts = linkContacts(clone.contacts, now);
clone.registrant = clone.registrant == null
? null : linkReference(clone.registrant, ContactResource.class, now);
return clone;
}
}
/** A delete command for a {@link DomainBase}. */
@XmlRootElement
public static class Delete extends AbstractSingleResourceCommand {}
/** An info request for a {@link DomainBase}. */
@XmlRootElement
public static class Info extends ImmutableObject implements SingleResourceCommand {
/** The name of the domain to look up, and an attribute specifying the host lookup type. */
@XmlElement(name = "name")
NameWithHosts fullyQualifiedDomainName;
DomainAuthInfo authInfo;
/** Enum of the possible values for the "hosts" attribute in info flows. */
public enum HostsRequest {
@XmlEnumValue("all")
ALL,
@XmlEnumValue("del")
DELEGATED,
@XmlEnumValue("sub")
SUBORDINATE,
@XmlEnumValue("none")
NONE;
public boolean requestDelegated() {
return this == ALL || this == DELEGATED;
}
public boolean requestSubordinate() {
return this == ALL || this == SUBORDINATE;
}
}
/** Info commands use a variant syntax where the name tag has a "hosts" attribute. */
public static class NameWithHosts extends ImmutableObject {
@XmlAttribute
HostsRequest hosts;
@XmlValue
String name;
}
/** Get the enum that specifies the requested hosts (applies only to info flows). */
public HostsRequest getHostsRequest() {
// Null "hosts" is implicitly ALL.
return MoreObjects.firstNonNull(fullyQualifiedDomainName.hosts, HostsRequest.ALL);
}
@Override
public String getTargetId() {
return fullyQualifiedDomainName.name;
}
@Override
public DomainAuthInfo getAuthInfo() {
return authInfo;
}
}
/** A check request for {@link DomainResource}. */
@XmlRootElement
public static class Check extends ResourceCheck {}
/** A renew command for a {@link DomainResource}. */
@XmlRootElement
public static class Renew extends AbstractSingleResourceCommand {
@XmlElement(name = "curExpDate")
LocalDate currentExpirationDate;
/** The period that this domain's state was set to last for. */
Period period;
public LocalDate getCurrentExpirationDate() {
return currentExpirationDate;
}
public Period getPeriod() {
return firstNonNull(period, DEFAULT_PERIOD);
}
}
/** A transfer operation for a {@link DomainResource}. */
@XmlRootElement
public static class Transfer extends AbstractSingleResourceCommand {
/** The period to extend this domain's registration upon completion of the transfer. */
Period period;
/** Authorization info used to validate if client has permissions to perform this operation. */
DomainAuthInfo authInfo;
public Period getPeriod() {
return firstNonNull(period, DEFAULT_PERIOD);
}
@Override
public DomainAuthInfo getAuthInfo() {
return authInfo;
}
}
/** An update to a {@link DomainBase}. */
@XmlRootElement
@XmlType(propOrder = {"targetId", "innerAdd", "innerRemove", "innerChange"})
public static class Update
extends ResourceUpdate<Update.AddRemove, DomainBase.Builder<?, ?>, Update.Change>
implements CreateOrUpdate<Update> {
@XmlElement(name = "chg")
protected Change innerChange;
@XmlElement(name = "add")
protected AddRemove innerAdd;
@XmlElement(name = "rem")
protected AddRemove innerRemove;
@Override
protected Change getNullableInnerChange() {
return innerChange;
}
@Override
protected AddRemove getNullableInnerAdd() {
return innerAdd;
}
@Override
protected AddRemove getNullableInnerRemove() {
return innerRemove;
}
public boolean noChangesPresent() {
AddRemove emptyAddRemove = new AddRemove();
return emptyAddRemove.equals(getInnerAdd())
&& emptyAddRemove.equals(getInnerRemove())
&& new Change().equals(getInnerChange());
}
/** The inner change type on a domain update command. */
@XmlType(propOrder = {"nameservers", "contacts", "statusValues"})
public static class AddRemove extends ResourceUpdate.AddRemove {
/** References to hosts that are the nameservers for the domain. */
@XmlElementWrapper(name = "ns")
@XmlElement(name = "hostObj")
Set<ReferenceUnion<HostResource>> nameservers;
/** Associated contacts for the domain. */
@XmlElement(name = "contact")
Set<DesignatedContact> contacts;
public ImmutableSet<ReferenceUnion<HostResource>> getNameservers() {
return nullToEmptyImmutableCopy(nameservers);
}
public ImmutableSet<DesignatedContact> getContacts() {
return nullToEmptyImmutableCopy(contacts);
}
/** Creates a copy of this {@link AddRemove} with hard links to hosts and contacts. */
private AddRemove cloneAndLinkReferences(DateTime now) throws InvalidReferenceException {
AddRemove clone = clone(this);
clone.nameservers = linkHosts(clone.nameservers, now);
clone.contacts = linkContacts(clone.contacts, now);
return clone;
}
}
/** The inner change type on a domain update command. */
@XmlType(propOrder = {"registrant", "authInfo"})
public static class Change extends DomainCreateOrChange<DomainBase.Builder<?, ?>> {
public ReferenceUnion<ContactResource> getRegistrant() {
return registrant;
}
/** Creates a copy of this {@link Change} with hard links to hosts and contacts. */
Change cloneAndLinkReferences(DateTime now) throws InvalidReferenceException {
Change clone = clone(this);
clone.registrant = clone.registrant == null
? null : linkReference(clone.registrant, ContactResource.class, now);
return clone;
}
}
@Override
public void applyTo(DomainBase.Builder<?, ?> builder) throws AddRemoveSameValueException {
super.applyTo(builder);
getInnerChange().applyTo(builder);
AddRemove add = getInnerAdd();
AddRemove remove = getInnerRemove();
if (!intersection(add.getNameservers(), remove.getNameservers()).isEmpty()) {
throw new AddRemoveSameValueException();
}
builder.addNameservers(add.getNameservers());
builder.removeNameservers(remove.getNameservers());
if (!intersection(add.getContacts(), remove.getContacts()).isEmpty()) {
throw new AddRemoveSameValueException();
}
builder.addContacts(add.getContacts());
builder.removeContacts(remove.getContacts());
}
/**
* Creates a copy of this {@link Update} with hard links to hosts and contacts.
* <p>
* As a side effect, this will turn null innerAdd/innerRemove/innerChange into empty versions of
* those classes, which is harmless because the getters do that anyways.
*/
@Override
public Update cloneAndLinkReferences(DateTime now) throws InvalidReferenceException {
Update clone = clone(this);
clone.innerAdd = clone.getInnerAdd().cloneAndLinkReferences(now);
clone.innerRemove = clone.getInnerRemove().cloneAndLinkReferences(now);
clone.innerChange = clone.getInnerChange().cloneAndLinkReferences(now);
return clone;
}
}
private static Set<ReferenceUnion<HostResource>> linkHosts(
Set<ReferenceUnion<HostResource>> hosts,
DateTime now) throws InvalidReferenceException {
if (hosts == null) {
return null;
}
ImmutableSet.Builder<ReferenceUnion<HostResource>> linked = new ImmutableSet.Builder<>();
for (ReferenceUnion<HostResource> host : hosts) {
linked.add(linkReference(host, HostResource.class, now));
}
return linked.build();
}
private static Set<DesignatedContact> linkContacts(
Set<DesignatedContact> contacts, DateTime now) throws InvalidReferenceException {
if (contacts == null) {
return null;
}
ImmutableSet.Builder<DesignatedContact> linkedContacts = new ImmutableSet.Builder<>();
for (DesignatedContact contact : contacts) {
linkedContacts.add(DesignatedContact.create(
contact.getType(),
linkReference(contact.getContactId(), ContactResource.class, now)));
}
return linkedContacts.build();
}
/** Turn a foreign-keyed {@link ReferenceUnion} into a linked one. */
private static <T extends EppResource> ReferenceUnion<T> linkReference(
final ReferenceUnion<T> reference, final Class<T> clazz, final DateTime now)
throws InvalidReferenceException {
if (reference.getForeignKey() == null) {
return reference;
}
Ref<T> ref = ofy().doTransactionless(new Work<Ref<T>>() {
@Override
public Ref<T> run() {
return loadAndGetReference(clazz, reference.getForeignKey(), now);
}
});
if (ref == null) {
throw new InvalidReferenceException(clazz, reference.getForeignKey());
}
return ReferenceUnion.create(ref);
}
/** Exception to throw when a referenced object does not exist. */
public static class InvalidReferenceException extends Exception {
private String foreignKey;
private Class<?> type;
InvalidReferenceException(Class<?> type, String foreignKey) {
this.type = checkNotNull(type);
this.foreignKey = foreignKey;
}
public String getForeignKey() {
return foreignKey;
}
public Class<?> getType() {
return type;
}
}
}

View file

@ -0,0 +1,41 @@
// 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 com.google.domain.registry.model.domain;
import com.google.domain.registry.model.eppoutput.Response.ResponseData;
import org.joda.time.DateTime;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
/** The {@link ResponseData} returned when renewing a domain. */
@XmlRootElement(name = "renData")
@XmlType(propOrder = {"name", "expirationDate"})
public class DomainRenewData implements ResponseData {
String name;
@XmlElement(name = "exDate")
DateTime expirationDate;
public static DomainRenewData create(String name, DateTime expirationDate) {
DomainRenewData instance = new DomainRenewData();
instance.name = name;
instance.expirationDate = expirationDate;
return instance;
}
}

View file

@ -0,0 +1,414 @@
// 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 com.google.domain.registry.model.domain;
import static com.google.common.collect.Sets.intersection;
import static com.google.domain.registry.model.EppResourceUtils.projectResourceOntoBuilderAtTime;
import static com.google.domain.registry.model.EppResourceUtils.setAutomaticTransferSuccessProperties;
import static com.google.domain.registry.model.ofy.Ofy.RECOMMENDED_MEMCACHE_EXPIRATION;
import static com.google.domain.registry.util.CollectionUtils.difference;
import static com.google.domain.registry.util.CollectionUtils.nullToEmptyImmutableCopy;
import static com.google.domain.registry.util.CollectionUtils.union;
import static com.google.domain.registry.util.DateTimeUtils.earliestOf;
import static com.google.domain.registry.util.DateTimeUtils.isBeforeOrAt;
import static com.google.domain.registry.util.DateTimeUtils.leapSafeAddYears;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableSet;
import com.google.domain.registry.model.EppResource.ForeignKeyedEppResource;
import com.google.domain.registry.model.annotations.ExternalMessagingName;
import com.google.domain.registry.model.billing.BillingEvent;
import com.google.domain.registry.model.domain.rgp.GracePeriodStatus;
import com.google.domain.registry.model.eppcommon.StatusValue;
import com.google.domain.registry.model.poll.PollMessage;
import com.google.domain.registry.model.registry.Registry;
import com.google.domain.registry.model.transfer.TransferData;
import com.google.domain.registry.model.transfer.TransferStatus;
import com.googlecode.objectify.Key;
import com.googlecode.objectify.Ref;
import com.googlecode.objectify.annotation.Cache;
import com.googlecode.objectify.annotation.EntitySubclass;
import com.googlecode.objectify.annotation.IgnoreSave;
import com.googlecode.objectify.condition.IfNull;
import org.joda.time.DateTime;
import org.joda.time.Interval;
import java.util.HashSet;
import java.util.Set;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
import javax.xml.bind.annotation.XmlType;
/** A persistable domain resource including mutable and non-mutable fields. */
@XmlRootElement(name = "infData")
@XmlType(propOrder = {
"fullyQualifiedDomainName",
"repoId",
"status",
"registrant",
"contacts",
"nameservers",
"subordinateHosts",
"currentSponsorClientId",
"creationClientId",
"creationTime",
"lastEppUpdateClientId",
"lastEppUpdateTime",
"registrationExpirationTime",
"lastTransferTime",
"authInfo"})
@Cache(expirationSeconds = RECOMMENDED_MEMCACHE_EXPIRATION)
@EntitySubclass(index = true)
@ExternalMessagingName("domain")
public class DomainResource extends DomainBase implements ForeignKeyedEppResource {
/** The max number of years that a domain can be registered for, as set by ICANN policy. */
public static final int MAX_REGISTRATION_YEARS = 10;
/** Status values which prohibit DNS information from being published. */
private static final ImmutableSet<StatusValue> DNS_PUBLISHING_PROHIBITED_STATUSES =
ImmutableSet.of(
StatusValue.CLIENT_HOLD,
StatusValue.INACTIVE,
StatusValue.PENDING_DELETE,
StatusValue.SERVER_HOLD);
/** Fully qualified host names of this domain's active subordinate hosts. */
@XmlElement(name = "host")
Set<String> subordinateHosts;
/** When this domain's registration will expire. */
@XmlElement(name = "exDate")
DateTime registrationExpirationTime;
/**
* The poll message associated with this domain being deleted.
* <p>
* This field should be null if the domain is not in pending delete. If it is, the field should
* refer to a {@link PollMessage} timed to when the domain is fully deleted. If the domain is
* restored, the message should be deleted.
*/
@XmlTransient
Key<PollMessage.OneTime> deletePollMessage;
/**
* The recurring billing event associated with this domain's autorenewals.
* <p>
* The recurrence should be open ended unless the domain is in pending delete or fully deleted, in
* which case it should be closed at the time the delete was requested. Whenever the domain's
* {@link #registrationExpirationTime} is changed the recurrence should be closed, a new one
* should be created, and this field should be updated to point to the new one.
*/
@XmlTransient
Ref<BillingEvent.Recurring> autorenewBillingEvent;
/**
* The recurring poll message associated with this domain's autorenewals.
* <p>
* The recurrence should be open ended unless the domain is in pending delete or fully deleted, in
* which case it should be closed at the time the delete was requested. Whenever the domain's
* {@link #registrationExpirationTime} is changed the recurrence should be closed, a new one
* should be created, and this field should be updated to point to the new one.
*/
@XmlTransient
Ref<PollMessage.Autorenew> autorenewPollMessage;
/** The unexpired grace periods for this domain (some of which may not be active yet). */
@XmlTransient
Set<GracePeriod> gracePeriods;
/**
* The id of the signed mark that was used to create the sunrise application for this domain.
* Will only be populated for domains allocated from a sunrise application.
*/
@IgnoreSave(IfNull.class)
@XmlTransient
String smdId;
/**
* The time that the application used to allocate this domain was created. Will only be populated
* for domains allocated from an application.
*/
@IgnoreSave(IfNull.class)
@XmlTransient
DateTime applicationTime;
/**
* A reference to the application used to allocate this domain. Will only be populated for domains
* allocated from an application.
*/
@IgnoreSave(IfNull.class)
@XmlTransient
Ref<DomainApplication> application;
public ImmutableSet<String> getSubordinateHosts() {
return nullToEmptyImmutableCopy(subordinateHosts);
}
public DateTime getRegistrationExpirationTime() {
return registrationExpirationTime;
}
public Key<PollMessage.OneTime> getDeletePollMessage() {
return deletePollMessage;
}
public Ref<BillingEvent.Recurring> getAutorenewBillingEvent() {
return autorenewBillingEvent;
}
public Ref<PollMessage.Autorenew> getAutorenewPollMessage() {
return autorenewPollMessage;
}
public ImmutableSet<GracePeriod> getGracePeriods() {
return nullToEmptyImmutableCopy(gracePeriods);
}
public String getSmdId() {
return smdId;
}
public DateTime getApplicationTime() {
return applicationTime;
}
public Ref<DomainApplication> getApplication() {
return application;
}
@Override
public String getForeignKey() {
return fullyQualifiedDomainName;
}
/** Returns true if DNS information should be published for the given domain. */
public boolean shouldPublishToDns() {
return intersection(getStatusValues(), DNS_PUBLISHING_PROHIBITED_STATUSES).isEmpty();
}
/**
* Returns the Registry Grace Period Statuses for this domain.
* <p>
* This collects all statuses from the domain's {@link GracePeriod}s and also adds the
* PENDING_DELETE status if needed.
*/
public ImmutableSet<GracePeriodStatus> getGracePeriodStatuses() {
Set<GracePeriodStatus> gracePeriodStatuses = new HashSet<>();
for (GracePeriod gracePeriod : getGracePeriods()) {
gracePeriodStatuses.add(gracePeriod.getType());
}
if (getStatusValues().contains(StatusValue.PENDING_DELETE)
&& !gracePeriodStatuses.contains(GracePeriodStatus.REDEMPTION)) {
gracePeriodStatuses.add(GracePeriodStatus.PENDING_DELETE);
}
return ImmutableSet.copyOf(gracePeriodStatuses);
}
/**
* The logic in this method, which handles implicit server approval of transfers, very closely
* parallels the logic in {@code DomainTransferApproveFlow} which handles explicit client
* approvals.
*/
@Override
public DomainResource cloneProjectedAtTime(final DateTime now) {
TransferData transferData = getTransferData();
DateTime transferExpirationTime = transferData.getPendingTransferExpirationTime();
// If there's a pending transfer that has expired, handle it.
if (TransferStatus.PENDING.equals(transferData.getTransferStatus())
&& isBeforeOrAt(transferExpirationTime, now)) {
// Project until just before the transfer time. This will handle the case of an autorenew
// before the transfer was even requested or during the request period.
// If the transfer time is precisely the moment that the domain expires, there will not be an
// autorenew billing event (since we end the recurrence at transfer time and recurrences are
// exclusive of their ending), and we can just proceed with the transfer.
DomainResource domainAtTransferTime =
cloneProjectedAtTime(transferExpirationTime.minusMillis(1));
// If we are within an autorenew grace period, the transfer will subsume the autorenew. There
// will already be a cancellation written in advance by the transfer request flow, so we don't
// need to worry about billing, but we do need to reduce the number of years added to the
// expiration time by one to account for the year added by the autorenew.
int extraYears = transferData.getExtendedRegistrationYears();
if (domainAtTransferTime.getGracePeriodStatuses().contains(GracePeriodStatus.AUTO_RENEW)) {
extraYears--;
}
// Set the expiration, autorenew events, and grace period for the transfer. (Transfer ends
// all other graces).
Builder builder = domainAtTransferTime.asBuilder()
// Extend the registration by the correct number of years from the expiration time that
// was current on the domain right before the transfer, capped at 10 years from the
// moment of the transfer.
.setRegistrationExpirationTime(extendRegistrationWithCap(
transferExpirationTime,
domainAtTransferTime.getRegistrationExpirationTime(),
extraYears))
// Set the speculatively-written new autorenew events as the domain's autorenew events.
.setAutorenewBillingEvent(transferData.getServerApproveAutorenewEvent())
.setAutorenewPollMessage(transferData.getServerApproveAutorenewPollMessage())
// Set the grace period using a ref to the prescheduled transfer billing event. Not using
// GracePeriod.forBillingEvent() here in order to avoid the actual datastore fetch.
.setGracePeriods(ImmutableSet.of(GracePeriod.create(
GracePeriodStatus.TRANSFER,
transferExpirationTime.plus(Registry.get(getTld()).getTransferGracePeriodLength()),
transferData.getGainingClientId(),
Ref.create(transferData.getServerApproveBillingEvent().key()))));
// Set all remaining transfer properties.
setAutomaticTransferSuccessProperties(builder, transferData);
// Finish projecting to now.
return builder.build().cloneProjectedAtTime(now);
}
// There is no transfer. Do any necessary autorenews.
Builder builder = asBuilder();
if (isBeforeOrAt(registrationExpirationTime, now)) {
// Autorenew by the number of years between the old expiration time and now.
DateTime lastAutorenewTime = leapSafeAddYears(
registrationExpirationTime,
new Interval(registrationExpirationTime, now).toPeriod().getYears());
DateTime newExpirationTime = lastAutorenewTime.plusYears(1);
builder
.setRegistrationExpirationTime(newExpirationTime)
.addGracePeriod(GracePeriod.createForRecurring(
GracePeriodStatus.AUTO_RENEW,
lastAutorenewTime.plus(Registry.get(getTld()).getAutoRenewGracePeriodLength()),
getCurrentSponsorClientId(),
Ref.create(autorenewBillingEvent.key())));
}
// Remove any grace periods that have expired.
DomainResource almostBuilt = builder.build();
builder = almostBuilt.asBuilder();
for (GracePeriod gracePeriod : almostBuilt.getGracePeriods()) {
if (isBeforeOrAt(gracePeriod.getExpirationTime(), now)) {
builder.removeGracePeriod(gracePeriod);
}
}
// Handle common properties like setting or unsetting linked status. This also handles the
// general case of pending transfers for other resource types, but since we've always handled
// a pending transfer by this point that's a no-op for domains.
projectResourceOntoBuilderAtTime(almostBuilt, builder, now);
return builder.build();
}
/** Return what the expiration time would be if the given number of years were added to it. */
public static DateTime extendRegistrationWithCap(
DateTime now, DateTime currentExpirationTime, Integer extendedRegistrationYears) {
// We must cap registration at the max years (aka 10), even if that truncates the last year.
return earliestOf(
leapSafeAddYears(
currentExpirationTime, Optional.fromNullable(extendedRegistrationYears).or(0)),
leapSafeAddYears(now, MAX_REGISTRATION_YEARS));
}
@Override
public Builder asBuilder() {
return new Builder(clone(this));
}
/** A builder for constructing {@link DomainResource}, since it is immutable. */
public static class Builder extends DomainBase.Builder<DomainResource, Builder> {
public Builder() {}
private Builder(DomainResource instance) {
super(instance);
}
@Override
public DomainResource build() {
// A DomainResource has status INACTIVE if there are no nameservers.
if (getInstance().getNameservers().isEmpty()) {
addStatusValue(StatusValue.INACTIVE);
} else { // There are nameservers, so make sure INACTIVE isn't there.
removeStatusValue(StatusValue.INACTIVE);
}
// This must be called after we add or remove INACTIVE, since that affects whether we get OK.
return super.build();
}
public Builder setSubordinateHosts(ImmutableSet<String> subordinateHosts) {
getInstance().subordinateHosts = subordinateHosts;
return thisCastToDerived();
}
public Builder addSubordinateHost(String hostToAdd) {
return setSubordinateHosts(ImmutableSet.copyOf(
union(getInstance().getSubordinateHosts(), hostToAdd)));
}
public Builder removeSubordinateHost(String hostToRemove) {
return setSubordinateHosts(ImmutableSet.copyOf(
difference(getInstance().getSubordinateHosts(), hostToRemove)));
}
public Builder setRegistrationExpirationTime(DateTime registrationExpirationTime) {
getInstance().registrationExpirationTime = registrationExpirationTime;
return this;
}
public Builder setDeletePollMessage(Key<PollMessage.OneTime> deletePollMessage) {
getInstance().deletePollMessage = deletePollMessage;
return this;
}
public Builder setAutorenewBillingEvent(Ref<BillingEvent.Recurring> autorenewBillingEvent) {
getInstance().autorenewBillingEvent = autorenewBillingEvent;
return this;
}
public Builder setAutorenewPollMessage(Ref<PollMessage.Autorenew> autorenewPollMessage) {
getInstance().autorenewPollMessage = autorenewPollMessage;
return this;
}
public Builder setSmdId(String smdId) {
getInstance().smdId = smdId;
return this;
}
public Builder setApplicationTime(DateTime applicationTime) {
getInstance().applicationTime = applicationTime;
return this;
}
public Builder setApplication(Ref<DomainApplication> application) {
getInstance().application = application;
return this;
}
public Builder setGracePeriods(ImmutableSet<GracePeriod> gracePeriods) {
getInstance().gracePeriods = gracePeriods;
return this;
}
public Builder addGracePeriod(GracePeriod gracePeriod) {
getInstance().gracePeriods = union(getInstance().getGracePeriods(), gracePeriod);
return this;
}
public Builder removeGracePeriod(GracePeriod gracePeriod) {
getInstance().gracePeriods = difference(getInstance().getGracePeriods(), gracePeriod);
return this;
}
}
}

View file

@ -0,0 +1,158 @@
// 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 com.google.domain.registry.model.domain;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.domain.registry.util.PreconditionsUtils.checkArgumentNotNull;
import com.google.domain.registry.model.ImmutableObject;
import com.google.domain.registry.model.billing.BillingEvent;
import com.google.domain.registry.model.domain.rgp.GracePeriodStatus;
import com.googlecode.objectify.Ref;
import com.googlecode.objectify.annotation.Embed;
import org.joda.time.DateTime;
import javax.annotation.Nullable;
/**
* A domain grace period with an expiration time.
* <p>
* When a grace period expires, it is lazily removed from the {@link DomainResource} the next time
* the resource is loaded from the datastore.
*/
@Embed
public class GracePeriod extends ImmutableObject {
/** The type of grace period. */
GracePeriodStatus type;
/** When the grace period ends. */
DateTime expirationTime;
/** The registrar to bill. */
String clientId;
/**
* The one-time billing event corresponding to the action that triggered this grace period, or
* null if not applicable. Not set for autorenew grace periods (which instead use the field
* {@code billingEventRecurring}) or for redemption grace periods (since deletes have no cost).
*/
// NB: Would @IgnoreSave(IfNull.class), but not allowed for @Embed collections.
Ref<BillingEvent.OneTime> billingEventOneTime = null;
/**
* The recurring billing event corresponding to the action that triggered this grace period, if
* applicable - i.e. if the action was an autorenew - or null in all other cases.
*/
// NB: Would @IgnoreSave(IfNull.class), but not allowed for @Embed collections.
Ref<BillingEvent.Recurring> billingEventRecurring = null;
public GracePeriodStatus getType() {
// NB: We implicitly convert SUNRUSH_ADD to ADD, since they should be functionally equivalent.
return type == GracePeriodStatus.SUNRUSH_ADD ? GracePeriodStatus.ADD : type;
}
public boolean isSunrushAddGracePeriod() {
return type == GracePeriodStatus.SUNRUSH_ADD;
}
public DateTime getExpirationTime() {
return expirationTime;
}
public String getClientId() {
return clientId;
}
/** Returns true if this GracePeriod has an associated BillingEvent; i.e. if it's refundable. */
public boolean hasBillingEvent() {
return billingEventOneTime != null || billingEventRecurring != null;
}
/**
* Returns the one time billing event. The value will only be non-null if the type of this grace
* period is not AUTO_RENEW.
*/
public Ref<BillingEvent.OneTime> getOneTimeBillingEvent() {
return billingEventOneTime;
}
/**
* Returns the recurring billing event. The value will only be non-null if the type of this grace
* period is AUTO_RENEW.
*/
public Ref<BillingEvent.Recurring> getRecurringBillingEvent() {
return billingEventRecurring;
}
private static GracePeriod createInternal(
GracePeriodStatus type,
DateTime expirationTime,
String clientId,
@Nullable Ref<BillingEvent.OneTime> billingEventOneTime,
@Nullable Ref<BillingEvent.Recurring> billingEventRecurring) {
checkArgument((billingEventOneTime == null) || (billingEventRecurring == null),
"A grace period can have at most one billing event");
checkArgument((billingEventRecurring != null) == (GracePeriodStatus.AUTO_RENEW.equals(type)),
"Recurring billing events must be present on (and only on) autorenew grace periods");
GracePeriod instance = new GracePeriod();
instance.type = checkArgumentNotNull(type);
instance.expirationTime = checkArgumentNotNull(expirationTime);
instance.clientId = checkArgumentNotNull(clientId);
instance.billingEventOneTime = billingEventOneTime;
instance.billingEventRecurring = billingEventRecurring;
return instance;
}
/** Create a GracePeriod for an (optional) OneTime billing event.
*
* <p>Normal callers should always use {@link #forBillingEvent} instead, assuming they do not
* need to avoid loading the BillingEvent from datastore. This method should typically be
* called only from test code to explicitly construct GracePeriods.
*/
public static GracePeriod create(
GracePeriodStatus type,
DateTime expirationTime,
String clientId,
@Nullable Ref<BillingEvent.OneTime> billingEventOneTime) {
return createInternal(type, expirationTime, clientId, billingEventOneTime, null);
}
/** Create a GracePeriod for a Recurring billing event. */
public static GracePeriod createForRecurring(
GracePeriodStatus type,
DateTime expirationTime,
String clientId,
Ref<BillingEvent.Recurring> billingEventRecurring) {
checkArgumentNotNull(billingEventRecurring);
return createInternal(type, expirationTime, clientId, null, billingEventRecurring);
}
/** Create a GracePeriod with no billing event. */
public static GracePeriod createWithoutBillingEvent(
GracePeriodStatus type, DateTime expirationTime, String clientId) {
return createInternal(type, expirationTime, clientId, null, null);
}
/** Constructs a GracePeriod of the given type from the provided one-time BillingEvent. */
public static GracePeriod forBillingEvent(
GracePeriodStatus type, BillingEvent.OneTime billingEvent) {
return create(
type, billingEvent.getBillingTime(), billingEvent.getClientId(), Ref.create(billingEvent));
}
}

View file

@ -0,0 +1,59 @@
// 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 com.google.domain.registry.model.domain;
import com.google.domain.registry.model.ImmutableObject;
import com.googlecode.objectify.annotation.Embed;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlEnumValue;
import javax.xml.bind.annotation.XmlValue;
/** The "periodType" from {@link "http://tools.ietf.org/html/rfc5731"}. */
@Embed
public class Period extends ImmutableObject {
@XmlAttribute
Unit unit;
@XmlValue
Integer value;
public Unit getUnit() {
return unit;
}
public Integer getValue() {
return value;
}
/** The unit enum. */
public enum Unit {
@XmlEnumValue("y")
YEARS,
@XmlEnumValue("m")
MONTHS,
}
public static Period create(int value, Unit unit) {
Period instance = new Period();
instance.value = value;
instance.unit = unit;
return instance;
}
}

View file

@ -0,0 +1,104 @@
// 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 com.google.domain.registry.model.domain;
import com.google.domain.registry.model.EppResource;
import com.google.domain.registry.model.ImmutableObject;
import com.google.domain.registry.model.contact.ContactResource;
import com.google.domain.registry.model.host.HostResource;
import com.googlecode.objectify.Ref;
import com.googlecode.objectify.annotation.Embed;
import com.googlecode.objectify.annotation.Ignore;
import com.googlecode.objectify.annotation.Index;
import java.io.Serializable;
import javax.xml.bind.annotation.adapters.XmlAdapter;
/**
* A "union" type to represent referenced objects as either a foreign key or as a link to another
* object in the datastore.
* <p>
* This type always marshals as the "foreign key". When it is explicitly storing a foreign key it
* gets the value from its own string field. When it is linked to another object, it gets the value
* from the other object.
* <p>
* When a {@link ReferenceUnion} comes in from Epp, either in an update or a delete, it fills in the
* "foreign key" string field, but as soon as the relevant Flow runs it deletes that field and
* replaces it with a linked {@link Ref} to the object named by that string. We can't do this in a
* {@code XmlJavaTypeAdapter} because failing a lookup is a business logic error, not a failure to
* parse the XML.
*
* @param <T> the type being referenced
*/
@Embed
public class ReferenceUnion<T extends EppResource> extends ImmutableObject implements Serializable {
@Index
Ref<T> linked;
/** This is never persisted, and only ever populated to marshal or unmarshal to or from XML. */
@Ignore
String foreignKey;
public Ref<T> getLinked() {
return linked;
}
public String getForeignKey() {
return foreignKey;
}
/** An adapter that is aware of the union inside {@link ReferenceUnion}. */
public static class Adapter<T extends EppResource>
extends XmlAdapter<String, ReferenceUnion<T>> {
@Override
public ReferenceUnion<T> unmarshal(String foreignKey) throws Exception {
return ReferenceUnion.<T>create(foreignKey);
}
@Override
public String marshal(ReferenceUnion<T> reference) throws Exception {
return reference.getForeignKey() == null
? reference.getLinked().get().getForeignKey()
: reference.getForeignKey();
}
}
/** An adapter for references to contacts. */
static class ContactReferenceUnionAdapter extends ReferenceUnion.Adapter<ContactResource>{}
/** An adapter for references to hosts. */
static class HostReferenceUnionAdapter extends ReferenceUnion.Adapter<HostResource>{}
public static <T extends EppResource> ReferenceUnion<T> create(String foreignKey) {
ReferenceUnion<T> instance = new ReferenceUnion<>();
instance.foreignKey = foreignKey;
return instance;
}
public static <T extends EppResource> ReferenceUnion<T> create(Ref<T> linked) {
ReferenceUnion<T> instance = new ReferenceUnion<>();
instance.linked = linked;
return instance;
}
/** Convenience method. */
public static <T extends EppResource> ReferenceUnion<T> create(T resource) {
return create(Ref.create(resource));
}
}

View file

@ -0,0 +1,85 @@
// 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 com.google.domain.registry.model.domain.allocate;
import com.google.domain.registry.model.ImmutableObject;
import com.google.domain.registry.model.domain.launch.LaunchNotice;
import com.google.domain.registry.model.eppinput.EppInput.CommandExtension;
import org.joda.time.DateTime;
import javax.xml.bind.annotation.XmlRootElement;
/**
* An XML data object that represents an allocate extension that will be present on EPP commands to
* allocate a domain from an application.
* <p>
* This object holds XML data which JAXB will unmarshal from an EPP domain create command extension.
* The XML will have the following enclosing structure:
*
* <pre> {@code
* <epp>
* <command>
* <create>
* <!-- domain create XML data -->
* </create>
* <extension>
* <allocate:create>
* <!-- allocate create XML payload data -->
* </allocate:create>
* </extension>
* </command>
* </epp>
* } </pre>
*
* @see CommandExtension
*/
@XmlRootElement(name = "create")
public class AllocateCreateExtension extends ImmutableObject implements CommandExtension {
/** Holds the ROID of the application that was used to allocate this domain. */
String applicationRoid;
/** The time that the application was created. */
DateTime applicationTime;
/**
* Signed mark identifier for this create. Only present when allocating a domain from a sunrise
* application.
*/
String smdId;
/**
* The claims notice for this create. Only present when allocating a domain from a landrush
* application that matches a pre-registered mark in the TMCH.
*/
LaunchNotice notice;
public String getApplicationRoid() {
return applicationRoid;
}
public DateTime getApplicationTime() {
return applicationTime;
}
public String getSmdId() {
return smdId;
}
public LaunchNotice getNotice() {
return notice;
}
}

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.
@XmlSchema(
namespace = "urn:google:params:xml:ns:allocate-1.0",
xmlns = @XmlNs(prefix = "allocate", namespaceURI = "urn:google:params:xml:ns:allocate-1.0"),
elementFormDefault = XmlNsForm.QUALIFIED)
@XmlAccessorType(XmlAccessType.FIELD)
@XmlJavaTypeAdapter(UtcDateTimeAdapter.class)
package com.google.domain.registry.model.domain.allocate;
import com.google.domain.registry.xml.UtcDateTimeAdapter;
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

@ -0,0 +1,86 @@
// 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 com.google.domain.registry.model.domain.fee;
import static com.google.common.base.MoreObjects.firstNonNull;
import com.google.domain.registry.model.ImmutableObject;
import com.google.domain.registry.xml.PeriodAdapter;
import org.joda.time.Period;
import java.math.BigDecimal;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlEnumValue;
import javax.xml.bind.annotation.XmlTransient;
import javax.xml.bind.annotation.XmlValue;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
/** Base class for the fee and credit types. */
@XmlTransient
public class BaseFee extends ImmutableObject {
/** Enum for when a fee is applied. */
public enum AppliedType {
@XmlEnumValue("immediate")
IMMEDIATE,
@XmlEnumValue("delayed")
DELAYED
}
@XmlAttribute
String description;
@XmlAttribute
AppliedType applied;
@XmlAttribute(name = "grace-period")
@XmlJavaTypeAdapter(PeriodAdapter.class)
Period gracePeriod;
@XmlAttribute
Boolean refundable;
@XmlValue
BigDecimal cost;
public String getDescription() {
return description;
}
public AppliedType getApplied() {
return firstNonNull(applied, AppliedType.IMMEDIATE);
}
public Period getGracePeriod() {
return firstNonNull(gracePeriod, Period.ZERO);
}
public Boolean getRefundable() {
return firstNonNull(refundable, true);
}
public BigDecimal getCost() {
return cost;
}
public boolean hasDefaultAttributes() {
return getGracePeriod().equals(Period.ZERO)
&& getApplied().equals(AppliedType.IMMEDIATE)
&& getRefundable();
}
}

View file

@ -0,0 +1,48 @@
// 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 com.google.domain.registry.model.domain.fee;
import com.google.domain.registry.model.ImmutableObject;
import org.joda.money.CurrencyUnit;
import java.util.List;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlTransient;
/** Base class for general transform commands with fees (create, renew, update, transfer). */
@XmlTransient
public class BaseFeeCommand extends ImmutableObject {
/** 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;
public CurrencyUnit getCurrency() {
return currency;
}
public List<Fee> getFees() {
return fees;
}
}

View file

@ -0,0 +1,54 @@
// 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 com.google.domain.registry.model.domain.fee;
import com.google.common.collect.ImmutableList;
import com.google.domain.registry.model.Buildable.GenericBuilder;
import com.google.domain.registry.model.ImmutableObject;
import org.joda.money.CurrencyUnit;
import java.util.List;
import javax.xml.bind.annotation.XmlTransient;
/** Base class for fee responses on general transform commands (create, update, renew, transfer). */
@XmlTransient
public class BaseFeeCommandResponse extends ImmutableObject {
/** 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.
*/
List<Fee> fee;
/** Abstract builder for {@link BaseFeeCommandResponse}. */
public abstract static class Builder<T extends BaseFeeCommandResponse, B extends Builder<?, ?>>
extends GenericBuilder<T, B> {
public B setCurrency(CurrencyUnit currency) {
getInstance().currency = currency;
return thisCastToDerived();
}
public B setFee(ImmutableList<Fee> fee) {
getInstance().fee = fee;
return thisCastToDerived();
}
}
}

View file

@ -0,0 +1,52 @@
// 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 com.google.domain.registry.model.domain.fee;
import com.google.common.base.Optional;
import com.google.domain.registry.model.ImmutableObject;
import com.google.domain.registry.model.domain.Period;
import org.joda.money.CurrencyUnit;
import javax.xml.bind.annotation.XmlTransient;
/** Base class for the fee requests on check and info. */
@XmlTransient
public class BaseFeeRequest extends ImmutableObject {
/** 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;
/** The period for the command being checked. */
Period period;
public CurrencyUnit getCurrency() {
return currency;
}
public FeeCommandDescriptor getCommand() {
return command;
}
public Period getPeriod() {
return Optional.fromNullable(period).or(DEFAULT_PERIOD);
}
}

View file

@ -0,0 +1,91 @@
// 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 com.google.domain.registry.model.domain.fee;
import static com.google.domain.registry.util.CollectionUtils.forceEmptyToNull;
import com.google.common.collect.ImmutableList;
import com.google.domain.registry.model.Buildable.GenericBuilder;
import com.google.domain.registry.model.ImmutableObject;
import com.google.domain.registry.model.domain.Period;
import org.joda.money.CurrencyUnit;
import java.util.List;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlTransient;
/** Base class for the fee responses on check and info. */
@XmlTransient
public class BaseFeeResponse extends ImmutableObject {
/** The currency of the fee. */
CurrencyUnit currency;
/** The command that was checked. */
FeeCommandDescriptor command;
/** The period that was checked. */
Period period;
/**
* 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.
*/
List<Fee> fee;
/**
* The type of the fee.
* <p>
* We will use "premium" for fees on premium names, and omit the field otherwise.
*/
@XmlElement(name = "class")
String feeClass;
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;
return thisCastToDerived();
}
public B setPeriod(Period period) {
getInstance().period = period;
return thisCastToDerived();
}
public B setFee(Fee... fee) {
// If there are no fees, set the field to null to suppress the 'fee' section in the xml.
getInstance().fee = forceEmptyToNull(ImmutableList.copyOf(fee));
return thisCastToDerived();
}
public B setClass(String feeClass) {
getInstance().feeClass = feeClass;
return thisCastToDerived();
}
}
}

View file

@ -0,0 +1,29 @@
// 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 com.google.domain.registry.model.domain.fee;
import static com.google.common.base.Preconditions.checkNotNull;
import java.math.BigDecimal;
/** A credit, in currency units specified elsewhere in the xml, and with an optional description. */
public class Credit extends BaseFee {
public static Credit create(BigDecimal cost, String description) {
Credit instance = new Credit();
instance.cost = checkNotNull(cost);
instance.description = description;
return instance;
}
}

View file

@ -0,0 +1,29 @@
// 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 com.google.domain.registry.model.domain.fee;
import static com.google.common.base.Preconditions.checkNotNull;
import java.math.BigDecimal;
/** A fee, in currency units specified elsewhere in the xml, and with an optional description. */
public class Fee extends BaseFee {
public static Fee create(BigDecimal cost, String description) {
Fee instance = new Fee();
instance.cost = checkNotNull(cost);
instance.description = description;
return instance;
}
}

View file

@ -0,0 +1,54 @@
// 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 com.google.domain.registry.model.domain.fee;
import static com.google.domain.registry.util.CollectionUtils.nullToEmptyImmutableCopy;
import com.google.common.collect.ImmutableSet;
import com.google.domain.registry.model.ImmutableObject;
import com.google.domain.registry.model.domain.Period;
import com.google.domain.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

@ -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 com.google.domain.registry.model.domain.fee;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import com.google.domain.registry.model.ImmutableObject;
import com.google.domain.registry.model.eppoutput.Response.ResponseExtension;
import javax.xml.bind.annotation.XmlElement;
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 check commands.
*/
@XmlRootElement(name = "chkData")
public class FeeCheckResponseExtension extends ImmutableObject implements 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;
}
}
}
}

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 com.google.domain.registry.model.domain.fee;
import com.google.common.base.CharMatcher;
import com.google.domain.registry.model.ImmutableObject;
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
}
@XmlAttribute
String phase;
@XmlAttribute
String subphase;
@XmlValue
String command;
public String getPhase() {
return phase;
}
public String getSubphase() {
return subphase;
}
public String getUnparsedCommandName() {
return command;
}
public CommandName getCommand() {
// Require the xml string to be lowercase.
if (command != null && CharMatcher.javaLowerCase().matchesAllOf(command)) {
try {
return CommandName.valueOf(command.toUpperCase());
} catch (IllegalArgumentException e) {
// Swallow this and return UNKNOWN below because there's no matching CommandName.
}
}
return CommandName.UNKNOWN;
}
}

View file

@ -0,0 +1,25 @@
// 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 com.google.domain.registry.model.domain.fee;
import com.google.domain.registry.model.eppinput.EppInput.CommandExtension;
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 {}

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 com.google.domain.registry.model.domain.fee;
import com.google.domain.registry.model.eppoutput.Response.ResponseExtension;
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", "fee"})
public class FeeCreateResponseExtension extends BaseFeeCommandResponse
implements ResponseExtension {
/** A builder for {@link FeeCreateResponseExtension}. */
public static class Builder
extends BaseFeeCommandResponse.Builder<FeeCreateResponseExtension, Builder> {}
}

View file

@ -0,0 +1,59 @@
// 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 com.google.domain.registry.model.domain.fee;
import com.google.common.collect.ImmutableList;
import com.google.domain.registry.model.Buildable.GenericBuilder;
import com.google.domain.registry.model.ImmutableObject;
import com.google.domain.registry.model.eppoutput.Response.ResponseExtension;
import org.joda.money.CurrencyUnit;
import java.util.List;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
/**
* 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

@ -0,0 +1,25 @@
// 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 com.google.domain.registry.model.domain.fee;
import com.google.domain.registry.model.eppinput.EppInput.CommandExtension;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
/** 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 {}

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 com.google.domain.registry.model.domain.fee;
import com.google.domain.registry.model.eppoutput.Response.ResponseExtension;
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.
*/
@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> {}
}

View file

@ -0,0 +1,25 @@
// 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 com.google.domain.registry.model.domain.fee;
import com.google.domain.registry.model.eppinput.EppInput.CommandExtension;
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 {}

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 com.google.domain.registry.model.domain.fee;
import com.google.domain.registry.model.eppoutput.Response.ResponseExtension;
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 = "renData")
@XmlType(propOrder = {"currency", "fee"})
public class FeeRenewResponseExtension extends BaseFeeCommandResponse
implements ResponseExtension {
/** A builder for {@link FeeRenewResponseExtension}. */
public static class Builder
extends BaseFeeCommandResponse.Builder<FeeRenewResponseExtension, Builder> {}
}

View file

@ -0,0 +1,25 @@
// 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 com.google.domain.registry.model.domain.fee;
import com.google.domain.registry.model.eppinput.EppInput.CommandExtension;
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 FeeTransferExtension extends BaseFeeCommand implements CommandExtension {}

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 com.google.domain.registry.model.domain.fee;
import com.google.domain.registry.model.eppoutput.Response.ResponseExtension;
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", "fee"})
public class FeeTransferResponseExtension extends BaseFeeCommandResponse
implements ResponseExtension {
/** A builder for {@link FeeTransferResponseExtension}. */
public static class Builder
extends BaseFeeCommandResponse.Builder<FeeTransferResponseExtension, Builder> {}
}

View file

@ -0,0 +1,25 @@
// 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 com.google.domain.registry.model.domain.fee;
import com.google.domain.registry.model.eppinput.EppInput.CommandExtension;
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 {}

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 com.google.domain.registry.model.domain.fee;
import com.google.domain.registry.model.eppoutput.Response.ResponseExtension;
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", "fee"})
public class FeeUpdateResponseExtension extends BaseFeeCommandResponse
implements ResponseExtension {
/** A builder for {@link FeeUpdateResponseExtension}. */
public static class Builder
extends BaseFeeCommandResponse.Builder<FeeUpdateResponseExtension, 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.
@XmlSchema(
namespace = "urn:ietf:params:xml:ns:fee-0.6",
xmlns = @XmlNs(prefix = "fee", namespaceURI = "urn:ietf:params:xml:ns:fee-0.6"),
elementFormDefault = XmlNsForm.QUALIFIED)
@XmlAccessorType(XmlAccessType.FIELD)
@XmlJavaTypeAdapter(CurrencyUnitAdapter.class)
package com.google.domain.registry.model.domain.fee;
import com.google.domain.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

@ -0,0 +1,23 @@
// 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 com.google.domain.registry.model.domain.launch;
import com.google.domain.registry.model.eppinput.EppInput.CommandExtension;
/** Marker interface for EPP extensions which override the EPP notion of id with their own. */
public interface ApplicationIdTargetExtension extends CommandExtension {
/** Get the application id to use as the resource id for commands using this extension. */
String getApplicationId();
}

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 com.google.domain.registry.model.domain.launch;
import static com.google.common.base.CaseFormat.LOWER_CAMEL;
import static com.google.common.base.CaseFormat.UPPER_UNDERSCORE;
import com.google.domain.registry.model.translators.EnumToAttributeAdapter;
import com.google.domain.registry.model.translators.EnumToAttributeAdapter.EppEnum;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
/**
* Represents the EPP application status.
* <p>
* These values are never read from a command and only used in responses, so, we don't need to model
* anything we don't output. We don't model the CUSTOM status because we don't use it. This allows
* us to also avoid modeling the "name" attribute which is only used with CUSTOM. We don't model the
* "lang" attribute because we only support English and that's the default.
* <p>
* Given all of this, we can use {@link EnumToAttributeAdapter} to make this code very simple.
*
* @see "http://tools.ietf.org/html/draft-tan-epp-launchphase-11#section-2.3"
*/
@XmlJavaTypeAdapter(EnumToAttributeAdapter.class)
public enum ApplicationStatus implements EppEnum {
ALLOCATED,
INVALID,
PENDING_ALLOCATION,
PENDING_VALIDATION,
REJECTED,
VALIDATED;
@Override
public String getXmlName() {
return UPPER_UNDERSCORE.to(LOWER_CAMEL, name());
}
/**
* Returns true if this status is a final status - that is, it should not transition to any other
* application status after this one.
*/
public boolean isFinalStatus() {
return ALLOCATED.equals(this) || REJECTED.equals(this);
}
}

View file

@ -0,0 +1,83 @@
// 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 com.google.domain.registry.model.domain.launch;
import static com.google.common.base.MoreObjects.firstNonNull;
import com.google.domain.registry.model.ImmutableObject;
import com.google.domain.registry.model.eppinput.EppInput.CommandExtension;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlEnumValue;
import javax.xml.bind.annotation.XmlRootElement;
/**
* An XML data object that represents a launch extension that may be present on EPP domain check
* commands.
* <p>
* This object holds XML data which JAXB will unmarshal from an EPP domain check command extension.
* The XML will have the following enclosing structure:
*
* <pre> {@code
* <epp>
* <command>
* <create>
* <!-- domain check XML data -->
* </create>
* <extension>
* <launch:check>
* <!-- launch check XML payload data -->
* </launch:check>
* </extension>
* </command>
* </epp>
* } </pre>
*
* @see CommandExtension
*/
@XmlRootElement(name = "check")
public class LaunchCheckExtension extends ImmutableObject implements CommandExtension {
/** The default check type is "claims" if not specified. */
private static final CheckType DEFAULT_CHECK_TYPE = CheckType.CLAIMS;
/** Type of domain check being requested. */
public enum CheckType {
/** A check to see if the specified domain names are available to be provisioned. */
@XmlEnumValue("avail")
AVAILABILITY,
/** A check to see if there are matching trademarks on the specified domain names. */
@XmlEnumValue("claims")
CLAIMS;
}
/**
* The launch phase this command is intended to run against. If it does not match the server's
* current launch phase, the command will be rejected.
*/
LaunchPhase phase;
@XmlAttribute
CheckType type;
public CheckType getCheckType() {
return firstNonNull(type, DEFAULT_CHECK_TYPE);
}
public LaunchPhase getPhase() {
return phase;
}
}

View file

@ -0,0 +1,94 @@
// 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 com.google.domain.registry.model.domain.launch;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import com.google.domain.registry.model.ImmutableObject;
import com.google.domain.registry.model.eppoutput.Response.ResponseExtension;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
import javax.xml.bind.annotation.XmlValue;
/**
* An XML data object that represents a launch extension that may be present on the response to EPP
* domain check commands.
*/
@XmlRootElement(name = "chkData")
@XmlType(propOrder = {"phase", "launchChecks"})
public class LaunchCheckResponseExtension extends ImmutableObject implements ResponseExtension {
/** The launch phase that this domain check was run against. */
LaunchPhase phase;
/** Check responses. */
@XmlElement(name = "cd")
ImmutableList<LaunchCheck> launchChecks;
@VisibleForTesting
public LaunchPhase getPhase() {
return phase;
}
@VisibleForTesting
public ImmutableList<LaunchCheck> getChecks() {
return launchChecks;
}
/** The response for a check on a single resource. */
public static class LaunchCheck extends ImmutableObject {
/** An element containing the name and availability of a resource. */
LaunchCheckName name;
/** A key used to generate a Trademark Claims Notice. Only returned on claims checks. */
String claimKey;
public static LaunchCheck create(LaunchCheckName name, String claimKey) {
LaunchCheck instance = new LaunchCheck();
instance.name = name;
instance.claimKey = claimKey;
return instance;
}
}
/** Holds the name and availability of a checked resource. */
public static class LaunchCheckName extends ImmutableObject {
/** Whether the resource is available. */
@XmlAttribute
boolean exists;
/** The name of the resource being checked. */
@XmlValue
String name;
public static LaunchCheckName create(boolean exists, String name) {
LaunchCheckName instance = new LaunchCheckName();
instance.exists = exists;
instance.name = name;
return instance;
}
}
public static LaunchCheckResponseExtension create(
LaunchPhase phase, ImmutableList<LaunchCheck> launchChecks) {
LaunchCheckResponseExtension instance = new LaunchCheckResponseExtension();
instance.phase = phase;
instance.launchChecks = launchChecks;
return instance;
}
}

View file

@ -0,0 +1,117 @@
// 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 com.google.domain.registry.model.domain.launch;
import static com.google.domain.registry.util.CollectionUtils.nullToEmptyImmutableCopy;
import com.google.common.collect.ImmutableList;
import com.google.domain.registry.model.eppinput.EppInput.CommandExtension;
import com.google.domain.registry.model.smd.AbstractSignedMark;
import com.google.domain.registry.model.smd.EncodedSignedMark;
import com.google.domain.registry.model.smd.SignedMark;
import java.util.List;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElementRef;
import javax.xml.bind.annotation.XmlElementRefs;
import javax.xml.bind.annotation.XmlEnumValue;
import javax.xml.bind.annotation.XmlRootElement;
/**
* An XML data object that represents a launch extension that may be present on EPP domain create
* commands.
* <p>
* This object holds XML data which JAXB will unmarshal from an EPP domain create command extension.
* The XML will have the following enclosing structure:
*
* <pre> {@code
* <epp>
* <command>
* <create>
* <!-- domain create XML data -->
* </create>
* <extension>
* <launch:create>
* <!-- launch create XML payload data -->
* </launch:create>
* </extension>
* </command>
* </epp>
* } </pre>
*
* @see CommandExtension
*/
@XmlRootElement(name = "create")
public class LaunchCreateExtension extends LaunchExtension implements CommandExtension {
/** Type of domain creation being requested. */
public enum CreateType {
/**
* A Launch Application refers to a registration made during a launch phase when the server
* accepts multiple applications for the same domain name.
*/
@XmlEnumValue("application")
APPLICATION,
/**
* A Launch Registration refers to a registration made during a launch phase when the server
* uses a "first-come, first-served" model.
*/
@XmlEnumValue("registration")
REGISTRATION;
}
@XmlAttribute
CreateType type;
/**
* A list of signed marks or encoded signed marks which assert the client's ability to register
* the specified domain name. Each one contains both a Mark object with information about its
* claim(s), and an XML signature over that mark object which is cryptographically signed. This is
* used in the "signed mark" validation model.
*/
@XmlElementRefs({
@XmlElementRef(type = EncodedSignedMark.class),
@XmlElementRef(type = SignedMark.class)})
List<AbstractSignedMark> signedMarks;
/**
* A CodeMark is an abstract entity which contains either a secret code or a mark (or both) to
* assert its ability to register a particular mark. It is used in the "code", "mark", and "code
* with mark" validation models, none of which are supported by this codebase at this time. As
* such, it is stored only as an Object to mark its existence, but not further unmarshaled.
*/
List<Object> codeMark;
/** The claims notice for this create, required if creating a domain with a claimed label. */
LaunchNotice notice;
public CreateType getCreateType() {
return type;
}
public ImmutableList<AbstractSignedMark> getSignedMarks() {
return nullToEmptyImmutableCopy(signedMarks);
}
public boolean hasCodeMarks() {
return codeMark != null && !codeMark.isEmpty();
}
public LaunchNotice getNotice() {
return notice;
}
}

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 com.google.domain.registry.model.domain.launch;
import com.google.domain.registry.model.eppoutput.Response.ResponseExtension;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
/**
* An XML data object that represents a launch extension that may be present on the response to EPP
* domain application create commands.
*/
@XmlRootElement(name = "creData")
@XmlType(propOrder = {"phase", "applicationId"})
public class LaunchCreateResponseExtension extends LaunchExtension implements ResponseExtension {
/** Builder for {@link LaunchCreateResponseExtension}. */
public static class Builder
extends LaunchExtension.Builder<LaunchCreateResponseExtension, Builder> {}
}

View file

@ -0,0 +1,25 @@
// 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 com.google.domain.registry.model.domain.launch;
import javax.xml.bind.annotation.XmlRootElement;
/**
* An XML data object that represents a launch extension that may be present on EPP domain delete
* commands.
*/
@XmlRootElement(name = "delete")
public class LaunchDeleteExtension
extends LaunchExtension implements ApplicationIdTargetExtension {}

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 com.google.domain.registry.model.domain.launch;
import com.google.domain.registry.model.Buildable.GenericBuilder;
import com.google.domain.registry.model.ImmutableObject;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlTransient;
/**
* A launch extension which can be passed in to domain update and delete, and also returned from
* domain create.
*/
@XmlTransient
public abstract class LaunchExtension extends ImmutableObject {
/** The launch phase that this domain application was created in. */
LaunchPhase phase;
/** Application ID of the domain application. */
@XmlElement(name = "applicationID")
String applicationId;
public LaunchPhase getPhase() {
return phase;
}
public String getApplicationId() {
return applicationId;
}
/** A builder for constructing {@link LaunchExtension}. */
public static class Builder<T extends LaunchExtension, B extends Builder<?, ?>>
extends GenericBuilder<T, B> {
public B setPhase(LaunchPhase phase) {
getInstance().phase = phase;
return thisCastToDerived();
}
public B setApplicationId(String applicationId) {
getInstance().applicationId = applicationId;
return thisCastToDerived();
}
}
}

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 com.google.domain.registry.model.domain.launch;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;
/**
* An XML data object that represents a launch extension that may be present on EPP domain info
* commands.
*/
@XmlRootElement(name = "info")
public class LaunchInfoExtension
extends LaunchExtension implements ApplicationIdTargetExtension {
/** Whether or not to include mark information in the response. */
@XmlAttribute
Boolean includeMark;
public Boolean getIncludeMark() {
return includeMark;
}
}

View file

@ -0,0 +1,59 @@
// 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 com.google.domain.registry.model.domain.launch;
import com.google.common.collect.ImmutableList;
import com.google.domain.registry.model.eppoutput.Response.ResponseExtension;
import com.google.domain.registry.model.mark.Mark;
import com.googlecode.objectify.annotation.Embed;
import java.util.List;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
/**
* An XML data object that represents a launch extension that may be present on the response to EPP
* domain application info commands.
*/
@Embed
@XmlRootElement(name = "infData")
@XmlType(propOrder = { "phase", "applicationId", "applicationStatus", "marks"})
public class LaunchInfoResponseExtension extends LaunchExtension implements ResponseExtension {
/** The current status of this application. */
@XmlElement(name = "status")
ApplicationStatus applicationStatus;
/** The marks associated with this application. */
@XmlElement(name = "mark", namespace = "urn:ietf:params:xml:ns:mark-1.0")
List<Mark> marks;
/** Builder for {@link LaunchInfoResponseExtension}. */
public static class Builder
extends LaunchExtension.Builder<LaunchInfoResponseExtension, Builder> {
public Builder setApplicationStatus(ApplicationStatus applicationStatus) {
getInstance().applicationStatus = applicationStatus;
return this;
}
public Builder setMarks(ImmutableList<Mark> marks) {
getInstance().marks = marks;
return this;
}
}
}

View file

@ -0,0 +1,133 @@
// 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 com.google.domain.registry.model.domain.launch;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.hash.Hashing.crc32;
import static com.google.common.io.BaseEncoding.base16;
import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import com.google.common.base.CharMatcher;
import com.google.common.base.Optional;
import com.google.common.primitives.Ints;
import com.google.domain.registry.model.ImmutableObject;
import com.googlecode.objectify.annotation.Embed;
import com.googlecode.objectify.annotation.IgnoreSave;
import com.googlecode.objectify.condition.IfNull;
import org.joda.time.DateTime;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;
import javax.xml.bind.annotation.XmlValue;
/** The claims notice id from the claims phase. */
@Embed
@XmlType(propOrder = {"noticeId", "expirationTime", "acceptedTime"})
public class LaunchNotice extends ImmutableObject {
/** An empty instance to use in place of null. */
private static final NoticeIdType EMPTY_NOTICE_ID = new NoticeIdType();
/** An id with a validator-id attribute. */
@Embed
public static class NoticeIdType extends ImmutableObject {
/**
* The Trademark Claims Notice ID from
* {@link "http://tools.ietf.org/html/draft-lozano-tmch-func-spec-08#section-6.3"}.
*/
@XmlValue
String tcnId;
/** The identifier of the TMDB provider to use, defaulting to the TMCH. */
@IgnoreSave(IfNull.class)
@XmlAttribute(name = "validatorID")
String validatorId;
public String getTcnId() {
return tcnId;
}
public String getValidatorId() {
// The default value is "tmch".
return Optional.fromNullable(validatorId).or("tmch");
}
}
@XmlElement(name = "noticeID")
NoticeIdType noticeId;
@XmlElement(name = "notAfter")
DateTime expirationTime;
@XmlElement(name = "acceptedDate")
DateTime acceptedTime;
public NoticeIdType getNoticeId() {
return Optional.fromNullable(noticeId).or(EMPTY_NOTICE_ID);
}
public DateTime getExpirationTime() {
return expirationTime;
}
public DateTime getAcceptedTime() {
return acceptedTime;
}
/**
* Validate the checksum of the notice against the domain label.
*
* @throws IllegalArgumentException
* @throws InvalidChecksumException
*/
public void validate(String domainLabel) throws InvalidChecksumException {
// According to http://tools.ietf.org/html/draft-lozano-tmch-func-spec-08#section-6.3, a TCNID
// is always 8 chars of checksum + 19 chars of a decimal notice id. Check the length before
// taking substrings to avoid an IndexOutOfBoundsException.
String tcnId = getNoticeId().getTcnId();
checkArgument(tcnId.length() == 27);
int checksum = Ints.fromByteArray(base16().decode(tcnId.substring(0, 8).toUpperCase()));
String noticeId = tcnId.substring(8);
checkArgument(CharMatcher.inRange('0', '9').matchesAllOf(noticeId));
// The checksum in the first 8 chars must match the crc32 of label + expiration + notice id.
String stringToHash =
domainLabel + MILLISECONDS.toSeconds(getExpirationTime().getMillis()) + noticeId;
int computedChecksum = crc32().hashString(stringToHash, UTF_8).asInt();
if (checksum != computedChecksum) {
throw new InvalidChecksumException();
}
}
/** Thrown from validate() if the checksum is invalid. */
public static class InvalidChecksumException extends Exception {}
public static LaunchNotice create(
String tcnId, String validatorId, DateTime expirationTime, DateTime acceptedTime) {
LaunchNotice instance = new LaunchNotice();
instance.noticeId = new NoticeIdType();
instance.noticeId.tcnId = tcnId;
instance.noticeId.validatorId = "tmch".equals(validatorId) ? null : validatorId;
instance.expirationTime = expirationTime;
instance.acceptedTime = acceptedTime;
return instance;
}
}

View file

@ -0,0 +1,126 @@
// 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 com.google.domain.registry.model.domain.launch;
import static com.google.common.base.CaseFormat.LOWER_CAMEL;
import static com.google.common.base.CaseFormat.UPPER_UNDERSCORE;
import static com.google.domain.registry.util.TypeUtils.getTypesafeEnumMapping;
import static java.util.Objects.hash;
import com.google.common.collect.ImmutableMap;
import com.google.domain.registry.model.ImmutableObject;
import com.googlecode.objectify.annotation.Embed;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlValue;
/**
* The launch phase of the TLD being addressed by this command.
* <p>
* The launch phase refers to the various stages that a TLD goes through before entering general
* availability. The various phases are described below (in order that they usually occur).
*/
@Embed
public class LaunchPhase extends ImmutableObject {
/**
* The phase during which trademark holders can submit registrations or applications with
* trademark information that can be validated by the server.
*/
public static final LaunchPhase SUNRISE = create("sunrise", null);
/**
* A post-Sunrise phase when non-trademark holders are allowed to register domain names with steps
* taken to address a large volume of initial registrations.
*/
public static final LaunchPhase LANDRUSH = create("landrush", null);
/** A combined sunrise/landrush phase. */
public static final LaunchPhase SUNRUSH = create("sunrise", "landrush");
/**
* The Trademark Claims phase, as defined in the TMCH Functional Specification, in which a Claims
* Notice must be displayed to a prospective registrant of a domain name that matches trademarks.
*/
public static final LaunchPhase CLAIMS = create("claims", null);
/** A post-launch phase that is also referred to as "steady state". */
public static final LaunchPhase OPEN = create("open", null);
/** A custom server launch phase that is defined using the "name" attribute. */
public static final LaunchPhase CUSTOM = create("custom", null);
private static final Map<String, LaunchPhase> LAUNCH_PHASES = initEnumMapping();
/**
* Returns a map of the static final fields to their values, case-converted.
*/
private static final ImmutableMap<String, LaunchPhase> initEnumMapping() {
ImmutableMap.Builder<String, LaunchPhase> builder = new ImmutableMap.Builder<>();
for (Entry<String, LaunchPhase> entry : getTypesafeEnumMapping(LaunchPhase.class).entrySet()) {
builder.put(UPPER_UNDERSCORE.to(LOWER_CAMEL, entry.getKey()), entry.getValue());
}
return builder.build();
}
/** Private create function for the typesafe enum pattern. */
public static LaunchPhase create(String phase, String subphase) {
LaunchPhase instance = new LaunchPhase();
instance.phase = phase;
instance.subphase = subphase;
return instance;
}
@XmlValue
String phase;
/**
* Holds the name of a custom phase if the main phase is "custom", or a sub-phase for all other
* values.
*/
@XmlAttribute(name = "name")
String subphase;
public String getPhase() {
return phase;
}
public String getSubphase() {
return subphase;
}
public static LaunchPhase fromValue(String value) {
return LAUNCH_PHASES.get(value);
}
/** A special equals implementation that only considers the string value. */
@Override
public boolean equals(Object other) {
return other instanceof LaunchPhase
&& Objects.equals(phase, ((LaunchPhase) other).phase)
&& Objects.equals(subphase, ((LaunchPhase) other).subphase);
}
/** A special hashCode implementation that only considers the string value. */
@Override
public int hashCode() {
return hash(phase, subphase);
}
}

View file

@ -0,0 +1,25 @@
// 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 com.google.domain.registry.model.domain.launch;
import javax.xml.bind.annotation.XmlRootElement;
/**
* An XML data object that represents a launch extension that may be present on EPP domain update
* commands.
*/
@XmlRootElement(name = "update")
public class LaunchUpdateExtension
extends LaunchExtension implements ApplicationIdTargetExtension {}

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.
@XmlSchema(
namespace = "urn:ietf:params:xml:ns:launch-1.0",
xmlns = @XmlNs(prefix = "launch", namespaceURI = "urn:ietf:params:xml:ns:launch-1.0"),
elementFormDefault = XmlNsForm.QUALIFIED)
@XmlAccessorType(XmlAccessType.FIELD)
@XmlJavaTypeAdapter(UtcDateTimeAdapter.class)
package com.google.domain.registry.model.domain.launch;
import com.google.domain.registry.xml.UtcDateTimeAdapter;
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

@ -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 com.google.domain.registry.model.domain.metadata;
import com.google.domain.registry.model.ImmutableObject;
import com.google.domain.registry.model.eppinput.EppInput.CommandExtension;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
/** A metadata extension that may be present on EPP create/mutate commands. */
@XmlRootElement(name = "metadata")
public class MetadataExtension extends ImmutableObject implements CommandExtension {
/** The reason for the change. */
@XmlElement(name = "reason")
String reason;
/** Whether a change was requested by a registrar. */
@XmlElement(name = "requestedByRegistrar")
boolean requestedByRegistrar;
/**
* Whether a domain is being created for an anchor tenant. This field is only
* relevant for domain creates, and should be omitted for all other operations.
*/
@XmlElement(name = "anchorTenant")
boolean isAnchorTenant;
public String getReason() {
return reason;
}
public boolean getRequestedByRegistrar() {
return requestedByRegistrar;
}
public boolean getIsAnchorTenant() {
return isAnchorTenant;
}
}

View file

@ -0,0 +1,27 @@
// 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:google:params:xml:ns:metadata-1.0",
xmlns = @XmlNs(prefix = "metadata", namespaceURI = "urn:google:params:xml:ns:metadata-1.0"),
elementFormDefault = XmlNsForm.QUALIFIED)
@XmlAccessorType(XmlAccessType.FIELD)
package com.google.domain.registry.model.domain.metadata;
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;

View file

@ -0,0 +1,39 @@
// 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:domain-1.0",
xmlns = @XmlNs(prefix = "domain", namespaceURI = "urn:ietf:params:xml:ns:domain-1.0"),
elementFormDefault = XmlNsForm.QUALIFIED)
@XmlAccessorType(XmlAccessType.FIELD)
@XmlJavaTypeAdapters({
@XmlJavaTypeAdapter(UtcDateTimeAdapter.class),
@XmlJavaTypeAdapter(ContactReferenceUnionAdapter.class),
@XmlJavaTypeAdapter(HostReferenceUnionAdapter.class),
@XmlJavaTypeAdapter(DateAdapter.class)})
package com.google.domain.registry.model.domain;
import com.google.domain.registry.model.domain.ReferenceUnion.ContactReferenceUnionAdapter;
import com.google.domain.registry.model.domain.ReferenceUnion.HostReferenceUnionAdapter;
import com.google.domain.registry.xml.DateAdapter;
import com.google.domain.registry.xml.UtcDateTimeAdapter;
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;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapters;

View file

@ -0,0 +1,104 @@
// 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 com.google.domain.registry.model.domain.rgp;
import com.google.domain.registry.model.translators.EnumToAttributeAdapter;
import com.google.domain.registry.model.translators.EnumToAttributeAdapter.EppEnum;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
/**
* Represents a Registry Grace Period status, as defined by
* <a href="https://tools.ietf.org/html/rfc3915">RFC 3915</a>.
*
* @see "https://www.icann.org/resources/pages/epp-status-codes-2014-06-16-en"
*/
@XmlJavaTypeAdapter(EnumToAttributeAdapter.class)
public enum GracePeriodStatus implements EppEnum {
/**
* This grace period is provided after the initial registration of a domain name. If the domain
* name is deleted by the registrar during this period, the registry provides a credit to the
* registrar for the cost of the registration.
*/
ADD("addPeriod"),
/**
* This grace period is provided after a domain name registration period expires and is extended
* (renewed) automatically by the registry. If the domain name is deleted by the registrar during
* this period, the registry provides a credit to the registrar for the cost of the renewal.
*/
AUTO_RENEW("autoRenewPeriod"),
/**
* This status value is used to describe a domain for which a <delete> command has been received,
* but the domain has not yet been purged because an opportunity exists to restore the domain and
* abort the deletion process.
*/
REDEMPTION("redemptionPeriod"),
/**
* This grace period is provided after a domain name registration period is explicitly extended
* (renewed) by the registrar. If the domain name is deleted by the registrar during this period,
* the registry provides a credit to the registrar for the cost of the renewal.
*/
RENEW("renewPeriod"),
/**
* This status value is used to describe a domain that has entered the purge processing state
* after completing the redemptionPeriod state. A domain in this status MUST also have the EPP
* pendingDelete status.
*/
PENDING_DELETE("pendingDelete"),
/**
* This status value is used to describe a domain that is in the process of being restored after
* being in the redemptionPeriod state.
*/
PENDING_RESTORE("pendingRestore"),
/**
* This grace period is provided after the allocation of a domain name that was applied for during
* sunrise or landrush. If the domain name is deleted by the registrar during this period, the
* registry provides a credit to the registrar for the cost of the registration. This grace period
* is cancelled when any nameservers are set on the domain, at which point it converts to a
* standard add grace period.
*
* <p>Note that this status shows up as "addPeriod" in XML, which is the same as the add grace
* period. This is done deliberately so as not to break the standard EPP schema.
*/
SUNRUSH_ADD("addPeriod"),
/**
* This grace period is provided after the successful transfer of domain name registration
* sponsorship from one registrar to another registrar. If the domain name is deleted by the new
* sponsoring registrar during this period, the registry provides a credit to the registrar for
* the cost of the transfer.
*/
TRANSFER("transferPeriod");
@XmlAttribute(name = "s")
private final String xmlName;
GracePeriodStatus(String xmlName) {
this.xmlName = xmlName;
}
@Override
public String getXmlName() {
return xmlName;
}
}

View file

@ -0,0 +1,48 @@
// 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 com.google.domain.registry.model.domain.rgp;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlEnum;
import javax.xml.bind.annotation.XmlEnumValue;
/** The EPP RGP restore command. */
public class RestoreCommand {
/** Restore operation to perform on this domain. */
@XmlEnum
public enum RestoreOp {
@XmlEnumValue("request")
REQUEST,
@XmlEnumValue("report")
REPORT;
}
/** The restore operation. */
@XmlAttribute
RestoreOp op;
/** A marker object that will be non-null if a report was passed. */
Object report;
public RestoreOp getRestoreOp() {
return op;
}
public boolean hasRestoreReport() {
return report != null;
}
}

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 com.google.domain.registry.model.domain.rgp;
import com.google.common.collect.ImmutableSet;
import com.google.domain.registry.model.ImmutableObject;
import com.google.domain.registry.model.eppoutput.Response.ResponseExtension;
import javax.xml.bind.annotation.XmlRootElement;
/** The EPP registry grace period extension to be returned with domain info commands. */
@XmlRootElement(name = "infData")
public class RgpInfoExtension extends ImmutableObject implements ResponseExtension {
/** Registry grace period statuses for this domain. */
ImmutableSet<GracePeriodStatus> rgpStatus;
public static RgpInfoExtension create(ImmutableSet<GracePeriodStatus> rgpStatus) {
RgpInfoExtension instance = new RgpInfoExtension();
instance.rgpStatus = rgpStatus;
return instance;
}
}

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 com.google.domain.registry.model.domain.rgp;
import com.google.domain.registry.model.ImmutableObject;
import com.google.domain.registry.model.eppinput.EppInput.CommandExtension;
import javax.xml.bind.annotation.XmlRootElement;
/** The EPP RGP extension that may be present on domain update commands. */
@XmlRootElement(name = "update")
public class RgpUpdateExtension extends ImmutableObject implements CommandExtension {
RestoreCommand restore;
public RestoreCommand getRestoreCommand() {
return restore;
}
}

View file

@ -0,0 +1,27 @@
// 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:rgp-1.0",
xmlns = @XmlNs(prefix = "rgp", namespaceURI = "urn:ietf:params:xml:ns:rgp-1.0"),
elementFormDefault = XmlNsForm.QUALIFIED)
@XmlAccessorType(XmlAccessType.FIELD)
package com.google.domain.registry.model.domain.rgp;
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;

View file

@ -0,0 +1,95 @@
// 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 com.google.domain.registry.model.domain.secdns;
import com.google.common.annotations.VisibleForTesting;
import com.google.domain.registry.model.ImmutableObject;
import com.googlecode.objectify.annotation.Embed;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;
import javax.xml.bind.annotation.adapters.HexBinaryAdapter;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
/**
* Holds the data necessary to construct a single Delegation Signer (DS) record for a domain.
*
* @see <a href="http://tools.ietf.org/html/rfc5910">RFC 5910</a>
* @see <a href="http://tools.ietf.org/html/rfc4034">RFC 4034</a>
*/
@Embed
@XmlType(name = "dsData")
public class DelegationSignerData
extends ImmutableObject implements Comparable<DelegationSignerData> {
/** The identifier for this particular key in the domain. */
int keyTag;
/**
* The algorithm used by this key.
*
* @see <a href="http://tools.ietf.org/html/rfc4034#appendix-A.1">RFC 4034 Appendix A.1</a>
*/
@XmlElement(name = "alg")
int algorithm;
/**
* The algorithm used to generate the digest.
*
* @see <a href="http://tools.ietf.org/html/rfc4034#appendix-A.2">RFC 4034 Appendix A.2</a>
*/
int digestType;
/**
* The hexBinary digest of the public key.
*
* @see <a href="http://tools.ietf.org/html/rfc4034#section-5.1.4">RFC 4034 Section 5.1.4</a>
*/
@XmlJavaTypeAdapter(HexBinaryAdapter.class)
byte[] digest;
public int getKeyTag() {
return keyTag;
}
public int getAlgorithm() {
return algorithm;
}
public int getDigestType() {
return digestType;
}
public byte[] getDigest() {
return digest;
}
@VisibleForTesting
public static DelegationSignerData create(
int keyTag, int algorithm, int digestType, byte[] digest) {
DelegationSignerData instance = new DelegationSignerData();
instance.keyTag = keyTag;
instance.algorithm = algorithm;
instance.digestType = digestType;
instance.digest = digest;
return instance;
}
@Override
public int compareTo(DelegationSignerData other) {
return Integer.compare(getKeyTag(), other.getKeyTag());
}
}

View file

@ -0,0 +1,49 @@
// 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 com.google.domain.registry.model.domain.secdns;
import static com.google.domain.registry.util.CollectionUtils.nullSafeImmutableCopy;
import com.google.common.collect.ImmutableSet;
import com.google.domain.registry.model.ImmutableObject;
import com.google.domain.registry.model.eppinput.EppInput.CommandExtension;
import java.util.Set;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
/** The EPP secDNS extension that may be present on domain create commands. */
@XmlRootElement(name = "create")
@XmlType(propOrder = {"maxSigLife", "dsData"})
public class SecDnsCreateExtension extends ImmutableObject implements CommandExtension {
/**
* Time in seconds until the signature should expire.
* <p>
* We do not support expirations, but we need this field to be able to return appropriate errors.
*/
Long maxSigLife;
/** Signatures for this domain. */
Set<DelegationSignerData> dsData;
public Long getMaxSigLife() {
return maxSigLife;
}
public ImmutableSet<DelegationSignerData> getDsData() {
return nullSafeImmutableCopy(dsData);
}
}

View file

@ -0,0 +1,38 @@
// 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 com.google.domain.registry.model.domain.secdns;
import com.google.common.collect.ImmutableSet;
import com.google.domain.registry.model.ImmutableObject;
import com.google.domain.registry.model.eppoutput.Response.ResponseExtension;
import com.googlecode.objectify.annotation.Embed;
import javax.xml.bind.annotation.XmlRootElement;
/** The EPP secDNS extension to be returned with domain info commands. */
@XmlRootElement(name = "infData")
@Embed
public class SecDnsInfoExtension extends ImmutableObject implements ResponseExtension {
/** Signatures for this domain. */
ImmutableSet<DelegationSignerData> dsData;
public static SecDnsInfoExtension create(ImmutableSet<DelegationSignerData> dsData) {
SecDnsInfoExtension instance = new SecDnsInfoExtension();
instance.dsData = dsData;
return instance;
}
}

View file

@ -0,0 +1,106 @@
// 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 com.google.domain.registry.model.domain.secdns;
import static com.google.domain.registry.util.CollectionUtils.nullToEmptyImmutableCopy;
import com.google.common.collect.ImmutableSet;
import com.google.domain.registry.model.ImmutableObject;
import com.google.domain.registry.model.eppinput.EppInput.CommandExtension;
import java.util.Set;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
import javax.xml.bind.annotation.XmlType;
/** The EPP secDNS extension that may be present on domain update commands. */
@XmlRootElement(name = "update")
@XmlType(propOrder = {"remove", "add", "change"})
public class SecDnsUpdateExtension extends ImmutableObject implements CommandExtension {
/**
* Specifies whether this update is urgent.
* <p>
* We don't support urgent updates but we need this to be present to provide appropriate error
* messages if a client requests it.
*/
@XmlAttribute
Boolean urgent;
/** Allows removing some or all delegations. */
@XmlElement(name = "rem")
Remove remove;
/** Allows adding new delegations. */
Add add;
/** Would allow changing maxSigLife except that we don't support it. */
@XmlElement(name = "chg")
Change change;
public Boolean getUrgent() {
return urgent;
}
public Remove getRemove() {
return remove;
}
public Add getAdd() {
return add;
}
public Change getChange() {
return change;
}
@XmlTransient
abstract static class AddRemoveBase extends ImmutableObject {
/** Delegations to add or remove. */
Set<DelegationSignerData> dsData;
public ImmutableSet<DelegationSignerData> getDsData() {
return nullToEmptyImmutableCopy(dsData);
}
}
/** The inner add type on the update extension. */
public static class Add extends AddRemoveBase {}
/** The inner remove type on the update extension. */
@XmlType(propOrder = {"all", "dsData"})
public static class Remove extends AddRemoveBase {
/** Whether to remove all delegations. */
Boolean all;
public Boolean getAll() {
return all;
}
}
/** The inner change type on the update extension, though we don't actually support changes. */
public static class Change extends ImmutableObject {
/**
* Time in seconds until the signature should expire.
* <p>
* We do not support expirations, but we need this field to be able to return appropriate
* errors.
*/
Long maxSigLife;
}
}

View file

@ -0,0 +1,27 @@
// 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:secDNS-1.1",
xmlns = @XmlNs(prefix = "secDNS", namespaceURI = "urn:ietf:params:xml:ns:secDNS-1.1"),
elementFormDefault = XmlNsForm.QUALIFIED)
@XmlAccessorType(XmlAccessType.FIELD)
package com.google.domain.registry.model.domain.secdns;
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;