mirror of
https://github.com/google/nomulus.git
synced 2025-05-13 16:07:15 +02:00
RDAP: Display summary data for search result items
It appears to be standard RDAP practice when returning result sets for domain, nameserver and entity searches to give only summary data for each result item. Any information that can be gleaned from the object itself is included, but related resources are not included. For a domain, for instance, the domain information is included, but nameservers, entities and events (which come from history entries) are suppressed. In their place, there is a standard boilerplate remark in the object indicating that only summary data is included, and that the user should query the item directly to get the full data. Note that summary data is used only for searches; direct queries for an item will still return full data. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=133973835
This commit is contained in:
parent
740d49e22e
commit
b5e421cee3
25 changed files with 773 additions and 1120 deletions
|
@ -90,7 +90,7 @@ public abstract class RdapActionBase implements Runnable {
|
||||||
* @return A map (probably containing nested maps and lists) with the final JSON response data.
|
* @return A map (probably containing nested maps and lists) with the final JSON response data.
|
||||||
*/
|
*/
|
||||||
abstract ImmutableMap<String, Object> getJsonObjectForResource(
|
abstract ImmutableMap<String, Object> getJsonObjectForResource(
|
||||||
String pathSearchString, boolean isHeadRequest, String linkBase) throws HttpException;
|
String pathSearchString, boolean isHeadRequest, String linkBase);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
|
|
|
@ -19,7 +19,6 @@ import static google.registry.request.Action.Method.HEAD;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import google.registry.request.Action;
|
import google.registry.request.Action;
|
||||||
import google.registry.request.HttpException;
|
|
||||||
import google.registry.request.HttpException.NotImplementedException;
|
import google.registry.request.HttpException.NotImplementedException;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
@ -48,7 +47,7 @@ public class RdapAutnumAction extends RdapActionBase {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ImmutableMap<String, Object> getJsonObjectForResource(
|
public ImmutableMap<String, Object> getJsonObjectForResource(
|
||||||
String pathSearchString, boolean isHeadRequest, String linkBase) throws HttpException {
|
String pathSearchString, boolean isHeadRequest, String linkBase) {
|
||||||
throw new NotImplementedException("Domain Name Registry information only");
|
throw new NotImplementedException("Domain Name Registry information only");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,8 +20,8 @@ import static google.registry.request.Action.Method.HEAD;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import google.registry.model.domain.DomainResource;
|
import google.registry.model.domain.DomainResource;
|
||||||
|
import google.registry.rdap.RdapJsonFormatter.OutputDataType;
|
||||||
import google.registry.request.Action;
|
import google.registry.request.Action;
|
||||||
import google.registry.request.HttpException;
|
|
||||||
import google.registry.request.HttpException.NotFoundException;
|
import google.registry.request.HttpException.NotFoundException;
|
||||||
import google.registry.util.Clock;
|
import google.registry.util.Clock;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
@ -50,7 +50,7 @@ public class RdapDomainAction extends RdapActionBase {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ImmutableMap<String, Object> getJsonObjectForResource(
|
public ImmutableMap<String, Object> getJsonObjectForResource(
|
||||||
String pathSearchString, boolean isHeadRequest, String linkBase) throws HttpException {
|
String pathSearchString, boolean isHeadRequest, String linkBase) {
|
||||||
DateTime now = clock.nowUtc();
|
DateTime now = clock.nowUtc();
|
||||||
pathSearchString = canonicalizeName(pathSearchString);
|
pathSearchString = canonicalizeName(pathSearchString);
|
||||||
validateDomainName(pathSearchString);
|
validateDomainName(pathSearchString);
|
||||||
|
@ -61,6 +61,6 @@ public class RdapDomainAction extends RdapActionBase {
|
||||||
throw new NotFoundException(pathSearchString + " not found");
|
throw new NotFoundException(pathSearchString + " not found");
|
||||||
}
|
}
|
||||||
return RdapJsonFormatter.makeRdapJsonForDomain(
|
return RdapJsonFormatter.makeRdapJsonForDomain(
|
||||||
domainResource, true, rdapLinkBase, rdapWhoisServer, now);
|
domainResource, true, rdapLinkBase, rdapWhoisServer, now, OutputDataType.FULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,14 +34,15 @@ import google.registry.model.EppResourceUtils;
|
||||||
import google.registry.model.domain.DomainResource;
|
import google.registry.model.domain.DomainResource;
|
||||||
import google.registry.model.host.HostResource;
|
import google.registry.model.host.HostResource;
|
||||||
import google.registry.rdap.RdapJsonFormatter.BoilerplateType;
|
import google.registry.rdap.RdapJsonFormatter.BoilerplateType;
|
||||||
|
import google.registry.rdap.RdapJsonFormatter.OutputDataType;
|
||||||
import google.registry.request.Action;
|
import google.registry.request.Action;
|
||||||
import google.registry.request.HttpException;
|
|
||||||
import google.registry.request.HttpException.BadRequestException;
|
import google.registry.request.HttpException.BadRequestException;
|
||||||
import google.registry.request.HttpException.NotFoundException;
|
import google.registry.request.HttpException.NotFoundException;
|
||||||
import google.registry.request.Parameter;
|
import google.registry.request.Parameter;
|
||||||
import google.registry.util.Clock;
|
import google.registry.util.Clock;
|
||||||
import google.registry.util.Idn;
|
import google.registry.util.Idn;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import org.joda.time.DateTime;
|
import org.joda.time.DateTime;
|
||||||
|
@ -60,7 +61,7 @@ import org.joda.time.DateTime;
|
||||||
public class RdapDomainSearchAction extends RdapActionBase {
|
public class RdapDomainSearchAction extends RdapActionBase {
|
||||||
|
|
||||||
public static final String PATH = "/rdap/domains";
|
public static final String PATH = "/rdap/domains";
|
||||||
|
|
||||||
public static final int CHUNK_SIZE_SCALING_FACTOR = 5;
|
public static final int CHUNK_SIZE_SCALING_FACTOR = 5;
|
||||||
public static final int MAX_CHUNK_FETCHES = 20;
|
public static final int MAX_CHUNK_FETCHES = 20;
|
||||||
|
|
||||||
|
@ -84,7 +85,7 @@ public class RdapDomainSearchAction extends RdapActionBase {
|
||||||
/** Parses the parameters and calls the appropriate search function. */
|
/** Parses the parameters and calls the appropriate search function. */
|
||||||
@Override
|
@Override
|
||||||
public ImmutableMap<String, Object> getJsonObjectForResource(
|
public ImmutableMap<String, Object> getJsonObjectForResource(
|
||||||
String pathSearchString, boolean isHeadRequest, String linkBase) throws HttpException {
|
String pathSearchString, boolean isHeadRequest, String linkBase) {
|
||||||
DateTime now = clock.nowUtc();
|
DateTime now = clock.nowUtc();
|
||||||
// RDAP syntax example: /rdap/domains?name=exam*.com.
|
// RDAP syntax example: /rdap/domains?name=exam*.com.
|
||||||
// The pathSearchString is not used by search commands.
|
// The pathSearchString is not used by search commands.
|
||||||
|
@ -124,7 +125,8 @@ public class RdapDomainSearchAction extends RdapActionBase {
|
||||||
}
|
}
|
||||||
ImmutableMap.Builder<String, Object> builder = new ImmutableMap.Builder<>();
|
ImmutableMap.Builder<String, Object> builder = new ImmutableMap.Builder<>();
|
||||||
builder.put("domainSearchResults", results);
|
builder.put("domainSearchResults", results);
|
||||||
RdapJsonFormatter.addTopLevelEntries(builder, BoilerplateType.DOMAIN, null, rdapLinkBase);
|
RdapJsonFormatter.addTopLevelEntries(
|
||||||
|
builder, BoilerplateType.DOMAIN, ImmutableList.of(), ImmutableList.of(), rdapLinkBase);
|
||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,9 +140,7 @@ public class RdapDomainSearchAction extends RdapActionBase {
|
||||||
if (domainResource == null) {
|
if (domainResource == null) {
|
||||||
return ImmutableList.of();
|
return ImmutableList.of();
|
||||||
}
|
}
|
||||||
return ImmutableList.of(
|
return makeSearchResults(ImmutableList.of(domainResource), now);
|
||||||
RdapJsonFormatter.makeRdapJsonForDomain(
|
|
||||||
domainResource, false, rdapLinkBase, rdapWhoisServer, now));
|
|
||||||
// Handle queries with a wildcard.
|
// Handle queries with a wildcard.
|
||||||
} else {
|
} else {
|
||||||
// We can't query for undeleted domains as part of the query itself; that would require an
|
// We can't query for undeleted domains as part of the query itself; that would require an
|
||||||
|
@ -154,54 +154,49 @@ public class RdapDomainSearchAction extends RdapActionBase {
|
||||||
// domains as the result set size limit), then give up and return a result set that is smaller
|
// domains as the result set size limit), then give up and return a result set that is smaller
|
||||||
// than the limit. Ugly? You bet!
|
// than the limit. Ugly? You bet!
|
||||||
// TODO(b/31546493): Add metrics to figure out how well this algorithm works.
|
// TODO(b/31546493): Add metrics to figure out how well this algorithm works.
|
||||||
ImmutableList.Builder<ImmutableMap<String, Object>> builder = new ImmutableList.Builder<>();
|
List<DomainResource> domainList = new ArrayList<>();
|
||||||
String previousChunkEnd = null;
|
String previousChunkEndString = null;
|
||||||
for (int numResultsFound = 0, retry = 0;
|
for (int numChunkFetches = 0;
|
||||||
(retry < MAX_CHUNK_FETCHES) && (numResultsFound < rdapResultSetMaxSize);
|
(numChunkFetches < MAX_CHUNK_FETCHES) && (domainList.size() < rdapResultSetMaxSize);
|
||||||
retry++) {
|
numChunkFetches++) {
|
||||||
// Construct the query.
|
// Construct the query.
|
||||||
Query<DomainResource> query = ofy().load()
|
Query<DomainResource> query = ofy().load()
|
||||||
.type(DomainResource.class)
|
.type(DomainResource.class)
|
||||||
.filter("fullyQualifiedDomainName <", partialStringQuery.getNextInitialString());
|
.filter("fullyQualifiedDomainName <", partialStringQuery.getNextInitialString());
|
||||||
if (previousChunkEnd == null) {
|
if (previousChunkEndString == null) {
|
||||||
query = query.filter(
|
query = query.filter(
|
||||||
"fullyQualifiedDomainName >=", partialStringQuery.getInitialString());
|
"fullyQualifiedDomainName >=", partialStringQuery.getInitialString());
|
||||||
} else {
|
} else {
|
||||||
query = query.filter("fullyQualifiedDomainName >", previousChunkEnd);
|
query = query.filter("fullyQualifiedDomainName >", previousChunkEndString);
|
||||||
}
|
}
|
||||||
if (partialStringQuery.getSuffix() != null) {
|
if (partialStringQuery.getSuffix() != null) {
|
||||||
query = query.filter("tld", partialStringQuery.getSuffix());
|
query = query.filter("tld", partialStringQuery.getSuffix());
|
||||||
}
|
}
|
||||||
// Perform the query and weed out deleted domains.
|
// Perform the query and weed out deleted domains.
|
||||||
previousChunkEnd = null;
|
previousChunkEndString = null;
|
||||||
int numDomainsInChunk = 0;
|
int numDomainsInChunk = 0;
|
||||||
for (DomainResource domainResource :
|
for (DomainResource domain :
|
||||||
query.limit(rdapResultSetMaxSize * CHUNK_SIZE_SCALING_FACTOR)) {
|
query.limit(rdapResultSetMaxSize * CHUNK_SIZE_SCALING_FACTOR)) {
|
||||||
previousChunkEnd = domainResource.getFullyQualifiedDomainName();
|
previousChunkEndString = domain.getFullyQualifiedDomainName();
|
||||||
numDomainsInChunk++;
|
numDomainsInChunk++;
|
||||||
if (EppResourceUtils.isActive(domainResource, now)) {
|
if (EppResourceUtils.isActive(domain, now)) {
|
||||||
builder.add(
|
domainList.add(domain);
|
||||||
RdapJsonFormatter.makeRdapJsonForDomain(
|
if (domainList.size() >= rdapResultSetMaxSize) {
|
||||||
domainResource, false, rdapLinkBase, rdapWhoisServer, now));
|
break;
|
||||||
numResultsFound++;
|
|
||||||
if (numResultsFound >= rdapResultSetMaxSize) {
|
|
||||||
return builder.build();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((previousChunkEnd == null)
|
if (numDomainsInChunk < rdapResultSetMaxSize * CHUNK_SIZE_SCALING_FACTOR) {
|
||||||
|| (numDomainsInChunk < rdapResultSetMaxSize * CHUNK_SIZE_SCALING_FACTOR)) {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return builder.build();
|
return makeSearchResults(domainList, now);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Searches for domains by nameserver name, returning a JSON array of domain info maps. */
|
/** Searches for domains by nameserver name, returning a JSON array of domain info maps. */
|
||||||
private ImmutableList<ImmutableMap<String, Object>>
|
private ImmutableList<ImmutableMap<String, Object>>
|
||||||
searchByNameserverLdhName(final RdapSearchPattern partialStringQuery, final DateTime now)
|
searchByNameserverLdhName(final RdapSearchPattern partialStringQuery, final DateTime now) {
|
||||||
throws HttpException {
|
|
||||||
Iterable<Key<HostResource>> hostKeys;
|
Iterable<Key<HostResource>> hostKeys;
|
||||||
// Handle queries without a wildcard; just load the host by foreign key in the usual way.
|
// Handle queries without a wildcard; just load the host by foreign key in the usual way.
|
||||||
if (!partialStringQuery.getHasWildcard()) {
|
if (!partialStringQuery.getHasWildcard()) {
|
||||||
|
@ -278,19 +273,29 @@ public class RdapDomainSearchAction extends RdapActionBase {
|
||||||
private ImmutableList<ImmutableMap<String, Object>>
|
private ImmutableList<ImmutableMap<String, Object>>
|
||||||
searchByNameserverRefs(final Iterable<Key<HostResource>> hostKeys, final DateTime now) {
|
searchByNameserverRefs(final Iterable<Key<HostResource>> hostKeys, final DateTime now) {
|
||||||
// We must break the query up into chunks, because the in operator is limited to 30 subqueries.
|
// We must break the query up into chunks, because the in operator is limited to 30 subqueries.
|
||||||
ImmutableList.Builder<ImmutableMap<String, Object>> builder = new ImmutableList.Builder<>();
|
ImmutableList.Builder<DomainResource> domainListBuilder = new ImmutableList.Builder<>();
|
||||||
for (List<Key<HostResource>> chunk : Iterables.partition(hostKeys, 30)) {
|
for (List<Key<HostResource>> chunk : Iterables.partition(hostKeys, 30)) {
|
||||||
Query<DomainResource> query = ofy().load()
|
domainListBuilder.addAll(
|
||||||
.type(DomainResource.class)
|
ofy().load()
|
||||||
.filter("nameservers.linked in", chunk)
|
.type(DomainResource.class)
|
||||||
.filter("deletionTime >", now)
|
.filter("nameservers.linked in", chunk)
|
||||||
.limit(1000);
|
.filter("deletionTime >", now)
|
||||||
for (DomainResource domainResource : query) {
|
.limit(1000));
|
||||||
builder.add(
|
|
||||||
RdapJsonFormatter.makeRdapJsonForDomain(
|
|
||||||
domainResource, false, rdapLinkBase, rdapWhoisServer, now));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return builder.build();
|
return makeSearchResults(domainListBuilder.build(), now);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Output JSON for a list of domains. */
|
||||||
|
private ImmutableList<ImmutableMap<String, Object>> makeSearchResults(
|
||||||
|
List<DomainResource> domains, DateTime now) {
|
||||||
|
OutputDataType outputDataType =
|
||||||
|
(domains.size() > 1) ? OutputDataType.SUMMARY : OutputDataType.FULL;
|
||||||
|
ImmutableList.Builder<ImmutableMap<String, Object>> jsonBuilder = new ImmutableList.Builder<>();
|
||||||
|
for (DomainResource domain : domains) {
|
||||||
|
jsonBuilder.add(
|
||||||
|
RdapJsonFormatter.makeRdapJsonForDomain(
|
||||||
|
domain, false, rdapLinkBase, rdapWhoisServer, now, outputDataType));
|
||||||
|
}
|
||||||
|
return jsonBuilder.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,8 +26,8 @@ import com.googlecode.objectify.Key;
|
||||||
import google.registry.model.contact.ContactResource;
|
import google.registry.model.contact.ContactResource;
|
||||||
import google.registry.model.domain.DesignatedContact;
|
import google.registry.model.domain.DesignatedContact;
|
||||||
import google.registry.model.registrar.Registrar;
|
import google.registry.model.registrar.Registrar;
|
||||||
|
import google.registry.rdap.RdapJsonFormatter.OutputDataType;
|
||||||
import google.registry.request.Action;
|
import google.registry.request.Action;
|
||||||
import google.registry.request.HttpException;
|
|
||||||
import google.registry.request.HttpException.BadRequestException;
|
import google.registry.request.HttpException.BadRequestException;
|
||||||
import google.registry.request.HttpException.NotFoundException;
|
import google.registry.request.HttpException.NotFoundException;
|
||||||
import google.registry.util.Clock;
|
import google.registry.util.Clock;
|
||||||
|
@ -66,7 +66,7 @@ public class RdapEntityAction extends RdapActionBase {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ImmutableMap<String, Object> getJsonObjectForResource(
|
public ImmutableMap<String, Object> getJsonObjectForResource(
|
||||||
String pathSearchString, boolean isHeadRequest, String linkBase) throws HttpException {
|
String pathSearchString, boolean isHeadRequest, String linkBase) {
|
||||||
DateTime now = clock.nowUtc();
|
DateTime now = clock.nowUtc();
|
||||||
// The query string is not used; the RDAP syntax is /rdap/entity/handle (the handle is the roid
|
// The query string is not used; the RDAP syntax is /rdap/entity/handle (the handle is the roid
|
||||||
// for contacts and the client identifier for registrars). Since RDAP's concept of an entity
|
// for contacts and the client identifier for registrars). Since RDAP's concept of an entity
|
||||||
|
@ -85,7 +85,8 @@ public class RdapEntityAction extends RdapActionBase {
|
||||||
Optional.<DesignatedContact.Type>absent(),
|
Optional.<DesignatedContact.Type>absent(),
|
||||||
rdapLinkBase,
|
rdapLinkBase,
|
||||||
rdapWhoisServer,
|
rdapWhoisServer,
|
||||||
now);
|
now,
|
||||||
|
OutputDataType.FULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
@ -95,7 +96,7 @@ public class RdapEntityAction extends RdapActionBase {
|
||||||
Registrar.loadByIanaIdentifierRange(ianaIdentifier, ianaIdentifier + 1, 1), null);
|
Registrar.loadByIanaIdentifierRange(ianaIdentifier, ianaIdentifier + 1, 1), null);
|
||||||
if ((registrar != null) && registrar.isActiveAndPubliclyVisible()) {
|
if ((registrar != null) && registrar.isActiveAndPubliclyVisible()) {
|
||||||
return RdapJsonFormatter.makeRdapJsonForRegistrar(
|
return RdapJsonFormatter.makeRdapJsonForRegistrar(
|
||||||
registrar, true, rdapLinkBase, rdapWhoisServer, now);
|
registrar, true, rdapLinkBase, rdapWhoisServer, now, OutputDataType.FULL);
|
||||||
}
|
}
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
// Although the search string was not a valid IANA identifier, it might still have been a
|
// Although the search string was not a valid IANA identifier, it might still have been a
|
||||||
|
|
|
@ -29,13 +29,15 @@ import google.registry.model.contact.ContactResource;
|
||||||
import google.registry.model.domain.DesignatedContact;
|
import google.registry.model.domain.DesignatedContact;
|
||||||
import google.registry.model.registrar.Registrar;
|
import google.registry.model.registrar.Registrar;
|
||||||
import google.registry.rdap.RdapJsonFormatter.BoilerplateType;
|
import google.registry.rdap.RdapJsonFormatter.BoilerplateType;
|
||||||
|
import google.registry.rdap.RdapJsonFormatter.OutputDataType;
|
||||||
import google.registry.request.Action;
|
import google.registry.request.Action;
|
||||||
import google.registry.request.HttpException;
|
|
||||||
import google.registry.request.HttpException.BadRequestException;
|
import google.registry.request.HttpException.BadRequestException;
|
||||||
import google.registry.request.HttpException.NotFoundException;
|
import google.registry.request.HttpException.NotFoundException;
|
||||||
import google.registry.request.HttpException.UnprocessableEntityException;
|
import google.registry.request.HttpException.UnprocessableEntityException;
|
||||||
import google.registry.request.Parameter;
|
import google.registry.request.Parameter;
|
||||||
import google.registry.util.Clock;
|
import google.registry.util.Clock;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import org.joda.time.DateTime;
|
import org.joda.time.DateTime;
|
||||||
|
|
||||||
|
@ -73,7 +75,7 @@ public class RdapEntitySearchAction extends RdapActionBase {
|
||||||
/** Parses the parameters and calls the appropriate search function. */
|
/** Parses the parameters and calls the appropriate search function. */
|
||||||
@Override
|
@Override
|
||||||
public ImmutableMap<String, Object> getJsonObjectForResource(
|
public ImmutableMap<String, Object> getJsonObjectForResource(
|
||||||
String pathSearchString, boolean isHeadRequest, String linkBase) throws HttpException {
|
String pathSearchString, boolean isHeadRequest, String linkBase) {
|
||||||
DateTime now = clock.nowUtc();
|
DateTime now = clock.nowUtc();
|
||||||
// RDAP syntax example: /rdap/entities?fn=Bobby%20Joe*.
|
// RDAP syntax example: /rdap/entities?fn=Bobby%20Joe*.
|
||||||
// The pathSearchString is not used by search commands.
|
// The pathSearchString is not used by search commands.
|
||||||
|
@ -96,10 +98,11 @@ public class RdapEntitySearchAction extends RdapActionBase {
|
||||||
if (results.isEmpty()) {
|
if (results.isEmpty()) {
|
||||||
throw new NotFoundException("No entities found");
|
throw new NotFoundException("No entities found");
|
||||||
}
|
}
|
||||||
ImmutableMap.Builder<String, Object> builder = new ImmutableMap.Builder<>();
|
ImmutableMap.Builder<String, Object> jsonBuilder = new ImmutableMap.Builder<>();
|
||||||
builder.put("entitySearchResults", results);
|
jsonBuilder.put("entitySearchResults", results);
|
||||||
RdapJsonFormatter.addTopLevelEntries(builder, BoilerplateType.ENTITY, null, rdapLinkBase);
|
RdapJsonFormatter.addTopLevelEntries(
|
||||||
return builder.build();
|
jsonBuilder, BoilerplateType.ENTITY, ImmutableList.of(), ImmutableList.of(), rdapLinkBase);
|
||||||
|
return jsonBuilder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -117,7 +120,7 @@ public class RdapEntitySearchAction extends RdapActionBase {
|
||||||
* assume that entity names are regular unicode.
|
* assume that entity names are regular unicode.
|
||||||
*/
|
*/
|
||||||
private ImmutableList<ImmutableMap<String, Object>>
|
private ImmutableList<ImmutableMap<String, Object>>
|
||||||
searchByName(final RdapSearchPattern partialStringQuery, DateTime now) throws HttpException {
|
searchByName(final RdapSearchPattern partialStringQuery, DateTime now) {
|
||||||
// Handle queries without a wildcard -- load by name, which may not be unique.
|
// Handle queries without a wildcard -- load by name, which may not be unique.
|
||||||
if (!partialStringQuery.getHasWildcard()) {
|
if (!partialStringQuery.getHasWildcard()) {
|
||||||
Registrar registrar = Registrar.loadByName(partialStringQuery.getInitialString());
|
Registrar registrar = Registrar.loadByName(partialStringQuery.getInitialString());
|
||||||
|
@ -126,7 +129,8 @@ public class RdapEntitySearchAction extends RdapActionBase {
|
||||||
.type(ContactResource.class)
|
.type(ContactResource.class)
|
||||||
.filter("searchName", partialStringQuery.getInitialString())
|
.filter("searchName", partialStringQuery.getInitialString())
|
||||||
.filter("deletionTime", END_OF_TIME)
|
.filter("deletionTime", END_OF_TIME)
|
||||||
.limit(rdapResultSetMaxSize),
|
.limit(rdapResultSetMaxSize)
|
||||||
|
.list(),
|
||||||
(registrar == null)
|
(registrar == null)
|
||||||
? ImmutableList.<Registrar>of() : ImmutableList.of(registrar),
|
? ImmutableList.<Registrar>of() : ImmutableList.of(registrar),
|
||||||
now);
|
now);
|
||||||
|
@ -141,11 +145,12 @@ public class RdapEntitySearchAction extends RdapActionBase {
|
||||||
.filter("searchName >=", partialStringQuery.getInitialString())
|
.filter("searchName >=", partialStringQuery.getInitialString())
|
||||||
.filter("searchName <", partialStringQuery.getNextInitialString())
|
.filter("searchName <", partialStringQuery.getNextInitialString())
|
||||||
.filter("deletionTime", END_OF_TIME)
|
.filter("deletionTime", END_OF_TIME)
|
||||||
.limit(rdapResultSetMaxSize),
|
.limit(rdapResultSetMaxSize)
|
||||||
Registrar.loadByNameRange(
|
.list(),
|
||||||
|
ImmutableList.copyOf(Registrar.loadByNameRange(
|
||||||
partialStringQuery.getInitialString(),
|
partialStringQuery.getInitialString(),
|
||||||
partialStringQuery.getNextInitialString(),
|
partialStringQuery.getNextInitialString(),
|
||||||
rdapResultSetMaxSize),
|
rdapResultSetMaxSize)),
|
||||||
now);
|
now);
|
||||||
// Don't allow suffixes in entity name search queries.
|
// Don't allow suffixes in entity name search queries.
|
||||||
} else {
|
} else {
|
||||||
|
@ -155,7 +160,7 @@ public class RdapEntitySearchAction extends RdapActionBase {
|
||||||
|
|
||||||
/** Searches for entities by handle, returning a JSON array of entity info maps. */
|
/** Searches for entities by handle, returning a JSON array of entity info maps. */
|
||||||
private ImmutableList<ImmutableMap<String, Object>> searchByHandle(
|
private ImmutableList<ImmutableMap<String, Object>> searchByHandle(
|
||||||
final RdapSearchPattern partialStringQuery, DateTime now) throws HttpException {
|
final RdapSearchPattern partialStringQuery, DateTime now) {
|
||||||
// Handle queries without a wildcard -- load by ID.
|
// Handle queries without a wildcard -- load by ID.
|
||||||
if (!partialStringQuery.getHasWildcard()) {
|
if (!partialStringQuery.getHasWildcard()) {
|
||||||
ContactResource contactResource = ofy().load()
|
ContactResource contactResource = ofy().load()
|
||||||
|
@ -183,7 +188,8 @@ public class RdapEntitySearchAction extends RdapActionBase {
|
||||||
.filterKey(
|
.filterKey(
|
||||||
"<", Key.create(ContactResource.class, partialStringQuery.getNextInitialString()))
|
"<", Key.create(ContactResource.class, partialStringQuery.getNextInitialString()))
|
||||||
.filter("deletionTime", END_OF_TIME)
|
.filter("deletionTime", END_OF_TIME)
|
||||||
.limit(rdapResultSetMaxSize),
|
.limit(rdapResultSetMaxSize)
|
||||||
|
.list(),
|
||||||
ImmutableList.<Registrar>of(),
|
ImmutableList.<Registrar>of(),
|
||||||
now);
|
now);
|
||||||
// Don't allow suffixes in entity handle search queries.
|
// Don't allow suffixes in entity handle search queries.
|
||||||
|
@ -207,29 +213,58 @@ public class RdapEntitySearchAction extends RdapActionBase {
|
||||||
|
|
||||||
/** Builds a JSON array of entity info maps based on the specified contacts and registrars. */
|
/** Builds a JSON array of entity info maps based on the specified contacts and registrars. */
|
||||||
private ImmutableList<ImmutableMap<String, Object>> makeSearchResults(
|
private ImmutableList<ImmutableMap<String, Object>> makeSearchResults(
|
||||||
Iterable<ContactResource> contactResources, Iterable<Registrar> registrars, DateTime now)
|
List<ContactResource> contacts,
|
||||||
throws HttpException {
|
List<Registrar> registrars,
|
||||||
ImmutableList.Builder<ImmutableMap<String, Object>> builder = new ImmutableList.Builder<>();
|
DateTime now) {
|
||||||
for (ContactResource contact : contactResources) {
|
|
||||||
|
// Determine what output data type to use, depending on whether more than one entity will be
|
||||||
|
// returned.
|
||||||
|
int numEntities = contacts.size();
|
||||||
|
OutputDataType outputDataType;
|
||||||
|
// If there's more than one contact, then we know already that we need SUMMARY mode.
|
||||||
|
if (numEntities > 1) {
|
||||||
|
outputDataType = OutputDataType.SUMMARY;
|
||||||
|
// If there are fewer than two contacts, loop through and compute the total number of contacts
|
||||||
|
// and registrars, stopping as soon as we find two.
|
||||||
|
} else {
|
||||||
|
outputDataType = OutputDataType.FULL;
|
||||||
|
for (Registrar registrar : registrars) {
|
||||||
|
if (registrar.isActiveAndPubliclyVisible()) {
|
||||||
|
numEntities++;
|
||||||
|
if (numEntities > 1) {
|
||||||
|
outputDataType = OutputDataType.SUMMARY;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<ImmutableMap<String, Object>> jsonOutputList = new ArrayList<>();
|
||||||
|
// In theory, there could be more results than our max size, so limit the size.
|
||||||
|
for (ContactResource contact : contacts) {
|
||||||
|
if (jsonOutputList.size() >= rdapResultSetMaxSize) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
// As per Andy Newton on the regext mailing list, contacts by themselves have no role, since
|
// As per Andy Newton on the regext mailing list, contacts by themselves have no role, since
|
||||||
// they are global, and might have different roles for different domains.
|
// they are global, and might have different roles for different domains.
|
||||||
builder.add(RdapJsonFormatter.makeRdapJsonForContact(
|
jsonOutputList.add(RdapJsonFormatter.makeRdapJsonForContact(
|
||||||
contact,
|
contact,
|
||||||
false,
|
false,
|
||||||
Optional.<DesignatedContact.Type>absent(),
|
Optional.<DesignatedContact.Type>absent(),
|
||||||
rdapLinkBase,
|
rdapLinkBase,
|
||||||
rdapWhoisServer, now));
|
rdapWhoisServer,
|
||||||
|
now,
|
||||||
|
outputDataType));
|
||||||
}
|
}
|
||||||
for (Registrar registrar : registrars) {
|
for (Registrar registrar : registrars) {
|
||||||
|
if (jsonOutputList.size() >= rdapResultSetMaxSize) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (registrar.isActiveAndPubliclyVisible()) {
|
if (registrar.isActiveAndPubliclyVisible()) {
|
||||||
builder.add(RdapJsonFormatter.makeRdapJsonForRegistrar(
|
jsonOutputList.add(RdapJsonFormatter.makeRdapJsonForRegistrar(
|
||||||
registrar, false, rdapLinkBase, rdapWhoisServer, now));
|
registrar, false, rdapLinkBase, rdapWhoisServer, now, outputDataType));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// In theory, there could be more results than our max size, so limit the size.
|
return ImmutableList.copyOf(jsonOutputList);
|
||||||
ImmutableList<ImmutableMap<String, Object>> resultSet = builder.build();
|
|
||||||
return (resultSet.size() <= rdapResultSetMaxSize)
|
|
||||||
? resultSet
|
|
||||||
: resultSet.subList(0, rdapResultSetMaxSize);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,6 @@ import com.google.common.collect.ImmutableMap;
|
||||||
import google.registry.rdap.RdapJsonFormatter.BoilerplateType;
|
import google.registry.rdap.RdapJsonFormatter.BoilerplateType;
|
||||||
import google.registry.rdap.RdapJsonFormatter.MakeRdapJsonNoticeParameters;
|
import google.registry.rdap.RdapJsonFormatter.MakeRdapJsonNoticeParameters;
|
||||||
import google.registry.request.Action;
|
import google.registry.request.Action;
|
||||||
import google.registry.request.HttpException;
|
|
||||||
import google.registry.request.HttpException.InternalServerErrorException;
|
import google.registry.request.HttpException.InternalServerErrorException;
|
||||||
import google.registry.request.HttpException.NotFoundException;
|
import google.registry.request.HttpException.NotFoundException;
|
||||||
import google.registry.util.Clock;
|
import google.registry.util.Clock;
|
||||||
|
@ -130,7 +129,7 @@ public class RdapHelpAction extends RdapActionBase {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ImmutableMap<String, Object> getJsonObjectForResource(
|
public ImmutableMap<String, Object> getJsonObjectForResource(
|
||||||
String pathSearchString, boolean isHeadRequest, String linkBase) throws HttpException {
|
String pathSearchString, boolean isHeadRequest, String linkBase) {
|
||||||
// We rely on addTopLevelEntries to notice if we are sending the TOS notice, and not add a
|
// We rely on addTopLevelEntries to notice if we are sending the TOS notice, and not add a
|
||||||
// duplicate boilerplate entry.
|
// duplicate boilerplate entry.
|
||||||
ImmutableMap.Builder<String, Object> builder = new ImmutableMap.Builder<>();
|
ImmutableMap.Builder<String, Object> builder = new ImmutableMap.Builder<>();
|
||||||
|
@ -138,6 +137,7 @@ public class RdapHelpAction extends RdapActionBase {
|
||||||
builder,
|
builder,
|
||||||
BoilerplateType.OTHER,
|
BoilerplateType.OTHER,
|
||||||
ImmutableList.of(getJsonHelpNotice(pathSearchString, rdapLinkBase)),
|
ImmutableList.of(getJsonHelpNotice(pathSearchString, rdapLinkBase)),
|
||||||
|
ImmutableList.of(),
|
||||||
rdapLinkBase);
|
rdapLinkBase);
|
||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,4 +71,15 @@ public class RdapIcannStandardInformation {
|
||||||
/** Boilerplate remarks required by nameserver and entity responses. */
|
/** Boilerplate remarks required by nameserver and entity responses. */
|
||||||
static final ImmutableList<ImmutableMap<String, Object>> nameserverAndEntityBoilerplateRemarks =
|
static final ImmutableList<ImmutableMap<String, Object>> nameserverAndEntityBoilerplateRemarks =
|
||||||
ImmutableList.of(CONFORMANCE_REMARK);
|
ImmutableList.of(CONFORMANCE_REMARK);
|
||||||
|
|
||||||
|
/** Required by ICANN RDAP Profile section 1.1.18. */
|
||||||
|
static final ImmutableMap<String, Object> SUMMARY_DATA_REMARK =
|
||||||
|
ImmutableMap.<String, Object> of(
|
||||||
|
"title",
|
||||||
|
"Incomplete Data",
|
||||||
|
"description",
|
||||||
|
ImmutableList.of(
|
||||||
|
"Summary data only. For complete data, send a specific query for the object."),
|
||||||
|
"type",
|
||||||
|
"object truncated due to unexplainable reasons");
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,6 @@ import static google.registry.request.Action.Method.HEAD;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import google.registry.request.Action;
|
import google.registry.request.Action;
|
||||||
import google.registry.request.HttpException;
|
|
||||||
import google.registry.request.HttpException.NotImplementedException;
|
import google.registry.request.HttpException.NotImplementedException;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
@ -49,7 +48,7 @@ public class RdapIpAction extends RdapActionBase {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ImmutableMap<String, Object> getJsonObjectForResource(
|
public ImmutableMap<String, Object> getJsonObjectForResource(
|
||||||
String pathSearchString, boolean isHeadRequest, String linkBase) throws HttpException {
|
String pathSearchString, boolean isHeadRequest, String linkBase) {
|
||||||
throw new NotImplementedException("Domain Name Registry information only");
|
throw new NotImplementedException("Domain Name Registry information only");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,6 +48,7 @@ import java.net.Inet4Address;
|
||||||
import java.net.Inet6Address;
|
import java.net.Inet6Address;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
@ -66,6 +67,19 @@ import org.joda.time.DateTime;
|
||||||
*/
|
*/
|
||||||
public class RdapJsonFormatter {
|
public class RdapJsonFormatter {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* What type of data to generate. Summary data includes only information about the object itself,
|
||||||
|
* while full data includes associated items (e.g. for domains, full data includes the hosts,
|
||||||
|
* contacts and history entries connected with the domain). Summary data is appropriate for search
|
||||||
|
* queries which return many results, to avoid load on the system. According to the ICANN
|
||||||
|
* operational profile, a remark must be attached to the returned object indicating that it
|
||||||
|
* includes only summary data.
|
||||||
|
*/
|
||||||
|
public enum OutputDataType {
|
||||||
|
FULL,
|
||||||
|
SUMMARY
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indication of what type of boilerplate notices are required for the RDAP JSON messages. The
|
* Indication of what type of boilerplate notices are required for the RDAP JSON messages. The
|
||||||
* ICANN RDAP Profile specifies that, for instance, domain name responses should include a remark
|
* ICANN RDAP Profile specifies that, for instance, domain name responses should include a remark
|
||||||
|
@ -269,24 +283,27 @@ public class RdapJsonFormatter {
|
||||||
* 1.5.20. Note that this method will only work if there are no object-specific remarks already in
|
* 1.5.20. Note that this method will only work if there are no object-specific remarks already in
|
||||||
* the JSON object being built. If there are, the boilerplate must be merged in.
|
* the JSON object being built. If there are, the boilerplate must be merged in.
|
||||||
*
|
*
|
||||||
* @param builder a builder for a JSON map object
|
* @param jsonBuilder a builder for a JSON map object
|
||||||
* @param boilerplateType type of boilerplate to be added; the ICANN RDAP Profile document
|
* @param boilerplateType type of boilerplate to be added; the ICANN RDAP Profile document
|
||||||
* mandates extra boilerplate for domain objects
|
* mandates extra boilerplate for domain objects
|
||||||
* @param notices a list of notices to be inserted before the boilerplate notices. If the TOS
|
* @param notices a list of notices to be inserted before the boilerplate notices. If the TOS
|
||||||
* notice is in this list, the method avoids adding a second copy.
|
* notice is in this list, the method avoids adding a second copy.
|
||||||
|
* @param remarks a list of remarks to be inserted before the boilerplate notices.
|
||||||
* @param rdapLinkBase the base for link URLs
|
* @param rdapLinkBase the base for link URLs
|
||||||
*/
|
*/
|
||||||
static void addTopLevelEntries(
|
static void addTopLevelEntries(
|
||||||
ImmutableMap.Builder<String, Object> builder,
|
ImmutableMap.Builder<String, Object> jsonBuilder,
|
||||||
BoilerplateType boilerplateType,
|
BoilerplateType boilerplateType,
|
||||||
@Nullable Iterable<ImmutableMap<String, Object>> notices,
|
List<ImmutableMap<String, Object>> notices,
|
||||||
|
List<ImmutableMap<String, Object>> remarks,
|
||||||
String rdapLinkBase) {
|
String rdapLinkBase) {
|
||||||
builder.put("rdapConformance", CONFORMANCE_LIST);
|
jsonBuilder.put("rdapConformance", CONFORMANCE_LIST);
|
||||||
ImmutableList.Builder<ImmutableMap<String, Object>> noticesBuilder = ImmutableList.builder();
|
ImmutableList.Builder<ImmutableMap<String, Object>> noticesBuilder =
|
||||||
|
new ImmutableList.Builder<>();
|
||||||
ImmutableMap<String, Object> tosNotice =
|
ImmutableMap<String, Object> tosNotice =
|
||||||
RdapHelpAction.getJsonHelpNotice(RdapHelpAction.TERMS_OF_SERVICE_PATH, rdapLinkBase);
|
RdapHelpAction.getJsonHelpNotice(RdapHelpAction.TERMS_OF_SERVICE_PATH, rdapLinkBase);
|
||||||
boolean tosNoticeFound = false;
|
boolean tosNoticeFound = false;
|
||||||
if (notices != null) {
|
if (!notices.isEmpty()) {
|
||||||
noticesBuilder.addAll(notices);
|
noticesBuilder.addAll(notices);
|
||||||
for (ImmutableMap<String, Object> notice : notices) {
|
for (ImmutableMap<String, Object> notice : notices) {
|
||||||
if (notice.equals(tosNotice)) {
|
if (notice.equals(tosNotice)) {
|
||||||
|
@ -298,18 +315,25 @@ public class RdapJsonFormatter {
|
||||||
if (!tosNoticeFound) {
|
if (!tosNoticeFound) {
|
||||||
noticesBuilder.add(tosNotice);
|
noticesBuilder.add(tosNotice);
|
||||||
}
|
}
|
||||||
builder.put(NOTICES, noticesBuilder.build());
|
jsonBuilder.put(NOTICES, noticesBuilder.build());
|
||||||
|
ImmutableList.Builder<ImmutableMap<String, Object>> remarksBuilder =
|
||||||
|
new ImmutableList.Builder<>();
|
||||||
|
remarksBuilder.addAll(remarks);
|
||||||
switch (boilerplateType) {
|
switch (boilerplateType) {
|
||||||
case DOMAIN:
|
case DOMAIN:
|
||||||
builder.put(REMARKS, RdapIcannStandardInformation.domainBoilerplateRemarks);
|
remarksBuilder.addAll(RdapIcannStandardInformation.domainBoilerplateRemarks);
|
||||||
break;
|
break;
|
||||||
case NAMESERVER:
|
case NAMESERVER:
|
||||||
case ENTITY:
|
case ENTITY:
|
||||||
builder.put(REMARKS, RdapIcannStandardInformation.nameserverAndEntityBoilerplateRemarks);
|
remarksBuilder.addAll(RdapIcannStandardInformation.nameserverAndEntityBoilerplateRemarks);
|
||||||
break;
|
break;
|
||||||
default: // things other than domains, nameservers and entities cannot contain remarks
|
default: // things other than domains, nameservers and entities cannot contain remarks
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
ImmutableList<ImmutableMap<String, Object>> remarksToAdd = remarksBuilder.build();
|
||||||
|
if (!remarksToAdd.isEmpty()) {
|
||||||
|
jsonBuilder.put(REMARKS, remarksToAdd);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** AutoValue class to build parameters to {@link #makeRdapJsonNotice}. */
|
/** AutoValue class to build parameters to {@link #makeRdapJsonNotice}. */
|
||||||
|
@ -367,22 +391,22 @@ public class RdapJsonFormatter {
|
||||||
*/
|
*/
|
||||||
static ImmutableMap<String, Object> makeRdapJsonNotice(
|
static ImmutableMap<String, Object> makeRdapJsonNotice(
|
||||||
MakeRdapJsonNoticeParameters parameters, @Nullable String linkBase) {
|
MakeRdapJsonNoticeParameters parameters, @Nullable String linkBase) {
|
||||||
ImmutableMap.Builder<String, Object> builder = new ImmutableMap.Builder<>();
|
ImmutableMap.Builder<String, Object> jsonBuilder = new ImmutableMap.Builder<>();
|
||||||
if (parameters.title() != null) {
|
if (parameters.title() != null) {
|
||||||
builder.put("title", parameters.title());
|
jsonBuilder.put("title", parameters.title());
|
||||||
}
|
}
|
||||||
ImmutableList.Builder<String> descriptionBuilder = new ImmutableList.Builder<>();
|
ImmutableList.Builder<String> descriptionBuilder = new ImmutableList.Builder<>();
|
||||||
for (String line : parameters.description()) {
|
for (String line : parameters.description()) {
|
||||||
descriptionBuilder.add(nullToEmpty(line));
|
descriptionBuilder.add(nullToEmpty(line));
|
||||||
}
|
}
|
||||||
builder.put("description", descriptionBuilder.build());
|
jsonBuilder.put("description", descriptionBuilder.build());
|
||||||
if (parameters.typeString() != null) {
|
if (parameters.typeString() != null) {
|
||||||
builder.put("typeString", parameters.typeString());
|
jsonBuilder.put("typeString", parameters.typeString());
|
||||||
}
|
}
|
||||||
String linkValueString =
|
String linkValueString =
|
||||||
nullToEmpty(linkBase) + nullToEmpty(parameters.linkValueSuffix());
|
nullToEmpty(linkBase) + nullToEmpty(parameters.linkValueSuffix());
|
||||||
if (parameters.linkHrefUrlString() == null) {
|
if (parameters.linkHrefUrlString() == null) {
|
||||||
builder.put("links", ImmutableList.of(ImmutableMap.of(
|
jsonBuilder.put("links", ImmutableList.of(ImmutableMap.of(
|
||||||
"value", linkValueString,
|
"value", linkValueString,
|
||||||
"rel", "self",
|
"rel", "self",
|
||||||
"href", linkValueString,
|
"href", linkValueString,
|
||||||
|
@ -390,112 +414,146 @@ public class RdapJsonFormatter {
|
||||||
} else {
|
} else {
|
||||||
URI htmlBaseURI = URI.create(nullToEmpty(linkBase));
|
URI htmlBaseURI = URI.create(nullToEmpty(linkBase));
|
||||||
URI htmlUri = htmlBaseURI.resolve(parameters.linkHrefUrlString());
|
URI htmlUri = htmlBaseURI.resolve(parameters.linkHrefUrlString());
|
||||||
builder.put("links", ImmutableList.of(ImmutableMap.of(
|
jsonBuilder.put("links", ImmutableList.of(ImmutableMap.of(
|
||||||
"value", linkValueString,
|
"value", linkValueString,
|
||||||
"rel", "alternate",
|
"rel", "alternate",
|
||||||
"href", htmlUri.toString(),
|
"href", htmlUri.toString(),
|
||||||
"type", "text/html")));
|
"type", "text/html")));
|
||||||
}
|
}
|
||||||
return builder.build();
|
return jsonBuilder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a JSON object for a {@link DomainResource}.
|
* Creates a JSON object for a {@link DomainResource}.
|
||||||
*
|
*
|
||||||
* @param domainResource the domain resource object from which the JSON object should be created
|
* @param domainResource the domain resource object from which the JSON object should be created
|
||||||
|
* @param isTopLevel if true, the top-level boilerplate will be added
|
||||||
* @param linkBase the URL base to be used when creating links
|
* @param linkBase the URL base to be used when creating links
|
||||||
* @param whoisServer the fully-qualified domain name of the WHOIS server to be listed in the
|
* @param whoisServer the fully-qualified domain name of the WHOIS server to be listed in the
|
||||||
* port43 field; if null, port43 is not added to the object
|
* port43 field; if null, port43 is not added to the object
|
||||||
|
* @param now the as-date
|
||||||
|
* @param outputDataType whether to generate full or summary data
|
||||||
*/
|
*/
|
||||||
static ImmutableMap<String, Object> makeRdapJsonForDomain(
|
static ImmutableMap<String, Object> makeRdapJsonForDomain(
|
||||||
DomainResource domainResource,
|
DomainResource domainResource,
|
||||||
boolean isTopLevel,
|
boolean isTopLevel,
|
||||||
@Nullable String linkBase,
|
@Nullable String linkBase,
|
||||||
@Nullable String whoisServer,
|
@Nullable String whoisServer,
|
||||||
DateTime now) {
|
DateTime now,
|
||||||
// Kick off the database loads of the nameservers that we will need.
|
OutputDataType outputDataType) {
|
||||||
Map<Key<HostResource>, HostResource> loadedHosts =
|
// Start with the domain-level information.
|
||||||
ofy().load().keys(domainResource.getNameservers());
|
ImmutableMap.Builder<String, Object> jsonBuilder = new ImmutableMap.Builder<>();
|
||||||
// And the registrant and other contacts.
|
jsonBuilder.put("objectClassName", "domain");
|
||||||
Map<Key<ContactResource>, ContactResource> loadedContacts =
|
jsonBuilder.put("handle", domainResource.getRepoId());
|
||||||
ofy().load().keys(domainResource.getReferencedContacts());
|
jsonBuilder.put("ldhName", domainResource.getFullyQualifiedDomainName());
|
||||||
|
|
||||||
// Now, assemble the results, using the loaded objects as needed.
|
|
||||||
ImmutableMap.Builder<String, Object> builder = new ImmutableMap.Builder<>();
|
|
||||||
builder.put("objectClassName", "domain");
|
|
||||||
builder.put("handle", domainResource.getRepoId());
|
|
||||||
builder.put("ldhName", domainResource.getFullyQualifiedDomainName());
|
|
||||||
// Only include the unicodeName field if there are unicode characters.
|
// Only include the unicodeName field if there are unicode characters.
|
||||||
if (hasUnicodeComponents(domainResource.getFullyQualifiedDomainName())) {
|
if (hasUnicodeComponents(domainResource.getFullyQualifiedDomainName())) {
|
||||||
builder.put("unicodeName", Idn.toUnicode(domainResource.getFullyQualifiedDomainName()));
|
jsonBuilder.put("unicodeName", Idn.toUnicode(domainResource.getFullyQualifiedDomainName()));
|
||||||
}
|
}
|
||||||
builder.put("status", makeStatusValueList(domainResource.getStatusValues()));
|
jsonBuilder.put("status", makeStatusValueList(domainResource.getStatusValues()));
|
||||||
builder.put("links", ImmutableList.of(
|
jsonBuilder.put("links", ImmutableList.of(
|
||||||
makeLink("domain", domainResource.getFullyQualifiedDomainName(), linkBase)));
|
makeLink("domain", domainResource.getFullyQualifiedDomainName(), linkBase)));
|
||||||
ImmutableList<Object> events = makeEvents(domainResource, now);
|
// If we are outputting all data (not just summary data), also add information about hosts,
|
||||||
if (!events.isEmpty()) {
|
// contacts and events (history entries). If we are outputting summary data, instead add a
|
||||||
builder.put("events", events);
|
// remark indicating that fact.
|
||||||
}
|
List<ImmutableMap<String, Object>> remarks;
|
||||||
// Nameservers
|
if (outputDataType == OutputDataType.SUMMARY) {
|
||||||
ImmutableList.Builder<Object> nsBuilder = new ImmutableList.Builder<>();
|
remarks = ImmutableList.of(RdapIcannStandardInformation.SUMMARY_DATA_REMARK);
|
||||||
for (HostResource hostResource
|
} else {
|
||||||
: HOST_RESOURCE_ORDERING.immutableSortedCopy(loadedHosts.values())) {
|
remarks = ImmutableList.of();
|
||||||
nsBuilder.add(makeRdapJsonForHost(hostResource, false, linkBase, null, now));
|
ImmutableList<Object> events = makeEvents(domainResource, now);
|
||||||
}
|
if (!events.isEmpty()) {
|
||||||
ImmutableList<Object> ns = nsBuilder.build();
|
jsonBuilder.put("events", events);
|
||||||
if (!ns.isEmpty()) {
|
}
|
||||||
builder.put("nameservers", ns);
|
// Kick off the database loads of the nameservers that we will need.
|
||||||
}
|
Map<Key<HostResource>, HostResource> loadedHosts =
|
||||||
// Contacts
|
ofy().load().keys(domainResource.getNameservers());
|
||||||
ImmutableList.Builder<Object> entitiesBuilder = new ImmutableList.Builder<>();
|
// And the registrant and other contacts.
|
||||||
for (DesignatedContact designatedContact : FluentIterable.from(domainResource.getContacts())
|
Map<Key<ContactResource>, ContactResource> loadedContacts =
|
||||||
.append(DesignatedContact.create(Type.REGISTRANT, domainResource.getRegistrant()))
|
ofy().load().keys(domainResource.getReferencedContacts());
|
||||||
.toSortedList(DESIGNATED_CONTACT_ORDERING)) {
|
// Nameservers
|
||||||
ContactResource loadedContact = loadedContacts.get(designatedContact.getContactKey());
|
ImmutableList.Builder<Object> nsBuilder = new ImmutableList.Builder<>();
|
||||||
entitiesBuilder.add(makeRdapJsonForContact(
|
for (HostResource hostResource
|
||||||
loadedContact, false, Optional.of(designatedContact.getType()), linkBase, null, now));
|
: HOST_RESOURCE_ORDERING.immutableSortedCopy(loadedHosts.values())) {
|
||||||
}
|
nsBuilder.add(makeRdapJsonForHost(
|
||||||
ImmutableList<Object> entities = entitiesBuilder.build();
|
hostResource, false, linkBase, null, now, outputDataType));
|
||||||
if (!entities.isEmpty()) {
|
}
|
||||||
builder.put("entities", entities);
|
ImmutableList<Object> ns = nsBuilder.build();
|
||||||
|
if (!ns.isEmpty()) {
|
||||||
|
jsonBuilder.put("nameservers", ns);
|
||||||
|
}
|
||||||
|
// Contacts
|
||||||
|
ImmutableList.Builder<Object> entitiesBuilder = new ImmutableList.Builder<>();
|
||||||
|
for (DesignatedContact designatedContact : FluentIterable.from(domainResource.getContacts())
|
||||||
|
.append(DesignatedContact.create(Type.REGISTRANT, domainResource.getRegistrant()))
|
||||||
|
.toSortedList(DESIGNATED_CONTACT_ORDERING)) {
|
||||||
|
ContactResource loadedContact = loadedContacts.get(designatedContact.getContactKey());
|
||||||
|
entitiesBuilder.add(makeRdapJsonForContact(
|
||||||
|
loadedContact,
|
||||||
|
false,
|
||||||
|
Optional.of(designatedContact.getType()),
|
||||||
|
linkBase,
|
||||||
|
null,
|
||||||
|
now,
|
||||||
|
outputDataType));
|
||||||
|
}
|
||||||
|
ImmutableList<Object> entities = entitiesBuilder.build();
|
||||||
|
if (!entities.isEmpty()) {
|
||||||
|
jsonBuilder.put("entities", entities);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (whoisServer != null) {
|
if (whoisServer != null) {
|
||||||
builder.put("port43", whoisServer);
|
jsonBuilder.put("port43", whoisServer);
|
||||||
}
|
}
|
||||||
if (isTopLevel) {
|
if (isTopLevel) {
|
||||||
addTopLevelEntries(builder, BoilerplateType.DOMAIN, null, linkBase);
|
addTopLevelEntries(
|
||||||
|
jsonBuilder, BoilerplateType.DOMAIN, remarks, ImmutableList.of(), linkBase);
|
||||||
|
} else if (!remarks.isEmpty()) {
|
||||||
|
jsonBuilder.put(REMARKS, remarks);
|
||||||
}
|
}
|
||||||
return builder.build();
|
return jsonBuilder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a JSON object for a {@link HostResource}.
|
* Creates a JSON object for a {@link HostResource}.
|
||||||
*
|
*
|
||||||
* @param hostResource the host resource object from which the JSON object should be created
|
* @param hostResource the host resource object from which the JSON object should be created
|
||||||
|
* @param isTopLevel if true, the top-level boilerplate will be added
|
||||||
* @param linkBase the URL base to be used when creating links
|
* @param linkBase the URL base to be used when creating links
|
||||||
* @param whoisServer the fully-qualified domain name of the WHOIS server to be listed in the
|
* @param whoisServer the fully-qualified domain name of the WHOIS server to be listed in the
|
||||||
* port43 field; if null, port43 is not added to the object
|
* port43 field; if null, port43 is not added to the object
|
||||||
|
* @param now the as-date
|
||||||
|
* @param outputDataType whether to generate full or summary data
|
||||||
*/
|
*/
|
||||||
static ImmutableMap<String, Object> makeRdapJsonForHost(
|
static ImmutableMap<String, Object> makeRdapJsonForHost(
|
||||||
HostResource hostResource,
|
HostResource hostResource,
|
||||||
boolean isTopLevel,
|
boolean isTopLevel,
|
||||||
@Nullable String linkBase,
|
@Nullable String linkBase,
|
||||||
@Nullable String whoisServer,
|
@Nullable String whoisServer,
|
||||||
DateTime now) {
|
DateTime now,
|
||||||
ImmutableMap.Builder<String, Object> builder = new ImmutableMap.Builder<>();
|
OutputDataType outputDataType) {
|
||||||
builder.put("objectClassName", "nameserver");
|
ImmutableMap.Builder<String, Object> jsonBuilder = new ImmutableMap.Builder<>();
|
||||||
builder.put("handle", hostResource.getRepoId());
|
jsonBuilder.put("objectClassName", "nameserver");
|
||||||
builder.put("ldhName", hostResource.getFullyQualifiedHostName());
|
jsonBuilder.put("handle", hostResource.getRepoId());
|
||||||
|
jsonBuilder.put("ldhName", hostResource.getFullyQualifiedHostName());
|
||||||
// Only include the unicodeName field if there are unicode characters.
|
// Only include the unicodeName field if there are unicode characters.
|
||||||
if (hasUnicodeComponents(hostResource.getFullyQualifiedHostName())) {
|
if (hasUnicodeComponents(hostResource.getFullyQualifiedHostName())) {
|
||||||
builder.put("unicodeName", Idn.toUnicode(hostResource.getFullyQualifiedHostName()));
|
jsonBuilder.put("unicodeName", Idn.toUnicode(hostResource.getFullyQualifiedHostName()));
|
||||||
}
|
}
|
||||||
builder.put("status", makeStatusValueList(hostResource.getStatusValues()));
|
jsonBuilder.put("status", makeStatusValueList(hostResource.getStatusValues()));
|
||||||
builder.put("links", ImmutableList.of(
|
jsonBuilder.put("links", ImmutableList.of(
|
||||||
makeLink("nameserver", hostResource.getFullyQualifiedHostName(), linkBase)));
|
makeLink("nameserver", hostResource.getFullyQualifiedHostName(), linkBase)));
|
||||||
ImmutableList<Object> events = makeEvents(hostResource, now);
|
List<ImmutableMap<String, Object>> remarks;
|
||||||
if (!events.isEmpty()) {
|
// If we are outputting all data (not just summary data), also add events taken from the history
|
||||||
builder.put("events", events);
|
// entries. If we are outputting summary data, instead add a remark indicating that fact.
|
||||||
|
if (outputDataType == OutputDataType.SUMMARY) {
|
||||||
|
remarks = ImmutableList.of(RdapIcannStandardInformation.SUMMARY_DATA_REMARK);
|
||||||
|
} else {
|
||||||
|
remarks = ImmutableList.of();
|
||||||
|
ImmutableList<Object> events = makeEvents(hostResource, now);
|
||||||
|
if (!events.isEmpty()) {
|
||||||
|
jsonBuilder.put("events", events);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ImmutableSet<InetAddress> inetAddresses = hostResource.getInetAddresses();
|
ImmutableSet<InetAddress> inetAddresses = hostResource.getInetAddresses();
|
||||||
if (!inetAddresses.isEmpty()) {
|
if (!inetAddresses.isEmpty()) {
|
||||||
|
@ -520,26 +578,32 @@ public class RdapJsonFormatter {
|
||||||
}
|
}
|
||||||
ImmutableMap<String, ImmutableList<String>> ipAddresses = ipAddressesBuilder.build();
|
ImmutableMap<String, ImmutableList<String>> ipAddresses = ipAddressesBuilder.build();
|
||||||
if (!ipAddresses.isEmpty()) {
|
if (!ipAddresses.isEmpty()) {
|
||||||
builder.put("ipAddresses", ipAddressesBuilder.build());
|
jsonBuilder.put("ipAddresses", ipAddressesBuilder.build());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (whoisServer != null) {
|
if (whoisServer != null) {
|
||||||
builder.put("port43", whoisServer);
|
jsonBuilder.put("port43", whoisServer);
|
||||||
}
|
}
|
||||||
if (isTopLevel) {
|
if (isTopLevel) {
|
||||||
addTopLevelEntries(builder, BoilerplateType.NAMESERVER, null, linkBase);
|
addTopLevelEntries(
|
||||||
|
jsonBuilder, BoilerplateType.NAMESERVER, remarks, ImmutableList.of(), linkBase);
|
||||||
|
} else if (!remarks.isEmpty()) {
|
||||||
|
jsonBuilder.put(REMARKS, remarks);
|
||||||
}
|
}
|
||||||
return builder.build();
|
return jsonBuilder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a JSON object for a {@link ContactResource} and associated contact type.
|
* Creates a JSON object for a {@link ContactResource} and associated contact type.
|
||||||
*
|
*
|
||||||
* @param contactResource the contact resource object from which the JSON object should be created
|
* @param contactResource the contact resource object from which the JSON object should be created
|
||||||
|
* @param isTopLevel if true, the top-level boilerplate will be added
|
||||||
* @param contactType the contact type to map to an RDAP role; if absent, no role is listed
|
* @param contactType the contact type to map to an RDAP role; if absent, no role is listed
|
||||||
* @param linkBase the URL base to be used when creating links
|
* @param linkBase the URL base to be used when creating links
|
||||||
* @param whoisServer the fully-qualified domain name of the WHOIS server to be listed in the
|
* @param whoisServer the fully-qualified domain name of the WHOIS server to be listed in the
|
||||||
* port43 field; if null, port43 is not added to the object
|
* port43 field; if null, port43 is not added to the object
|
||||||
|
* @param now the as-date
|
||||||
|
* @param outputDataType whether to generate full or summary data
|
||||||
*/
|
*/
|
||||||
static ImmutableMap<String, Object> makeRdapJsonForContact(
|
static ImmutableMap<String, Object> makeRdapJsonForContact(
|
||||||
ContactResource contactResource,
|
ContactResource contactResource,
|
||||||
|
@ -547,15 +611,17 @@ public class RdapJsonFormatter {
|
||||||
Optional<DesignatedContact.Type> contactType,
|
Optional<DesignatedContact.Type> contactType,
|
||||||
@Nullable String linkBase,
|
@Nullable String linkBase,
|
||||||
@Nullable String whoisServer,
|
@Nullable String whoisServer,
|
||||||
DateTime now) {
|
DateTime now,
|
||||||
ImmutableMap.Builder<String, Object> builder = new ImmutableMap.Builder<>();
|
OutputDataType outputDataType) {
|
||||||
builder.put("objectClassName", "entity");
|
ImmutableMap.Builder<String, Object> jsonBuilder = new ImmutableMap.Builder<>();
|
||||||
builder.put("handle", contactResource.getRepoId());
|
jsonBuilder.put("objectClassName", "entity");
|
||||||
builder.put("status", makeStatusValueList(contactResource.getStatusValues()));
|
jsonBuilder.put("handle", contactResource.getRepoId());
|
||||||
|
jsonBuilder.put("status", makeStatusValueList(contactResource.getStatusValues()));
|
||||||
if (contactType.isPresent()) {
|
if (contactType.isPresent()) {
|
||||||
builder.put("roles", ImmutableList.of(convertContactTypeToRdapRole(contactType.get())));
|
jsonBuilder.put("roles",
|
||||||
|
ImmutableList.of(convertContactTypeToRdapRole(contactType.get())));
|
||||||
}
|
}
|
||||||
builder.put("links",
|
jsonBuilder.put("links",
|
||||||
ImmutableList.of(makeLink("entity", contactResource.getRepoId(), linkBase)));
|
ImmutableList.of(makeLink("entity", contactResource.getRepoId(), linkBase)));
|
||||||
// Create the vCard.
|
// Create the vCard.
|
||||||
ImmutableList.Builder<Object> vcardBuilder = new ImmutableList.Builder<>();
|
ImmutableList.Builder<Object> vcardBuilder = new ImmutableList.Builder<>();
|
||||||
|
@ -588,42 +654,57 @@ public class RdapJsonFormatter {
|
||||||
if (emailAddress != null) {
|
if (emailAddress != null) {
|
||||||
vcardBuilder.add(ImmutableList.of("email", ImmutableMap.of(), "text", emailAddress));
|
vcardBuilder.add(ImmutableList.of("email", ImmutableMap.of(), "text", emailAddress));
|
||||||
}
|
}
|
||||||
builder.put("vcardArray", ImmutableList.of("vcard", vcardBuilder.build()));
|
jsonBuilder.put("vcardArray", ImmutableList.of("vcard", vcardBuilder.build()));
|
||||||
ImmutableList<Object> events = makeEvents(contactResource, now);
|
// If we are outputting all data (not just summary data), also add events taken from the history
|
||||||
if (!events.isEmpty()) {
|
// entries. If we are outputting summary data, instead add a remark indicating that fact.
|
||||||
builder.put("events", events);
|
List<ImmutableMap<String, Object>> remarks;
|
||||||
|
if (outputDataType == OutputDataType.SUMMARY) {
|
||||||
|
remarks = ImmutableList.of(RdapIcannStandardInformation.SUMMARY_DATA_REMARK);
|
||||||
|
} else {
|
||||||
|
remarks = ImmutableList.of();
|
||||||
|
ImmutableList<Object> events = makeEvents(contactResource, now);
|
||||||
|
if (!events.isEmpty()) {
|
||||||
|
jsonBuilder.put("events", events);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (whoisServer != null) {
|
if (whoisServer != null) {
|
||||||
builder.put("port43", whoisServer);
|
jsonBuilder.put("port43", whoisServer);
|
||||||
}
|
}
|
||||||
if (isTopLevel) {
|
if (isTopLevel) {
|
||||||
addTopLevelEntries(builder, BoilerplateType.ENTITY, null, linkBase);
|
addTopLevelEntries(
|
||||||
|
jsonBuilder, BoilerplateType.ENTITY, remarks, ImmutableList.of(), linkBase);
|
||||||
|
} else if (!remarks.isEmpty()) {
|
||||||
|
jsonBuilder.put(REMARKS, remarks);
|
||||||
}
|
}
|
||||||
return builder.build();
|
return jsonBuilder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a JSON object for a {@link Registrar}.
|
* Creates a JSON object for a {@link Registrar}.
|
||||||
*
|
*
|
||||||
* @param registrar the registrar object from which the JSON object should be created
|
* @param registrar the registrar object from which the JSON object should be created
|
||||||
|
* @param isTopLevel if true, the top-level boilerplate will be added
|
||||||
* @param linkBase the URL base to be used when creating links
|
* @param linkBase the URL base to be used when creating links
|
||||||
* @param whoisServer the fully-qualified domain name of the WHOIS server to be listed in the
|
* @param whoisServer the fully-qualified domain name of the WHOIS server to be listed in the
|
||||||
* port43 field; if null, port43 is not added to the object
|
* port43 field; if null, port43 is not added to the object
|
||||||
|
* @param now the as-date
|
||||||
|
* @param outputDataType whether to generate full or summary data
|
||||||
*/
|
*/
|
||||||
static ImmutableMap<String, Object> makeRdapJsonForRegistrar(
|
static ImmutableMap<String, Object> makeRdapJsonForRegistrar(
|
||||||
Registrar registrar,
|
Registrar registrar,
|
||||||
boolean isTopLevel,
|
boolean isTopLevel,
|
||||||
@Nullable String linkBase,
|
@Nullable String linkBase,
|
||||||
@Nullable String whoisServer,
|
@Nullable String whoisServer,
|
||||||
DateTime now) {
|
DateTime now,
|
||||||
ImmutableMap.Builder<String, Object> builder = new ImmutableMap.Builder<>();
|
OutputDataType outputDataType) {
|
||||||
builder.put("objectClassName", "entity");
|
ImmutableMap.Builder<String, Object> jsonBuilder = new ImmutableMap.Builder<>();
|
||||||
builder.put("handle", registrar.getIanaIdentifier().toString());
|
jsonBuilder.put("objectClassName", "entity");
|
||||||
builder.put("status", STATUS_LIST_ACTIVE);
|
jsonBuilder.put("handle", registrar.getIanaIdentifier().toString());
|
||||||
builder.put("roles", ImmutableList.of(RdapEntityRole.REGISTRAR.rfc7483String));
|
jsonBuilder.put("status", STATUS_LIST_ACTIVE);
|
||||||
builder.put("links",
|
jsonBuilder.put("roles", ImmutableList.of(RdapEntityRole.REGISTRAR.rfc7483String));
|
||||||
|
jsonBuilder.put("links",
|
||||||
ImmutableList.of(makeLink("entity", registrar.getIanaIdentifier().toString(), linkBase)));
|
ImmutableList.of(makeLink("entity", registrar.getIanaIdentifier().toString(), linkBase)));
|
||||||
builder.put("publicIds",
|
jsonBuilder.put("publicIds",
|
||||||
ImmutableList.of(
|
ImmutableList.of(
|
||||||
ImmutableMap.of(
|
ImmutableMap.of(
|
||||||
"type", "IANA Registrar ID",
|
"type", "IANA Registrar ID",
|
||||||
|
@ -657,30 +738,41 @@ public class RdapJsonFormatter {
|
||||||
if (emailAddress != null) {
|
if (emailAddress != null) {
|
||||||
vcardBuilder.add(ImmutableList.of("email", ImmutableMap.of(), "text", emailAddress));
|
vcardBuilder.add(ImmutableList.of("email", ImmutableMap.of(), "text", emailAddress));
|
||||||
}
|
}
|
||||||
builder.put("vcardArray", ImmutableList.of("vcard", vcardBuilder.build()));
|
jsonBuilder.put("vcardArray", ImmutableList.of("vcard", vcardBuilder.build()));
|
||||||
ImmutableList<Object> events = makeEvents(registrar, now);
|
// If we are outputting all data (not just summary data), also add registrar contacts. If we are
|
||||||
if (!events.isEmpty()) {
|
// outputting summary data, instead add a remark indicating that fact.
|
||||||
builder.put("events", events);
|
List<ImmutableMap<String, Object>> remarks;
|
||||||
}
|
if (outputDataType == OutputDataType.SUMMARY) {
|
||||||
// include the registrar contacts as subentities
|
remarks = ImmutableList.of(RdapIcannStandardInformation.SUMMARY_DATA_REMARK);
|
||||||
ImmutableList.Builder<Map<String, Object>> registrarContactsBuilder =
|
} else {
|
||||||
new ImmutableList.Builder<>();
|
remarks = ImmutableList.of();
|
||||||
for (RegistrarContact registrarContact : registrar.getContacts()) {
|
ImmutableList<Object> events = makeEvents(registrar, now);
|
||||||
if (isVisible(registrarContact)) {
|
if (!events.isEmpty()) {
|
||||||
registrarContactsBuilder.add(makeRdapJsonForRegistrarContact(registrarContact, null));
|
jsonBuilder.put("events", events);
|
||||||
|
}
|
||||||
|
// include the registrar contacts as subentities
|
||||||
|
ImmutableList.Builder<Map<String, Object>> registrarContactsBuilder =
|
||||||
|
new ImmutableList.Builder<>();
|
||||||
|
for (RegistrarContact registrarContact : registrar.getContacts()) {
|
||||||
|
if (isVisible(registrarContact)) {
|
||||||
|
registrarContactsBuilder.add(makeRdapJsonForRegistrarContact(registrarContact, null));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImmutableList<Map<String, Object>> registrarContacts = registrarContactsBuilder.build();
|
||||||
|
if (!registrarContacts.isEmpty()) {
|
||||||
|
jsonBuilder.put("entities", registrarContacts);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ImmutableList<Map<String, Object>> registrarContacts = registrarContactsBuilder.build();
|
|
||||||
if (!registrarContacts.isEmpty()) {
|
|
||||||
builder.put("entities", registrarContacts);
|
|
||||||
}
|
|
||||||
if (whoisServer != null) {
|
if (whoisServer != null) {
|
||||||
builder.put("port43", whoisServer);
|
jsonBuilder.put("port43", whoisServer);
|
||||||
}
|
}
|
||||||
if (isTopLevel) {
|
if (isTopLevel) {
|
||||||
addTopLevelEntries(builder, BoilerplateType.ENTITY, null, linkBase);
|
addTopLevelEntries(
|
||||||
|
jsonBuilder, BoilerplateType.ENTITY, remarks, ImmutableList.of(), linkBase);
|
||||||
|
} else if (!remarks.isEmpty()) {
|
||||||
|
jsonBuilder.put(REMARKS, remarks);
|
||||||
}
|
}
|
||||||
return builder.build();
|
return jsonBuilder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -692,14 +784,14 @@ public class RdapJsonFormatter {
|
||||||
*/
|
*/
|
||||||
static ImmutableMap<String, Object> makeRdapJsonForRegistrarContact(
|
static ImmutableMap<String, Object> makeRdapJsonForRegistrarContact(
|
||||||
RegistrarContact registrarContact, @Nullable String whoisServer) {
|
RegistrarContact registrarContact, @Nullable String whoisServer) {
|
||||||
ImmutableMap.Builder<String, Object> builder = new ImmutableMap.Builder<>();
|
ImmutableMap.Builder<String, Object> jsonBuilder = new ImmutableMap.Builder<>();
|
||||||
builder.put("objectClassName", "entity");
|
jsonBuilder.put("objectClassName", "entity");
|
||||||
String gaeUserId = registrarContact.getGaeUserId();
|
String gaeUserId = registrarContact.getGaeUserId();
|
||||||
if (gaeUserId != null) {
|
if (gaeUserId != null) {
|
||||||
builder.put("handle", registrarContact.getGaeUserId());
|
jsonBuilder.put("handle", registrarContact.getGaeUserId());
|
||||||
}
|
}
|
||||||
builder.put("status", STATUS_LIST_ACTIVE);
|
jsonBuilder.put("status", STATUS_LIST_ACTIVE);
|
||||||
builder.put("roles", makeRdapRoleList(registrarContact));
|
jsonBuilder.put("roles", makeRdapRoleList(registrarContact));
|
||||||
// Create the vCard.
|
// Create the vCard.
|
||||||
ImmutableList.Builder<Object> vcardBuilder = new ImmutableList.Builder<>();
|
ImmutableList.Builder<Object> vcardBuilder = new ImmutableList.Builder<>();
|
||||||
vcardBuilder.add(VCARD_ENTRY_VERSION);
|
vcardBuilder.add(VCARD_ENTRY_VERSION);
|
||||||
|
@ -719,11 +811,11 @@ public class RdapJsonFormatter {
|
||||||
if (emailAddress != null) {
|
if (emailAddress != null) {
|
||||||
vcardBuilder.add(ImmutableList.of("email", ImmutableMap.of(), "text", emailAddress));
|
vcardBuilder.add(ImmutableList.of("email", ImmutableMap.of(), "text", emailAddress));
|
||||||
}
|
}
|
||||||
builder.put("vcardArray", ImmutableList.of("vcard", vcardBuilder.build()));
|
jsonBuilder.put("vcardArray", ImmutableList.of("vcard", vcardBuilder.build()));
|
||||||
if (whoisServer != null) {
|
if (whoisServer != null) {
|
||||||
builder.put("port43", whoisServer);
|
jsonBuilder.put("port43", whoisServer);
|
||||||
}
|
}
|
||||||
return builder.build();
|
return jsonBuilder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Converts a domain registry contact type into a role as defined by RFC 7483. */
|
/** Converts a domain registry contact type into a role as defined by RFC 7483. */
|
||||||
|
@ -818,13 +910,13 @@ public class RdapJsonFormatter {
|
||||||
*/
|
*/
|
||||||
private static ImmutableMap<String, Object> makeEvent(
|
private static ImmutableMap<String, Object> makeEvent(
|
||||||
RdapEventAction eventAction, @Nullable String eventActor, DateTime eventDate) {
|
RdapEventAction eventAction, @Nullable String eventActor, DateTime eventDate) {
|
||||||
ImmutableMap.Builder<String, Object> builder = new ImmutableMap.Builder<>();
|
ImmutableMap.Builder<String, Object> jsonBuilder = new ImmutableMap.Builder<>();
|
||||||
builder.put("eventAction", eventAction.getDisplayName());
|
jsonBuilder.put("eventAction", eventAction.getDisplayName());
|
||||||
if (eventActor != null) {
|
if (eventActor != null) {
|
||||||
builder.put("eventActor", eventActor);
|
jsonBuilder.put("eventActor", eventActor);
|
||||||
}
|
}
|
||||||
builder.put("eventDate", eventDate.toString());
|
jsonBuilder.put("eventDate", eventDate.toString());
|
||||||
return builder.build();
|
return jsonBuilder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -837,9 +929,9 @@ public class RdapJsonFormatter {
|
||||||
if (address == null) {
|
if (address == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
ImmutableList.Builder<Object> builder = new ImmutableList.Builder<>();
|
ImmutableList.Builder<Object> jsonBuilder = new ImmutableList.Builder<>();
|
||||||
builder.add(""); // PO box
|
jsonBuilder.add(""); // PO box
|
||||||
builder.add(""); // extended address
|
jsonBuilder.add(""); // extended address
|
||||||
|
|
||||||
// The vCard spec allows several different ways to handle multiline street addresses. Per
|
// The vCard spec allows several different ways to handle multiline street addresses. Per
|
||||||
// Gustavo Lozano of ICANN, the one we should use is an embedded array of street address lines
|
// Gustavo Lozano of ICANN, the one we should use is an embedded array of street address lines
|
||||||
|
@ -859,21 +951,21 @@ public class RdapJsonFormatter {
|
||||||
// ]
|
// ]
|
||||||
ImmutableList<String> street = address.getStreet();
|
ImmutableList<String> street = address.getStreet();
|
||||||
if (street.isEmpty()) {
|
if (street.isEmpty()) {
|
||||||
builder.add("");
|
jsonBuilder.add("");
|
||||||
} else if (street.size() == 1) {
|
} else if (street.size() == 1) {
|
||||||
builder.add(street.get(0));
|
jsonBuilder.add(street.get(0));
|
||||||
} else {
|
} else {
|
||||||
builder.add(street);
|
jsonBuilder.add(street);
|
||||||
}
|
}
|
||||||
builder.add(nullToEmpty(address.getCity()));
|
jsonBuilder.add(nullToEmpty(address.getCity()));
|
||||||
builder.add(nullToEmpty(address.getState()));
|
jsonBuilder.add(nullToEmpty(address.getState()));
|
||||||
builder.add(nullToEmpty(address.getZip()));
|
jsonBuilder.add(nullToEmpty(address.getZip()));
|
||||||
builder.add(new Locale("en", address.getCountryCode()).getDisplayCountry(new Locale("en")));
|
jsonBuilder.add(new Locale("en", address.getCountryCode()).getDisplayCountry(new Locale("en")));
|
||||||
return ImmutableList.<Object>of(
|
return ImmutableList.<Object>of(
|
||||||
"adr",
|
"adr",
|
||||||
ImmutableMap.of(),
|
ImmutableMap.of(),
|
||||||
"text",
|
"text",
|
||||||
builder.build());
|
jsonBuilder.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Creates a vCard phone number entry. */
|
/** Creates a vCard phone number entry. */
|
||||||
|
|
|
@ -20,8 +20,8 @@ import static google.registry.request.Action.Method.HEAD;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import google.registry.model.host.HostResource;
|
import google.registry.model.host.HostResource;
|
||||||
|
import google.registry.rdap.RdapJsonFormatter.OutputDataType;
|
||||||
import google.registry.request.Action;
|
import google.registry.request.Action;
|
||||||
import google.registry.request.HttpException;
|
|
||||||
import google.registry.request.HttpException.NotFoundException;
|
import google.registry.request.HttpException.NotFoundException;
|
||||||
import google.registry.util.Clock;
|
import google.registry.util.Clock;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
@ -50,7 +50,7 @@ public class RdapNameserverAction extends RdapActionBase {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ImmutableMap<String, Object> getJsonObjectForResource(
|
public ImmutableMap<String, Object> getJsonObjectForResource(
|
||||||
String pathSearchString, boolean isHeadRequest, String linkBase) throws HttpException {
|
String pathSearchString, boolean isHeadRequest, String linkBase) {
|
||||||
DateTime now = clock.nowUtc();
|
DateTime now = clock.nowUtc();
|
||||||
pathSearchString = canonicalizeName(pathSearchString);
|
pathSearchString = canonicalizeName(pathSearchString);
|
||||||
// The RDAP syntax is /rdap/nameserver/ns1.mydomain.com.
|
// The RDAP syntax is /rdap/nameserver/ns1.mydomain.com.
|
||||||
|
@ -61,6 +61,6 @@ public class RdapNameserverAction extends RdapActionBase {
|
||||||
throw new NotFoundException(pathSearchString + " not found");
|
throw new NotFoundException(pathSearchString + " not found");
|
||||||
}
|
}
|
||||||
return RdapJsonFormatter.makeRdapJsonForHost(
|
return RdapJsonFormatter.makeRdapJsonForHost(
|
||||||
hostResource, true, rdapLinkBase, rdapWhoisServer, now);
|
hostResource, true, rdapLinkBase, rdapWhoisServer, now, OutputDataType.FULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,19 +25,19 @@ import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.collect.ImmutableSortedSet;
|
import com.google.common.collect.ImmutableSortedSet;
|
||||||
import com.google.common.primitives.Booleans;
|
import com.google.common.primitives.Booleans;
|
||||||
import com.googlecode.objectify.cmd.Query;
|
|
||||||
import google.registry.config.ConfigModule.Config;
|
import google.registry.config.ConfigModule.Config;
|
||||||
import google.registry.model.domain.DomainResource;
|
import google.registry.model.domain.DomainResource;
|
||||||
import google.registry.model.host.HostResource;
|
import google.registry.model.host.HostResource;
|
||||||
import google.registry.rdap.RdapJsonFormatter.BoilerplateType;
|
import google.registry.rdap.RdapJsonFormatter.BoilerplateType;
|
||||||
|
import google.registry.rdap.RdapJsonFormatter.OutputDataType;
|
||||||
import google.registry.request.Action;
|
import google.registry.request.Action;
|
||||||
import google.registry.request.HttpException;
|
|
||||||
import google.registry.request.HttpException.BadRequestException;
|
import google.registry.request.HttpException.BadRequestException;
|
||||||
import google.registry.request.HttpException.NotFoundException;
|
import google.registry.request.HttpException.NotFoundException;
|
||||||
import google.registry.request.Parameter;
|
import google.registry.request.Parameter;
|
||||||
import google.registry.util.Clock;
|
import google.registry.util.Clock;
|
||||||
import google.registry.util.Idn;
|
import google.registry.util.Idn;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
|
import java.util.List;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import org.joda.time.DateTime;
|
import org.joda.time.DateTime;
|
||||||
|
|
||||||
|
@ -75,7 +75,7 @@ public class RdapNameserverSearchAction extends RdapActionBase {
|
||||||
/** Parses the parameters and calls the appropriate search function. */
|
/** Parses the parameters and calls the appropriate search function. */
|
||||||
@Override
|
@Override
|
||||||
public ImmutableMap<String, Object> getJsonObjectForResource(
|
public ImmutableMap<String, Object> getJsonObjectForResource(
|
||||||
String pathSearchString, boolean isHeadRequest, String linkBase) throws HttpException {
|
String pathSearchString, boolean isHeadRequest, String linkBase) {
|
||||||
DateTime now = clock.nowUtc();
|
DateTime now = clock.nowUtc();
|
||||||
// RDAP syntax example: /rdap/nameservers?name=ns*.example.com.
|
// RDAP syntax example: /rdap/nameservers?name=ns*.example.com.
|
||||||
// The pathSearchString is not used by search commands.
|
// The pathSearchString is not used by search commands.
|
||||||
|
@ -101,16 +101,20 @@ public class RdapNameserverSearchAction extends RdapActionBase {
|
||||||
if (results.isEmpty()) {
|
if (results.isEmpty()) {
|
||||||
throw new NotFoundException("No nameservers found");
|
throw new NotFoundException("No nameservers found");
|
||||||
}
|
}
|
||||||
ImmutableMap.Builder<String, Object> builder = new ImmutableMap.Builder<>();
|
ImmutableMap.Builder<String, Object> jsonBuilder = new ImmutableMap.Builder<>();
|
||||||
builder.put("nameserverSearchResults", results);
|
jsonBuilder.put("nameserverSearchResults", results);
|
||||||
RdapJsonFormatter.addTopLevelEntries(builder, BoilerplateType.NAMESERVER, null, rdapLinkBase);
|
RdapJsonFormatter.addTopLevelEntries(
|
||||||
return builder.build();
|
jsonBuilder,
|
||||||
|
BoilerplateType.NAMESERVER,
|
||||||
|
ImmutableList.of(),
|
||||||
|
ImmutableList.of(),
|
||||||
|
rdapLinkBase);
|
||||||
|
return jsonBuilder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Searches for nameservers by name, returning a JSON array of nameserver info maps. */
|
/** Searches for nameservers by name, returning a JSON array of nameserver info maps. */
|
||||||
private ImmutableList<ImmutableMap<String, Object>>
|
private ImmutableList<ImmutableMap<String, Object>>
|
||||||
searchByName(final RdapSearchPattern partialStringQuery, final DateTime now)
|
searchByName(final RdapSearchPattern partialStringQuery, final DateTime now) {
|
||||||
throws HttpException {
|
|
||||||
// Handle queries without a wildcard -- just load by foreign key.
|
// Handle queries without a wildcard -- just load by foreign key.
|
||||||
if (!partialStringQuery.getHasWildcard()) {
|
if (!partialStringQuery.getHasWildcard()) {
|
||||||
HostResource hostResource =
|
HostResource hostResource =
|
||||||
|
@ -120,21 +124,18 @@ public class RdapNameserverSearchAction extends RdapActionBase {
|
||||||
}
|
}
|
||||||
return ImmutableList.of(
|
return ImmutableList.of(
|
||||||
RdapJsonFormatter.makeRdapJsonForHost(
|
RdapJsonFormatter.makeRdapJsonForHost(
|
||||||
hostResource, false, rdapLinkBase, rdapWhoisServer, now));
|
hostResource, false, rdapLinkBase, rdapWhoisServer, now, OutputDataType.FULL));
|
||||||
// Handle queries with a wildcard, but no suffix. There are no pending deletes for hosts, so we
|
// Handle queries with a wildcard, but no suffix. There are no pending deletes for hosts, so we
|
||||||
// can call queryUndeleted.
|
// can call queryUndeleted.
|
||||||
} else if (partialStringQuery.getSuffix() == null) {
|
} else if (partialStringQuery.getSuffix() == null) {
|
||||||
Query<HostResource> query = queryUndeleted(
|
return makeSearchResults(
|
||||||
HostResource.class,
|
queryUndeleted(
|
||||||
"fullyQualifiedHostName",
|
HostResource.class,
|
||||||
partialStringQuery, rdapResultSetMaxSize);
|
"fullyQualifiedHostName",
|
||||||
ImmutableList.Builder<ImmutableMap<String, Object>> builder = new ImmutableList.Builder<>();
|
partialStringQuery,
|
||||||
for (HostResource hostResource : query) {
|
rdapResultSetMaxSize)
|
||||||
builder.add(
|
.list(),
|
||||||
RdapJsonFormatter.makeRdapJsonForHost(
|
now);
|
||||||
hostResource, false, rdapLinkBase, rdapWhoisServer, now));
|
|
||||||
}
|
|
||||||
return builder.build();
|
|
||||||
// Handle queries with a wildcard and a suffix. In this case, it is more efficient to do things
|
// Handle queries with a wildcard and a suffix. In this case, it is more efficient to do things
|
||||||
// differently. We use the suffix to look up the domain, then loop through the subordinate hosts
|
// differently. We use the suffix to look up the domain, then loop through the subordinate hosts
|
||||||
// looking for matches.
|
// looking for matches.
|
||||||
|
@ -144,41 +145,45 @@ public class RdapNameserverSearchAction extends RdapActionBase {
|
||||||
if (domainResource == null) {
|
if (domainResource == null) {
|
||||||
throw new NotFoundException("No domain found for specified nameserver suffix");
|
throw new NotFoundException("No domain found for specified nameserver suffix");
|
||||||
}
|
}
|
||||||
ImmutableList.Builder<ImmutableMap<String, Object>> builder = new ImmutableList.Builder<>();
|
ImmutableList.Builder<HostResource> hostListBuilder = new ImmutableList.Builder<>();
|
||||||
for (String fqhn : ImmutableSortedSet.copyOf(domainResource.getSubordinateHosts())) {
|
for (String fqhn : ImmutableSortedSet.copyOf(domainResource.getSubordinateHosts())) {
|
||||||
// We can't just check that the host name starts with the initial query string, because then
|
// We can't just check that the host name starts with the initial query string, because then
|
||||||
// the query ns.exam*.example.com would match against nameserver ns.example.com.
|
// the query ns.exam*.example.com would match against nameserver ns.example.com.
|
||||||
if (partialStringQuery.matches(fqhn)) {
|
if (partialStringQuery.matches(fqhn)) {
|
||||||
HostResource hostResource = loadByUniqueId(HostResource.class, fqhn, now);
|
HostResource hostResource = loadByUniqueId(HostResource.class, fqhn, now);
|
||||||
if (hostResource != null) {
|
if (hostResource != null) {
|
||||||
builder.add(
|
hostListBuilder.add(hostResource);
|
||||||
RdapJsonFormatter.makeRdapJsonForHost(
|
|
||||||
hostResource, false, rdapLinkBase, rdapWhoisServer, now));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return builder.build();
|
return makeSearchResults(hostListBuilder.build(), now);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Searches for nameservers by IP address, returning a JSON array of nameserver info maps. */
|
/** Searches for nameservers by IP address, returning a JSON array of nameserver info maps. */
|
||||||
private ImmutableList<ImmutableMap<String, Object>>
|
private ImmutableList<ImmutableMap<String, Object>>
|
||||||
searchByIp(final InetAddress inetAddress, DateTime now) throws HttpException {
|
searchByIp(final InetAddress inetAddress, DateTime now) {
|
||||||
// In theory, we could filter on deletion time being in the future. But we can't do that in the
|
return makeSearchResults(
|
||||||
// name query above (because we already have an inequality filter), and filtering on deletion
|
ofy().load()
|
||||||
// time differently in the two cases seems like a recipe for future confusion.
|
.type(HostResource.class)
|
||||||
Query<HostResource> query = ofy()
|
.filter("inetAddresses", inetAddress.getHostAddress())
|
||||||
.load()
|
.filter("deletionTime", END_OF_TIME)
|
||||||
.type(HostResource.class)
|
.limit(rdapResultSetMaxSize)
|
||||||
.filter("inetAddresses", inetAddress.getHostAddress())
|
.list(),
|
||||||
.filter("deletionTime", END_OF_TIME)
|
now);
|
||||||
.limit(rdapResultSetMaxSize);
|
}
|
||||||
ImmutableList.Builder<ImmutableMap<String, Object>> builder = new ImmutableList.Builder<>();
|
|
||||||
for (HostResource hostResource : query) {
|
/** Output JSON for a list of hosts. */
|
||||||
builder.add(
|
private ImmutableList<ImmutableMap<String, Object>> makeSearchResults(
|
||||||
|
List<HostResource> hosts, DateTime now) {
|
||||||
|
OutputDataType outputDataType =
|
||||||
|
(hosts.size() > 1) ? OutputDataType.SUMMARY : OutputDataType.FULL;
|
||||||
|
ImmutableList.Builder<ImmutableMap<String, Object>> jsonBuilder = new ImmutableList.Builder<>();
|
||||||
|
for (HostResource host : hosts) {
|
||||||
|
jsonBuilder.add(
|
||||||
RdapJsonFormatter.makeRdapJsonForHost(
|
RdapJsonFormatter.makeRdapJsonForHost(
|
||||||
hostResource, false, rdapLinkBase, rdapWhoisServer, now));
|
host, false, rdapLinkBase, rdapWhoisServer, now, outputDataType));
|
||||||
}
|
}
|
||||||
return builder.build();
|
return jsonBuilder.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,10 +21,10 @@ import static google.registry.request.Action.Method.HEAD;
|
||||||
import static google.registry.testing.DatastoreHelper.createTld;
|
import static google.registry.testing.DatastoreHelper.createTld;
|
||||||
import static google.registry.testing.TestDataHelper.loadFileWithSubstitutions;
|
import static google.registry.testing.TestDataHelper.loadFileWithSubstitutions;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import google.registry.model.ofy.Ofy;
|
import google.registry.model.ofy.Ofy;
|
||||||
import google.registry.rdap.RdapJsonFormatter.BoilerplateType;
|
import google.registry.rdap.RdapJsonFormatter.BoilerplateType;
|
||||||
import google.registry.request.HttpException;
|
|
||||||
import google.registry.testing.AppEngineRule;
|
import google.registry.testing.AppEngineRule;
|
||||||
import google.registry.testing.FakeClock;
|
import google.registry.testing.FakeClock;
|
||||||
import google.registry.testing.FakeResponse;
|
import google.registry.testing.FakeResponse;
|
||||||
|
@ -55,7 +55,7 @@ public class RdapActionBaseTest {
|
||||||
/**
|
/**
|
||||||
* Dummy RdapActionBase subclass used for testing.
|
* Dummy RdapActionBase subclass used for testing.
|
||||||
*/
|
*/
|
||||||
class RdapTestAction extends RdapActionBase {
|
static class RdapTestAction extends RdapActionBase {
|
||||||
|
|
||||||
public static final String PATH = "/rdap/test/";
|
public static final String PATH = "/rdap/test/";
|
||||||
|
|
||||||
|
@ -71,7 +71,7 @@ public class RdapActionBaseTest {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ImmutableMap<String, Object> getJsonObjectForResource(
|
public ImmutableMap<String, Object> getJsonObjectForResource(
|
||||||
String pathSearchString, boolean isHeadRequest, String linkBase) throws HttpException {
|
String pathSearchString, boolean isHeadRequest, String linkBase) {
|
||||||
if (pathSearchString.equals("IllegalArgumentException")) {
|
if (pathSearchString.equals("IllegalArgumentException")) {
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
}
|
}
|
||||||
|
@ -83,7 +83,8 @@ public class RdapActionBaseTest {
|
||||||
RdapJsonFormatter.addTopLevelEntries(
|
RdapJsonFormatter.addTopLevelEntries(
|
||||||
builder,
|
builder,
|
||||||
BoilerplateType.OTHER,
|
BoilerplateType.OTHER,
|
||||||
null,
|
ImmutableList.of(),
|
||||||
|
ImmutableList.of(),
|
||||||
"http://myserver.google.com/");
|
"http://myserver.google.com/");
|
||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ import static com.google.common.truth.Truth.assertThat;
|
||||||
import static google.registry.testing.DatastoreHelper.createTld;
|
import static google.registry.testing.DatastoreHelper.createTld;
|
||||||
import static google.registry.testing.DatastoreHelper.persistDomainAsDeleted;
|
import static google.registry.testing.DatastoreHelper.persistDomainAsDeleted;
|
||||||
import static google.registry.testing.DatastoreHelper.persistResource;
|
import static google.registry.testing.DatastoreHelper.persistResource;
|
||||||
|
import static google.registry.testing.DatastoreHelper.persistResources;
|
||||||
import static google.registry.testing.DatastoreHelper.persistSimpleResources;
|
import static google.registry.testing.DatastoreHelper.persistSimpleResources;
|
||||||
import static google.registry.testing.FullFieldsTestEntityHelper.makeAndPersistContactResource;
|
import static google.registry.testing.FullFieldsTestEntityHelper.makeAndPersistContactResource;
|
||||||
import static google.registry.testing.FullFieldsTestEntityHelper.makeAndPersistHostResource;
|
import static google.registry.testing.FullFieldsTestEntityHelper.makeAndPersistHostResource;
|
||||||
|
@ -110,7 +111,7 @@ public class RdapDomainSearchActionTest {
|
||||||
action.nsIpParam = Optional.absent();
|
action.nsIpParam = Optional.absent();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
action.rdapResultSetMaxSize = 5;
|
action.rdapResultSetMaxSize = 4;
|
||||||
action.run();
|
action.run();
|
||||||
return JSONValue.parse(response.getPayload());
|
return JSONValue.parse(response.getPayload());
|
||||||
}
|
}
|
||||||
|
@ -518,20 +519,21 @@ public class RdapDomainSearchActionTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createManyDomains(int numActiveDomains, int numTotalDomainsPerActiveDomain) {
|
private void createManyDomains(int numActiveDomains, int numTotalDomainsPerActiveDomain) {
|
||||||
|
// Create all the domains at once, then persist them in parallel, for increased efficiency.
|
||||||
|
ImmutableList.Builder<DomainResource> domainsBuilder = new ImmutableList.Builder<>();
|
||||||
for (int i = 1; i <= numActiveDomains * numTotalDomainsPerActiveDomain; i++) {
|
for (int i = 1; i <= numActiveDomains * numTotalDomainsPerActiveDomain; i++) {
|
||||||
String domainName = String.format("domain%d.lol", i);
|
String domainName = String.format("domain%d.lol", i);
|
||||||
DomainResource domain =
|
DomainResource.Builder builder =
|
||||||
makeDomainResource(
|
makeDomainResource(
|
||||||
domainName, contact1, contact2, contact3, hostNs1CatLol, hostNs2CatLol, registrar)
|
domainName, contact1, contact2, contact3, hostNs1CatLol, hostNs2CatLol, registrar)
|
||||||
.asBuilder()
|
.asBuilder()
|
||||||
.setCreationTimeForTest(clock.nowUtc().minusYears(3))
|
.setCreationTimeForTest(clock.nowUtc().minusYears(3));
|
||||||
.build();
|
if (i % numTotalDomainsPerActiveDomain != 0) {
|
||||||
if (i % numTotalDomainsPerActiveDomain == 0) {
|
builder = builder.setDeletionTime(clock.nowUtc().minusDays(1));
|
||||||
persistResource(domain);
|
|
||||||
} else {
|
|
||||||
persistDomainAsDeleted(domain, clock.nowUtc());
|
|
||||||
}
|
}
|
||||||
|
domainsBuilder.add(builder.build());
|
||||||
}
|
}
|
||||||
|
persistResources(domainsBuilder.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkNumberOfDomainsInResult(Object obj, int expected) {
|
private void checkNumberOfDomainsInResult(Object obj, int expected) {
|
||||||
|
@ -549,10 +551,10 @@ public class RdapDomainSearchActionTest {
|
||||||
@Test
|
@Test
|
||||||
public void testDomainMatch_manyDeletedDomains_fullResultSet() throws Exception {
|
public void testDomainMatch_manyDeletedDomains_fullResultSet() throws Exception {
|
||||||
// There are enough domains to fill a full result set; deleted domains are ignored.
|
// There are enough domains to fill a full result set; deleted domains are ignored.
|
||||||
createManyDomains(5, 4);
|
createManyDomains(4, 4);
|
||||||
Object obj = generateActualJson(RequestType.NAME, "domain*.lol");
|
Object obj = generateActualJson(RequestType.NAME, "domain*.lol");
|
||||||
assertThat(response.getStatus()).isEqualTo(200);
|
assertThat(response.getStatus()).isEqualTo(200);
|
||||||
checkNumberOfDomainsInResult(obj, 5);
|
checkNumberOfDomainsInResult(obj, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -571,7 +573,7 @@ public class RdapDomainSearchActionTest {
|
||||||
// This is not exactly desired behavior, but expected: There are enough domains to fill a full
|
// This is not exactly desired behavior, but expected: There are enough domains to fill a full
|
||||||
// result set, but there are so many deleted domains that we run out of patience before we work
|
// result set, but there are so many deleted domains that we run out of patience before we work
|
||||||
// our way through all of them.
|
// our way through all of them.
|
||||||
createManyDomains(5, 150);
|
createManyDomains(4, 150);
|
||||||
Object obj = generateActualJson(RequestType.NAME, "domain*.lol");
|
Object obj = generateActualJson(RequestType.NAME, "domain*.lol");
|
||||||
assertThat(response.getStatus()).isEqualTo(200);
|
assertThat(response.getStatus()).isEqualTo(200);
|
||||||
checkNumberOfDomainsInResult(obj, 3);
|
checkNumberOfDomainsInResult(obj, 3);
|
||||||
|
@ -587,7 +589,8 @@ public class RdapDomainSearchActionTest {
|
||||||
@Test
|
@Test
|
||||||
public void testNameserverMatchWithWildcard_found() throws Exception {
|
public void testNameserverMatchWithWildcard_found() throws Exception {
|
||||||
assertThat(generateActualJson(RequestType.NS_LDH_NAME, "ns2.cat.l*"))
|
assertThat(generateActualJson(RequestType.NS_LDH_NAME, "ns2.cat.l*"))
|
||||||
.isEqualTo(generateExpectedJsonForDomain("cat.lol", null, "C-LOL", "rdap_domain.json"));
|
.isEqualTo(
|
||||||
|
generateExpectedJsonForDomain("cat.lol", null, "C-LOL", "rdap_domain.json"));
|
||||||
assertThat(response.getStatus()).isEqualTo(200);
|
assertThat(response.getStatus()).isEqualTo(200);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -672,7 +675,8 @@ public class RdapDomainSearchActionTest {
|
||||||
public void testNameserverMatchOneDeletedDomain_foundTheOther() throws Exception {
|
public void testNameserverMatchOneDeletedDomain_foundTheOther() throws Exception {
|
||||||
persistDomainAsDeleted(domainCatExample, clock.nowUtc());
|
persistDomainAsDeleted(domainCatExample, clock.nowUtc());
|
||||||
assertThat(generateActualJson(RequestType.NS_LDH_NAME, "ns1.cat.lol"))
|
assertThat(generateActualJson(RequestType.NS_LDH_NAME, "ns1.cat.lol"))
|
||||||
.isEqualTo(generateExpectedJsonForDomain("cat.lol", null, "C-LOL", "rdap_domain.json"));
|
.isEqualTo(
|
||||||
|
generateExpectedJsonForDomain("cat.lol", null, "C-LOL", "rdap_domain.json"));
|
||||||
assertThat(response.getStatus()).isEqualTo(200);
|
assertThat(response.getStatus()).isEqualTo(200);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -748,7 +752,8 @@ public class RdapDomainSearchActionTest {
|
||||||
public void testAddressMatchOneDeletedDomain_foundTheOther() throws Exception {
|
public void testAddressMatchOneDeletedDomain_foundTheOther() throws Exception {
|
||||||
persistDomainAsDeleted(domainCatExample, clock.nowUtc());
|
persistDomainAsDeleted(domainCatExample, clock.nowUtc());
|
||||||
assertThat(generateActualJson(RequestType.NS_IP, "1.2.3.4"))
|
assertThat(generateActualJson(RequestType.NS_IP, "1.2.3.4"))
|
||||||
.isEqualTo(generateExpectedJsonForDomain("cat.lol", null, "C-LOL", "rdap_domain.json"));
|
.isEqualTo(
|
||||||
|
generateExpectedJsonForDomain("cat.lol", null, "C-LOL", "rdap_domain.json"));
|
||||||
assertThat(response.getStatus()).isEqualTo(200);
|
assertThat(response.getStatus()).isEqualTo(200);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,7 @@ import google.registry.model.registrar.RegistrarContact;
|
||||||
import google.registry.model.registry.Registry.TldState;
|
import google.registry.model.registry.Registry.TldState;
|
||||||
import google.registry.model.reporting.HistoryEntry;
|
import google.registry.model.reporting.HistoryEntry;
|
||||||
import google.registry.rdap.RdapJsonFormatter.MakeRdapJsonNoticeParameters;
|
import google.registry.rdap.RdapJsonFormatter.MakeRdapJsonNoticeParameters;
|
||||||
|
import google.registry.rdap.RdapJsonFormatter.OutputDataType;
|
||||||
import google.registry.testing.AppEngineRule;
|
import google.registry.testing.AppEngineRule;
|
||||||
import google.registry.testing.FakeClock;
|
import google.registry.testing.FakeClock;
|
||||||
import google.registry.testing.InjectRule;
|
import google.registry.testing.InjectRule;
|
||||||
|
@ -204,35 +205,59 @@ public class RdapJsonFormatterTest {
|
||||||
@Test
|
@Test
|
||||||
public void testRegistrar() throws Exception {
|
public void testRegistrar() throws Exception {
|
||||||
assertThat(RdapJsonFormatter.makeRdapJsonForRegistrar(
|
assertThat(RdapJsonFormatter.makeRdapJsonForRegistrar(
|
||||||
registrar, false, LINK_BASE, WHOIS_SERVER, clock.nowUtc()))
|
registrar, false, LINK_BASE, WHOIS_SERVER, clock.nowUtc(), OutputDataType.FULL))
|
||||||
.isEqualTo(loadJson("rdapjson_registrar.json"));
|
.isEqualTo(loadJson("rdapjson_registrar.json"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRegistrar_summary() throws Exception {
|
||||||
|
assertThat(RdapJsonFormatter.makeRdapJsonForRegistrar(
|
||||||
|
registrar, false, LINK_BASE, WHOIS_SERVER, clock.nowUtc(), OutputDataType.SUMMARY))
|
||||||
|
.isEqualTo(loadJson("rdapjson_registrar_summary.json"));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testHost_ipv4() throws Exception {
|
public void testHost_ipv4() throws Exception {
|
||||||
assertThat(RdapJsonFormatter.makeRdapJsonForHost(
|
assertThat(RdapJsonFormatter.makeRdapJsonForHost(
|
||||||
hostResourceIpv4, false, LINK_BASE, WHOIS_SERVER, clock.nowUtc()))
|
hostResourceIpv4, false, LINK_BASE, WHOIS_SERVER, clock.nowUtc(), OutputDataType.FULL))
|
||||||
.isEqualTo(loadJson("rdapjson_host_ipv4.json"));
|
.isEqualTo(loadJson("rdapjson_host_ipv4.json"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testHost_ipv6() throws Exception {
|
public void testHost_ipv6() throws Exception {
|
||||||
assertThat(RdapJsonFormatter.makeRdapJsonForHost(
|
assertThat(RdapJsonFormatter.makeRdapJsonForHost(
|
||||||
hostResourceIpv6, false, LINK_BASE, WHOIS_SERVER, clock.nowUtc()))
|
hostResourceIpv6, false, LINK_BASE, WHOIS_SERVER, clock.nowUtc(), OutputDataType.FULL))
|
||||||
.isEqualTo(loadJson("rdapjson_host_ipv6.json"));
|
.isEqualTo(loadJson("rdapjson_host_ipv6.json"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testHost_both() throws Exception {
|
public void testHost_both() throws Exception {
|
||||||
assertThat(RdapJsonFormatter.makeRdapJsonForHost(
|
assertThat(RdapJsonFormatter.makeRdapJsonForHost(
|
||||||
hostResourceBoth, false, LINK_BASE, WHOIS_SERVER, clock.nowUtc()))
|
hostResourceBoth, false, LINK_BASE, WHOIS_SERVER, clock.nowUtc(), OutputDataType.FULL))
|
||||||
.isEqualTo(loadJson("rdapjson_host_both.json"));
|
.isEqualTo(loadJson("rdapjson_host_both.json"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHost_both_summary() throws Exception {
|
||||||
|
assertThat(RdapJsonFormatter.makeRdapJsonForHost(
|
||||||
|
hostResourceBoth,
|
||||||
|
false,
|
||||||
|
LINK_BASE,
|
||||||
|
WHOIS_SERVER,
|
||||||
|
clock.nowUtc(),
|
||||||
|
OutputDataType.SUMMARY))
|
||||||
|
.isEqualTo(loadJson("rdapjson_host_both_summary.json"));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testHost_noAddresses() throws Exception {
|
public void testHost_noAddresses() throws Exception {
|
||||||
assertThat(RdapJsonFormatter.makeRdapJsonForHost(
|
assertThat(RdapJsonFormatter.makeRdapJsonForHost(
|
||||||
hostResourceNoAddresses, false, LINK_BASE, WHOIS_SERVER, clock.nowUtc()))
|
hostResourceNoAddresses,
|
||||||
|
false,
|
||||||
|
LINK_BASE,
|
||||||
|
WHOIS_SERVER,
|
||||||
|
clock.nowUtc(),
|
||||||
|
OutputDataType.FULL))
|
||||||
.isEqualTo(loadJson("rdapjson_host_no_addresses.json"));
|
.isEqualTo(loadJson("rdapjson_host_no_addresses.json"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -245,10 +270,25 @@ public class RdapJsonFormatterTest {
|
||||||
Optional.of(DesignatedContact.Type.REGISTRANT),
|
Optional.of(DesignatedContact.Type.REGISTRANT),
|
||||||
LINK_BASE,
|
LINK_BASE,
|
||||||
WHOIS_SERVER,
|
WHOIS_SERVER,
|
||||||
clock.nowUtc()))
|
clock.nowUtc(),
|
||||||
|
OutputDataType.FULL))
|
||||||
.isEqualTo(loadJson("rdapjson_registrant.json"));
|
.isEqualTo(loadJson("rdapjson_registrant.json"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRegistrant_summary() throws Exception {
|
||||||
|
assertThat(
|
||||||
|
RdapJsonFormatter.makeRdapJsonForContact(
|
||||||
|
contactResourceRegistrant,
|
||||||
|
false,
|
||||||
|
Optional.of(DesignatedContact.Type.REGISTRANT),
|
||||||
|
LINK_BASE,
|
||||||
|
WHOIS_SERVER,
|
||||||
|
clock.nowUtc(),
|
||||||
|
OutputDataType.SUMMARY))
|
||||||
|
.isEqualTo(loadJson("rdapjson_registrant_summary.json"));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRegistrant_baseHasNoTrailingSlash() throws Exception {
|
public void testRegistrant_baseHasNoTrailingSlash() throws Exception {
|
||||||
assertThat(
|
assertThat(
|
||||||
|
@ -258,7 +298,8 @@ public class RdapJsonFormatterTest {
|
||||||
Optional.of(DesignatedContact.Type.REGISTRANT),
|
Optional.of(DesignatedContact.Type.REGISTRANT),
|
||||||
LINK_BASE_NO_TRAILING_SLASH,
|
LINK_BASE_NO_TRAILING_SLASH,
|
||||||
WHOIS_SERVER,
|
WHOIS_SERVER,
|
||||||
clock.nowUtc()))
|
clock.nowUtc(),
|
||||||
|
OutputDataType.FULL))
|
||||||
.isEqualTo(loadJson("rdapjson_registrant.json"));
|
.isEqualTo(loadJson("rdapjson_registrant.json"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -271,7 +312,8 @@ public class RdapJsonFormatterTest {
|
||||||
Optional.of(DesignatedContact.Type.REGISTRANT),
|
Optional.of(DesignatedContact.Type.REGISTRANT),
|
||||||
null,
|
null,
|
||||||
WHOIS_SERVER,
|
WHOIS_SERVER,
|
||||||
clock.nowUtc()))
|
clock.nowUtc(),
|
||||||
|
OutputDataType.FULL))
|
||||||
.isEqualTo(loadJson("rdapjson_registrant_nobase.json"));
|
.isEqualTo(loadJson("rdapjson_registrant_nobase.json"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -284,7 +326,8 @@ public class RdapJsonFormatterTest {
|
||||||
Optional.of(DesignatedContact.Type.ADMIN),
|
Optional.of(DesignatedContact.Type.ADMIN),
|
||||||
LINK_BASE,
|
LINK_BASE,
|
||||||
WHOIS_SERVER,
|
WHOIS_SERVER,
|
||||||
clock.nowUtc()))
|
clock.nowUtc(),
|
||||||
|
OutputDataType.FULL))
|
||||||
.isEqualTo(loadJson("rdapjson_admincontact.json"));
|
.isEqualTo(loadJson("rdapjson_admincontact.json"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -297,7 +340,8 @@ public class RdapJsonFormatterTest {
|
||||||
Optional.of(DesignatedContact.Type.TECH),
|
Optional.of(DesignatedContact.Type.TECH),
|
||||||
LINK_BASE,
|
LINK_BASE,
|
||||||
WHOIS_SERVER,
|
WHOIS_SERVER,
|
||||||
clock.nowUtc()))
|
clock.nowUtc(),
|
||||||
|
OutputDataType.FULL))
|
||||||
.isEqualTo(loadJson("rdapjson_techcontact.json"));
|
.isEqualTo(loadJson("rdapjson_techcontact.json"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -310,21 +354,44 @@ public class RdapJsonFormatterTest {
|
||||||
Optional.<DesignatedContact.Type>absent(),
|
Optional.<DesignatedContact.Type>absent(),
|
||||||
LINK_BASE,
|
LINK_BASE,
|
||||||
WHOIS_SERVER,
|
WHOIS_SERVER,
|
||||||
clock.nowUtc()))
|
clock.nowUtc(),
|
||||||
|
OutputDataType.FULL))
|
||||||
.isEqualTo(loadJson("rdapjson_rolelesscontact.json"));
|
.isEqualTo(loadJson("rdapjson_rolelesscontact.json"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDomain_full() throws Exception {
|
public void testDomain_full() throws Exception {
|
||||||
assertThat(RdapJsonFormatter.makeRdapJsonForDomain(
|
assertThat(RdapJsonFormatter.makeRdapJsonForDomain(
|
||||||
domainResourceFull, false, LINK_BASE, WHOIS_SERVER, clock.nowUtc()))
|
domainResourceFull,
|
||||||
|
false,
|
||||||
|
LINK_BASE,
|
||||||
|
WHOIS_SERVER,
|
||||||
|
clock.nowUtc(),
|
||||||
|
OutputDataType.FULL))
|
||||||
.isEqualTo(loadJson("rdapjson_domain_full.json"));
|
.isEqualTo(loadJson("rdapjson_domain_full.json"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDomain_summary() throws Exception {
|
||||||
|
assertThat(RdapJsonFormatter.makeRdapJsonForDomain(
|
||||||
|
domainResourceFull,
|
||||||
|
false,
|
||||||
|
LINK_BASE,
|
||||||
|
WHOIS_SERVER,
|
||||||
|
clock.nowUtc(),
|
||||||
|
OutputDataType.SUMMARY))
|
||||||
|
.isEqualTo(loadJson("rdapjson_domain_summary.json"));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDomain_noNameservers() throws Exception {
|
public void testDomain_noNameservers() throws Exception {
|
||||||
assertThat(RdapJsonFormatter.makeRdapJsonForDomain(
|
assertThat(RdapJsonFormatter.makeRdapJsonForDomain(
|
||||||
domainResourceNoNameservers, false, LINK_BASE, WHOIS_SERVER, clock.nowUtc()))
|
domainResourceNoNameservers,
|
||||||
|
false,
|
||||||
|
LINK_BASE,
|
||||||
|
WHOIS_SERVER,
|
||||||
|
clock.nowUtc(),
|
||||||
|
OutputDataType.FULL))
|
||||||
.isEqualTo(loadJson("rdapjson_domain_no_nameservers.json"));
|
.isEqualTo(loadJson("rdapjson_domain_no_nameservers.json"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -406,7 +473,8 @@ public class RdapJsonFormatterTest {
|
||||||
RdapJsonFormatter.addTopLevelEntries(
|
RdapJsonFormatter.addTopLevelEntries(
|
||||||
builder,
|
builder,
|
||||||
RdapJsonFormatter.BoilerplateType.OTHER,
|
RdapJsonFormatter.BoilerplateType.OTHER,
|
||||||
null,
|
ImmutableList.of(),
|
||||||
|
ImmutableList.of(),
|
||||||
LINK_BASE);
|
LINK_BASE);
|
||||||
assertThat(builder.build()).isEqualTo(loadJson("rdapjson_toplevel.json"));
|
assertThat(builder.build()).isEqualTo(loadJson("rdapjson_toplevel.json"));
|
||||||
}
|
}
|
||||||
|
@ -419,6 +487,7 @@ public class RdapJsonFormatterTest {
|
||||||
builder,
|
builder,
|
||||||
RdapJsonFormatter.BoilerplateType.OTHER,
|
RdapJsonFormatter.BoilerplateType.OTHER,
|
||||||
ImmutableList.of(RdapHelpAction.getJsonHelpNotice("/tos", LINK_BASE)),
|
ImmutableList.of(RdapHelpAction.getJsonHelpNotice("/tos", LINK_BASE)),
|
||||||
|
ImmutableList.of(),
|
||||||
LINK_BASE);
|
LINK_BASE);
|
||||||
assertThat(builder.build()).isEqualTo(loadJson("rdapjson_toplevel.json"));
|
assertThat(builder.build()).isEqualTo(loadJson("rdapjson_toplevel.json"));
|
||||||
}
|
}
|
||||||
|
@ -430,7 +499,8 @@ public class RdapJsonFormatterTest {
|
||||||
RdapJsonFormatter.addTopLevelEntries(
|
RdapJsonFormatter.addTopLevelEntries(
|
||||||
builder,
|
builder,
|
||||||
RdapJsonFormatter.BoilerplateType.DOMAIN,
|
RdapJsonFormatter.BoilerplateType.DOMAIN,
|
||||||
null,
|
ImmutableList.of(),
|
||||||
|
ImmutableList.of(),
|
||||||
LINK_BASE);
|
LINK_BASE);
|
||||||
assertThat(builder.build()).isEqualTo(loadJson("rdapjson_toplevel_domain.json"));
|
assertThat(builder.build()).isEqualTo(loadJson("rdapjson_toplevel_domain.json"));
|
||||||
}
|
}
|
||||||
|
@ -443,6 +513,7 @@ public class RdapJsonFormatterTest {
|
||||||
builder,
|
builder,
|
||||||
RdapJsonFormatter.BoilerplateType.DOMAIN,
|
RdapJsonFormatter.BoilerplateType.DOMAIN,
|
||||||
ImmutableList.of(RdapHelpAction.getJsonHelpNotice("/tos", LINK_BASE)),
|
ImmutableList.of(RdapHelpAction.getJsonHelpNotice("/tos", LINK_BASE)),
|
||||||
|
ImmutableList.of(),
|
||||||
LINK_BASE);
|
LINK_BASE);
|
||||||
assertThat(builder.build()).isEqualTo(loadJson("rdapjson_toplevel_domain.json"));
|
assertThat(builder.build()).isEqualTo(loadJson("rdapjson_toplevel_domain.json"));
|
||||||
}
|
}
|
||||||
|
|
|
@ -382,7 +382,12 @@ public class RdapNameserverSearchActionTest {
|
||||||
assertThat(generateActualJsonWithIp("bad:f00d:cafe::15:beef"))
|
assertThat(generateActualJsonWithIp("bad:f00d:cafe::15:beef"))
|
||||||
.isEqualTo(
|
.isEqualTo(
|
||||||
generateExpectedJsonForNameserver(
|
generateExpectedJsonForNameserver(
|
||||||
"ns2.cat.lol", null, "4-ROID", "v6", "bad:f00d:cafe::15:beef", "rdap_host.json"));
|
"ns2.cat.lol",
|
||||||
|
null,
|
||||||
|
"4-ROID",
|
||||||
|
"v6",
|
||||||
|
"bad:f00d:cafe::15:beef",
|
||||||
|
"rdap_host.json"));
|
||||||
assertThat(response.getStatus()).isEqualTo(200);
|
assertThat(response.getStatus()).isEqualTo(200);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,15 +14,13 @@
|
||||||
"type" : "application/rdap+json"
|
"type" : "application/rdap+json"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"events": [
|
"remarks": [
|
||||||
{
|
{
|
||||||
"eventAction": "registration",
|
"title": "Incomplete Data",
|
||||||
"eventActor": "foo",
|
"description": [
|
||||||
"eventDate": "2000-01-01T00:00:00.000Z"
|
"Summary data only. For complete data, send a specific query for the object."
|
||||||
},
|
],
|
||||||
{
|
"type": "object truncated due to unexplainable reasons"
|
||||||
"eventAction": "last update of RDAP database",
|
|
||||||
"eventDate": "2000-01-01T00:00:00.000Z"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"vcardArray" :
|
"vcardArray" :
|
||||||
|
@ -63,15 +61,13 @@
|
||||||
"type" : "application/rdap+json"
|
"type" : "application/rdap+json"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"events": [
|
"remarks": [
|
||||||
{
|
{
|
||||||
"eventAction": "registration",
|
"title": "Incomplete Data",
|
||||||
"eventActor": "2-Registrar",
|
"description": [
|
||||||
"eventDate": "2000-01-01T00:00:00.000Z"
|
"Summary data only. For complete data, send a specific query for the object."
|
||||||
},
|
],
|
||||||
{
|
"type": "object truncated due to unexplainable reasons"
|
||||||
"eventAction": "last update of RDAP database",
|
|
||||||
"eventDate": "2000-01-01T00:00:00.000Z"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"publicIds" :
|
"publicIds" :
|
||||||
|
@ -102,41 +98,6 @@
|
||||||
["tel", {"type" : ["fax"]}, "uri", "tel:+1.2125551213"],
|
["tel", {"type" : ["fax"]}, "uri", "tel:+1.2125551213"],
|
||||||
["email", {}, "text", "contact-us@example.com"]
|
["email", {}, "text", "contact-us@example.com"]
|
||||||
]
|
]
|
||||||
],
|
|
||||||
"entities" :
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"objectClassName" : "entity",
|
|
||||||
"status" : ["active"],
|
|
||||||
"roles" : ["administrative"],
|
|
||||||
"vcardArray" :
|
|
||||||
[
|
|
||||||
"vcard",
|
|
||||||
[
|
|
||||||
["version", {}, "text", "4.0"],
|
|
||||||
["fn", {}, "text", "Jane Doe"],
|
|
||||||
["tel", {"type" : ["voice"]}, "uri", "tel:+1.2125551215"],
|
|
||||||
["tel", {"type" : ["fax"]}, "uri", "tel:+1.2125551216"],
|
|
||||||
["email", {}, "text", "janedoe@example.com"]
|
|
||||||
]
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"objectClassName" : "entity",
|
|
||||||
"status" : ["active"],
|
|
||||||
"roles" : ["technical"],
|
|
||||||
"vcardArray" :
|
|
||||||
[
|
|
||||||
"vcard",
|
|
||||||
[
|
|
||||||
["version", {}, "text", "4.0"],
|
|
||||||
["fn", {}, "text", "John Doe"],
|
|
||||||
["tel", {"type" : ["voice"]}, "uri", "tel:+1.2125551213"],
|
|
||||||
["tel", {"type" : ["fax"]}, "uri", "tel:+1.2125551213"],
|
|
||||||
["email", {}, "text", "johndoe@example.com"]
|
|
||||||
]
|
|
||||||
],
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
|
@ -14,15 +14,13 @@
|
||||||
"type" : "application/rdap+json"
|
"type" : "application/rdap+json"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"events": [
|
"remarks": [
|
||||||
{
|
{
|
||||||
"eventAction": "registration",
|
"title": "Incomplete Data",
|
||||||
"eventActor": "foo",
|
"description": [
|
||||||
"eventDate": "2000-01-01T00:00:00.000Z"
|
"Summary data only. For complete data, send a specific query for the object."
|
||||||
},
|
],
|
||||||
{
|
"type": "object truncated due to unexplainable reasons"
|
||||||
"eventAction": "last update of RDAP database",
|
|
||||||
"eventDate": "2000-01-01T00:00:00.000Z"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"vcardArray" :
|
"vcardArray" :
|
||||||
|
@ -62,15 +60,13 @@
|
||||||
"type" : "application/rdap+json"
|
"type" : "application/rdap+json"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"events": [
|
"remarks": [
|
||||||
{
|
{
|
||||||
"eventAction": "registration",
|
"title": "Incomplete Data",
|
||||||
"eventActor": "foo",
|
"description": [
|
||||||
"eventDate": "2000-01-01T00:00:00.000Z"
|
"Summary data only. For complete data, send a specific query for the object."
|
||||||
},
|
],
|
||||||
{
|
"type": "object truncated due to unexplainable reasons"
|
||||||
"eventAction": "last update of RDAP database",
|
|
||||||
"eventDate": "2000-01-01T00:00:00.000Z"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"vcardArray" :
|
"vcardArray" :
|
||||||
|
|
|
@ -16,371 +16,17 @@
|
||||||
"value": "https://example.com/rdap/domain/cat.example"
|
"value": "https://example.com/rdap/domain/cat.example"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"events": [
|
|
||||||
{
|
|
||||||
"eventAction": "registration",
|
|
||||||
"eventActor": "foo",
|
|
||||||
"eventDate": "2000-01-01T00:00:00.000Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"eventAction": "expiration",
|
|
||||||
"eventDate": "2110-10-08T00:44:59.000Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"eventAction": "last changed",
|
|
||||||
"eventDate": "2009-05-29T20:13:00.000Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"eventAction": "last update of RDAP database",
|
|
||||||
"eventDate": "2000-01-01T00:00:00.000Z"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"nameservers": [
|
|
||||||
{
|
|
||||||
"status": [
|
|
||||||
"active"
|
|
||||||
],
|
|
||||||
"handle": "8-ROID",
|
|
||||||
"links": [
|
|
||||||
{
|
|
||||||
"href": "https://example.com/rdap/nameserver/ns1.cat.lol",
|
|
||||||
"type": "application/rdap+json",
|
|
||||||
"rel": "self",
|
|
||||||
"value": "https://example.com/rdap/nameserver/ns1.cat.lol"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"ldhName": "ns1.cat.lol",
|
|
||||||
"ipAddresses": {
|
|
||||||
"v4": [
|
|
||||||
"1.2.3.4"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"events": [
|
|
||||||
{
|
|
||||||
"eventAction": "registration",
|
|
||||||
"eventActor": "foo",
|
|
||||||
"eventDate": "1999-01-01T00:00:00.000Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"eventAction": "last update of RDAP database",
|
|
||||||
"eventDate": "2000-01-01T00:00:00.000Z"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"objectClassName": "nameserver"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"status": [
|
|
||||||
"active"
|
|
||||||
],
|
|
||||||
"handle": "1F-ROID",
|
|
||||||
"links": [
|
|
||||||
{
|
|
||||||
"href": "https://example.com/rdap/nameserver/ns2.external.tld",
|
|
||||||
"type": "application/rdap+json",
|
|
||||||
"rel": "self",
|
|
||||||
"value": "https://example.com/rdap/nameserver/ns2.external.tld"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"ldhName": "ns2.external.tld",
|
|
||||||
"ipAddresses": {
|
|
||||||
"v6": [
|
|
||||||
"bad:f00d:cafe::15:beef"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"events": [
|
|
||||||
{
|
|
||||||
"eventAction": "registration",
|
|
||||||
"eventActor": "foo",
|
|
||||||
"eventDate": "1998-01-01T00:00:00.000Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"eventAction": "last update of RDAP database",
|
|
||||||
"eventDate": "2000-01-01T00:00:00.000Z"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"objectClassName": "nameserver"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"ldhName": "cat.example",
|
"ldhName": "cat.example",
|
||||||
"entities": [
|
"objectClassName": "domain",
|
||||||
|
"remarks": [
|
||||||
{
|
{
|
||||||
"status": [
|
"title": "Incomplete Data",
|
||||||
"active"
|
"description": [
|
||||||
|
"Summary data only. For complete data, send a specific query for the object."
|
||||||
],
|
],
|
||||||
"handle": "1B-ROID",
|
"type": "object truncated due to unexplainable reasons"
|
||||||
"roles": [
|
|
||||||
"administrative"
|
|
||||||
],
|
|
||||||
"links": [
|
|
||||||
{
|
|
||||||
"href": "https://example.com/rdap/entity/1B-ROID",
|
|
||||||
"type": "application/rdap+json",
|
|
||||||
"rel": "self",
|
|
||||||
"value": "https://example.com/rdap/entity/1B-ROID"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"events": [
|
|
||||||
{
|
|
||||||
"eventAction": "registration",
|
|
||||||
"eventActor": "foo",
|
|
||||||
"eventDate": "1998-01-01T00:00:00.000Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"eventAction": "last update of RDAP database",
|
|
||||||
"eventDate": "2000-01-01T00:00:00.000Z"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"objectClassName": "entity",
|
|
||||||
"vcardArray": [
|
|
||||||
"vcard",
|
|
||||||
[
|
|
||||||
[
|
|
||||||
"version",
|
|
||||||
{},
|
|
||||||
"text",
|
|
||||||
"4.0"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"fn",
|
|
||||||
{},
|
|
||||||
"text",
|
|
||||||
"Mark"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"org",
|
|
||||||
{},
|
|
||||||
"text",
|
|
||||||
"GOOGLE INCORPORATED <script>"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"adr",
|
|
||||||
{},
|
|
||||||
"text",
|
|
||||||
[
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
"123 Example Boulevard <script>",
|
|
||||||
"KOKOMO",
|
|
||||||
"BM",
|
|
||||||
"31337",
|
|
||||||
"United States"
|
|
||||||
]
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"tel",
|
|
||||||
{
|
|
||||||
"type": [
|
|
||||||
"voice"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"uri",
|
|
||||||
"tel:+1.2126660420"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"tel",
|
|
||||||
{
|
|
||||||
"type": [
|
|
||||||
"fax"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"uri",
|
|
||||||
"tel:+1.2126660420"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"email",
|
|
||||||
{},
|
|
||||||
"text",
|
|
||||||
"BOFH@cat.lol"
|
|
||||||
]
|
|
||||||
]
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"status": [
|
|
||||||
"active"
|
|
||||||
],
|
|
||||||
"handle": "1D-ROID",
|
|
||||||
"roles": [
|
|
||||||
"technical"
|
|
||||||
],
|
|
||||||
"links": [
|
|
||||||
{
|
|
||||||
"href": "https://example.com/rdap/entity/1D-ROID",
|
|
||||||
"type": "application/rdap+json",
|
|
||||||
"rel": "self",
|
|
||||||
"value": "https://example.com/rdap/entity/1D-ROID"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"events": [
|
|
||||||
{
|
|
||||||
"eventAction": "registration",
|
|
||||||
"eventActor": "foo",
|
|
||||||
"eventDate": "1997-01-01T00:00:00.000Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"eventAction": "last update of RDAP database",
|
|
||||||
"eventDate": "2000-01-01T00:00:00.000Z"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"objectClassName": "entity",
|
|
||||||
"vcardArray": [
|
|
||||||
"vcard",
|
|
||||||
[
|
|
||||||
[
|
|
||||||
"version",
|
|
||||||
{},
|
|
||||||
"text",
|
|
||||||
"4.0"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"fn",
|
|
||||||
{},
|
|
||||||
"text",
|
|
||||||
"Luke"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"org",
|
|
||||||
{},
|
|
||||||
"text",
|
|
||||||
"GOOGLE INCORPORATED <script>"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"adr",
|
|
||||||
{},
|
|
||||||
"text",
|
|
||||||
[
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
"123 Example Boulevard <script>",
|
|
||||||
"KOKOMO",
|
|
||||||
"BM",
|
|
||||||
"31337",
|
|
||||||
"United States"
|
|
||||||
]
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"tel",
|
|
||||||
{
|
|
||||||
"type": [
|
|
||||||
"voice"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"uri",
|
|
||||||
"tel:+1.2126660420"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"tel",
|
|
||||||
{
|
|
||||||
"type": [
|
|
||||||
"fax"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"uri",
|
|
||||||
"tel:+1.2126660420"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"email",
|
|
||||||
{},
|
|
||||||
"text",
|
|
||||||
"bog@cat.lol"
|
|
||||||
]
|
|
||||||
]
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"status": [
|
|
||||||
"active"
|
|
||||||
],
|
|
||||||
"handle": "19-ROID",
|
|
||||||
"roles": [
|
|
||||||
"registrant"
|
|
||||||
],
|
|
||||||
"links": [
|
|
||||||
{
|
|
||||||
"href": "https://example.com/rdap/entity/19-ROID",
|
|
||||||
"type": "application/rdap+json",
|
|
||||||
"rel": "self",
|
|
||||||
"value": "https://example.com/rdap/entity/19-ROID"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"events": [
|
|
||||||
{
|
|
||||||
"eventAction": "registration",
|
|
||||||
"eventActor": "foo",
|
|
||||||
"eventDate": "1999-01-01T00:00:00.000Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"eventAction": "last update of RDAP database",
|
|
||||||
"eventDate": "2000-01-01T00:00:00.000Z"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"objectClassName": "entity",
|
|
||||||
"vcardArray": [
|
|
||||||
"vcard",
|
|
||||||
[
|
|
||||||
[
|
|
||||||
"version",
|
|
||||||
{},
|
|
||||||
"text",
|
|
||||||
"4.0"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"fn",
|
|
||||||
{},
|
|
||||||
"text",
|
|
||||||
"Matthew"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"org",
|
|
||||||
{},
|
|
||||||
"text",
|
|
||||||
"GOOGLE INCORPORATED <script>"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"adr",
|
|
||||||
{},
|
|
||||||
"text",
|
|
||||||
[
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
"123 Example Boulevard <script>",
|
|
||||||
"KOKOMO",
|
|
||||||
"BM",
|
|
||||||
"31337",
|
|
||||||
"United States"
|
|
||||||
]
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"tel",
|
|
||||||
{
|
|
||||||
"type": [
|
|
||||||
"voice"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"uri",
|
|
||||||
"tel:+1.2126660420"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"tel",
|
|
||||||
{
|
|
||||||
"type": [
|
|
||||||
"fax"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"uri",
|
|
||||||
"tel:+1.2126660420"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"email",
|
|
||||||
{},
|
|
||||||
"text",
|
|
||||||
"lol@cat.lol"
|
|
||||||
]
|
|
||||||
]
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
],
|
]
|
||||||
"objectClassName": "domain"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"status": [
|
"status": [
|
||||||
|
@ -398,371 +44,17 @@
|
||||||
"value": "https://example.com/rdap/domain/cat.lol"
|
"value": "https://example.com/rdap/domain/cat.lol"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"events": [
|
|
||||||
{
|
|
||||||
"eventAction": "registration",
|
|
||||||
"eventActor": "foo",
|
|
||||||
"eventDate": "2000-01-01T00:00:00.000Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"eventAction": "expiration",
|
|
||||||
"eventDate": "2110-10-08T00:44:59.000Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"eventAction": "last changed",
|
|
||||||
"eventDate": "2009-05-29T20:13:00.000Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"eventAction": "last update of RDAP database",
|
|
||||||
"eventDate": "2000-01-01T00:00:00.000Z"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"nameservers": [
|
|
||||||
{
|
|
||||||
"status": [
|
|
||||||
"active"
|
|
||||||
],
|
|
||||||
"handle": "8-ROID",
|
|
||||||
"links": [
|
|
||||||
{
|
|
||||||
"href": "https://example.com/rdap/nameserver/ns1.cat.lol",
|
|
||||||
"type": "application/rdap+json",
|
|
||||||
"rel": "self",
|
|
||||||
"value": "https://example.com/rdap/nameserver/ns1.cat.lol"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"ldhName": "ns1.cat.lol",
|
|
||||||
"ipAddresses": {
|
|
||||||
"v4": [
|
|
||||||
"1.2.3.4"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"events": [
|
|
||||||
{
|
|
||||||
"eventAction": "registration",
|
|
||||||
"eventActor": "foo",
|
|
||||||
"eventDate": "1999-01-01T00:00:00.000Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"eventAction": "last update of RDAP database",
|
|
||||||
"eventDate": "2000-01-01T00:00:00.000Z"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"objectClassName": "nameserver"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"status": [
|
|
||||||
"active"
|
|
||||||
],
|
|
||||||
"handle": "A-ROID",
|
|
||||||
"links": [
|
|
||||||
{
|
|
||||||
"href": "https://example.com/rdap/nameserver/ns2.cat.lol",
|
|
||||||
"type": "application/rdap+json",
|
|
||||||
"rel": "self",
|
|
||||||
"value": "https://example.com/rdap/nameserver/ns2.cat.lol"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"ldhName": "ns2.cat.lol",
|
|
||||||
"ipAddresses": {
|
|
||||||
"v6": [
|
|
||||||
"bad:f00d:cafe::15:beef"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"events": [
|
|
||||||
{
|
|
||||||
"eventAction": "registration",
|
|
||||||
"eventActor": "foo",
|
|
||||||
"eventDate": "1998-01-01T00:00:00.000Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"eventAction": "last update of RDAP database",
|
|
||||||
"eventDate": "2000-01-01T00:00:00.000Z"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"objectClassName": "nameserver"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"ldhName": "cat.lol",
|
"ldhName": "cat.lol",
|
||||||
"entities": [
|
"objectClassName": "domain",
|
||||||
|
"remarks": [
|
||||||
{
|
{
|
||||||
"status": [
|
"title": "Incomplete Data",
|
||||||
"active"
|
"description": [
|
||||||
|
"Summary data only. For complete data, send a specific query for the object."
|
||||||
],
|
],
|
||||||
"handle": "4-ROID",
|
"type": "object truncated due to unexplainable reasons"
|
||||||
"roles": [
|
|
||||||
"administrative"
|
|
||||||
],
|
|
||||||
"links": [
|
|
||||||
{
|
|
||||||
"href": "https://example.com/rdap/entity/4-ROID",
|
|
||||||
"type": "application/rdap+json",
|
|
||||||
"rel": "self",
|
|
||||||
"value": "https://example.com/rdap/entity/4-ROID"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"events": [
|
|
||||||
{
|
|
||||||
"eventAction": "registration",
|
|
||||||
"eventActor": "foo",
|
|
||||||
"eventDate": "1998-01-01T00:00:00.000Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"eventAction": "last update of RDAP database",
|
|
||||||
"eventDate": "2000-01-01T00:00:00.000Z"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"objectClassName": "entity",
|
|
||||||
"vcardArray": [
|
|
||||||
"vcard",
|
|
||||||
[
|
|
||||||
[
|
|
||||||
"version",
|
|
||||||
{},
|
|
||||||
"text",
|
|
||||||
"4.0"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"fn",
|
|
||||||
{},
|
|
||||||
"text",
|
|
||||||
"Santa Claus"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"org",
|
|
||||||
{},
|
|
||||||
"text",
|
|
||||||
"GOOGLE INCORPORATED <script>"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"adr",
|
|
||||||
{},
|
|
||||||
"text",
|
|
||||||
[
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
"123 Example Boulevard <script>",
|
|
||||||
"KOKOMO",
|
|
||||||
"BM",
|
|
||||||
"31337",
|
|
||||||
"United States"
|
|
||||||
]
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"tel",
|
|
||||||
{
|
|
||||||
"type": [
|
|
||||||
"voice"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"uri",
|
|
||||||
"tel:+1.2126660420"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"tel",
|
|
||||||
{
|
|
||||||
"type": [
|
|
||||||
"fax"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"uri",
|
|
||||||
"tel:+1.2126660420"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"email",
|
|
||||||
{},
|
|
||||||
"text",
|
|
||||||
"BOFH@cat.lol"
|
|
||||||
]
|
|
||||||
]
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"status": [
|
|
||||||
"active"
|
|
||||||
],
|
|
||||||
"handle": "6-ROID",
|
|
||||||
"roles": [
|
|
||||||
"technical"
|
|
||||||
],
|
|
||||||
"links": [
|
|
||||||
{
|
|
||||||
"href": "https://example.com/rdap/entity/6-ROID",
|
|
||||||
"type": "application/rdap+json",
|
|
||||||
"rel": "self",
|
|
||||||
"value": "https://example.com/rdap/entity/6-ROID"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"events": [
|
|
||||||
{
|
|
||||||
"eventAction": "registration",
|
|
||||||
"eventActor": "foo",
|
|
||||||
"eventDate": "1997-01-01T00:00:00.000Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"eventAction": "last update of RDAP database",
|
|
||||||
"eventDate": "2000-01-01T00:00:00.000Z"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"objectClassName": "entity",
|
|
||||||
"vcardArray": [
|
|
||||||
"vcard",
|
|
||||||
[
|
|
||||||
[
|
|
||||||
"version",
|
|
||||||
{},
|
|
||||||
"text",
|
|
||||||
"4.0"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"fn",
|
|
||||||
{},
|
|
||||||
"text",
|
|
||||||
"The Raven"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"org",
|
|
||||||
{},
|
|
||||||
"text",
|
|
||||||
"GOOGLE INCORPORATED <script>"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"adr",
|
|
||||||
{},
|
|
||||||
"text",
|
|
||||||
[
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
"123 Example Boulevard <script>",
|
|
||||||
"KOKOMO",
|
|
||||||
"BM",
|
|
||||||
"31337",
|
|
||||||
"United States"
|
|
||||||
]
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"tel",
|
|
||||||
{
|
|
||||||
"type": [
|
|
||||||
"voice"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"uri",
|
|
||||||
"tel:+1.2126660420"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"tel",
|
|
||||||
{
|
|
||||||
"type": [
|
|
||||||
"fax"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"uri",
|
|
||||||
"tel:+1.2126660420"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"email",
|
|
||||||
{},
|
|
||||||
"text",
|
|
||||||
"bog@cat.lol"
|
|
||||||
]
|
|
||||||
]
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"status": [
|
|
||||||
"active"
|
|
||||||
],
|
|
||||||
"handle": "2-ROID",
|
|
||||||
"roles": [
|
|
||||||
"registrant"
|
|
||||||
],
|
|
||||||
"links": [
|
|
||||||
{
|
|
||||||
"href": "https://example.com/rdap/entity/2-ROID",
|
|
||||||
"type": "application/rdap+json",
|
|
||||||
"rel": "self",
|
|
||||||
"value": "https://example.com/rdap/entity/2-ROID"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"events": [
|
|
||||||
{
|
|
||||||
"eventAction": "registration",
|
|
||||||
"eventActor": "foo",
|
|
||||||
"eventDate": "1999-01-01T00:00:00.000Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"eventAction": "last update of RDAP database",
|
|
||||||
"eventDate": "2000-01-01T00:00:00.000Z"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"objectClassName": "entity",
|
|
||||||
"vcardArray": [
|
|
||||||
"vcard",
|
|
||||||
[
|
|
||||||
[
|
|
||||||
"version",
|
|
||||||
{},
|
|
||||||
"text",
|
|
||||||
"4.0"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"fn",
|
|
||||||
{},
|
|
||||||
"text",
|
|
||||||
"Goblin Market"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"org",
|
|
||||||
{},
|
|
||||||
"text",
|
|
||||||
"GOOGLE INCORPORATED <script>"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"adr",
|
|
||||||
{},
|
|
||||||
"text",
|
|
||||||
[
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
"123 Example Boulevard <script>",
|
|
||||||
"KOKOMO",
|
|
||||||
"BM",
|
|
||||||
"31337",
|
|
||||||
"United States"
|
|
||||||
]
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"tel",
|
|
||||||
{
|
|
||||||
"type": [
|
|
||||||
"voice"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"uri",
|
|
||||||
"tel:+1.2126660420"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"tel",
|
|
||||||
{
|
|
||||||
"type": [
|
|
||||||
"fax"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"uri",
|
|
||||||
"tel:+1.2126660420"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"email",
|
|
||||||
{},
|
|
||||||
"text",
|
|
||||||
"lol@cat.lol"
|
|
||||||
]
|
|
||||||
]
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
],
|
]
|
||||||
"objectClassName": "domain"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"rdapConformance": [
|
"rdapConformance": [
|
||||||
|
|
|
@ -19,15 +19,13 @@
|
||||||
{
|
{
|
||||||
"v6" : ["bad:f00d:cafe::15:beef"]
|
"v6" : ["bad:f00d:cafe::15:beef"]
|
||||||
},
|
},
|
||||||
"events": [
|
"remarks": [
|
||||||
{
|
{
|
||||||
"eventAction": "registration",
|
"title": "Incomplete Data",
|
||||||
"eventActor": "foo",
|
"description": [
|
||||||
"eventDate": "1999-01-01T00:00:00.000Z"
|
"Summary data only. For complete data, send a specific query for the object."
|
||||||
},
|
],
|
||||||
{
|
"type": "object truncated due to unexplainable reasons"
|
||||||
"eventAction": "last update of RDAP database",
|
|
||||||
"eventDate": "2000-01-01T00:00:00.000Z"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -50,15 +48,13 @@
|
||||||
"v4" : ["1.2.3.3"]
|
"v4" : ["1.2.3.3"]
|
||||||
"v6" : ["bad:f00d:cafe::15:beef"]
|
"v6" : ["bad:f00d:cafe::15:beef"]
|
||||||
},
|
},
|
||||||
"events": [
|
"remarks": [
|
||||||
{
|
{
|
||||||
"eventAction": "registration",
|
"title": "Incomplete Data",
|
||||||
"eventActor": "foo",
|
"description": [
|
||||||
"eventDate": "1999-01-01T00:00:00.000Z"
|
"Summary data only. For complete data, send a specific query for the object."
|
||||||
},
|
],
|
||||||
{
|
"type": "object truncated due to unexplainable reasons"
|
||||||
"eventAction": "last update of RDAP database",
|
|
||||||
"eventDate": "2000-01-01T00:00:00.000Z"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
31
javatests/google/registry/rdap/testdata/rdapjson_domain_summary.json
vendored
Normal file
31
javatests/google/registry/rdap/testdata/rdapjson_domain_summary.json
vendored
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
{
|
||||||
|
"objectClassName" : "domain",
|
||||||
|
"handle" : "10-Q9JYB4C",
|
||||||
|
"ldhName" : "cat.xn--q9jyb4c",
|
||||||
|
"unicodeName" : "cat.みんな",
|
||||||
|
"status" :
|
||||||
|
[
|
||||||
|
"client delete prohibited",
|
||||||
|
"client renew prohibited",
|
||||||
|
"client transfer prohibited",
|
||||||
|
"server update prohibited"
|
||||||
|
],
|
||||||
|
"links" :
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"value" : "http://myserver.google.com/domain/cat.xn--q9jyb4c",
|
||||||
|
"rel" : "self",
|
||||||
|
"href" : "http://myserver.google.com/domain/cat.xn--q9jyb4c",
|
||||||
|
"type" : "application/rdap+json"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"remarks": [
|
||||||
|
{
|
||||||
|
"title": "Incomplete Data",
|
||||||
|
"description": [
|
||||||
|
"Summary data only. For complete data, send a specific query for the object."
|
||||||
|
],
|
||||||
|
"type": "object truncated due to unexplainable reasons"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
30
javatests/google/registry/rdap/testdata/rdapjson_host_both_summary.json
vendored
Normal file
30
javatests/google/registry/rdap/testdata/rdapjson_host_both_summary.json
vendored
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
{
|
||||||
|
"objectClassName" : "nameserver",
|
||||||
|
"handle" : "C-ROID",
|
||||||
|
"ldhName" : "ns3.cat.xn--q9jyb4c",
|
||||||
|
"unicodeName" : "ns3.cat.みんな",
|
||||||
|
"status" : ["active"],
|
||||||
|
"links" :
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"value" : "http://myserver.google.com/nameserver/ns3.cat.xn--q9jyb4c",
|
||||||
|
"rel" : "self",
|
||||||
|
"href" : "http://myserver.google.com/nameserver/ns3.cat.xn--q9jyb4c",
|
||||||
|
"type" : "application/rdap+json"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"ipAddresses" :
|
||||||
|
{
|
||||||
|
"v4" : ["1.2.3.4"],
|
||||||
|
"v6" : ["bad:f00d:cafe::15:beef"]
|
||||||
|
},
|
||||||
|
"remarks": [
|
||||||
|
{
|
||||||
|
"title": "Incomplete Data",
|
||||||
|
"description": [
|
||||||
|
"Summary data only. For complete data, send a specific query for the object."
|
||||||
|
],
|
||||||
|
"type": "object truncated due to unexplainable reasons"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
36
javatests/google/registry/rdap/testdata/rdapjson_registrant_summary.json
vendored
Normal file
36
javatests/google/registry/rdap/testdata/rdapjson_registrant_summary.json
vendored
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
{
|
||||||
|
"objectClassName" : "entity",
|
||||||
|
"handle" : "2-ROID",
|
||||||
|
"status" : ["active"],
|
||||||
|
"roles" : ["registrant"],
|
||||||
|
"links" :
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"value" : "http://myserver.google.com/entity/2-ROID",
|
||||||
|
"rel" : "self",
|
||||||
|
"href" : "http://myserver.google.com/entity/2-ROID",
|
||||||
|
"type" : "application/rdap+json"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"vcardArray" :
|
||||||
|
[
|
||||||
|
"vcard",
|
||||||
|
[
|
||||||
|
["version", {}, "text", "4.0"],
|
||||||
|
["fn", {}, "text", "(◕‿◕)"],
|
||||||
|
["org", {}, "text", "GOOGLE INCORPORATED <script>"],
|
||||||
|
["tel", {"type" : ["voice"]}, "uri", "tel:+1.2126660420"],
|
||||||
|
["tel", {"type" : ["fax"]}, "uri", "tel:+1.2126660420"],
|
||||||
|
["email", {}, "text", "lol@cat.みんな"]
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"remarks": [
|
||||||
|
{
|
||||||
|
"title": "Incomplete Data",
|
||||||
|
"description": [
|
||||||
|
"Summary data only. For complete data, send a specific query for the object."
|
||||||
|
],
|
||||||
|
"type": "object truncated due to unexplainable reasons"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
50
javatests/google/registry/rdap/testdata/rdapjson_registrar_summary.json
vendored
Normal file
50
javatests/google/registry/rdap/testdata/rdapjson_registrar_summary.json
vendored
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
{
|
||||||
|
"objectClassName" : "entity",
|
||||||
|
"handle" : "1",
|
||||||
|
"status" : ["active"],
|
||||||
|
"roles" : ["registrar"],
|
||||||
|
"links" :
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"value" : "http://myserver.google.com/entity/1",
|
||||||
|
"rel" : "self",
|
||||||
|
"href" : "http://myserver.google.com/entity/1",
|
||||||
|
"type" : "application/rdap+json"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"publicIds" :
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"type" : "IANA Registrar ID",
|
||||||
|
"identifier" : "1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"vcardArray" :
|
||||||
|
[
|
||||||
|
"vcard",
|
||||||
|
[
|
||||||
|
["version", {}, "text", "4.0"],
|
||||||
|
["fn", {}, "text", "みんな"],
|
||||||
|
["adr", {}, "text", [
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"123 Example Boulevard <script>",
|
||||||
|
"Williamsburg <script>",
|
||||||
|
"NY",
|
||||||
|
"11211",
|
||||||
|
"United States"]],
|
||||||
|
["tel", {"type" : ["voice"]}, "uri", "tel:+1.2125551212"],
|
||||||
|
["tel", {"type" : ["fax"]}, "uri", "tel:+1.2125551213"],
|
||||||
|
["email", {}, "text", "contact-us@example.com"]
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"remarks": [
|
||||||
|
{
|
||||||
|
"title": "Incomplete Data",
|
||||||
|
"description": [
|
||||||
|
"Summary data only. For complete data, send a specific query for the object."
|
||||||
|
],
|
||||||
|
"type": "object truncated due to unexplainable reasons"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -732,6 +732,25 @@ public class DatastoreHelper {
|
||||||
return persistResource(resource, true);
|
return persistResource(resource, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static <R> void saveResource(final R resource, final boolean wantBackup) {
|
||||||
|
Saver saver = wantBackup ? ofy().save() : ofy().saveWithoutBackup();
|
||||||
|
saver.entity(resource);
|
||||||
|
if (resource instanceof EppResource) {
|
||||||
|
EppResource eppResource = (EppResource) resource;
|
||||||
|
assertWithMessage("Cannot persist an EppResource with a missing repoId in tests")
|
||||||
|
.that(eppResource.getRepoId()).isNotEmpty();
|
||||||
|
Key<EppResource> eppResourceKey = Key.create(eppResource);
|
||||||
|
saver.entity(EppResourceIndex.create(eppResourceKey));
|
||||||
|
if (resource instanceof ForeignKeyedEppResource) {
|
||||||
|
saver.entity(ForeignKeyIndex.create(eppResource, eppResource.getDeletionTime()));
|
||||||
|
}
|
||||||
|
if (resource instanceof DomainApplication) {
|
||||||
|
saver.entity(
|
||||||
|
DomainApplicationIndex.createUpdatedInstance((DomainApplication) resource));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static <R> R persistResource(final R resource, final boolean wantBackup) {
|
private static <R> R persistResource(final R resource, final boolean wantBackup) {
|
||||||
assertWithMessage("Attempting to persist a Builder is almost certainly an error in test code")
|
assertWithMessage("Attempting to persist a Builder is almost certainly an error in test code")
|
||||||
.that(resource)
|
.that(resource)
|
||||||
|
@ -739,22 +758,7 @@ public class DatastoreHelper {
|
||||||
ofy().transact(new VoidWork() {
|
ofy().transact(new VoidWork() {
|
||||||
@Override
|
@Override
|
||||||
public void vrun() {
|
public void vrun() {
|
||||||
Saver saver = wantBackup ? ofy().save() : ofy().saveWithoutBackup();
|
saveResource(resource, wantBackup);
|
||||||
saver.entity(resource);
|
|
||||||
if (resource instanceof EppResource) {
|
|
||||||
EppResource eppResource = (EppResource) resource;
|
|
||||||
assertWithMessage("Cannot persist an EppResource with a missing repoId in tests")
|
|
||||||
.that(eppResource.getRepoId()).isNotEmpty();
|
|
||||||
Key<EppResource> eppResourceKey = Key.create(eppResource);
|
|
||||||
saver.entity(EppResourceIndex.create(eppResourceKey));
|
|
||||||
if (resource instanceof ForeignKeyedEppResource) {
|
|
||||||
saver.entity(ForeignKeyIndex.create(eppResource, eppResource.getDeletionTime()));
|
|
||||||
}
|
|
||||||
if (resource instanceof DomainApplication) {
|
|
||||||
saver.entity(
|
|
||||||
DomainApplicationIndex.createUpdatedInstance((DomainApplication) resource));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}});
|
}});
|
||||||
// Force the session to be cleared so that when we read it back, we read from the datastore
|
// Force the session to be cleared so that when we read it back, we read from the datastore
|
||||||
// and not from the transaction cache or memcache.
|
// and not from the transaction cache or memcache.
|
||||||
|
@ -762,6 +766,34 @@ public class DatastoreHelper {
|
||||||
return ofy().load().entity(resource).now();
|
return ofy().load().entity(resource).now();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static <R> void persistResources(final Iterable<R> resources) {
|
||||||
|
persistResources(resources, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static <R> void persistResources(final Iterable<R> resources, final boolean wantBackup) {
|
||||||
|
for (R resource : resources) {
|
||||||
|
assertWithMessage("Attempting to persist a Builder is almost certainly an error in test code")
|
||||||
|
.that(resource)
|
||||||
|
.isNotInstanceOf(Buildable.Builder.class);
|
||||||
|
}
|
||||||
|
// Persist domains ten at a time, to avoid exceeding the entity group limit.
|
||||||
|
for (final List<R> chunk : Iterables.partition(resources, 10)) {
|
||||||
|
ofy().transact(new VoidWork() {
|
||||||
|
@Override
|
||||||
|
public void vrun() {
|
||||||
|
for (R resource : chunk) {
|
||||||
|
saveResource(resource, wantBackup);
|
||||||
|
}
|
||||||
|
}});
|
||||||
|
}
|
||||||
|
// Force the session to be cleared so that when we read it back, we read from the datastore
|
||||||
|
// and not from the transaction cache or memcache.
|
||||||
|
ofy().clearSessionCache();
|
||||||
|
for (R resource : resources) {
|
||||||
|
ofy().load().entity(resource).now();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Saves an {@link EppResource} with partial history and commit log entries.
|
* Saves an {@link EppResource} with partial history and commit log entries.
|
||||||
*
|
*
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue