mirror of
https://github.com/google/nomulus
synced 2026-06-09 16:33:02 +00:00
Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b159541278 | |||
| 335b229ce8 | |||
| 8ee0a85531 | |||
| 5cbc307cd1 | |||
| bd37541b49 | |||
| 312bc143d5 | |||
| 49ade014ab | |||
| b8d901effe | |||
| 23520048dc | |||
| 37ed6c925c |
@@ -61,12 +61,6 @@ by Joshua Bloch in his book Effective Java -->
|
||||
<property name="message" value="Use assertThrows and expectThrows from JUnitBackports instead of the deprecated methods on ExpectedException."/>
|
||||
</module>
|
||||
|
||||
<!-- Checks that the deprecated MockitoJUnitRunner is not used. -->
|
||||
<module name="RegexpSingleline">
|
||||
<property name="format" value="MockitoJUnitRunner"/>
|
||||
<property name="message" value="MockitoJUnitRunner is deprecated. Use @RunWith(JUnit4.class) and MockitoRule instead."/>
|
||||
</module>
|
||||
|
||||
<module name="LineLength">
|
||||
<!-- Checks if a line is too long. -->
|
||||
<property name="max" value="${com.puppycrawl.tools.checkstyle.checks.sizes.LineLength.max}" default="100"/>
|
||||
|
||||
@@ -19,7 +19,6 @@ import static com.google.common.base.Preconditions.checkState;
|
||||
import static com.google.common.collect.ImmutableSet.toImmutableSet;
|
||||
import static google.registry.batch.BatchModule.PARAM_DRY_RUN;
|
||||
import static google.registry.config.RegistryEnvironment.PRODUCTION;
|
||||
import static google.registry.model.ResourceTransferUtils.updateForeignKeyIndexDeletionTime;
|
||||
import static google.registry.model.reporting.HistoryEntry.Type.DOMAIN_DELETE;
|
||||
import static google.registry.model.tld.Registries.getTldsOfType;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
|
||||
@@ -267,8 +266,6 @@ public class DeleteProberDataAction implements Runnable {
|
||||
// messages, or auto-renews because those will all be hard-deleted the next time the job runs
|
||||
// anyway.
|
||||
tm().putAll(ImmutableList.of(deletedDomain, historyEntry));
|
||||
// updating foreign keys is a no-op in SQL
|
||||
updateForeignKeyIndexDeletionTime(deletedDomain);
|
||||
dnsQueue.addDomainRefreshTask(deletedDomain.getDomainName());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,6 @@ import google.registry.model.eppinput.ResourceCommand;
|
||||
import google.registry.model.eppoutput.CreateData.ContactCreateData;
|
||||
import google.registry.model.eppoutput.EppResponse;
|
||||
import google.registry.model.index.EppResourceIndex;
|
||||
import google.registry.model.index.ForeignKeyIndex;
|
||||
import google.registry.model.reporting.HistoryEntry;
|
||||
import google.registry.model.reporting.IcannReportingTypes.ActivityReportField;
|
||||
import javax.inject.Inject;
|
||||
@@ -100,7 +99,6 @@ public final class ContactCreateFlow implements TransactionalFlow {
|
||||
ImmutableSet.of(
|
||||
newContact,
|
||||
historyBuilder.build(),
|
||||
ForeignKeyIndex.create(newContact, newContact.getDeletionTime()),
|
||||
EppResourceIndex.create(Key.create(newContact))));
|
||||
return responseBuilder
|
||||
.setResData(ContactCreateData.create(newContact.getContactId(), now))
|
||||
|
||||
@@ -106,7 +106,6 @@ import google.registry.model.eppinput.ResourceCommand;
|
||||
import google.registry.model.eppoutput.CreateData.DomainCreateData;
|
||||
import google.registry.model.eppoutput.EppResponse;
|
||||
import google.registry.model.index.EppResourceIndex;
|
||||
import google.registry.model.index.ForeignKeyIndex;
|
||||
import google.registry.model.poll.PendingActionNotificationResponse.DomainPendingActionNotificationResponse;
|
||||
import google.registry.model.poll.PollMessage;
|
||||
import google.registry.model.poll.PollMessage.Autorenew;
|
||||
@@ -404,7 +403,6 @@ public final class DomainCreateFlow implements TransactionalFlow {
|
||||
entitiesToSave.add(
|
||||
domain,
|
||||
domainHistory,
|
||||
ForeignKeyIndex.create(domain, domain.getDeletionTime()),
|
||||
EppResourceIndex.create(Key.create(domain)));
|
||||
if (allocationToken.isPresent()
|
||||
&& TokenType.SINGLE_USE.equals(allocationToken.get().getTokenType())) {
|
||||
|
||||
@@ -29,7 +29,6 @@ import static google.registry.flows.domain.DomainFlowUtils.updateAutorenewRecurr
|
||||
import static google.registry.flows.domain.DomainFlowUtils.verifyNotInPredelegation;
|
||||
import static google.registry.model.ResourceTransferUtils.denyPendingTransfer;
|
||||
import static google.registry.model.ResourceTransferUtils.handlePendingTransferOnDelete;
|
||||
import static google.registry.model.ResourceTransferUtils.updateForeignKeyIndexDeletionTime;
|
||||
import static google.registry.model.eppoutput.Result.Code.SUCCESS;
|
||||
import static google.registry.model.eppoutput.Result.Code.SUCCESS_WITH_ACTION_PENDING;
|
||||
import static google.registry.model.reporting.DomainTransactionRecord.TransactionReportField.ADD_FIELDS;
|
||||
@@ -257,7 +256,6 @@ public final class DomainDeleteFlow implements TransactionalFlow {
|
||||
Domain newDomain = builder.build();
|
||||
DomainHistory domainHistory =
|
||||
buildDomainHistory(newDomain, registry, now, durationUntilDelete, inAddGracePeriod);
|
||||
updateForeignKeyIndexDeletionTime(newDomain);
|
||||
handlePendingTransferOnDelete(existingDomain, newDomain, now, domainHistory);
|
||||
// Close the autorenew billing event and poll message. This may delete the poll message. Store
|
||||
// the updated recurring billing event, we'll need it later and can't reload it.
|
||||
|
||||
@@ -27,7 +27,6 @@ import static google.registry.flows.domain.DomainFlowUtils.validateFeeChallenge;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.verifyNotReserved;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.verifyPremiumNameIsNotBlocked;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.verifyRegistrarIsActive;
|
||||
import static google.registry.model.ResourceTransferUtils.updateForeignKeyIndexDeletionTime;
|
||||
import static google.registry.model.reporting.HistoryEntry.Type.DOMAIN_RESTORE;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.util.DateTimeUtils.END_OF_TIME;
|
||||
@@ -188,7 +187,6 @@ public final class DomainRestoreRequestFlow implements TransactionalFlow {
|
||||
autorenewPollMessage,
|
||||
now,
|
||||
registrarId);
|
||||
updateForeignKeyIndexDeletionTime(newDomain);
|
||||
DomainHistory domainHistory = buildDomainHistory(newDomain, now);
|
||||
entitiesToSave.add(newDomain, domainHistory, autorenewEvent, autorenewPollMessage);
|
||||
tm().putAll(entitiesToSave.build());
|
||||
|
||||
@@ -152,7 +152,7 @@ public class AllocationTokenFlowUtils {
|
||||
}
|
||||
|
||||
maybeTokenEntity =
|
||||
tm().transact(() -> tm().loadByKeyIfPresent(VKey.create(AllocationToken.class, token)));
|
||||
tm().transact(() -> tm().loadByKeyIfPresent(VKey.createSql(AllocationToken.class, token)));
|
||||
|
||||
if (!maybeTokenEntity.isPresent()) {
|
||||
throw new InvalidAllocationTokenException();
|
||||
|
||||
@@ -50,7 +50,6 @@ import google.registry.model.host.Host;
|
||||
import google.registry.model.host.HostCommand.Create;
|
||||
import google.registry.model.host.HostHistory;
|
||||
import google.registry.model.index.EppResourceIndex;
|
||||
import google.registry.model.index.ForeignKeyIndex;
|
||||
import google.registry.model.reporting.IcannReportingTypes.ActivityReportField;
|
||||
import java.util.Optional;
|
||||
import javax.inject.Inject;
|
||||
@@ -135,7 +134,6 @@ public final class HostCreateFlow implements TransactionalFlow {
|
||||
ImmutableSet.of(
|
||||
newHost,
|
||||
historyBuilder.build(),
|
||||
ForeignKeyIndex.create(newHost, newHost.getDeletionTime()),
|
||||
EppResourceIndex.create(Key.create(newHost)));
|
||||
if (superordinateDomain.isPresent()) {
|
||||
tm().update(
|
||||
|
||||
@@ -57,7 +57,6 @@ import google.registry.model.host.HostCommand.Update;
|
||||
import google.registry.model.host.HostCommand.Update.AddRemove;
|
||||
import google.registry.model.host.HostCommand.Update.Change;
|
||||
import google.registry.model.host.HostHistory;
|
||||
import google.registry.model.index.ForeignKeyIndex;
|
||||
import google.registry.model.reporting.IcannReportingTypes.ActivityReportField;
|
||||
import google.registry.persistence.VKey;
|
||||
import java.util.Objects;
|
||||
@@ -194,11 +193,7 @@ public final class HostUpdateFlow implements TransactionalFlow {
|
||||
ImmutableSet.Builder<ImmutableObject> entitiesToInsert = new ImmutableSet.Builder<>();
|
||||
ImmutableSet.Builder<ImmutableObject> entitiesToUpdate = new ImmutableSet.Builder<>();
|
||||
entitiesToUpdate.add(newHost);
|
||||
// Keep the {@link ForeignKeyIndex} for this host up to date.
|
||||
if (isHostRename) {
|
||||
// Update the foreign key for the old host name and save one for the new host name.
|
||||
entitiesToUpdate.add(ForeignKeyIndex.create(existingHost, now));
|
||||
entitiesToUpdate.add(ForeignKeyIndex.create(newHost, newHost.getDeletionTime()));
|
||||
updateSuperordinateDomains(existingHost, newHost);
|
||||
}
|
||||
enqueueTasks(existingHost, newHost);
|
||||
|
||||
@@ -16,23 +16,16 @@ package google.registry.model;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import google.registry.model.annotations.DeleteAfterMigration;
|
||||
import google.registry.model.common.EntityGroupRoot;
|
||||
import google.registry.model.common.GaeUserIdConverter;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.model.contact.ContactHistory;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.domain.DomainHistory;
|
||||
import google.registry.model.domain.token.AllocationToken;
|
||||
import google.registry.model.host.Host;
|
||||
import google.registry.model.host.HostHistory;
|
||||
import google.registry.model.index.EppResourceIndex;
|
||||
import google.registry.model.index.EppResourceIndexBucket;
|
||||
import google.registry.model.index.ForeignKeyIndex;
|
||||
import google.registry.model.rde.RdeRevision;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.model.reporting.HistoryEntry;
|
||||
import google.registry.model.server.Lock;
|
||||
import google.registry.model.server.ServerSecret;
|
||||
|
||||
/** Sets of classes of the Objectify-registered entities in use throughout the model. */
|
||||
@DeleteAfterMigration
|
||||
@@ -41,25 +34,16 @@ public final class EntityClasses {
|
||||
/** Set of entity classes. */
|
||||
public static final ImmutableSet<Class<? extends ImmutableObject>> ALL_CLASSES =
|
||||
ImmutableSet.of(
|
||||
AllocationToken.class,
|
||||
Contact.class,
|
||||
ContactHistory.class,
|
||||
Domain.class,
|
||||
DomainHistory.class,
|
||||
EntityGroupRoot.class,
|
||||
EppResourceIndex.class,
|
||||
EppResourceIndexBucket.class,
|
||||
ForeignKeyIndex.ForeignKeyContactIndex.class,
|
||||
ForeignKeyIndex.ForeignKeyDomainIndex.class,
|
||||
ForeignKeyIndex.ForeignKeyHostIndex.class,
|
||||
GaeUserIdConverter.class,
|
||||
HistoryEntry.class,
|
||||
Host.class,
|
||||
HostHistory.class,
|
||||
Lock.class,
|
||||
RdeRevision.class,
|
||||
Registrar.class,
|
||||
ServerSecret.class);
|
||||
HostHistory.class);
|
||||
|
||||
private EntityClasses() {}
|
||||
}
|
||||
|
||||
@@ -140,6 +140,7 @@ public abstract class EppResource extends BackupGroupRoot implements Buildable {
|
||||
DateTime lastEppUpdateTime;
|
||||
|
||||
/** Status values associated with this resource. */
|
||||
@Ignore
|
||||
@Column(name = "statuses")
|
||||
// TODO(b/177567432): rename to "statuses" once we're off datastore.
|
||||
Set<StatusValue> status;
|
||||
|
||||
@@ -257,7 +257,7 @@ public abstract class ImmutableObject implements Cloneable {
|
||||
return (Map<String, Object>) toMapRecursive(this);
|
||||
}
|
||||
|
||||
public VKey createVKey() {
|
||||
public VKey<? extends ImmutableObject> createVKey() {
|
||||
throw new UnsupportedOperationException("VKey creation is not supported for this entity");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,13 +23,11 @@ import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Sets;
|
||||
import google.registry.model.EppResource.BuilderWithTransferData;
|
||||
import google.registry.model.EppResource.ForeignKeyedEppResource;
|
||||
import google.registry.model.EppResource.ResourceWithTransferData;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.eppcommon.StatusValue;
|
||||
import google.registry.model.eppcommon.Trid;
|
||||
import google.registry.model.index.ForeignKeyIndex;
|
||||
import google.registry.model.poll.PendingActionNotificationResponse;
|
||||
import google.registry.model.poll.PendingActionNotificationResponse.ContactPendingActionNotificationResponse;
|
||||
import google.registry.model.poll.PendingActionNotificationResponse.DomainPendingActionNotificationResponse;
|
||||
@@ -104,13 +102,6 @@ public final class ResourceTransferUtils {
|
||||
checkState(eppResource instanceof Contact || eppResource instanceof Domain);
|
||||
}
|
||||
|
||||
/** Update the relevant {@link ForeignKeyIndex} to cache the new deletion time. */
|
||||
public static <R extends EppResource> void updateForeignKeyIndexDeletionTime(R resource) {
|
||||
if (resource instanceof ForeignKeyedEppResource) {
|
||||
tm().insert(ForeignKeyIndex.create(resource, resource.getDeletionTime()));
|
||||
}
|
||||
}
|
||||
|
||||
/** If there is a transfer out, delete the server-approve entities and enqueue a poll message. */
|
||||
public static <R extends EppResource & ResourceWithTransferData>
|
||||
void handlePendingTransferOnDelete(
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
// Copyright 2021 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.model.annotations;
|
||||
|
||||
import com.googlecode.objectify.annotation.Entity;
|
||||
import google.registry.model.common.EntityGroupRoot;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Inherited;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Annotation for an Objectify {@link Entity} to indicate that it is in the cross-TLD entity group.
|
||||
*
|
||||
* <p>This means that the entity's <code>@Parent</code> field has to have the value of {@link
|
||||
* EntityGroupRoot#getCrossTldKey}.
|
||||
*/
|
||||
@DeleteAfterMigration
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.TYPE})
|
||||
@Inherited
|
||||
public @interface InCrossTld {}
|
||||
@@ -212,6 +212,9 @@ public abstract class BillingEvent extends ImmutableObject
|
||||
return nullToEmptyImmutableCopy(flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract VKey<? extends BillingEvent> createVKey();
|
||||
|
||||
/** Override Buildable.asBuilder() to give this method stronger typing. */
|
||||
@Override
|
||||
public abstract Builder<?, ?> asBuilder();
|
||||
|
||||
@@ -14,26 +14,22 @@
|
||||
|
||||
package google.registry.model.common;
|
||||
|
||||
import static google.registry.model.common.EntityGroupRoot.getCrossTldKey;
|
||||
|
||||
import com.googlecode.objectify.Key;
|
||||
import com.googlecode.objectify.annotation.Id;
|
||||
import com.googlecode.objectify.annotation.Parent;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.annotations.DeleteAfterMigration;
|
||||
import google.registry.model.annotations.InCrossTld;
|
||||
import javax.persistence.MappedSuperclass;
|
||||
import javax.persistence.Transient;
|
||||
|
||||
/** A singleton entity in Datastore. */
|
||||
/**
|
||||
* A singleton entity in the database.
|
||||
*
|
||||
* <p>This class should not be deleted after the migration, because there is still a concept of
|
||||
* singleton in SQL. We should remove the ofy @Id annotation after all of its subclass are Ofy-free.
|
||||
*/
|
||||
@DeleteAfterMigration
|
||||
@MappedSuperclass
|
||||
@InCrossTld
|
||||
public abstract class CrossTldSingleton extends ImmutableObject {
|
||||
|
||||
public static final long SINGLETON_ID = 1; // There is always exactly one of these.
|
||||
|
||||
@Id @javax.persistence.Id long id = SINGLETON_ID;
|
||||
|
||||
@Transient @Parent Key<EntityGroupRoot> parent = getCrossTldKey();
|
||||
}
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
// Copyright 2017 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.model.common;
|
||||
|
||||
import com.google.apphosting.api.ApiProxy;
|
||||
import com.googlecode.objectify.Key;
|
||||
import com.googlecode.objectify.annotation.Entity;
|
||||
import com.googlecode.objectify.annotation.Id;
|
||||
import google.registry.model.BackupGroupRoot;
|
||||
import google.registry.model.annotations.DeleteAfterMigration;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* The root key for the entity group which is known as the cross-tld entity group for historical
|
||||
* reasons.
|
||||
*
|
||||
* <p>This exists as a storage place for common configuration options and global settings that
|
||||
* aren't updated too frequently. Entities in this entity group are usually cached upon load. The
|
||||
* reason this common entity group exists is because it enables strongly consistent queries and
|
||||
* updates across this seldomly updated data. This shared entity group also helps cut down on a
|
||||
* potential ballooning in the number of entity groups enlisted in transactions.
|
||||
*
|
||||
* <p>Historically, each TLD used to have a separate namespace, and all entities for a TLD were in a
|
||||
* single EntityGroupRoot for that TLD. Hence why there was a "cross-tld" entity group -- it was the
|
||||
* entity group for the single namespace where global data applicable for all TLDs lived.
|
||||
*/
|
||||
@Entity
|
||||
@DeleteAfterMigration
|
||||
public class EntityGroupRoot extends BackupGroupRoot {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Id
|
||||
private String id;
|
||||
|
||||
/** The root key for cross-tld resources such as registrars. */
|
||||
public static @Nullable Key<EntityGroupRoot> getCrossTldKey() {
|
||||
// If we cannot get a current environment, calling Key.create() will fail. Instead we return a
|
||||
// null in cases where this key is not actually needed (for example when loading an entity from
|
||||
// SQL) to initialize an object, to avoid having to register a DatastoreEntityExtension in
|
||||
// tests.
|
||||
return ApiProxy.getCurrentEnvironment() == null
|
||||
? null
|
||||
: Key.create(EntityGroupRoot.class, "cross-tld");
|
||||
}
|
||||
}
|
||||
@@ -25,7 +25,6 @@ import static org.joda.time.DateTimeZone.UTC;
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.collect.ContiguousSet;
|
||||
import com.google.common.collect.Range;
|
||||
import com.googlecode.objectify.annotation.Embed;
|
||||
import com.googlecode.objectify.annotation.Index;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.UnsafeSerializable;
|
||||
@@ -44,7 +43,6 @@ import org.joda.time.DateTime;
|
||||
* allows it to be embeddable with no translation needed and also delays parsing of the string on
|
||||
* load until it's actually needed.
|
||||
*/
|
||||
@Embed
|
||||
@Embeddable
|
||||
public class TimeOfYear extends ImmutableObject implements UnsafeSerializable {
|
||||
|
||||
|
||||
@@ -22,10 +22,12 @@ import static google.registry.util.PasswordUtils.SALT_SUPPLIER;
|
||||
import static google.registry.util.PasswordUtils.hashPassword;
|
||||
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
|
||||
|
||||
import google.registry.model.BackupGroupRoot;
|
||||
import google.registry.model.Buildable;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Index;
|
||||
import javax.persistence.Table;
|
||||
@@ -37,10 +39,12 @@ import javax.persistence.Table;
|
||||
@Index(columnList = "gaiaId", name = "user_gaia_id_idx"),
|
||||
@Index(columnList = "emailAddress", name = "user_email_address_idx")
|
||||
})
|
||||
public class User extends ImmutableObject implements Buildable {
|
||||
public class User extends BackupGroupRoot implements Buildable {
|
||||
|
||||
/** Autogenerated unique ID of this user. */
|
||||
@Id private long id;
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
/** GAIA ID associated with the user in question. */
|
||||
@Column(nullable = false)
|
||||
@@ -63,7 +67,7 @@ public class User extends ImmutableObject implements Buildable {
|
||||
/** Randomly generated hash salt. */
|
||||
String registryLockPasswordSalt;
|
||||
|
||||
public long getId() {
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
// Copyright 2022 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.model.console;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/** Data access object for {@link User} objects to simplify saving and retrieval. */
|
||||
public class UserDao {
|
||||
|
||||
/** Retrieves the one user with this email address if it exists. */
|
||||
public static Optional<User> loadUser(String emailAddress) {
|
||||
return jpaTm()
|
||||
.transact(
|
||||
() ->
|
||||
jpaTm()
|
||||
.query("FROM User WHERE emailAddress = :emailAddress", User.class)
|
||||
.setParameter("emailAddress", emailAddress)
|
||||
.getResultStream()
|
||||
.findFirst());
|
||||
}
|
||||
|
||||
/** Saves the given user, checking that no existing user already exists with this email. */
|
||||
public static void saveUser(User user) {
|
||||
jpaTm()
|
||||
.transact(
|
||||
() -> {
|
||||
// Check for an existing user (the unique constraint protects us, but this gives a
|
||||
// nicer exception)
|
||||
Optional<User> maybeSavedUser = loadUser(user.getEmailAddress());
|
||||
if (maybeSavedUser.isPresent()) {
|
||||
User savedUser = maybeSavedUser.get();
|
||||
checkArgument(
|
||||
savedUser.getId().equals(user.getId()),
|
||||
String.format(
|
||||
"Attempted save of User with email address %s and ID %s, user with that"
|
||||
+ " email already exists with ID %s",
|
||||
user.getEmailAddress(), user.getId(), savedUser.getId()));
|
||||
}
|
||||
jpaTm().put(user);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -14,13 +14,12 @@
|
||||
|
||||
package google.registry.model.contact;
|
||||
|
||||
import com.googlecode.objectify.annotation.Embed;
|
||||
import google.registry.model.eppcommon.AuthInfo;
|
||||
import javax.persistence.Embeddable;
|
||||
import javax.xml.bind.annotation.XmlType;
|
||||
|
||||
/** A version of authInfo specifically for contacts. */
|
||||
@Embed
|
||||
@javax.persistence.Embeddable
|
||||
@Embeddable
|
||||
@XmlType(namespace = "urn:ietf:params:xml:ns:contact-1.0")
|
||||
public class ContactAuthInfo extends AuthInfo {
|
||||
public static ContactAuthInfo create(PasswordAuth pw) {
|
||||
|
||||
@@ -129,7 +129,7 @@ public class ContactBase extends EppResource implements ResourceWithTransferData
|
||||
@Index String searchName;
|
||||
|
||||
/** Contact’s voice number. Personal info; cleared by {@link Contact.Builder#wipeOut}. */
|
||||
@IgnoreSave(IfNull.class)
|
||||
@Ignore
|
||||
@Embedded
|
||||
@AttributeOverrides({
|
||||
@AttributeOverride(name = "phoneNumber", column = @Column(name = "voice_phone_number")),
|
||||
@@ -138,7 +138,7 @@ public class ContactBase extends EppResource implements ResourceWithTransferData
|
||||
ContactPhoneNumber voice;
|
||||
|
||||
/** Contact’s fax number. Personal info; cleared by {@link Contact.Builder#wipeOut}. */
|
||||
@IgnoreSave(IfNull.class)
|
||||
@Ignore
|
||||
@Embedded
|
||||
@AttributeOverrides({
|
||||
@AttributeOverride(name = "phoneNumber", column = @Column(name = "fax_phone_number")),
|
||||
@@ -151,6 +151,7 @@ public class ContactBase extends EppResource implements ResourceWithTransferData
|
||||
String email;
|
||||
|
||||
/** Authorization info (aka transfer secret) of the contact. */
|
||||
@Ignore
|
||||
@Embedded
|
||||
@AttributeOverrides({
|
||||
@AttributeOverride(name = "pw.value", column = @Column(name = "auth_info_value")),
|
||||
@@ -159,7 +160,7 @@ public class ContactBase extends EppResource implements ResourceWithTransferData
|
||||
ContactAuthInfo authInfo;
|
||||
|
||||
/** Data about any pending or past transfers on this contact. */
|
||||
ContactTransferData transferData;
|
||||
@Ignore ContactTransferData transferData;
|
||||
|
||||
/**
|
||||
* The time that this resource was last transferred.
|
||||
@@ -172,6 +173,7 @@ public class ContactBase extends EppResource implements ResourceWithTransferData
|
||||
// the wipeOut() function, so that data is not kept around for deleted contacts.
|
||||
|
||||
/** Disclosure policy. */
|
||||
@Ignore
|
||||
@Embedded
|
||||
@AttributeOverrides({
|
||||
@AttributeOverride(name = "name", column = @Column(name = "disclose_types_name")),
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
|
||||
package google.registry.model.contact;
|
||||
|
||||
import com.googlecode.objectify.annotation.Embed;
|
||||
import google.registry.model.eppcommon.PhoneNumber;
|
||||
import javax.persistence.Embeddable;
|
||||
|
||||
@@ -27,7 +26,6 @@ import javax.persistence.Embeddable;
|
||||
*
|
||||
* @see Contact
|
||||
*/
|
||||
@Embed
|
||||
@Embeddable
|
||||
public class ContactPhoneNumber extends PhoneNumber {
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@ package google.registry.model.contact;
|
||||
import static google.registry.util.CollectionUtils.nullToEmptyImmutableCopy;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.googlecode.objectify.annotation.Embed;
|
||||
import google.registry.model.Buildable;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.UnsafeSerializable;
|
||||
@@ -30,7 +29,6 @@ import javax.xml.bind.annotation.XmlAttribute;
|
||||
import javax.xml.bind.annotation.XmlType;
|
||||
|
||||
/** The "discloseType" from <a href="http://tools.ietf.org/html/rfc5733">RFC5733</a>. */
|
||||
@Embed
|
||||
@Embeddable
|
||||
@XmlType(propOrder = {"name", "org", "addr", "voice", "fax", "email"})
|
||||
public class Disclose extends ImmutableObject implements UnsafeSerializable {
|
||||
@@ -79,7 +77,6 @@ public class Disclose extends ImmutableObject implements UnsafeSerializable {
|
||||
}
|
||||
|
||||
/** The "intLocType" from <a href="http://tools.ietf.org/html/rfc5733">RFC5733</a>. */
|
||||
@Embed
|
||||
public static class PostalInfoChoice extends ImmutableObject implements Serializable {
|
||||
@XmlAttribute
|
||||
PostalInfo.Type type;
|
||||
|
||||
@@ -17,7 +17,6 @@ package google.registry.model.domain;
|
||||
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
|
||||
|
||||
import com.googlecode.objectify.Key;
|
||||
import com.googlecode.objectify.annotation.Embed;
|
||||
import com.googlecode.objectify.annotation.Ignore;
|
||||
import com.googlecode.objectify.annotation.Index;
|
||||
import google.registry.model.ImmutableObject;
|
||||
@@ -45,7 +44,6 @@ import javax.xml.bind.annotation.XmlEnumValue;
|
||||
* @see <a href="http://tools.ietf.org/html/rfc5731#section-2.2">RFC 5731 - EPP Domain Name Mapping
|
||||
* - Contact and Client Identifiers</a>
|
||||
*/
|
||||
@Embed
|
||||
@Embeddable
|
||||
public class DesignatedContact extends ImmutableObject implements UnsafeSerializable {
|
||||
|
||||
|
||||
@@ -14,12 +14,11 @@
|
||||
|
||||
package google.registry.model.domain;
|
||||
|
||||
import com.googlecode.objectify.annotation.Embed;
|
||||
import google.registry.model.eppcommon.AuthInfo;
|
||||
import javax.persistence.Embeddable;
|
||||
|
||||
/** A version of authInfo specifically for domains. */
|
||||
@Embed
|
||||
@javax.persistence.Embeddable
|
||||
@Embeddable
|
||||
public class DomainAuthInfo extends AuthInfo {
|
||||
public static DomainAuthInfo create(PasswordAuth pw) {
|
||||
DomainAuthInfo instance = new DomainAuthInfo();
|
||||
|
||||
@@ -41,7 +41,6 @@ import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableSortedSet;
|
||||
import com.google.common.collect.Ordering;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.googlecode.objectify.Key;
|
||||
import com.googlecode.objectify.annotation.Ignore;
|
||||
import com.googlecode.objectify.annotation.IgnoreSave;
|
||||
import com.googlecode.objectify.annotation.Index;
|
||||
@@ -51,7 +50,6 @@ import google.registry.flows.ResourceFlowUtils;
|
||||
import google.registry.model.EppResource;
|
||||
import google.registry.model.EppResource.ResourceWithTransferData;
|
||||
import google.registry.model.billing.BillingEvent;
|
||||
import google.registry.model.common.EntityGroupRoot;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.model.domain.launch.LaunchNotice;
|
||||
import google.registry.model.domain.rgp.GracePeriodStatus;
|
||||
@@ -60,7 +58,6 @@ import google.registry.model.domain.token.AllocationToken;
|
||||
import google.registry.model.eppcommon.StatusValue;
|
||||
import google.registry.model.host.Host;
|
||||
import google.registry.model.poll.PollMessage;
|
||||
import google.registry.model.reporting.HistoryEntry;
|
||||
import google.registry.model.tld.Registry;
|
||||
import google.registry.model.transfer.DomainTransferData;
|
||||
import google.registry.model.transfer.TransferStatus;
|
||||
@@ -139,6 +136,7 @@ public class DomainBase extends EppResource
|
||||
VKey<Contact> registrantContact;
|
||||
|
||||
/** Authorization info (aka transfer secret) of the domain. */
|
||||
@Ignore
|
||||
@Embedded
|
||||
@AttributeOverrides({
|
||||
@AttributeOverride(name = "pw.value", column = @Column(name = "auth_info_value")),
|
||||
@@ -147,13 +145,14 @@ public class DomainBase extends EppResource
|
||||
DomainAuthInfo authInfo;
|
||||
|
||||
/** Data used to construct DS records for this domain. */
|
||||
@Transient Set<DelegationSignerData> dsData;
|
||||
@Ignore @Transient Set<DelegationSignerData> dsData;
|
||||
|
||||
/**
|
||||
* The claims notice supplied when this domain was created, if there was one.
|
||||
*
|
||||
* <p>It's {@literal @}XmlTransient because it's not returned in an info response.
|
||||
*/
|
||||
@Ignore
|
||||
@Embedded
|
||||
@AttributeOverrides({
|
||||
@AttributeOverride(name = "noticeId.tcnId", column = @Column(name = "launch_notice_tcn_id")),
|
||||
@@ -217,7 +216,7 @@ public class DomainBase extends EppResource
|
||||
VKey<PollMessage.Autorenew> autorenewPollMessage;
|
||||
|
||||
/** The unexpired grace periods for this domain (some of which may not be active yet). */
|
||||
@Transient Set<GracePeriod> gracePeriods;
|
||||
@Ignore @Transient Set<GracePeriod> gracePeriods;
|
||||
|
||||
/**
|
||||
* The id of the signed mark that was used to create this domain in sunrise.
|
||||
@@ -228,7 +227,7 @@ public class DomainBase extends EppResource
|
||||
String smdId;
|
||||
|
||||
/** Data about any pending or past transfers on this domain. */
|
||||
DomainTransferData transferData;
|
||||
@Ignore DomainTransferData transferData;
|
||||
|
||||
/**
|
||||
* The time that this resource was last transferred.
|
||||
@@ -277,7 +276,7 @@ public class DomainBase extends EppResource
|
||||
@Ignore DateTime dnsRefreshRequestTime;
|
||||
|
||||
/** The {@link AllocationToken} for the package this domain is currently a part of. */
|
||||
@Nullable VKey<AllocationToken> currentPackageToken;
|
||||
@Ignore @Nullable VKey<AllocationToken> currentPackageToken;
|
||||
|
||||
/**
|
||||
* Returns the DNS refresh request time iff this domain's DNS needs refreshing, otherwise absent.
|
||||
@@ -286,15 +285,6 @@ public class DomainBase extends EppResource
|
||||
return Optional.ofNullable(dnsRefreshRequestTime);
|
||||
}
|
||||
|
||||
public static <T> VKey<T> restoreOfyFrom(Key<Domain> domainKey, VKey<T> key, Long historyId) {
|
||||
if (historyId == null) {
|
||||
// This is a legacy key (or a null key, in which case this works too)
|
||||
return VKey.restoreOfyFrom(key, EntityGroupRoot.class, "per-tld");
|
||||
} else {
|
||||
return VKey.restoreOfyFrom(key, domainKey, HistoryEntry.class, historyId);
|
||||
}
|
||||
}
|
||||
|
||||
public ImmutableSet<String> getSubordinateHosts() {
|
||||
return nullToEmptyImmutableCopy(subordinateHosts);
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import static google.registry.util.CollectionUtils.nullToEmptyImmutableCopy;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.googlecode.objectify.Key;
|
||||
import com.googlecode.objectify.annotation.EntitySubclass;
|
||||
import com.googlecode.objectify.annotation.Ignore;
|
||||
import google.registry.model.EppResource;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.domain.DomainHistory.DomainHistoryId;
|
||||
@@ -133,6 +134,7 @@ public class DomainHistory extends HistoryEntry {
|
||||
updatable = false)
|
||||
})
|
||||
// HashSet rather than ImmutableSet so that Hibernate can fill them out lazily on request
|
||||
@Ignore
|
||||
Set<DomainDsDataHistory> dsDataHistories = new HashSet<>();
|
||||
|
||||
@DoNotCompare
|
||||
@@ -153,6 +155,7 @@ public class DomainHistory extends HistoryEntry {
|
||||
updatable = false)
|
||||
})
|
||||
// HashSet rather than ImmutableSet so that Hibernate can fill them out lazily on request
|
||||
@Ignore
|
||||
Set<GracePeriodHistory> gracePeriodHistories = new HashSet<>();
|
||||
|
||||
@Override
|
||||
|
||||
@@ -19,7 +19,6 @@ import static google.registry.model.IdService.allocateId;
|
||||
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.googlecode.objectify.annotation.Embed;
|
||||
import google.registry.model.billing.BillingEvent;
|
||||
import google.registry.model.billing.BillingEvent.Recurring;
|
||||
import google.registry.model.domain.DomainHistory.DomainHistoryId;
|
||||
@@ -40,7 +39,6 @@ import org.joda.time.DateTime;
|
||||
* <p>When a grace period expires, it is lazily removed from the {@link Domain} the next time the
|
||||
* resource is loaded from Datastore.
|
||||
*/
|
||||
@Embed
|
||||
@Entity
|
||||
@Table(
|
||||
indexes = {
|
||||
|
||||
@@ -14,8 +14,6 @@
|
||||
|
||||
package google.registry.model.domain;
|
||||
|
||||
import com.googlecode.objectify.annotation.Embed;
|
||||
import com.googlecode.objectify.annotation.Ignore;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.UnsafeSerializable;
|
||||
import google.registry.model.billing.BillingEvent;
|
||||
@@ -31,7 +29,6 @@ import javax.persistence.Transient;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
/** Base class containing common fields and methods for {@link GracePeriod}. */
|
||||
@Embed
|
||||
@MappedSuperclass
|
||||
@Access(AccessType.FIELD)
|
||||
public class GracePeriodBase extends ImmutableObject implements UnsafeSerializable {
|
||||
@@ -40,7 +37,6 @@ public class GracePeriodBase extends ImmutableObject implements UnsafeSerializab
|
||||
@Transient long gracePeriodId;
|
||||
|
||||
/** Repository id for the domain which this grace period belongs to. */
|
||||
@Ignore
|
||||
@Column(nullable = false)
|
||||
String domainRepoId;
|
||||
|
||||
@@ -65,7 +61,6 @@ public class GracePeriodBase extends ImmutableObject implements UnsafeSerializab
|
||||
// NB: Would @IgnoreSave(IfNull.class), but not allowed for @Embed collections.
|
||||
@Access(AccessType.FIELD)
|
||||
@Column(name = "billing_event_id")
|
||||
@Ignore
|
||||
VKey<BillingEvent.OneTime> billingEventOneTime = null;
|
||||
|
||||
/**
|
||||
@@ -75,7 +70,6 @@ public class GracePeriodBase extends ImmutableObject implements UnsafeSerializab
|
||||
// NB: Would @IgnoreSave(IfNull.class), but not allowed for @Embed collections.
|
||||
@Access(AccessType.FIELD)
|
||||
@Column(name = "billing_recurrence_id")
|
||||
@Ignore
|
||||
VKey<BillingEvent.Recurring> billingEventRecurring = null;
|
||||
|
||||
public long getGracePeriodId() {
|
||||
|
||||
@@ -14,9 +14,9 @@
|
||||
|
||||
package google.registry.model.domain;
|
||||
|
||||
import com.googlecode.objectify.annotation.Embed;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.UnsafeSerializable;
|
||||
import javax.persistence.Embeddable;
|
||||
import javax.persistence.EnumType;
|
||||
import javax.persistence.Enumerated;
|
||||
import javax.xml.bind.annotation.XmlAttribute;
|
||||
@@ -24,8 +24,7 @@ import javax.xml.bind.annotation.XmlEnumValue;
|
||||
import javax.xml.bind.annotation.XmlValue;
|
||||
|
||||
/** The "periodType" from <a href="http://tools.ietf.org/html/rfc5731">RFC5731</a>. */
|
||||
@Embed
|
||||
@javax.persistence.Embeddable
|
||||
@Embeddable
|
||||
public class Period extends ImmutableObject implements UnsafeSerializable {
|
||||
|
||||
@Enumerated(EnumType.STRING)
|
||||
|
||||
@@ -23,12 +23,10 @@ import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
||||
import com.google.common.base.Ascii;
|
||||
import com.google.common.base.CharMatcher;
|
||||
import com.google.common.primitives.Ints;
|
||||
import com.googlecode.objectify.annotation.Embed;
|
||||
import com.googlecode.objectify.annotation.IgnoreSave;
|
||||
import com.googlecode.objectify.condition.IfNull;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.UnsafeSerializable;
|
||||
import java.util.Optional;
|
||||
import javax.persistence.Embeddable;
|
||||
import javax.persistence.Embedded;
|
||||
import javax.xml.bind.annotation.XmlAttribute;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
@@ -37,17 +35,15 @@ import javax.xml.bind.annotation.XmlValue;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
/** The claims notice id from the claims phase. */
|
||||
@Embed
|
||||
@XmlType(propOrder = {"noticeId", "expirationTime", "acceptedTime"})
|
||||
@javax.persistence.Embeddable
|
||||
@Embeddable
|
||||
public class LaunchNotice extends ImmutableObject implements UnsafeSerializable {
|
||||
|
||||
/** An empty instance to use in place of null. */
|
||||
private static final NoticeIdType EMPTY_NOTICE_ID = new NoticeIdType();
|
||||
|
||||
/** An id with a validator-id attribute. */
|
||||
@Embed
|
||||
@javax.persistence.Embeddable
|
||||
@Embeddable
|
||||
public static class NoticeIdType extends ImmutableObject implements UnsafeSerializable {
|
||||
|
||||
/**
|
||||
@@ -57,7 +53,6 @@ public class LaunchNotice extends ImmutableObject implements UnsafeSerializable
|
||||
@XmlValue String tcnId;
|
||||
|
||||
/** The identifier of the TMDB provider to use, defaulting to the TMCH. */
|
||||
@IgnoreSave(IfNull.class)
|
||||
@XmlAttribute(name = "validatorID")
|
||||
String validatorId;
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@ package google.registry.model.domain.launch;
|
||||
|
||||
import static java.util.Objects.hash;
|
||||
|
||||
import com.googlecode.objectify.annotation.Embed;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import java.util.Objects;
|
||||
import javax.xml.bind.annotation.XmlAttribute;
|
||||
@@ -47,7 +46,6 @@ import javax.xml.bind.annotation.XmlValue;
|
||||
* sets it is the one that needs to make sure the domain isn't a trademark and that the fields are
|
||||
* correct.
|
||||
*/
|
||||
@Embed
|
||||
public class LaunchPhase extends ImmutableObject {
|
||||
|
||||
/**
|
||||
|
||||
@@ -16,7 +16,6 @@ package google.registry.model.domain.secdns;
|
||||
|
||||
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
|
||||
|
||||
import com.googlecode.objectify.annotation.Embed;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.domain.secdns.DelegationSignerData.DomainDsDataId;
|
||||
import java.io.Serializable;
|
||||
@@ -37,7 +36,6 @@ import javax.xml.bind.annotation.XmlType;
|
||||
* @see <a href="http://tools.ietf.org/html/rfc4034">RFC 4034</a>
|
||||
* <p>TODO(b/177567432): Rename this class to DomainDsData.
|
||||
*/
|
||||
@Embed
|
||||
@XmlType(name = "dsData")
|
||||
@Entity
|
||||
@IdClass(DomainDsDataId.class)
|
||||
|
||||
@@ -14,8 +14,6 @@
|
||||
|
||||
package google.registry.model.domain.secdns;
|
||||
|
||||
import com.googlecode.objectify.annotation.Embed;
|
||||
import com.googlecode.objectify.annotation.Ignore;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.UnsafeSerializable;
|
||||
import javax.persistence.Access;
|
||||
@@ -29,12 +27,11 @@ import javax.xml.bind.annotation.adapters.HexBinaryAdapter;
|
||||
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
|
||||
|
||||
/** Base class for {@link DelegationSignerData} and {@link DomainDsDataHistory}. */
|
||||
@Embed
|
||||
@MappedSuperclass
|
||||
@Access(AccessType.FIELD)
|
||||
public abstract class DomainDsDataBase extends ImmutableObject implements UnsafeSerializable {
|
||||
|
||||
@Ignore @XmlTransient @Transient String domainRepoId;
|
||||
@XmlTransient @Transient String domainRepoId;
|
||||
|
||||
/** The identifier for this particular key in the domain. */
|
||||
@Transient int keyTag;
|
||||
|
||||
@@ -15,14 +15,12 @@
|
||||
package google.registry.model.domain.secdns;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.googlecode.objectify.annotation.Embed;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.eppoutput.EppResponse.ResponseExtension;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
/** The EPP secDNS extension to be returned with domain info commands. */
|
||||
@XmlRootElement(name = "infData")
|
||||
@Embed
|
||||
public class SecDnsInfoExtension extends ImmutableObject implements ResponseExtension {
|
||||
|
||||
/** Signatures for this domain. */
|
||||
|
||||
@@ -31,18 +31,11 @@ import com.google.common.collect.ImmutableMultimap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableSortedMap;
|
||||
import com.google.common.collect.Range;
|
||||
import com.googlecode.objectify.Key;
|
||||
import com.googlecode.objectify.annotation.Entity;
|
||||
import com.googlecode.objectify.annotation.Id;
|
||||
import com.googlecode.objectify.annotation.Ignore;
|
||||
import com.googlecode.objectify.annotation.Index;
|
||||
import com.googlecode.objectify.annotation.OnLoad;
|
||||
import google.registry.flows.EppException;
|
||||
import google.registry.flows.domain.DomainFlowUtils;
|
||||
import google.registry.model.BackupGroupRoot;
|
||||
import google.registry.model.Buildable;
|
||||
import google.registry.model.CreateAutoTimestamp;
|
||||
import google.registry.model.annotations.ReportedOn;
|
||||
import google.registry.model.billing.BillingEvent.RenewalPriceBehavior;
|
||||
import google.registry.model.common.TimedTransitionProperty;
|
||||
import google.registry.model.reporting.HistoryEntry;
|
||||
@@ -55,27 +48,23 @@ import javax.annotation.Nullable;
|
||||
import javax.persistence.AttributeOverride;
|
||||
import javax.persistence.AttributeOverrides;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.EnumType;
|
||||
import javax.persistence.Enumerated;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Index;
|
||||
import javax.persistence.Table;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
/** An entity representing an allocation token. */
|
||||
@ReportedOn
|
||||
@Entity
|
||||
@WithStringVKey
|
||||
@javax.persistence.Entity
|
||||
@WithStringVKey(compositeKey = true)
|
||||
@Table(
|
||||
indexes = {
|
||||
@javax.persistence.Index(
|
||||
columnList = "token",
|
||||
name = "allocation_token_token_idx",
|
||||
unique = true),
|
||||
@javax.persistence.Index(
|
||||
columnList = "domainName",
|
||||
name = "allocation_token_domain_name_idx"),
|
||||
@javax.persistence.Index(columnList = "tokenType"),
|
||||
@javax.persistence.Index(columnList = "redemption_domain_repo_id")
|
||||
@Index(columnList = "token", name = "allocation_token_token_idx", unique = true),
|
||||
@Index(columnList = "domainName", name = "allocation_token_domain_name_idx"),
|
||||
@Index(columnList = "tokenType"),
|
||||
@Index(columnList = "redemption_domain_repo_id")
|
||||
})
|
||||
public class AllocationToken extends BackupGroupRoot implements Buildable {
|
||||
|
||||
@@ -157,11 +146,10 @@ public class AllocationToken extends BackupGroupRoot implements Buildable {
|
||||
}
|
||||
|
||||
/** The allocation token string. */
|
||||
@javax.persistence.Id @Id String token;
|
||||
@Id String token;
|
||||
|
||||
/** The key of the history entry for which the token was used. Null if not yet used. */
|
||||
@Nullable
|
||||
@Index
|
||||
@AttributeOverrides({
|
||||
@AttributeOverride(name = "repoId", column = @Column(name = "redemption_domain_repo_id")),
|
||||
@AttributeOverride(
|
||||
@@ -171,10 +159,10 @@ public class AllocationToken extends BackupGroupRoot implements Buildable {
|
||||
DomainHistoryVKey redemptionHistoryEntry;
|
||||
|
||||
/** The fully-qualified domain name that this token is limited to, if any. */
|
||||
@Nullable @Index String domainName;
|
||||
@Nullable String domainName;
|
||||
|
||||
/** When this token was created. */
|
||||
@Ignore CreateAutoTimestamp creationTime = CreateAutoTimestamp.create(null);
|
||||
CreateAutoTimestamp creationTime = CreateAutoTimestamp.create(null);
|
||||
|
||||
/** Allowed registrar client IDs for this token, or null if all registrars are allowed. */
|
||||
@Column(name = "allowedRegistrarIds")
|
||||
@@ -203,21 +191,12 @@ public class AllocationToken extends BackupGroupRoot implements Buildable {
|
||||
|
||||
@Enumerated(EnumType.STRING)
|
||||
@Column(name = "renewalPriceBehavior", nullable = false)
|
||||
@Ignore
|
||||
RenewalPriceBehavior renewalPriceBehavior = RenewalPriceBehavior.DEFAULT;
|
||||
|
||||
@Enumerated(EnumType.STRING)
|
||||
@Column(nullable = false)
|
||||
RegistrationBehavior registrationBehavior = RegistrationBehavior.DEFAULT;
|
||||
|
||||
// TODO: Remove onLoad once all allocation tokens are migrated to have a discountYears of 1.
|
||||
@OnLoad
|
||||
void onLoad() {
|
||||
if (discountYears == 0) {
|
||||
discountYears = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Promotional token validity periods.
|
||||
*
|
||||
@@ -296,7 +275,7 @@ public class AllocationToken extends BackupGroupRoot implements Buildable {
|
||||
throw new IllegalArgumentException(
|
||||
String.format("%s tokens are not stored in the database", getTokenBehavior()));
|
||||
}
|
||||
return VKey.create(AllocationToken.class, getToken(), Key.create(this));
|
||||
return VKey.createSql(AllocationToken.class, getToken());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -330,7 +309,8 @@ public class AllocationToken extends BackupGroupRoot implements Buildable {
|
||||
"Redemption history entry can only be specified for SINGLE_USE tokens");
|
||||
checkArgument(
|
||||
getInstance().tokenType != TokenType.PACKAGE
|
||||
|| getInstance().allowedClientIds.size() == 1,
|
||||
|| (getInstance().allowedClientIds != null
|
||||
&& getInstance().allowedClientIds.size() == 1),
|
||||
"PACKAGE tokens must have exactly one allowed client registrar");
|
||||
checkArgument(
|
||||
getInstance().discountFraction > 0 || !getInstance().discountPremiums,
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
|
||||
package google.registry.model.eppcommon;
|
||||
|
||||
import com.googlecode.objectify.annotation.Embed;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.UnsafeSerializable;
|
||||
import javax.persistence.Embeddable;
|
||||
@@ -45,7 +44,6 @@ public abstract class AuthInfo extends ImmutableObject implements UnsafeSerializ
|
||||
}
|
||||
|
||||
/** The "pwAuthInfoType" complex type. */
|
||||
@Embed
|
||||
@XmlType(namespace = "urn:ietf:params:xml:ns:eppcom-1.0")
|
||||
@Embeddable
|
||||
public static class PasswordAuth extends ImmutableObject implements UnsafeSerializable {
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
|
||||
package google.registry.model.eppcommon;
|
||||
|
||||
import com.googlecode.objectify.annotation.Embed;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import java.io.Serializable;
|
||||
import javax.persistence.Embeddable;
|
||||
@@ -26,7 +25,6 @@ import javax.xml.bind.annotation.XmlTransient;
|
||||
* <p>When placed in a field "foo", this will correctly unmarshal from both {@code <foo/>} and
|
||||
* {@code <foo></foo>}, and will unmarshal always to {@code <foo/>}.
|
||||
*/
|
||||
@Embed
|
||||
@Embeddable
|
||||
public class PresenceMarker extends ImmutableObject implements Serializable {
|
||||
@XmlTransient
|
||||
|
||||
@@ -16,11 +16,11 @@ package google.registry.model.eppcommon;
|
||||
|
||||
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
|
||||
|
||||
import com.googlecode.objectify.annotation.Embed;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.UnsafeSerializable;
|
||||
import java.util.Optional;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.persistence.Embeddable;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlType;
|
||||
|
||||
@@ -30,9 +30,8 @@ import javax.xml.bind.annotation.XmlType;
|
||||
* is formed using the {@code clTRID} associated with the command if supplied by the client and a
|
||||
* {@code svTRID} (server transaction identifier) that is assigned by and unique to the server."
|
||||
*/
|
||||
@Embed
|
||||
@XmlType(propOrder = {"clientTransactionId", "serverTransactionId"})
|
||||
@javax.persistence.Embeddable
|
||||
@Embeddable
|
||||
public class Trid extends ImmutableObject implements UnsafeSerializable {
|
||||
|
||||
/** The server transaction id. */
|
||||
|
||||
@@ -19,10 +19,8 @@ import static com.google.common.collect.ImmutableMap.toImmutableMap;
|
||||
import static com.google.common.collect.ImmutableSet.toImmutableSet;
|
||||
import static google.registry.config.RegistryConfig.getEppResourceCachingDuration;
|
||||
import static google.registry.config.RegistryConfig.getEppResourceMaxCachedEntries;
|
||||
import static google.registry.model.ofy.ObjectifyService.auditedOfy;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.replicaJpaTm;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.util.CollectionUtils.entriesToImmutableMap;
|
||||
import static google.registry.util.TypeUtils.instantiate;
|
||||
|
||||
@@ -36,17 +34,10 @@ import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Multimaps;
|
||||
import com.google.common.collect.Streams;
|
||||
import com.googlecode.objectify.Key;
|
||||
import com.googlecode.objectify.annotation.Entity;
|
||||
import com.googlecode.objectify.annotation.Id;
|
||||
import com.googlecode.objectify.annotation.Index;
|
||||
import google.registry.config.RegistryConfig;
|
||||
import google.registry.model.BackupGroupRoot;
|
||||
import google.registry.model.CacheUtils;
|
||||
import google.registry.model.CacheUtils.AppEngineEnvironmentCacheLoader;
|
||||
import google.registry.model.EppResource;
|
||||
import google.registry.model.annotations.DeleteAfterMigration;
|
||||
import google.registry.model.annotations.ReportedOn;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.host.Host;
|
||||
@@ -67,22 +58,15 @@ import org.joda.time.DateTime;
|
||||
* the foreign key string. The instance is never deleted, but it is updated if a newer entity
|
||||
* becomes the active entity.
|
||||
*/
|
||||
@DeleteAfterMigration
|
||||
public abstract class ForeignKeyIndex<E extends EppResource> extends BackupGroupRoot {
|
||||
|
||||
/** The {@link ForeignKeyIndex} type for {@link Contact} entities. */
|
||||
@ReportedOn
|
||||
@Entity
|
||||
public static class ForeignKeyContactIndex extends ForeignKeyIndex<Contact> {}
|
||||
|
||||
/** The {@link ForeignKeyIndex} type for {@link Domain} entities. */
|
||||
@ReportedOn
|
||||
@Entity
|
||||
public static class ForeignKeyDomainIndex extends ForeignKeyIndex<Domain> {}
|
||||
|
||||
/** The {@link ForeignKeyIndex} type for {@link Host} entities. */
|
||||
@ReportedOn
|
||||
@Entity
|
||||
public static class ForeignKeyHostIndex extends ForeignKeyIndex<Host> {}
|
||||
|
||||
private static final ImmutableBiMap<
|
||||
@@ -100,23 +84,18 @@ public abstract class ForeignKeyIndex<E extends EppResource> extends BackupGroup
|
||||
Domain.class, "fullyQualifiedDomainName",
|
||||
Host.class, "fullyQualifiedHostName");
|
||||
|
||||
@Id String foreignKey;
|
||||
String foreignKey;
|
||||
|
||||
/**
|
||||
* The deletion time of this {@link ForeignKeyIndex}.
|
||||
*
|
||||
* <p>This will generally be equal to the deletion time of {@link #topReference}. However, in the
|
||||
* <p>This will generally be equal to the deletion time of {@link #reference}. However, in the
|
||||
* case of a {@link Host} that was renamed, this field will hold the time of the rename.
|
||||
*/
|
||||
@Index DateTime deletionTime;
|
||||
DateTime deletionTime;
|
||||
|
||||
/**
|
||||
* The referenced resource.
|
||||
*
|
||||
* <p>This field holds a key to the only referenced resource. It is named "topReference" for
|
||||
* historical reasons.
|
||||
*/
|
||||
VKey<E> topReference;
|
||||
/** The referenced resource. */
|
||||
VKey<E> reference;
|
||||
|
||||
public String getForeignKey() {
|
||||
return foreignKey;
|
||||
@@ -127,7 +106,7 @@ public abstract class ForeignKeyIndex<E extends EppResource> extends BackupGroup
|
||||
}
|
||||
|
||||
public VKey<E> getResourceKey() {
|
||||
return topReference;
|
||||
return reference;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -137,26 +116,19 @@ public abstract class ForeignKeyIndex<E extends EppResource> extends BackupGroup
|
||||
}
|
||||
|
||||
/** Create a {@link ForeignKeyIndex} instance for a resource, expiring at a specified time. */
|
||||
public static <E extends EppResource> ForeignKeyIndex<E> create(
|
||||
@SuppressWarnings("unchecked")
|
||||
private static <E extends EppResource> ForeignKeyIndex<E> create(
|
||||
E resource, DateTime deletionTime) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Class<E> resourceClass = (Class<E>) resource.getClass();
|
||||
ForeignKeyIndex<E> instance = instantiate(mapToFkiClass(resourceClass));
|
||||
instance.topReference = (VKey<E>) resource.createVKey();
|
||||
instance.reference = (VKey<E>) resource.createVKey();
|
||||
instance.foreignKey = resource.getForeignKey();
|
||||
instance.deletionTime = deletionTime;
|
||||
return instance;
|
||||
}
|
||||
|
||||
/** Create a {@link ForeignKeyIndex} key for a resource. */
|
||||
public static <E extends EppResource> Key<ForeignKeyIndex<E>> createKey(E resource) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Class<E> resourceClass = (Class<E>) resource.getClass();
|
||||
return Key.create(mapToFkiClass(resourceClass), resource.getForeignKey());
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a {@link Key} to an {@link EppResource} from Datastore by foreign key.
|
||||
* Loads a {@link VKey} to an {@link EppResource} from the database by foreign key.
|
||||
*
|
||||
* <p>Returns null if no foreign key index with this foreign key was ever created, or if the most
|
||||
* recently created foreign key index was deleted before time "now". This method does not actually
|
||||
@@ -172,7 +144,7 @@ public abstract class ForeignKeyIndex<E extends EppResource> extends BackupGroup
|
||||
public static <E extends EppResource> VKey<E> loadAndGetKey(
|
||||
Class<E> clazz, String foreignKey, DateTime now) {
|
||||
ForeignKeyIndex<E> index = load(clazz, foreignKey, now);
|
||||
return (index == null) ? null : index.getResourceKey();
|
||||
return index == null ? null : index.getResourceKey();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -196,7 +168,7 @@ public abstract class ForeignKeyIndex<E extends EppResource> extends BackupGroup
|
||||
*/
|
||||
public static <E extends EppResource> ImmutableMap<String, ForeignKeyIndex<E>> load(
|
||||
Class<E> clazz, Collection<String> foreignKeys, final DateTime now) {
|
||||
return loadIndexesFromStore(clazz, foreignKeys, true, false).entrySet().stream()
|
||||
return loadIndexesFromStore(clazz, foreignKeys, false).entrySet().stream()
|
||||
.filter(e -> now.isBefore(e.getValue().getDeletionTime()))
|
||||
.collect(entriesToImmutableMap());
|
||||
}
|
||||
@@ -206,55 +178,37 @@ public abstract class ForeignKeyIndex<E extends EppResource> extends BackupGroup
|
||||
* keys, regardless of whether or not they have been soft-deleted.
|
||||
*
|
||||
* <p>Used by both the cached (w/o deletion check) and the non-cached (with deletion check) calls.
|
||||
*
|
||||
* <p>Note that in the cached case, we wish to run this outside of any transaction because we may
|
||||
* be loading many entities, going over the Datastore limit on the number of enrolled entity
|
||||
* groups per transaction (25). If we require consistency, however, we must use a transaction.
|
||||
*
|
||||
* @param inTransaction whether or not to use an Objectify transaction
|
||||
*/
|
||||
private static <E extends EppResource>
|
||||
ImmutableMap<String, ForeignKeyIndex<E>> loadIndexesFromStore(
|
||||
Class<E> clazz,
|
||||
Collection<String> foreignKeys,
|
||||
boolean inTransaction,
|
||||
boolean useReplicaJpaTm) {
|
||||
if (tm().isOfy()) {
|
||||
Class<ForeignKeyIndex<E>> fkiClass = mapToFkiClass(clazz);
|
||||
return ImmutableMap.copyOf(
|
||||
inTransaction
|
||||
? auditedOfy().load().type(fkiClass).ids(foreignKeys)
|
||||
: tm().doTransactionless(() -> auditedOfy().load().type(fkiClass).ids(foreignKeys)));
|
||||
} else {
|
||||
String property = RESOURCE_CLASS_TO_FKI_PROPERTY.get(clazz);
|
||||
JpaTransactionManager jpaTmToUse = useReplicaJpaTm ? replicaJpaTm() : jpaTm();
|
||||
ImmutableList<ForeignKeyIndex<E>> indexes =
|
||||
jpaTmToUse.transact(
|
||||
() ->
|
||||
jpaTmToUse
|
||||
.criteriaQuery(
|
||||
CriteriaQueryBuilder.create(clazz)
|
||||
.whereFieldIsIn(property, foreignKeys)
|
||||
.build())
|
||||
.getResultStream()
|
||||
.map(e -> ForeignKeyIndex.create(e, e.getDeletionTime()))
|
||||
.collect(toImmutableList()));
|
||||
// We need to find and return the entities with the maximum deletionTime for each foreign key.
|
||||
return Multimaps.index(indexes, ForeignKeyIndex::getForeignKey).asMap().entrySet().stream()
|
||||
.map(
|
||||
entry ->
|
||||
Maps.immutableEntry(
|
||||
entry.getKey(),
|
||||
entry.getValue().stream()
|
||||
.max(Comparator.comparing(ForeignKeyIndex::getDeletionTime))
|
||||
.get()))
|
||||
.collect(entriesToImmutableMap());
|
||||
}
|
||||
Class<E> clazz, Collection<String> foreignKeys, boolean useReplicaJpaTm) {
|
||||
String property = RESOURCE_CLASS_TO_FKI_PROPERTY.get(clazz);
|
||||
JpaTransactionManager jpaTmToUse = useReplicaJpaTm ? replicaJpaTm() : jpaTm();
|
||||
ImmutableList<ForeignKeyIndex<E>> indexes =
|
||||
jpaTmToUse.transact(
|
||||
() ->
|
||||
jpaTmToUse
|
||||
.criteriaQuery(
|
||||
CriteriaQueryBuilder.create(clazz)
|
||||
.whereFieldIsIn(property, foreignKeys)
|
||||
.build())
|
||||
.getResultStream()
|
||||
.map(e -> create(e, e.getDeletionTime()))
|
||||
.collect(toImmutableList()));
|
||||
// We need to find and return the entities with the maximum deletionTime for each foreign key.
|
||||
return Multimaps.index(indexes, ForeignKeyIndex::getForeignKey).asMap().entrySet().stream()
|
||||
.map(
|
||||
entry ->
|
||||
Maps.immutableEntry(
|
||||
entry.getKey(),
|
||||
entry.getValue().stream()
|
||||
.max(Comparator.comparing(ForeignKeyIndex::getDeletionTime))
|
||||
.get()))
|
||||
.collect(entriesToImmutableMap());
|
||||
}
|
||||
|
||||
static final CacheLoader<VKey<ForeignKeyIndex<?>>, Optional<ForeignKeyIndex<?>>> CACHE_LOADER =
|
||||
new AppEngineEnvironmentCacheLoader<
|
||||
VKey<ForeignKeyIndex<?>>, Optional<ForeignKeyIndex<?>>>() {
|
||||
new CacheLoader<VKey<ForeignKeyIndex<?>>, Optional<ForeignKeyIndex<?>>>() {
|
||||
|
||||
@Override
|
||||
public Optional<ForeignKeyIndex<?>> load(VKey<ForeignKeyIndex<?>> key) {
|
||||
@@ -263,7 +217,6 @@ public abstract class ForeignKeyIndex<E extends EppResource> extends BackupGroup
|
||||
loadIndexesFromStore(
|
||||
RESOURCE_CLASS_TO_FKI_CLASS.inverse().get(key.getKind()),
|
||||
ImmutableSet.of(foreignKey),
|
||||
false,
|
||||
true)
|
||||
.get(foreignKey));
|
||||
}
|
||||
@@ -280,7 +233,7 @@ public abstract class ForeignKeyIndex<E extends EppResource> extends BackupGroup
|
||||
Streams.stream(keys).map(v -> v.getSqlKey().toString()).collect(toImmutableSet());
|
||||
ImmutableSet<VKey<ForeignKeyIndex<?>>> typedKeys = ImmutableSet.copyOf(keys);
|
||||
ImmutableMap<String, ? extends ForeignKeyIndex<? extends EppResource>> existingFkis =
|
||||
loadIndexesFromStore(resourceClass, foreignKeys, false, true);
|
||||
loadIndexesFromStore(resourceClass, foreignKeys, true);
|
||||
// ofy omits keys that don't have values in Datastore, so re-add them in
|
||||
// here with Optional.empty() values.
|
||||
return Maps.asMap(
|
||||
@@ -333,14 +286,14 @@ public abstract class ForeignKeyIndex<E extends EppResource> extends BackupGroup
|
||||
public static <E extends EppResource> ImmutableMap<String, ForeignKeyIndex<E>> loadCached(
|
||||
Class<E> clazz, Collection<String> foreignKeys, final DateTime now) {
|
||||
if (!RegistryConfig.isEppResourceCachingEnabled()) {
|
||||
return tm().doTransactionless(() -> load(clazz, foreignKeys, now));
|
||||
return load(clazz, foreignKeys, now);
|
||||
}
|
||||
Class<? extends ForeignKeyIndex<?>> fkiClass = mapToFkiClass(clazz);
|
||||
// Safe to cast VKey<FKI<E>> to VKey<FKI<?>>
|
||||
@SuppressWarnings("unchecked")
|
||||
ImmutableList<VKey<ForeignKeyIndex<?>>> fkiVKeys =
|
||||
foreignKeys.stream()
|
||||
.map(fk -> (VKey<ForeignKeyIndex<?>>) VKey.create(fkiClass, fk))
|
||||
.map(fk -> (VKey<ForeignKeyIndex<?>>) VKey.createSql(fkiClass, fk))
|
||||
.collect(toImmutableList());
|
||||
// This cast is safe because when we loaded ForeignKeyIndexes above we used type clazz, which
|
||||
// is scoped to E.
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
package google.registry.model.poll;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.googlecode.objectify.annotation.Embed;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.UnsafeSerializable;
|
||||
import google.registry.model.eppcommon.Trid;
|
||||
@@ -36,7 +35,6 @@ public class PendingActionNotificationResponse extends ImmutableObject
|
||||
implements ResponseData, UnsafeSerializable {
|
||||
|
||||
/** The inner name type that contains a name and the result boolean. */
|
||||
@Embed
|
||||
@Embeddable
|
||||
static class NameOrId extends ImmutableObject implements UnsafeSerializable {
|
||||
@XmlValue
|
||||
@@ -80,7 +78,6 @@ public class PendingActionNotificationResponse extends ImmutableObject
|
||||
}
|
||||
|
||||
/** An adapter to output the XML in response to resolving a pending command on a domain. */
|
||||
@Embed
|
||||
@XmlRootElement(name = "panData", namespace = "urn:ietf:params:xml:ns:domain-1.0")
|
||||
@XmlType(
|
||||
propOrder = {"name", "trid", "processedDate"},
|
||||
@@ -105,7 +102,6 @@ public class PendingActionNotificationResponse extends ImmutableObject
|
||||
}
|
||||
|
||||
/** An adapter to output the XML in response to resolving a pending command on a contact. */
|
||||
@Embed
|
||||
@XmlRootElement(name = "panData", namespace = "urn:ietf:params:xml:ns:contact-1.0")
|
||||
@XmlType(
|
||||
propOrder = {"id", "trid", "processedDate"},
|
||||
@@ -130,7 +126,6 @@ public class PendingActionNotificationResponse extends ImmutableObject
|
||||
}
|
||||
|
||||
/** An adapter to output the XML in response to resolving a pending command on a host. */
|
||||
@Embed
|
||||
@XmlRootElement(name = "panData", namespace = "urn:ietf:params:xml:ns:domain-1.0")
|
||||
@XmlType(
|
||||
propOrder = {"name", "trid", "processedDate"},
|
||||
|
||||
@@ -215,6 +215,9 @@ public abstract class PollMessage extends ImmutableObject
|
||||
return domainRepoId != null ? Type.DOMAIN : contactRepoId != null ? Type.CONTACT : Type.HOST;
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract VKey<? extends PollMessage> createVKey();
|
||||
|
||||
public abstract ImmutableList<ResponseData> getResponseData();
|
||||
|
||||
/** Override Buildable.asBuilder() to give this method stronger typing. */
|
||||
|
||||
@@ -19,10 +19,6 @@ import static google.registry.model.rde.RdeNamingUtils.makePartialName;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
|
||||
import com.google.common.base.VerifyException;
|
||||
import com.googlecode.objectify.Key;
|
||||
import com.googlecode.objectify.annotation.Entity;
|
||||
import com.googlecode.objectify.annotation.Id;
|
||||
import com.googlecode.objectify.annotation.Ignore;
|
||||
import google.registry.model.BackupGroupRoot;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.rde.RdeRevision.RdeRevisionId;
|
||||
@@ -32,10 +28,11 @@ import java.io.Serializable;
|
||||
import java.util.Optional;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Convert;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.EnumType;
|
||||
import javax.persistence.Enumerated;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.IdClass;
|
||||
import javax.persistence.Transient;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.LocalDate;
|
||||
|
||||
@@ -47,18 +44,14 @@ import org.joda.time.LocalDate;
|
||||
* flag is included in the generated XML.
|
||||
*/
|
||||
@Entity
|
||||
@javax.persistence.Entity
|
||||
@IdClass(RdeRevisionId.class)
|
||||
public final class RdeRevision extends BackupGroupRoot {
|
||||
|
||||
/** String triplet of tld, date, and mode, e.g. {@code soy_2015-09-01_full}. */
|
||||
@Id @Transient String id;
|
||||
@Id String tld;
|
||||
|
||||
@javax.persistence.Id @Ignore String tld;
|
||||
@Id LocalDate date;
|
||||
|
||||
@javax.persistence.Id @Ignore LocalDate date;
|
||||
|
||||
@javax.persistence.Id @Ignore RdeMode mode;
|
||||
@Id RdeMode mode;
|
||||
|
||||
/**
|
||||
* Number of last revision successfully staged to GCS.
|
||||
@@ -71,10 +64,8 @@ public final class RdeRevision extends BackupGroupRoot {
|
||||
/** Hibernate requires an empty constructor. */
|
||||
private RdeRevision() {}
|
||||
|
||||
public static RdeRevision create(
|
||||
String id, String tld, LocalDate date, RdeMode mode, int revision) {
|
||||
public static RdeRevision create(String tld, LocalDate date, RdeMode mode, int revision) {
|
||||
RdeRevision instance = new RdeRevision();
|
||||
instance.id = id;
|
||||
instance.tld = tld;
|
||||
instance.date = date;
|
||||
instance.mode = mode;
|
||||
@@ -92,12 +83,9 @@ public final class RdeRevision extends BackupGroupRoot {
|
||||
* @return {@code 0} for first deposit generation and {@code >0} for resends
|
||||
*/
|
||||
public static int getNextRevision(String tld, DateTime date, RdeMode mode) {
|
||||
String id = makePartialName(tld, date, mode);
|
||||
RdeRevisionId sqlKey = RdeRevisionId.create(tld, date.toLocalDate(), mode);
|
||||
Key<RdeRevision> ofyKey = Key.create(RdeRevision.class, id);
|
||||
Optional<RdeRevision> revisionOptional =
|
||||
tm().transact(
|
||||
() -> tm().loadByKeyIfPresent(VKey.create(RdeRevision.class, sqlKey, ofyKey)));
|
||||
tm().transact(() -> tm().loadByKeyIfPresent(VKey.createSql(RdeRevision.class, sqlKey)));
|
||||
return revisionOptional.map(rdeRevision -> rdeRevision.revision + 1).orElse(0);
|
||||
}
|
||||
|
||||
@@ -121,12 +109,10 @@ public final class RdeRevision extends BackupGroupRoot {
|
||||
*/
|
||||
public static void saveRevision(String tld, DateTime date, RdeMode mode, int revision) {
|
||||
checkArgument(revision >= 0, "Negative revision: %s", revision);
|
||||
String triplet = makePartialName(tld, date, mode);
|
||||
tm().assertInTransaction();
|
||||
RdeRevisionId sqlKey = RdeRevisionId.create(tld, date.toLocalDate(), mode);
|
||||
Key<RdeRevision> ofyKey = Key.create(RdeRevision.class, triplet);
|
||||
Optional<RdeRevision> revisionOptional =
|
||||
tm().loadByKeyIfPresent(VKey.create(RdeRevision.class, sqlKey, ofyKey));
|
||||
tm().loadByKeyIfPresent(VKey.createSql(RdeRevision.class, sqlKey));
|
||||
if (revision == 0) {
|
||||
revisionOptional.ifPresent(
|
||||
rdeRevision -> {
|
||||
@@ -139,7 +125,7 @@ public final class RdeRevision extends BackupGroupRoot {
|
||||
checkArgument(
|
||||
revisionOptional.isPresent(),
|
||||
"Couldn't find existing RDE revision %s when trying to save new revision %s",
|
||||
triplet,
|
||||
makePartialName(tld, date, mode),
|
||||
revision);
|
||||
checkArgument(
|
||||
revisionOptional.get().revision == revision - 1,
|
||||
@@ -147,7 +133,7 @@ public final class RdeRevision extends BackupGroupRoot {
|
||||
revision - 1,
|
||||
revisionOptional.get());
|
||||
}
|
||||
RdeRevision object = RdeRevision.create(triplet, tld, date.toLocalDate(), mode, revision);
|
||||
RdeRevision object = create(tld, date.toLocalDate(), mode, revision);
|
||||
tm().put(object);
|
||||
}
|
||||
|
||||
|
||||
@@ -26,8 +26,6 @@ import static com.google.common.collect.Sets.immutableEnumSet;
|
||||
import static com.google.common.io.BaseEncoding.base64;
|
||||
import static google.registry.config.RegistryConfig.getDefaultRegistrarWhoisServer;
|
||||
import static google.registry.model.CacheUtils.memoizeWithShortExpiration;
|
||||
import static google.registry.model.common.EntityGroupRoot.getCrossTldKey;
|
||||
import static google.registry.model.ofy.ObjectifyService.auditedOfy;
|
||||
import static google.registry.model.tld.Registries.assertTldsExist;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
@@ -44,7 +42,6 @@ import static java.util.function.Predicate.isEqual;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
@@ -55,12 +52,6 @@ import com.google.common.collect.Range;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.common.collect.Streams;
|
||||
import com.google.re2j.Pattern;
|
||||
import com.googlecode.objectify.Key;
|
||||
import com.googlecode.objectify.annotation.Entity;
|
||||
import com.googlecode.objectify.annotation.Id;
|
||||
import com.googlecode.objectify.annotation.Ignore;
|
||||
import com.googlecode.objectify.annotation.Index;
|
||||
import com.googlecode.objectify.annotation.Parent;
|
||||
import google.registry.model.Buildable;
|
||||
import google.registry.model.CreateAutoTimestamp;
|
||||
import google.registry.model.ImmutableObject;
|
||||
@@ -68,9 +59,6 @@ import google.registry.model.JsonMapBuilder;
|
||||
import google.registry.model.Jsonifiable;
|
||||
import google.registry.model.UnsafeSerializable;
|
||||
import google.registry.model.UpdateAutoTimestamp;
|
||||
import google.registry.model.annotations.InCrossTld;
|
||||
import google.registry.model.annotations.ReportedOn;
|
||||
import google.registry.model.common.EntityGroupRoot;
|
||||
import google.registry.model.tld.Registry;
|
||||
import google.registry.model.tld.Registry.TldType;
|
||||
import google.registry.persistence.VKey;
|
||||
@@ -83,6 +71,7 @@ import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.Supplier;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.mail.internet.AddressException;
|
||||
import javax.mail.internet.InternetAddress;
|
||||
@@ -90,25 +79,22 @@ import javax.persistence.AttributeOverride;
|
||||
import javax.persistence.AttributeOverrides;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Embedded;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.EnumType;
|
||||
import javax.persistence.Enumerated;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Index;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Transient;
|
||||
import org.joda.money.CurrencyUnit;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
/** Information about a registrar. */
|
||||
@ReportedOn
|
||||
@Entity
|
||||
@javax.persistence.Entity
|
||||
@Table(
|
||||
indexes = {
|
||||
@javax.persistence.Index(columnList = "registrarName", name = "registrar_name_idx"),
|
||||
@javax.persistence.Index(
|
||||
columnList = "ianaIdentifier",
|
||||
name = "registrar_iana_identifier_idx"),
|
||||
@Index(columnList = "registrarName", name = "registrar_name_idx"),
|
||||
@Index(columnList = "ianaIdentifier", name = "registrar_iana_identifier_idx"),
|
||||
})
|
||||
@InCrossTld
|
||||
public class Registrar extends ImmutableObject
|
||||
implements Buildable, Jsonifiable, UnsafeSerializable {
|
||||
|
||||
@@ -197,7 +183,7 @@ public class Registrar extends ImmutableObject
|
||||
|
||||
/** The states in which a {@link Registrar} is considered {@link #isLive live}. */
|
||||
private static final ImmutableSet<State> LIVE_STATES =
|
||||
Sets.immutableEnumSet(State.ACTIVE, State.SUSPENDED);
|
||||
immutableEnumSet(State.ACTIVE, State.SUSPENDED);
|
||||
|
||||
/**
|
||||
* The types for which a {@link Registrar} should be included in WHOIS and RDAP output. We exclude
|
||||
@@ -213,18 +199,9 @@ public class Registrar extends ImmutableObject
|
||||
private static final Comparator<RegistrarPoc> CONTACT_EMAIL_COMPARATOR =
|
||||
comparing(RegistrarPoc::getEmailAddress, String::compareTo);
|
||||
|
||||
/**
|
||||
* A caching {@link Supplier} of a registrarId to {@link Registrar} map.
|
||||
*
|
||||
* <p>The supplier's get() method enters a transactionless context briefly to avoid enrolling the
|
||||
* query inside an unrelated client-affecting transaction.
|
||||
*/
|
||||
/** A caching {@link Supplier} of a registrarId to {@link Registrar} map. */
|
||||
private static final Supplier<ImmutableMap<String, Registrar>> CACHE_BY_REGISTRAR_ID =
|
||||
memoizeWithShortExpiration(
|
||||
() ->
|
||||
tm().doTransactionless(() -> Maps.uniqueIndex(loadAll(), Registrar::getRegistrarId)));
|
||||
|
||||
@Parent @Transient Key<EntityGroupRoot> parent = getCrossTldKey();
|
||||
memoizeWithShortExpiration(() -> Maps.uniqueIndex(loadAll(), Registrar::getRegistrarId));
|
||||
|
||||
/**
|
||||
* Unique registrar client id. Must conform to "clIDType" as defined in RFC5730.
|
||||
@@ -233,7 +210,6 @@ public class Registrar extends ImmutableObject
|
||||
* <p>TODO(b/177567432): Rename this field to registrarId.
|
||||
*/
|
||||
@Id
|
||||
@javax.persistence.Id
|
||||
@Column(name = "registrarId", nullable = false)
|
||||
String clientIdentifier;
|
||||
|
||||
@@ -248,7 +224,6 @@ public class Registrar extends ImmutableObject
|
||||
* @see <a href="http://www.icann.org/registrar-reports/accredited-list.html">ICANN-Accredited
|
||||
* Registrars</a>
|
||||
*/
|
||||
@Index
|
||||
@Column(nullable = false)
|
||||
String registrarName;
|
||||
|
||||
@@ -313,7 +288,6 @@ public class Registrar extends ImmutableObject
|
||||
* Localized {@link RegistrarAddress} for this registrar. Contents can be represented in
|
||||
* unrestricted UTF-8.
|
||||
*/
|
||||
@Ignore
|
||||
@Embedded
|
||||
@AttributeOverrides({
|
||||
@AttributeOverride(
|
||||
@@ -338,7 +312,6 @@ public class Registrar extends ImmutableObject
|
||||
* Internationalized {@link RegistrarAddress} for this registrar. All contained values must be
|
||||
* representable in the 7-bit US-ASCII character set.
|
||||
*/
|
||||
@Ignore
|
||||
@Embedded
|
||||
@AttributeOverrides({
|
||||
@AttributeOverride(name = "streetLine1", column = @Column(name = "i18n_address_street_line1")),
|
||||
@@ -367,14 +340,14 @@ public class Registrar extends ImmutableObject
|
||||
*
|
||||
* <ul>
|
||||
* <li>8 is used for Testing Registrar.
|
||||
* <li>9997 is used by ICAAN for SLA monitoring.
|
||||
* <li>9997 is used by ICANN for SLA monitoring.
|
||||
* <li>9999 is used for cases when the registry operator acts as registrar.
|
||||
* </ul>
|
||||
*
|
||||
* @see <a href="http://www.iana.org/assignments/registrar-ids/registrar-ids.txt">Registrar
|
||||
* IDs</a>
|
||||
*/
|
||||
@Index @Nullable Long ianaIdentifier;
|
||||
@Nullable Long ianaIdentifier;
|
||||
|
||||
/** Purchase Order number used for invoices in external billing system, if applicable. */
|
||||
@Nullable String poNumber;
|
||||
@@ -395,7 +368,7 @@ public class Registrar extends ImmutableObject
|
||||
/**
|
||||
* ICANN referral email address.
|
||||
*
|
||||
* <p>This value is specified in the initial registrar contact. It can't be edited in the web GUI
|
||||
* <p>This value is specified in the initial registrar contact. It can't be edited in the web GUI,
|
||||
* and it must be specified when the registrar account is created.
|
||||
*/
|
||||
String icannReferralEmail;
|
||||
@@ -406,10 +379,10 @@ public class Registrar extends ImmutableObject
|
||||
// Metadata.
|
||||
|
||||
/** The time when this registrar was created. */
|
||||
@Ignore CreateAutoTimestamp creationTime = CreateAutoTimestamp.create(null);
|
||||
CreateAutoTimestamp creationTime = CreateAutoTimestamp.create(null);
|
||||
|
||||
/** An automatically managed last-saved timestamp. */
|
||||
@Ignore UpdateAutoTimestamp lastUpdateTime = UpdateAutoTimestamp.create(null);
|
||||
UpdateAutoTimestamp lastUpdateTime = UpdateAutoTimestamp.create(null);
|
||||
|
||||
/** The time that the certificate was last updated. */
|
||||
DateTime lastCertificateUpdateTime;
|
||||
@@ -610,18 +583,13 @@ public class Registrar extends ImmutableObject
|
||||
}
|
||||
|
||||
private Iterable<RegistrarPoc> getContactsIterable() {
|
||||
if (tm().isOfy()) {
|
||||
return auditedOfy().load().type(RegistrarPoc.class).ancestor(Registrar.this);
|
||||
} else {
|
||||
return tm().transact(
|
||||
() ->
|
||||
jpaTm()
|
||||
.query(
|
||||
"FROM RegistrarPoc WHERE registrarId = :registrarId", RegistrarPoc.class)
|
||||
.setParameter("registrarId", clientIdentifier)
|
||||
.getResultStream()
|
||||
.collect(toImmutableList()));
|
||||
}
|
||||
return tm().transact(
|
||||
() ->
|
||||
jpaTm()
|
||||
.query("FROM RegistrarPoc WHERE registrarId = :registrarId", RegistrarPoc.class)
|
||||
.setParameter("registrarId", clientIdentifier)
|
||||
.getResultStream()
|
||||
.collect(toImmutableList()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -687,18 +655,13 @@ public class Registrar extends ImmutableObject
|
||||
/** Creates a {@link VKey} for this instance. */
|
||||
@Override
|
||||
public VKey<Registrar> createVKey() {
|
||||
return createVKey(Key.create(this));
|
||||
return createVKey(clientIdentifier);
|
||||
}
|
||||
|
||||
/** Creates a {@link VKey} for the given {@code registrarId}. */
|
||||
public static VKey<Registrar> createVKey(String registrarId) {
|
||||
checkArgumentNotNull(registrarId, "registrarId must be specified");
|
||||
return createVKey(Key.create(getCrossTldKey(), Registrar.class, registrarId));
|
||||
}
|
||||
|
||||
/** Creates a {@link VKey} instance from a {@link Key} instance. */
|
||||
public static VKey<Registrar> createVKey(Key<Registrar> key) {
|
||||
return VKey.create(Registrar.class, key.getName(), key);
|
||||
return VKey.createSql(Registrar.class, registrarId);
|
||||
}
|
||||
|
||||
/** A builder for constructing {@link Registrar}, since it is immutable. */
|
||||
@@ -774,7 +737,7 @@ public class Registrar extends ImmutableObject
|
||||
Set<VKey<Registry>> missingTldKeys =
|
||||
Sets.difference(
|
||||
newTldKeys, tm().transact(() -> tm().loadByKeysIfPresent(newTldKeys)).keySet());
|
||||
checkArgument(missingTldKeys.isEmpty(), "Trying to set nonexisting TLDs: %s", missingTldKeys);
|
||||
checkArgument(missingTldKeys.isEmpty(), "Trying to set nonexistent TLDs: %s", missingTldKeys);
|
||||
getInstance().allowedTlds = ImmutableSortedSet.copyOf(allowedTlds);
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -18,8 +18,6 @@ import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.googlecode.objectify.annotation.Embed;
|
||||
import com.googlecode.objectify.annotation.Ignore;
|
||||
import google.registry.model.Buildable;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.UnsafeSerializable;
|
||||
@@ -43,15 +41,13 @@ import org.joda.time.DateTime;
|
||||
* only exception is for reportField = TRANSFER_LOSING_SUCCESSFUL or TRANSFER_LOSING_NACKED, which
|
||||
* uses HistoryEntry.otherClientId because the losing party in a transfer is always the otherClient.
|
||||
*/
|
||||
@Embed
|
||||
@Entity
|
||||
public class DomainTransactionRecord extends ImmutableObject
|
||||
implements Buildable, UnsafeSerializable {
|
||||
|
||||
@Id
|
||||
@Ignore
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@ImmutableObject.Insignificant
|
||||
@Insignificant
|
||||
Long id;
|
||||
|
||||
/** The TLD this record operates on. */
|
||||
@@ -62,9 +58,9 @@ public class DomainTransactionRecord extends ImmutableObject
|
||||
// Datastore-SQL validation. They are excluded from equality check since they are not set in
|
||||
// Datastore.
|
||||
// TODO(b/203609782): post migration, decide whether to keep these two fields.
|
||||
@Ignore @ImmutableObject.Insignificant String domainRepoId;
|
||||
@Insignificant String domainRepoId;
|
||||
|
||||
@Ignore @ImmutableObject.Insignificant Long historyRevisionId;
|
||||
@Insignificant Long historyRevisionId;
|
||||
|
||||
/**
|
||||
* The time this Transaction takes effect (counting grace periods and other nuances).
|
||||
|
||||
@@ -25,10 +25,9 @@ import com.google.common.collect.ImmutableSet;
|
||||
import com.googlecode.objectify.Key;
|
||||
import com.googlecode.objectify.annotation.Entity;
|
||||
import com.googlecode.objectify.annotation.Id;
|
||||
import com.googlecode.objectify.annotation.IgnoreSave;
|
||||
import com.googlecode.objectify.annotation.Ignore;
|
||||
import com.googlecode.objectify.annotation.Index;
|
||||
import com.googlecode.objectify.annotation.Parent;
|
||||
import com.googlecode.objectify.condition.IfNull;
|
||||
import google.registry.model.Buildable;
|
||||
import google.registry.model.EppResource;
|
||||
import google.registry.model.ImmutableObject;
|
||||
@@ -155,8 +154,7 @@ public class HistoryEntry extends ImmutableObject implements Buildable, UnsafeSe
|
||||
* The length of time that a create, allocate, renewal, or transfer request was issued for. Will
|
||||
* be null for all other types.
|
||||
*/
|
||||
@IgnoreSave(IfNull.class)
|
||||
@Transient // domain-specific
|
||||
@Ignore @Transient // domain-specific
|
||||
Period period;
|
||||
|
||||
/**
|
||||
@@ -189,6 +187,7 @@ public class HistoryEntry extends ImmutableObject implements Buildable, UnsafeSe
|
||||
|
||||
/** Transaction id that made this change, or null if the entry was not created by a flow. */
|
||||
@Nullable
|
||||
@Ignore
|
||||
@AttributeOverrides({
|
||||
@AttributeOverride(
|
||||
name = "clientTransactionId",
|
||||
@@ -218,6 +217,7 @@ public class HistoryEntry extends ImmutableObject implements Buildable, UnsafeSe
|
||||
* also be empty if the HistoryEntry refers to an EPP mutation that does not affect domain
|
||||
* transaction counts (such as contact or host mutations).
|
||||
*/
|
||||
@Ignore
|
||||
@Transient // domain-specific
|
||||
@ImmutableObject.EmptySetToNull
|
||||
protected Set<DomainTransactionRecord> domainTransactionRecords;
|
||||
|
||||
@@ -16,7 +16,6 @@ package google.registry.model.server;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.util.DateTimeUtils.isAtOrAfter;
|
||||
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
|
||||
|
||||
@@ -24,15 +23,8 @@ import com.google.auto.value.AutoValue;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import com.googlecode.objectify.Key;
|
||||
import com.googlecode.objectify.annotation.Entity;
|
||||
import com.googlecode.objectify.annotation.Id;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.annotations.NotBackedUp;
|
||||
import google.registry.model.annotations.NotBackedUp.Reason;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.persistence.transaction.JpaTransactionManager;
|
||||
import google.registry.persistence.transaction.TransactionManager;
|
||||
import google.registry.util.RequestStatusChecker;
|
||||
import google.registry.util.RequestStatusCheckerImpl;
|
||||
import java.io.Serializable;
|
||||
@@ -40,6 +32,8 @@ import java.util.Optional;
|
||||
import java.util.function.Supplier;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.IdClass;
|
||||
import javax.persistence.PostLoad;
|
||||
import javax.persistence.Table;
|
||||
@@ -57,8 +51,6 @@ import org.joda.time.Duration;
|
||||
* safe calls that automatically lock and unlock, see LockHandler.
|
||||
*/
|
||||
@Entity
|
||||
@NotBackedUp(reason = Reason.TRANSIENT)
|
||||
@javax.persistence.Entity
|
||||
@Table
|
||||
@IdClass(Lock.LockId.class)
|
||||
public class Lock extends ImmutableObject implements Serializable {
|
||||
@@ -109,14 +101,13 @@ public class Lock extends ImmutableObject implements Serializable {
|
||||
|
||||
/** The resource name used to create the lock. */
|
||||
@Column(nullable = false)
|
||||
@javax.persistence.Id
|
||||
@Id
|
||||
String resourceName;
|
||||
|
||||
/** The tld used to create the lock, or GLOBAL if it's cross-TLD. */
|
||||
// TODO(b/177567432): rename to "scope" post-Datastore
|
||||
@Column(nullable = false, name = "scope")
|
||||
@javax.persistence.Id
|
||||
String tld;
|
||||
@Column(nullable = false)
|
||||
@Id
|
||||
String scope;
|
||||
|
||||
public DateTime getExpirationTime() {
|
||||
return expirationTime;
|
||||
@@ -124,7 +115,7 @@ public class Lock extends ImmutableObject implements Serializable {
|
||||
|
||||
@PostLoad
|
||||
void postLoad() {
|
||||
lockId = makeLockId(resourceName, tld);
|
||||
lockId = makeLockId(resourceName, scope);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -146,7 +137,7 @@ public class Lock extends ImmutableObject implements Serializable {
|
||||
instance.expirationTime = acquiredTime.plus(leaseLength);
|
||||
instance.acquiredTime = acquiredTime;
|
||||
instance.resourceName = resourceName;
|
||||
instance.tld = scope;
|
||||
instance.scope = scope;
|
||||
return instance;
|
||||
}
|
||||
|
||||
@@ -157,8 +148,13 @@ public class Lock extends ImmutableObject implements Serializable {
|
||||
@AutoValue
|
||||
abstract static class AcquireResult {
|
||||
public abstract DateTime transactionTime();
|
||||
public abstract @Nullable Lock existingLock();
|
||||
public abstract @Nullable Lock newLock();
|
||||
|
||||
@Nullable
|
||||
public abstract Lock existingLock();
|
||||
|
||||
@Nullable
|
||||
public abstract Lock newLock();
|
||||
|
||||
public abstract LockState lockState();
|
||||
|
||||
public static AcquireResult create(
|
||||
@@ -213,64 +209,18 @@ public class Lock extends ImmutableObject implements Serializable {
|
||||
Duration leaseLength,
|
||||
RequestStatusChecker requestStatusChecker,
|
||||
boolean checkThreadRunning) {
|
||||
return acquireWithTransactionManager(
|
||||
resourceName, tld, leaseLength, requestStatusChecker, checkThreadRunning, tm());
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to acquire a lock in SQL. Returns absent if it can't be acquired.
|
||||
*
|
||||
* <p>This method exists so that Beam pipelines can acquire / load / release locks.
|
||||
*/
|
||||
public static Optional<Lock> acquireSql(
|
||||
String resourceName,
|
||||
@Nullable String tld,
|
||||
Duration leaseLength,
|
||||
RequestStatusChecker requestStatusChecker,
|
||||
boolean checkThreadRunning) {
|
||||
return acquireWithTransactionManager(
|
||||
resourceName, tld, leaseLength, requestStatusChecker, checkThreadRunning, jpaTm());
|
||||
}
|
||||
|
||||
/** Release the lock. */
|
||||
public void release() {
|
||||
releaseWithTransactionManager(tm());
|
||||
}
|
||||
|
||||
/**
|
||||
* Release the lock from SQL.
|
||||
*
|
||||
* <p>This method exists so that Beam pipelines can acquire / load / release locks.
|
||||
*/
|
||||
public void releaseSql() {
|
||||
releaseWithTransactionManager(jpaTm());
|
||||
}
|
||||
|
||||
/** Try to acquire a lock. Returns absent if it can't be acquired. */
|
||||
private static Optional<Lock> acquireWithTransactionManager(
|
||||
String resourceName,
|
||||
@Nullable String tld,
|
||||
Duration leaseLength,
|
||||
RequestStatusChecker requestStatusChecker,
|
||||
boolean checkThreadRunning,
|
||||
TransactionManager transactionManager) {
|
||||
String scope = (tld != null) ? tld : GLOBAL;
|
||||
String lockId = makeLockId(resourceName, scope);
|
||||
String scope = tld != null ? tld : GLOBAL;
|
||||
// It's important to use transactNew rather than transact, because a Lock can be used to control
|
||||
// access to resources like GCS that can't be transactionally rolled back. Therefore, the lock
|
||||
// must be definitively acquired before it is used, even when called inside another transaction.
|
||||
Supplier<AcquireResult> lockAcquirer =
|
||||
() -> {
|
||||
DateTime now = transactionManager.getTransactionTime();
|
||||
DateTime now = jpaTm().getTransactionTime();
|
||||
|
||||
// Checking if an unexpired lock still exists - if so, the lock can't be acquired.
|
||||
Lock lock =
|
||||
transactionManager
|
||||
.loadByKeyIfPresent(
|
||||
VKey.create(
|
||||
Lock.class,
|
||||
new LockId(resourceName, scope),
|
||||
Key.create(Lock.class, lockId)))
|
||||
jpaTm()
|
||||
.loadByKeyIfPresent(VKey.createSql(Lock.class, new LockId(resourceName, scope)))
|
||||
.orElse(null);
|
||||
if (lock != null) {
|
||||
logger.atInfo().log(
|
||||
@@ -290,17 +240,11 @@ public class Lock extends ImmutableObject implements Serializable {
|
||||
|
||||
Lock newLock =
|
||||
create(resourceName, scope, requestStatusChecker.getLogId(), now, leaseLength);
|
||||
// Locks are not parented under an EntityGroupRoot (so as to avoid write
|
||||
// contention) and don't need to be backed up.
|
||||
transactionManager.put(newLock);
|
||||
jpaTm().put(newLock);
|
||||
|
||||
return AcquireResult.create(now, lock, newLock, lockState);
|
||||
};
|
||||
// In ofy, backup is determined per-action, but in SQL it's determined per-transaction
|
||||
AcquireResult acquireResult =
|
||||
transactionManager.isOfy()
|
||||
? transactionManager.transactNew(lockAcquirer)
|
||||
: ((JpaTransactionManager) transactionManager).transactWithoutBackup(lockAcquirer);
|
||||
AcquireResult acquireResult = jpaTm().transactWithoutBackup(lockAcquirer);
|
||||
|
||||
logAcquireResult(acquireResult);
|
||||
lockMetrics.recordAcquire(resourceName, scope, acquireResult.lockState());
|
||||
@@ -308,62 +252,51 @@ public class Lock extends ImmutableObject implements Serializable {
|
||||
}
|
||||
|
||||
/** Release the lock. */
|
||||
private void releaseWithTransactionManager(TransactionManager transactionManager) {
|
||||
public void release() {
|
||||
// Just use the default clock because we aren't actually doing anything that will use the clock.
|
||||
Supplier<Void> lockReleaser =
|
||||
() -> {
|
||||
// To release a lock, check that no one else has already obtained it and if not
|
||||
// delete it. If the lock in Datastore was different then this lock is gone already;
|
||||
// delete it. If the lock in the database was different, then this lock is gone already;
|
||||
// this can happen if release() is called around the expiration time and the lock
|
||||
// expires underneath us.
|
||||
VKey<Lock> key =
|
||||
VKey.create(
|
||||
Lock.class, new LockId(resourceName, tld), Key.create(Lock.class, lockId));
|
||||
Lock loadedLock = transactionManager.loadByKeyIfPresent(key).orElse(null);
|
||||
if (Lock.this.equals(loadedLock)) {
|
||||
VKey<Lock> key = VKey.createSql(Lock.class, new LockId(resourceName, scope));
|
||||
Lock loadedLock = jpaTm().loadByKeyIfPresent(key).orElse(null);
|
||||
if (equals(loadedLock)) {
|
||||
// Use deleteIgnoringReadOnly() so that we don't create a commit log entry for deleting
|
||||
// the lock.
|
||||
logger.atInfo().log("Deleting lock: %s", lockId);
|
||||
transactionManager.delete(key);
|
||||
jpaTm().delete(key);
|
||||
|
||||
lockMetrics.recordRelease(
|
||||
resourceName,
|
||||
tld,
|
||||
new Duration(acquiredTime, transactionManager.getTransactionTime()));
|
||||
resourceName, scope, new Duration(acquiredTime, jpaTm().getTransactionTime()));
|
||||
} else {
|
||||
logger.atSevere().log(
|
||||
"The lock we acquired was transferred to someone else before we"
|
||||
+ " released it! Did action take longer than lease length?"
|
||||
+ " Our lock: %s, current lock: %s",
|
||||
Lock.this, loadedLock);
|
||||
this, loadedLock);
|
||||
logger.atInfo().log(
|
||||
"Not deleting lock: %s - someone else has it: %s", lockId, loadedLock);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
// In ofy, backup is determined per-action, but in SQL it's determined per-transaction
|
||||
if (transactionManager.isOfy()) {
|
||||
transactionManager.transact(lockReleaser);
|
||||
} else {
|
||||
((JpaTransactionManager) transactionManager).transactWithoutBackup(lockReleaser);
|
||||
}
|
||||
jpaTm().transactWithoutBackup(lockReleaser);
|
||||
}
|
||||
|
||||
static class LockId extends ImmutableObject implements Serializable {
|
||||
|
||||
String resourceName;
|
||||
|
||||
// TODO(b/177567432): rename to "scope" post-Datastore
|
||||
@Column(name = "scope")
|
||||
String tld;
|
||||
String scope;
|
||||
|
||||
// Required for Hibernate
|
||||
@SuppressWarnings("unused")
|
||||
private LockId() {}
|
||||
|
||||
LockId(String resourceName, String tld) {
|
||||
LockId(String resourceName, String scope) {
|
||||
this.resourceName = checkArgumentNotNull(resourceName, "The resource name cannot be null");
|
||||
this.tld = checkArgumentNotNull(tld, "Scope of a lock cannot be null");
|
||||
this.scope = checkArgumentNotNull(scope, "Scope of a lock cannot be null");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,27 +19,16 @@ import static google.registry.persistence.transaction.TransactionManagerFactory.
|
||||
import com.github.benmanes.caffeine.cache.LoadingCache;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.primitives.Longs;
|
||||
import com.googlecode.objectify.annotation.Entity;
|
||||
import com.googlecode.objectify.annotation.Ignore;
|
||||
import com.googlecode.objectify.annotation.OnLoad;
|
||||
import com.googlecode.objectify.annotation.Unindex;
|
||||
import google.registry.model.CacheUtils;
|
||||
import google.registry.model.annotations.NotBackedUp;
|
||||
import google.registry.model.annotations.NotBackedUp.Reason;
|
||||
import google.registry.model.common.CrossTldSingleton;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.PostLoad;
|
||||
import javax.persistence.Transient;
|
||||
import javax.persistence.Entity;
|
||||
|
||||
/** A secret number used for generating tokens (such as XSRF tokens). */
|
||||
@Entity
|
||||
@javax.persistence.Entity
|
||||
@Unindex
|
||||
@NotBackedUp(reason = Reason.AUTO_GENERATED)
|
||||
// TODO(b/27427316): Replace this with an entry in KMSKeyring
|
||||
public class ServerSecret extends CrossTldSingleton {
|
||||
|
||||
/**
|
||||
@@ -52,13 +41,6 @@ public class ServerSecret extends CrossTldSingleton {
|
||||
CacheUtils.newCacheBuilder().build(singletonClazz -> retrieveAndSaveSecret());
|
||||
|
||||
private static ServerSecret retrieveAndSaveSecret() {
|
||||
if (tm().isOfy()) {
|
||||
// Attempt a quick load if we're in ofy first to short-circuit sans transaction
|
||||
Optional<ServerSecret> secretWithoutTransaction = tm().loadSingleton(ServerSecret.class);
|
||||
if (secretWithoutTransaction.isPresent()) {
|
||||
return secretWithoutTransaction.get();
|
||||
}
|
||||
}
|
||||
return tm().transact(
|
||||
() -> {
|
||||
// Make sure we're in a transaction and attempt to load any existing secret, then
|
||||
@@ -77,35 +59,13 @@ public class ServerSecret extends CrossTldSingleton {
|
||||
return CACHE.get(ServerSecret.class);
|
||||
}
|
||||
|
||||
/** Most significant 8 bytes of the UUID value (stored separately for legacy purposes). */
|
||||
@Transient long mostSignificant;
|
||||
|
||||
/** Least significant 8 bytes of the UUID value (stored separately for legacy purposes). */
|
||||
@Transient long leastSignificant;
|
||||
|
||||
/** The UUID value itself. */
|
||||
@Column(columnDefinition = "uuid")
|
||||
@Ignore
|
||||
UUID secret;
|
||||
|
||||
/** Convert the Datastore representation to SQL. */
|
||||
@OnLoad
|
||||
void onLoad() {
|
||||
secret = new UUID(mostSignificant, leastSignificant);
|
||||
}
|
||||
|
||||
/** Convert the SQL representation to Datastore. */
|
||||
@PostLoad
|
||||
void postLoad() {
|
||||
mostSignificant = secret.getMostSignificantBits();
|
||||
leastSignificant = secret.getLeastSignificantBits();
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
static ServerSecret create(UUID uuid) {
|
||||
ServerSecret secret = new ServerSecret();
|
||||
secret.mostSignificant = uuid.getMostSignificantBits();
|
||||
secret.leastSignificant = uuid.getLeastSignificantBits();
|
||||
secret.secret = uuid;
|
||||
return secret;
|
||||
}
|
||||
@@ -113,8 +73,8 @@ public class ServerSecret extends CrossTldSingleton {
|
||||
/** Returns the value of this ServerSecret as a byte array. */
|
||||
public byte[] asBytes() {
|
||||
return ByteBuffer.allocate(Longs.BYTES * 2)
|
||||
.putLong(mostSignificant)
|
||||
.putLong(leastSignificant)
|
||||
.putLong(secret.getMostSignificantBits())
|
||||
.putLong(secret.getLeastSignificantBits())
|
||||
.array();
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@ import static com.google.common.base.MoreObjects.firstNonNull;
|
||||
import static com.google.common.io.BaseEncoding.base64;
|
||||
|
||||
import com.google.appengine.api.datastore.Text;
|
||||
import com.googlecode.objectify.annotation.Embed;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import javax.xml.bind.annotation.XmlAttribute;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
@@ -31,7 +30,6 @@ import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
|
||||
* @see <a href="http://tools.ietf.org/html/draft-lozano-tmch-smd-02#section-2.4">
|
||||
* draft-lozano-tmch-smd-02 § 2.4</a>
|
||||
*/
|
||||
@Embed
|
||||
@XmlRootElement(name = "encodedSignedMark")
|
||||
public class EncodedSignedMark extends ImmutableObject implements AbstractSignedMark {
|
||||
|
||||
@@ -42,8 +40,9 @@ public class EncodedSignedMark extends ImmutableObject implements AbstractSigned
|
||||
String encoding;
|
||||
|
||||
/**
|
||||
* Encoded data. This is stored in a Text field rather than a String because Objectify cannot
|
||||
* autoconvert Strings greater than 500 characters to Text within {@link Embed} collections.
|
||||
* Encoded data. This is stored in a Text field rather than a String due to historical reasons,
|
||||
* namely that Objectify cannot autoconvert Strings greater than 500 characters to Text within
|
||||
* {@code Embed} collections.
|
||||
*/
|
||||
@XmlValue
|
||||
@XmlJavaTypeAdapter(RemoveWhitespaceTextAdapter.class)
|
||||
|
||||
@@ -22,7 +22,6 @@ import static com.google.common.base.Strings.emptyToNull;
|
||||
import static com.google.common.collect.ImmutableSet.toImmutableSet;
|
||||
import static com.google.common.collect.Maps.filterValues;
|
||||
import static google.registry.model.CacheUtils.memoizeWithShortExpiration;
|
||||
import static google.registry.model.common.EntityGroupRoot.getCrossTldKey;
|
||||
import static google.registry.model.ofy.ObjectifyService.auditedOfy;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
@@ -66,7 +65,6 @@ public final class Registries {
|
||||
auditedOfy()
|
||||
.load()
|
||||
.type(Registry.class)
|
||||
.ancestor(getCrossTldKey())
|
||||
.keys()
|
||||
.list()
|
||||
.stream()
|
||||
|
||||
@@ -14,13 +14,9 @@
|
||||
|
||||
package google.registry.model.transfer;
|
||||
|
||||
import com.googlecode.objectify.annotation.Embed;
|
||||
import com.googlecode.objectify.annotation.Unindex;
|
||||
import javax.persistence.Embeddable;
|
||||
|
||||
/** Transfer data for contact. */
|
||||
@Embed
|
||||
@Unindex
|
||||
@Embeddable
|
||||
public class ContactTransferData extends TransferData<ContactTransferData.Builder> {
|
||||
public static final ContactTransferData EMPTY = new ContactTransferData();
|
||||
@@ -35,12 +31,11 @@ public class ContactTransferData extends TransferData<ContactTransferData.Builde
|
||||
return new Builder(clone(this));
|
||||
}
|
||||
|
||||
public static class Builder
|
||||
extends TransferData.Builder<ContactTransferData, ContactTransferData.Builder> {
|
||||
/** Create a {@link ContactTransferData.Builder} wrapping a new instance. */
|
||||
public static class Builder extends TransferData.Builder<ContactTransferData, Builder> {
|
||||
/** Create a {@link Builder} wrapping a new instance. */
|
||||
public Builder() {}
|
||||
|
||||
/** Create a {@link ContactTransferData.Builder} wrapping the given instance. */
|
||||
/** Create a {@link Builder} wrapping the given instance. */
|
||||
private Builder(ContactTransferData instance) {
|
||||
super(instance);
|
||||
}
|
||||
|
||||
@@ -17,11 +17,6 @@ package google.registry.model.transfer;
|
||||
import static google.registry.util.CollectionUtils.isNullOrEmpty;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.googlecode.objectify.annotation.Embed;
|
||||
import com.googlecode.objectify.annotation.Ignore;
|
||||
import com.googlecode.objectify.annotation.IgnoreSave;
|
||||
import com.googlecode.objectify.annotation.Unindex;
|
||||
import com.googlecode.objectify.condition.IfNull;
|
||||
import google.registry.model.billing.BillingEvent;
|
||||
import google.registry.model.domain.Period;
|
||||
import google.registry.model.domain.Period.Unit;
|
||||
@@ -38,8 +33,6 @@ import javax.persistence.Embedded;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
/** Transfer data for domain. */
|
||||
@Embed
|
||||
@Unindex
|
||||
@Embeddable
|
||||
public class DomainTransferData extends TransferData<DomainTransferData.Builder> {
|
||||
public static final DomainTransferData EMPTY = new DomainTransferData();
|
||||
@@ -75,7 +68,6 @@ public class DomainTransferData extends TransferData<DomainTransferData.Builder>
|
||||
@Column(name = "transfer_registration_expiration_time")
|
||||
DateTime transferredRegistrationExpirationTime;
|
||||
|
||||
@Ignore
|
||||
@Column(name = "transfer_billing_cancellation_id")
|
||||
public VKey<BillingEvent.Cancellation> billingCancellationId;
|
||||
|
||||
@@ -86,7 +78,6 @@ public class DomainTransferData extends TransferData<DomainTransferData.Builder>
|
||||
* being transferred is not a domain.
|
||||
*/
|
||||
@Column(name = "transfer_billing_event_id")
|
||||
@Ignore
|
||||
VKey<BillingEvent.OneTime> serverApproveBillingEvent;
|
||||
|
||||
/**
|
||||
@@ -96,7 +87,6 @@ public class DomainTransferData extends TransferData<DomainTransferData.Builder>
|
||||
* being transferred is not a domain.
|
||||
*/
|
||||
@Column(name = "transfer_billing_recurrence_id")
|
||||
@Ignore
|
||||
VKey<BillingEvent.Recurring> serverApproveAutorenewEvent;
|
||||
|
||||
/**
|
||||
@@ -105,7 +95,6 @@ public class DomainTransferData extends TransferData<DomainTransferData.Builder>
|
||||
* <p>This field should be null if there is not currently a pending transfer or if the object
|
||||
* being transferred is not a domain.
|
||||
*/
|
||||
@IgnoreSave(IfNull.class)
|
||||
@Column(name = "transfer_autorenew_poll_message_id")
|
||||
VKey<PollMessage.Autorenew> serverApproveAutorenewPollMessage;
|
||||
|
||||
@@ -113,13 +102,12 @@ public class DomainTransferData extends TransferData<DomainTransferData.Builder>
|
||||
* Autorenew history, which we need to preserve because it's often used in contexts where we
|
||||
* haven't loaded the autorenew object.
|
||||
*/
|
||||
@Ignore
|
||||
@Column(name = "transfer_autorenew_poll_message_history_id")
|
||||
Long serverApproveAutorenewPollMessageHistoryId;
|
||||
|
||||
@Override
|
||||
public Builder copyConstantFieldsToBuilder() {
|
||||
return super.copyConstantFieldsToBuilder().setTransferPeriod(this.transferPeriod);
|
||||
return super.copyConstantFieldsToBuilder().setTransferPeriod(transferPeriod);
|
||||
}
|
||||
|
||||
public Period getTransferPeriod() {
|
||||
@@ -192,7 +180,7 @@ public class DomainTransferData extends TransferData<DomainTransferData.Builder>
|
||||
}
|
||||
|
||||
public static class Builder extends TransferData.Builder<DomainTransferData, Builder> {
|
||||
/** Create a {@link DomainTransferData.Builder} wrapping a new instance. */
|
||||
/** Create a {@link Builder} wrapping a new instance. */
|
||||
public Builder() {}
|
||||
|
||||
/** Create a {@link Builder} wrapping the given instance. */
|
||||
|
||||
@@ -21,7 +21,6 @@ import static google.registry.util.CollectionUtils.nullToEmpty;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.googlecode.objectify.annotation.Ignore;
|
||||
import google.registry.model.Buildable;
|
||||
import google.registry.model.EppResource;
|
||||
import google.registry.model.eppcommon.Trid;
|
||||
@@ -43,7 +42,8 @@ import javax.persistence.MappedSuperclass;
|
||||
*/
|
||||
@MappedSuperclass
|
||||
public abstract class TransferData<
|
||||
B extends TransferData.Builder<? extends TransferData, ? extends TransferData.Builder>>
|
||||
B extends
|
||||
TransferData.Builder<? extends TransferData<?>, ? extends TransferData.Builder<?, ?>>>
|
||||
extends BaseTransferObject implements Buildable {
|
||||
|
||||
/** The transaction id of the most recent transfer request (or null if there never was one). */
|
||||
@@ -58,11 +58,9 @@ public abstract class TransferData<
|
||||
})
|
||||
Trid transferRequestTrid;
|
||||
|
||||
@Ignore
|
||||
@Column(name = "transfer_repo_id")
|
||||
String repoId;
|
||||
|
||||
@Ignore
|
||||
@Column(name = "transfer_history_entry_id")
|
||||
Long historyEntryId;
|
||||
|
||||
@@ -71,15 +69,12 @@ public abstract class TransferData<
|
||||
//
|
||||
// In addition, there may be a third poll message for the autorenew poll message on domain
|
||||
// transfer if applicable.
|
||||
@Ignore
|
||||
@Column(name = "transfer_poll_message_id_1")
|
||||
Long pollMessageId1;
|
||||
|
||||
@Ignore
|
||||
@Column(name = "transfer_poll_message_id_2")
|
||||
Long pollMessageId2;
|
||||
|
||||
@Ignore
|
||||
@Column(name = "transfer_poll_message_id_3")
|
||||
Long pollMessageId3;
|
||||
|
||||
@@ -105,7 +100,7 @@ public abstract class TransferData<
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract Builder asBuilder();
|
||||
public abstract Builder<?, ?> asBuilder();
|
||||
|
||||
/**
|
||||
* Returns a fresh Builder populated only with the constant fields of this TransferData, i.e.
|
||||
@@ -124,17 +119,17 @@ public abstract class TransferData<
|
||||
public B copyConstantFieldsToBuilder() {
|
||||
B newBuilder = new TypeInstantiator<B>(getClass()) {}.instantiate();
|
||||
newBuilder
|
||||
.setTransferRequestTrid(this.transferRequestTrid)
|
||||
.setTransferRequestTime(this.transferRequestTime)
|
||||
.setGainingRegistrarId(this.gainingClientId)
|
||||
.setLosingRegistrarId(this.losingClientId);
|
||||
.setTransferRequestTrid(transferRequestTrid)
|
||||
.setTransferRequestTime(transferRequestTime)
|
||||
.setGainingRegistrarId(gainingClientId)
|
||||
.setLosingRegistrarId(losingClientId);
|
||||
return newBuilder;
|
||||
}
|
||||
|
||||
/** Maps serverApproveEntities set to the individual fields. */
|
||||
static void mapServerApproveEntitiesToFields(
|
||||
Set<VKey<? extends TransferServerApproveEntity>> serverApproveEntities,
|
||||
TransferData transferData) {
|
||||
TransferData<?> transferData) {
|
||||
if (isNullOrEmpty(serverApproveEntities)) {
|
||||
transferData.pollMessageId1 = null;
|
||||
transferData.pollMessageId2 = null;
|
||||
@@ -166,11 +161,11 @@ public abstract class TransferData<
|
||||
}
|
||||
|
||||
/** Builder for {@link TransferData} because it is immutable. */
|
||||
public abstract static class Builder<T extends TransferData, B extends Builder<T, B>>
|
||||
public abstract static class Builder<T extends TransferData<?>, B extends Builder<T, B>>
|
||||
extends BaseTransferObject.Builder<T, B> {
|
||||
|
||||
/** Create a {@link Builder} wrapping a new instance. */
|
||||
public Builder() {}
|
||||
protected Builder() {}
|
||||
|
||||
/** Create a {@link Builder} wrapping the given instance. */
|
||||
protected Builder(T instance) {
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
|
||||
package google.registry.model.transfer;
|
||||
|
||||
import com.googlecode.objectify.annotation.Embed;
|
||||
import google.registry.model.EppResource;
|
||||
import google.registry.model.eppoutput.EppResponse.ResponseData;
|
||||
import javax.persistence.Embeddable;
|
||||
@@ -33,7 +32,6 @@ import org.joda.time.DateTime;
|
||||
public class TransferResponse extends BaseTransferObject implements ResponseData {
|
||||
|
||||
/** An adapter to output the XML in response to a transfer command on a domain. */
|
||||
@Embed
|
||||
@XmlRootElement(name = "trnData", namespace = "urn:ietf:params:xml:ns:domain-1.0")
|
||||
@XmlType(propOrder = {
|
||||
"fullyQualifiedDomainName",
|
||||
@@ -82,7 +80,6 @@ public class TransferResponse extends BaseTransferObject implements ResponseData
|
||||
}
|
||||
|
||||
/** An adapter to output the XML in response to a transfer command on a contact. */
|
||||
@Embed
|
||||
@XmlRootElement(name = "trnData", namespace = "urn:ietf:params:xml:ns:contact-1.0")
|
||||
@XmlType(propOrder = {
|
||||
"contactId",
|
||||
|
||||
@@ -38,8 +38,8 @@ import javax.persistence.MappedSuperclass;
|
||||
*/
|
||||
@MappedSuperclass
|
||||
@Access(AccessType.FIELD)
|
||||
public abstract class EppHistoryVKey<K, E extends EppResource> extends ImmutableObject
|
||||
implements Serializable {
|
||||
public abstract class EppHistoryVKey<K extends ImmutableObject, E extends EppResource>
|
||||
extends ImmutableObject implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -3906580677709539818L;
|
||||
|
||||
|
||||
+1
-8
@@ -31,9 +31,6 @@ import com.google.common.collect.Streams;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.index.EppResourceIndex;
|
||||
import google.registry.model.index.ForeignKeyIndex.ForeignKeyContactIndex;
|
||||
import google.registry.model.index.ForeignKeyIndex.ForeignKeyDomainIndex;
|
||||
import google.registry.model.index.ForeignKeyIndex.ForeignKeyHostIndex;
|
||||
import google.registry.persistence.JpaRetries;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.util.Clock;
|
||||
@@ -83,11 +80,7 @@ public class JpaTransactionManagerImpl implements JpaTransactionManager {
|
||||
// to exclude the Datastore specific entities when the underlying tm() is jpaTm().
|
||||
// TODO(b/176108270): Remove this property after database migration.
|
||||
private static final ImmutableSet<Class<? extends ImmutableObject>> IGNORED_ENTITY_CLASSES =
|
||||
ImmutableSet.of(
|
||||
EppResourceIndex.class,
|
||||
ForeignKeyContactIndex.class,
|
||||
ForeignKeyDomainIndex.class,
|
||||
ForeignKeyHostIndex.class);
|
||||
ImmutableSet.of(EppResourceIndex.class);
|
||||
|
||||
// EntityManagerFactory is thread safe.
|
||||
private final EntityManagerFactory emf;
|
||||
|
||||
@@ -18,7 +18,6 @@ import com.google.common.collect.ImmutableCollection;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.annotations.InCrossTld;
|
||||
import google.registry.persistence.VKey;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Optional;
|
||||
@@ -176,18 +175,14 @@ public interface TransactionManager {
|
||||
/**
|
||||
* Returns a list of all entities of the given type that exist in the database.
|
||||
*
|
||||
* <p>The resulting list is empty if there are no entities of this type. In Datastore mode, if the
|
||||
* class is a member of the cross-TLD entity group (i.e. if it has the {@link InCrossTld}
|
||||
* annotation, then the correct ancestor query will automatically be applied.
|
||||
* <p>The resulting list is empty if there are no entities of this type.
|
||||
*/
|
||||
<T> ImmutableList<T> loadAllOf(Class<T> clazz);
|
||||
|
||||
/**
|
||||
* Returns a stream of all entities of the given type that exist in the database.
|
||||
*
|
||||
* <p>The resulting stream is empty if there are no entities of this type. In Datastore mode, if
|
||||
* the class is a member of the cross-TLD entity group (i.e. if it has the {@link InCrossTld}
|
||||
* annotation, then the correct ancestor query will automatically be applied.
|
||||
* <p>The resulting stream is empty if there are no entities of this type.
|
||||
*/
|
||||
<T> Stream<T> loadAllOfStream(Class<T> clazz);
|
||||
|
||||
|
||||
@@ -38,26 +38,5 @@ public interface LockHandler extends Serializable {
|
||||
* @return true if all locks were acquired and the callable was run; false otherwise.
|
||||
*/
|
||||
boolean executeWithLocks(
|
||||
final Callable<Void> callable,
|
||||
@Nullable String tld,
|
||||
Duration leaseLength,
|
||||
String... lockNames);
|
||||
|
||||
/**
|
||||
* Acquire one or more locks using only Cloud SQL and execute a Void {@link Callable}.
|
||||
*
|
||||
* <p>Runs on a thread that will be killed if it doesn't complete before the lease expires.
|
||||
*
|
||||
* <p>Note that locks are specific either to a given tld or to the entire system (in which case
|
||||
* tld should be passed as null).
|
||||
*
|
||||
* <p>This method exists so that Beam pipelines can acquire / load / release locks.
|
||||
*
|
||||
* @return true if all locks were acquired and the callable was run; false otherwise.
|
||||
*/
|
||||
boolean executeWithSqlLocks(
|
||||
final Callable<Void> callable,
|
||||
@Nullable String tld,
|
||||
Duration leaseLength,
|
||||
String... lockNames);
|
||||
Callable<Void> callable, @Nullable String tld, Duration leaseLength, String... lockNames);
|
||||
}
|
||||
|
||||
@@ -76,27 +76,6 @@ public class LockHandlerImpl implements LockHandler {
|
||||
return executeWithLockAcquirer(callable, tld, leaseLength, this::acquire, lockNames);
|
||||
}
|
||||
|
||||
/**
|
||||
* Acquire one or more locks using only Cloud SQL and execute a Void {@link Callable}.
|
||||
*
|
||||
* <p>Thread will be killed if it doesn't complete before the lease expires.
|
||||
*
|
||||
* <p>Note that locks are specific either to a given tld or to the entire system (in which case
|
||||
* tld should be passed as null).
|
||||
*
|
||||
* <p>This method exists so that Beam pipelines can acquire / load / release locks.
|
||||
*
|
||||
* @return whether all locks were acquired and the callable was run.
|
||||
*/
|
||||
@Override
|
||||
public boolean executeWithSqlLocks(
|
||||
final Callable<Void> callable,
|
||||
@Nullable String tld,
|
||||
Duration leaseLength,
|
||||
String... lockNames) {
|
||||
return executeWithLockAcquirer(callable, tld, leaseLength, this::acquireSql, lockNames);
|
||||
}
|
||||
|
||||
private boolean executeWithLockAcquirer(
|
||||
final Callable<Void> callable,
|
||||
@Nullable String tld,
|
||||
@@ -138,11 +117,6 @@ public class LockHandlerImpl implements LockHandler {
|
||||
return Lock.acquire(lockName, tld, leaseLength, requestStatusChecker, true);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
Optional<Lock> acquireSql(String lockName, @Nullable String tld, Duration leaseLength) {
|
||||
return Lock.acquireSql(lockName, tld, leaseLength, requestStatusChecker, true);
|
||||
}
|
||||
|
||||
private interface LockAcquirer {
|
||||
Optional<Lock> acquireLock(String lockName, @Nullable String tld, Duration leaseLength);
|
||||
}
|
||||
|
||||
@@ -314,7 +314,7 @@ class GenerateAllocationTokensCommand implements CommandWithRemoteApi {
|
||||
private ImmutableSet<String> getExistingTokenStrings(ImmutableSet<String> candidates) {
|
||||
ImmutableSet<VKey<AllocationToken>> existingTokenKeys =
|
||||
candidates.stream()
|
||||
.map(input -> VKey.create(AllocationToken.class, input))
|
||||
.map(input -> VKey.createSql(AllocationToken.class, input))
|
||||
.collect(toImmutableSet());
|
||||
return tm().transact(
|
||||
() ->
|
||||
|
||||
@@ -47,7 +47,7 @@ final class GetAllocationTokenCommand implements CommandWithRemoteApi {
|
||||
for (List<String> tokens : Lists.partition(mainParameters, BATCH_SIZE)) {
|
||||
ImmutableList<VKey<AllocationToken>> tokenKeys =
|
||||
tokens.stream()
|
||||
.map(t -> VKey.create(AllocationToken.class, t))
|
||||
.map(t -> VKey.createSql(AllocationToken.class, t))
|
||||
.collect(toImmutableList());
|
||||
tm().transact(
|
||||
() ->
|
||||
|
||||
@@ -92,7 +92,6 @@ public final class RegistryTool {
|
||||
.put("pending_escrow", PendingEscrowCommand.class)
|
||||
.put("registrar_poc", RegistrarPocCommand.class)
|
||||
.put("renew_domain", RenewDomainCommand.class)
|
||||
.put("resave_environment_entities", ResaveEnvironmentEntitiesCommand.class)
|
||||
.put("save_sql_credential", SaveSqlCredentialCommand.class)
|
||||
.put("send_escrow_report_to_icann", SendEscrowReportToIcannCommand.class)
|
||||
.put("set_database_migration_state", SetDatabaseMigrationStateCommand.class)
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
// Copyright 2017 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.tools;
|
||||
|
||||
import static com.google.common.collect.Lists.partition;
|
||||
import static google.registry.model.common.EntityGroupRoot.getCrossTldKey;
|
||||
import static google.registry.model.ofy.ObjectifyService.auditedOfy;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
|
||||
import com.beust.jcommander.Parameters;
|
||||
import com.googlecode.objectify.Key;
|
||||
import google.registry.model.annotations.DeleteAfterMigration;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.model.registrar.RegistrarPoc;
|
||||
import google.registry.model.tld.Registry;
|
||||
|
||||
/**
|
||||
* Command to re-save all environment entities to ensure that they have valid commit logs.
|
||||
*
|
||||
* <p>The entities that are re-saved are those of type {@link Registry}, {@link Registrar}, and
|
||||
* {@link RegistrarPoc}.
|
||||
*/
|
||||
@Parameters(commandDescription = "Re-save all environment entities.")
|
||||
@DeleteAfterMigration
|
||||
final class ResaveEnvironmentEntitiesCommand implements CommandWithRemoteApi {
|
||||
|
||||
private static final int BATCH_SIZE = 10;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
batchSave(Registry.class);
|
||||
batchSave(Registrar.class);
|
||||
batchSave(RegistrarPoc.class);
|
||||
}
|
||||
|
||||
private static <T> void batchSave(Class<T> clazz) {
|
||||
System.out.printf("Re-saving %s entities.\n", clazz.getSimpleName());
|
||||
for (final Iterable<Key<T>> batch :
|
||||
partition(
|
||||
auditedOfy().load().type(clazz).ancestor(getCrossTldKey()).keys().list(), BATCH_SIZE)) {
|
||||
tm().transact(() -> auditedOfy().save().entities(auditedOfy().load().keys(batch).values()));
|
||||
System.out.printf("Re-saved entities batch: %s.\n", batch);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -55,7 +55,7 @@ abstract class UpdateOrDeleteAllocationTokensCommand extends ConfirmingCommand
|
||||
if (tokens != null) {
|
||||
ImmutableSet<VKey<AllocationToken>> keys =
|
||||
tokens.stream()
|
||||
.map(token -> VKey.create(AllocationToken.class, token))
|
||||
.map(token -> VKey.createSql(AllocationToken.class, token))
|
||||
.collect(toImmutableSet());
|
||||
ImmutableSet<VKey<AllocationToken>> nonexistentKeys =
|
||||
tm().transact(
|
||||
|
||||
@@ -1352,7 +1352,7 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
|
||||
|
||||
private void assertAllocationTokenWasRedeemed(String token) throws Exception {
|
||||
AllocationToken reloadedToken =
|
||||
tm().transact(() -> tm().loadByKey(VKey.create(AllocationToken.class, token)));
|
||||
tm().transact(() -> tm().loadByKey(VKey.createSql(AllocationToken.class, token)));
|
||||
assertThat(reloadedToken.isRedeemed()).isTrue();
|
||||
assertThat(reloadedToken.getRedemptionHistoryEntry())
|
||||
.hasValue(
|
||||
@@ -1362,7 +1362,7 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
|
||||
|
||||
private void assertAllocationTokenWasNotRedeemed(String token) {
|
||||
AllocationToken reloadedToken =
|
||||
tm().transact(() -> tm().loadByKey(VKey.create(AllocationToken.class, token)));
|
||||
tm().transact(() -> tm().loadByKey(VKey.createSql(AllocationToken.class, token)));
|
||||
assertThat(reloadedToken.isRedeemed()).isFalse();
|
||||
}
|
||||
|
||||
|
||||
@@ -332,7 +332,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, Domain>
|
||||
@Test
|
||||
private void assertAllocationTokenWasNotRedeemed(String token) {
|
||||
AllocationToken reloadedToken =
|
||||
tm().transact(() -> tm().loadByKey(VKey.create(AllocationToken.class, token)));
|
||||
tm().transact(() -> tm().loadByKey(VKey.createSql(AllocationToken.class, token)));
|
||||
assertThat(reloadedToken.isRedeemed()).isFalse();
|
||||
}
|
||||
|
||||
|
||||
@@ -106,7 +106,7 @@ class HostUpdateFlowTest extends ResourceFlowTestCase<HostUpdateFlow, Host> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup a domain with a transfer that should have been server approved a day ago.
|
||||
* Set up a domain with a transfer that should have been server approved a day ago.
|
||||
*
|
||||
* <p>The transfer is from "TheRegistrar" to "NewRegistrar".
|
||||
*/
|
||||
@@ -508,7 +508,7 @@ class HostUpdateFlowTest extends ResourceFlowTestCase<HostUpdateFlow, Host> {
|
||||
.asBuilder()
|
||||
.setLastTransferTime(lastTransferTime)
|
||||
.build());
|
||||
// Set the new domain to have a last transfer time that is different than the last transfer
|
||||
// Set the new domain to have a last transfer time that is different from the last transfer
|
||||
// time on the host in question.
|
||||
persistResource(
|
||||
DatabaseHelper.newDomain("example.tld")
|
||||
@@ -546,7 +546,7 @@ class HostUpdateFlowTest extends ResourceFlowTestCase<HostUpdateFlow, Host> {
|
||||
.asBuilder()
|
||||
.setLastTransferTime(clock.nowUtc().minusDays(5))
|
||||
.build());
|
||||
// Set the new domain to have a last transfer time that is different than the last transfer
|
||||
// Set the new domain to have a last transfer time that is different from the last transfer
|
||||
// time on the host in question.
|
||||
persistResource(
|
||||
DatabaseHelper.newDomain("example.tld")
|
||||
@@ -814,7 +814,7 @@ class HostUpdateFlowTest extends ResourceFlowTestCase<HostUpdateFlow, Host> {
|
||||
clock.nowUtc().minusDays(2), clock.nowUtc().minusDays(3));
|
||||
}
|
||||
|
||||
/** Test when the new superdordinate domain has never been transferred before. */
|
||||
/** Test when the new superordinate domain has never been transferred before. */
|
||||
@Test
|
||||
void testSuccess_externalToSubord_lastTransferTimeNotOverridden_whenNull() throws Exception {
|
||||
doExternalToInternalLastTransferTimeTest(clock.nowUtc().minusDays(2), null);
|
||||
|
||||
@@ -20,18 +20,10 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.domain.DomainHistory;
|
||||
import google.registry.model.domain.token.AllocationToken;
|
||||
import google.registry.model.host.Host;
|
||||
import google.registry.model.index.EppResourceIndex;
|
||||
import google.registry.model.index.EppResourceIndexBucket;
|
||||
import google.registry.model.index.ForeignKeyIndex.ForeignKeyContactIndex;
|
||||
import google.registry.model.index.ForeignKeyIndex.ForeignKeyDomainIndex;
|
||||
import google.registry.model.index.ForeignKeyIndex.ForeignKeyHostIndex;
|
||||
import google.registry.model.rde.RdeRevision;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.model.reporting.HistoryEntry;
|
||||
import google.registry.model.server.Lock;
|
||||
import google.registry.model.server.ServerSecret;
|
||||
import google.registry.testing.TestObject;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@@ -48,26 +40,14 @@ public class ClassPathManagerTest {
|
||||
* below are all classes supported in CLASS_REGISTRY. This test breaks if someone changes a
|
||||
* classname without preserving the original name.
|
||||
*/
|
||||
assertThat(ClassPathManager.getClass("ForeignKeyContactIndex"))
|
||||
.isEqualTo(ForeignKeyContactIndex.class);
|
||||
assertThat(ClassPathManager.getClass("AllocationToken")).isEqualTo(AllocationToken.class);
|
||||
assertThat(ClassPathManager.getClass("RdeRevision")).isEqualTo(RdeRevision.class);
|
||||
assertThat(ClassPathManager.getClass("Host")).isEqualTo(Host.class);
|
||||
assertThat(ClassPathManager.getClass("Registrar")).isEqualTo(Registrar.class);
|
||||
assertThat(ClassPathManager.getClass("Contact")).isEqualTo(Contact.class);
|
||||
assertThat(ClassPathManager.getClass("GaeUserIdConverter")).isEqualTo(GaeUserIdConverter.class);
|
||||
assertThat(ClassPathManager.getClass("EppResourceIndexBucket"))
|
||||
.isEqualTo(EppResourceIndexBucket.class);
|
||||
assertThat(ClassPathManager.getClass("EntityGroupRoot")).isEqualTo(EntityGroupRoot.class);
|
||||
assertThat(ClassPathManager.getClass("Lock")).isEqualTo(Lock.class);
|
||||
assertThat(ClassPathManager.getClass("Domain")).isEqualTo(Domain.class);
|
||||
assertThat(ClassPathManager.getClass("HistoryEntry")).isEqualTo(HistoryEntry.class);
|
||||
assertThat(ClassPathManager.getClass("ForeignKeyHostIndex"))
|
||||
.isEqualTo(ForeignKeyHostIndex.class);
|
||||
assertThat(ClassPathManager.getClass("ServerSecret")).isEqualTo(ServerSecret.class);
|
||||
assertThat(ClassPathManager.getClass("EppResourceIndex")).isEqualTo(EppResourceIndex.class);
|
||||
assertThat(ClassPathManager.getClass("ForeignKeyDomainIndex"))
|
||||
.isEqualTo(ForeignKeyDomainIndex.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -100,27 +80,15 @@ public class ClassPathManagerTest {
|
||||
* The classes below are all classes supported in CLASS_NAME_REGISTRY. This test breaks if
|
||||
* someone changes a classname without preserving the original name.
|
||||
*/
|
||||
assertThat(ClassPathManager.getClassName(ForeignKeyContactIndex.class))
|
||||
.isEqualTo("ForeignKeyContactIndex");
|
||||
assertThat(ClassPathManager.getClassName(AllocationToken.class)).isEqualTo("AllocationToken");
|
||||
assertThat(ClassPathManager.getClassName(RdeRevision.class)).isEqualTo("RdeRevision");
|
||||
assertThat(ClassPathManager.getClassName(Host.class)).isEqualTo("Host");
|
||||
assertThat(ClassPathManager.getClassName(Registrar.class)).isEqualTo("Registrar");
|
||||
assertThat(ClassPathManager.getClassName(Contact.class)).isEqualTo("Contact");
|
||||
assertThat(ClassPathManager.getClassName(GaeUserIdConverter.class))
|
||||
.isEqualTo("GaeUserIdConverter");
|
||||
assertThat(ClassPathManager.getClassName(EppResourceIndexBucket.class))
|
||||
.isEqualTo("EppResourceIndexBucket");
|
||||
assertThat(ClassPathManager.getClassName(EntityGroupRoot.class)).isEqualTo("EntityGroupRoot");
|
||||
assertThat(ClassPathManager.getClassName(Lock.class)).isEqualTo("Lock");
|
||||
assertThat(ClassPathManager.getClassName(Domain.class)).isEqualTo("Domain");
|
||||
assertThat(ClassPathManager.getClassName(HistoryEntry.class)).isEqualTo("HistoryEntry");
|
||||
assertThat(ClassPathManager.getClassName(ForeignKeyHostIndex.class))
|
||||
.isEqualTo("ForeignKeyHostIndex");
|
||||
assertThat(ClassPathManager.getClassName(ServerSecret.class)).isEqualTo("ServerSecret");
|
||||
assertThat(ClassPathManager.getClassName(EppResourceIndex.class)).isEqualTo("EppResourceIndex");
|
||||
assertThat(ClassPathManager.getClassName(ForeignKeyDomainIndex.class))
|
||||
.isEqualTo("ForeignKeyDomainIndex");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
// Copyright 2022 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.model.console;
|
||||
|
||||
import static google.registry.model.ImmutableObjectSubject.assertAboutImmutableObjects;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
import com.google.common.truth.Truth8;
|
||||
import google.registry.model.EntityTestCase;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/** Tests for {@link UserDao}. */
|
||||
public class UserDaoTest extends EntityTestCase {
|
||||
|
||||
@Test
|
||||
void testSuccess_saveAndRetrieve() {
|
||||
User user1 =
|
||||
new User.Builder()
|
||||
.setEmailAddress("email@email.com")
|
||||
.setGaiaId("gaiaId")
|
||||
.setUserRoles(new UserRoles.Builder().setGlobalRole(GlobalRole.SUPPORT_AGENT).build())
|
||||
.build();
|
||||
User user2 =
|
||||
new User.Builder()
|
||||
.setEmailAddress("foo@bar.com")
|
||||
.setGaiaId("otherId")
|
||||
.setUserRoles(new UserRoles.Builder().setGlobalRole(GlobalRole.SUPPORT_AGENT).build())
|
||||
.build();
|
||||
UserDao.saveUser(user1);
|
||||
UserDao.saveUser(user2);
|
||||
assertAboutImmutableObjects()
|
||||
.that(user1)
|
||||
.isEqualExceptFields(UserDao.loadUser("email@email.com").get(), "id", "updateTimestamp");
|
||||
assertAboutImmutableObjects()
|
||||
.that(user2)
|
||||
.isEqualExceptFields(UserDao.loadUser("foo@bar.com").get(), "id", "updateTimestamp");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSuccess_absentUser() {
|
||||
User user =
|
||||
new User.Builder()
|
||||
.setEmailAddress("email@email.com")
|
||||
.setGaiaId("gaiaId")
|
||||
.setUserRoles(new UserRoles.Builder().setGlobalRole(GlobalRole.SUPPORT_AGENT).build())
|
||||
.build();
|
||||
UserDao.saveUser(user);
|
||||
User fromDb = UserDao.loadUser("email@email.com").get();
|
||||
// nonexistent one should never exist
|
||||
Truth8.assertThat(UserDao.loadUser("nonexistent@email.com")).isEmpty();
|
||||
// now try deleting the one that does exist
|
||||
jpaTm().transact(() -> jpaTm().delete(fromDb));
|
||||
Truth8.assertThat(UserDao.loadUser("email@email.com")).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFailure_sameEmail() {
|
||||
User user1 =
|
||||
new User.Builder()
|
||||
.setEmailAddress("email@email.com")
|
||||
.setGaiaId("gaiaId")
|
||||
.setUserRoles(new UserRoles.Builder().setGlobalRole(GlobalRole.SUPPORT_AGENT).build())
|
||||
.build();
|
||||
User user2 =
|
||||
new User.Builder()
|
||||
.setEmailAddress("email@email.com")
|
||||
.setGaiaId("otherId")
|
||||
.setUserRoles(new UserRoles.Builder().setGlobalRole(GlobalRole.SUPPORT_AGENT).build())
|
||||
.build();
|
||||
UserDao.saveUser(user1);
|
||||
assertThrows(IllegalArgumentException.class, () -> UserDao.saveUser(user2));
|
||||
assertAboutImmutableObjects()
|
||||
.that(user1)
|
||||
.isEqualExceptFields(UserDao.loadUser("email@email.com").get(), "id", "updateTimestamp");
|
||||
}
|
||||
}
|
||||
@@ -15,8 +15,8 @@
|
||||
package google.registry.model.console;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.model.ImmutableObjectSubject.assertAboutImmutableObjects;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
|
||||
import static google.registry.testing.DatabaseHelper.persistResource;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
import google.registry.model.EntityTestCase;
|
||||
@@ -29,32 +29,6 @@ public class UserTest extends EntityTestCase {
|
||||
super(JpaEntityCoverageCheck.ENABLED);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testPersistence_lookupByEmail() {
|
||||
User user =
|
||||
new User.Builder()
|
||||
.setGaiaId("gaiaId")
|
||||
.setEmailAddress("email@email.com")
|
||||
.setUserRoles(
|
||||
new UserRoles.Builder().setGlobalRole(GlobalRole.FTE).setIsAdmin(true).build())
|
||||
.build();
|
||||
persistResource(user);
|
||||
jpaTm()
|
||||
.transact(
|
||||
() -> {
|
||||
assertThat(
|
||||
jpaTm()
|
||||
.query("FROM User WHERE emailAddress = 'email@email.com'", User.class)
|
||||
.getSingleResult())
|
||||
.isEqualTo(user);
|
||||
assertThat(
|
||||
jpaTm()
|
||||
.query("FROM User WHERE emailAddress = 'bad@fake.com'", User.class)
|
||||
.getResultList())
|
||||
.isEmpty();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void testPersistence_lookupByGaiaId() {
|
||||
User user =
|
||||
@@ -64,15 +38,16 @@ public class UserTest extends EntityTestCase {
|
||||
.setUserRoles(
|
||||
new UserRoles.Builder().setGlobalRole(GlobalRole.FTE).setIsAdmin(true).build())
|
||||
.build();
|
||||
persistResource(user);
|
||||
jpaTm().transact(() -> jpaTm().put(user));
|
||||
jpaTm()
|
||||
.transact(
|
||||
() -> {
|
||||
assertThat(
|
||||
assertAboutImmutableObjects()
|
||||
.that(
|
||||
jpaTm()
|
||||
.query("FROM User WHERE gaiaId = 'gaiaId'", User.class)
|
||||
.getSingleResult())
|
||||
.isEqualTo(user);
|
||||
.isEqualExceptFields(user, "id", "updateTimestamp");
|
||||
assertThat(
|
||||
jpaTm()
|
||||
.query("FROM User WHERE gaiaId = 'badGaiaId'", User.class)
|
||||
|
||||
@@ -222,8 +222,7 @@ public class AllocationTokenTest extends EntityTestCase {
|
||||
.setToken("abc123")
|
||||
.setTokenType(TokenType.PACKAGE)
|
||||
.setRenewalPriceBehavior(RenewalPriceBehavior.DEFAULT);
|
||||
IllegalArgumentException thrown =
|
||||
assertThrows(IllegalArgumentException.class, () -> builder.build());
|
||||
IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, builder::build);
|
||||
assertThat(thrown)
|
||||
.hasMessageThat()
|
||||
.isEqualTo("Package tokens must have renewalPriceBehavior set to SPECIFIED");
|
||||
@@ -280,7 +279,7 @@ public class AllocationTokenTest extends EntityTestCase {
|
||||
|
||||
@Test
|
||||
void testBuild_onlyOneClientInPackage() {
|
||||
Buildable.Builder builder =
|
||||
Buildable.Builder<AllocationToken> builder =
|
||||
new AllocationToken.Builder()
|
||||
.setToken("foobar")
|
||||
.setTokenType(PACKAGE)
|
||||
@@ -531,7 +530,7 @@ public class AllocationTokenTest extends EntityTestCase {
|
||||
}
|
||||
|
||||
private void assertTerminal(TokenStatus status) {
|
||||
// The "terminal" message is slightly different so it must be tested separately
|
||||
// The "terminal" message is slightly different, so it must be tested separately
|
||||
IllegalArgumentException thrown =
|
||||
assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
|
||||
@@ -15,17 +15,13 @@
|
||||
package google.registry.model.index;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.testing.DatabaseHelper.createTld;
|
||||
import static google.registry.testing.DatabaseHelper.persistActiveHost;
|
||||
import static google.registry.testing.DatabaseHelper.persistResource;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import google.registry.model.EntityTestCase;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.host.Host;
|
||||
import google.registry.model.index.ForeignKeyIndex.ForeignKeyHostIndex;
|
||||
import google.registry.testing.DatabaseHelper;
|
||||
import google.registry.testing.TestCacheExtension;
|
||||
import java.time.Duration;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
@@ -44,16 +40,6 @@ class ForeignKeyIndexTest extends EntityTestCase {
|
||||
createTld("com");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testModifyForeignKeyIndex_notThrowExceptionInSql() {
|
||||
Domain domain = DatabaseHelper.newDomain("test.com");
|
||||
ForeignKeyIndex<Domain> fki = ForeignKeyIndex.create(domain, fakeClock.nowUtc());
|
||||
tm().transact(() -> tm().insert(fki));
|
||||
tm().transact(() -> tm().put(fki));
|
||||
tm().transact(() -> tm().delete(fki));
|
||||
tm().transact(() -> tm().update(fki));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testLoadForNonexistentForeignKey_returnsNull() {
|
||||
assertThat(ForeignKeyIndex.load(Host.class, "ns1.example.com", fakeClock.nowUtc())).isNull();
|
||||
@@ -62,11 +48,7 @@ class ForeignKeyIndexTest extends EntityTestCase {
|
||||
@Test
|
||||
void testLoadForDeletedForeignKey_returnsNull() {
|
||||
Host host = persistActiveHost("ns1.example.com");
|
||||
if (tm().isOfy()) {
|
||||
persistResource(ForeignKeyIndex.create(host, fakeClock.nowUtc().minusDays(1)));
|
||||
} else {
|
||||
persistResource(host.asBuilder().setDeletionTime(fakeClock.nowUtc().minusDays(1)).build());
|
||||
}
|
||||
persistResource(host.asBuilder().setDeletionTime(fakeClock.nowUtc().minusDays(1)).build());
|
||||
assertThat(ForeignKeyIndex.load(Host.class, "ns1.example.com", fakeClock.nowUtc())).isNull();
|
||||
}
|
||||
|
||||
@@ -74,15 +56,7 @@ class ForeignKeyIndexTest extends EntityTestCase {
|
||||
void testLoad_newerKeyHasBeenSoftDeleted() {
|
||||
Host host1 = persistActiveHost("ns1.example.com");
|
||||
fakeClock.advanceOneMilli();
|
||||
if (tm().isOfy()) {
|
||||
ForeignKeyHostIndex fki = new ForeignKeyHostIndex();
|
||||
fki.foreignKey = "ns1.example.com";
|
||||
fki.topReference = host1.createVKey();
|
||||
fki.deletionTime = fakeClock.nowUtc();
|
||||
persistResource(fki);
|
||||
} else {
|
||||
persistResource(host1.asBuilder().setDeletionTime(fakeClock.nowUtc()).build());
|
||||
}
|
||||
persistResource(host1.asBuilder().setDeletionTime(fakeClock.nowUtc()).build());
|
||||
assertThat(ForeignKeyIndex.load(Host.class, "ns1.example.com", fakeClock.nowUtc())).isNull();
|
||||
}
|
||||
|
||||
@@ -90,11 +64,7 @@ class ForeignKeyIndexTest extends EntityTestCase {
|
||||
void testBatchLoad_skipsDeletedAndNonexistent() {
|
||||
persistActiveHost("ns1.example.com");
|
||||
Host host = persistActiveHost("ns2.example.com");
|
||||
if (tm().isOfy()) {
|
||||
persistResource(ForeignKeyIndex.create(host, fakeClock.nowUtc().minusDays(1)));
|
||||
} else {
|
||||
persistResource(host.asBuilder().setDeletionTime(fakeClock.nowUtc().minusDays(1)).build());
|
||||
}
|
||||
persistResource(host.asBuilder().setDeletionTime(fakeClock.nowUtc().minusDays(1)).build());
|
||||
assertThat(
|
||||
ForeignKeyIndex.load(
|
||||
Host.class,
|
||||
|
||||
@@ -1,348 +0,0 @@
|
||||
// Copyright 2017 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.model.ofy;
|
||||
|
||||
import static com.google.appengine.api.datastore.DatastoreServiceFactory.getDatastoreService;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static com.google.common.util.concurrent.Uninterruptibles.sleepUninterruptibly;
|
||||
import static google.registry.model.ImmutableObjectSubject.assertAboutImmutableObjects;
|
||||
import static google.registry.model.common.EntityGroupRoot.getCrossTldKey;
|
||||
import static google.registry.model.ofy.ObjectifyService.auditedOfy;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.model.ofy.Ofy.getBaseEntityClassFromEntityOrKey;
|
||||
import static google.registry.testing.DatabaseHelper.newContact;
|
||||
import static google.registry.util.DateTimeUtils.END_OF_TIME;
|
||||
import static google.registry.util.DateTimeUtils.START_OF_TIME;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
import com.google.appengine.api.datastore.DatastoreFailureException;
|
||||
import com.google.appengine.api.datastore.DatastoreTimeoutException;
|
||||
import com.google.appengine.api.datastore.Entity;
|
||||
import com.google.appengine.api.taskqueue.TransientFailureException;
|
||||
import com.googlecode.objectify.Key;
|
||||
import com.googlecode.objectify.annotation.Id;
|
||||
import com.googlecode.objectify.annotation.OnLoad;
|
||||
import com.googlecode.objectify.annotation.OnSave;
|
||||
import com.googlecode.objectify.annotation.Parent;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.model.contact.ContactHistory;
|
||||
import google.registry.model.eppcommon.Trid;
|
||||
import google.registry.model.reporting.HistoryEntry;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.util.SystemClock;
|
||||
import java.util.ConcurrentModificationException;
|
||||
import java.util.function.Supplier;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
/** Tests for our wrapper around Objectify. */
|
||||
@Disabled
|
||||
public class OfyTest {
|
||||
|
||||
private final FakeClock fakeClock = new FakeClock(DateTime.parse("2000-01-01TZ"));
|
||||
|
||||
@RegisterExtension
|
||||
public final AppEngineExtension appEngine =
|
||||
AppEngineExtension.builder().withCloudSql().withClock(fakeClock).build();
|
||||
|
||||
/** An entity to use in save and delete tests. */
|
||||
private HistoryEntry someObject;
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() {
|
||||
someObject =
|
||||
new ContactHistory.Builder()
|
||||
.setRegistrarId("clientid")
|
||||
.setModificationTime(START_OF_TIME)
|
||||
.setType(HistoryEntry.Type.CONTACT_CREATE)
|
||||
.setContact(newContact("parentContact"))
|
||||
.setTrid(Trid.create("client", "server"))
|
||||
.setXmlBytes("<xml></xml>".getBytes(UTF_8))
|
||||
.build();
|
||||
// This can't be initialized earlier because namespaces need the AppEngineExtension to work.
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSavingKeyTwiceInOneCall() {
|
||||
assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> ofy().transact(() -> auditedOfy().save().entities(someObject, someObject)));
|
||||
}
|
||||
|
||||
/** Simple entity class with lifecycle callbacks. */
|
||||
@com.googlecode.objectify.annotation.Entity
|
||||
public static class LifecycleObject extends ImmutableObject {
|
||||
|
||||
@Parent Key<?> parent = getCrossTldKey();
|
||||
|
||||
@Id long id = 1;
|
||||
|
||||
boolean onLoadCalled;
|
||||
boolean onSaveCalled;
|
||||
|
||||
@OnLoad
|
||||
public void load() {
|
||||
onLoadCalled = true;
|
||||
}
|
||||
|
||||
@OnSave
|
||||
public void save() {
|
||||
onSaveCalled = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testLifecycleCallbacks_loadFromEntity() {
|
||||
auditedOfy().factory().register(LifecycleObject.class);
|
||||
LifecycleObject object = new LifecycleObject();
|
||||
Entity entity = auditedOfy().save().toEntity(object);
|
||||
assertThat(object.onSaveCalled).isTrue();
|
||||
assertThat(auditedOfy().load().<LifecycleObject>fromEntity(entity).onLoadCalled).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testLifecycleCallbacks_loadFromDatastore() {
|
||||
auditedOfy().factory().register(LifecycleObject.class);
|
||||
final LifecycleObject object = new LifecycleObject();
|
||||
ofy().transact(() -> auditedOfy().save().entity(object).now());
|
||||
assertThat(object.onSaveCalled).isTrue();
|
||||
auditedOfy().clearSessionCache();
|
||||
assertThat(auditedOfy().load().entity(object).now().onLoadCalled).isTrue();
|
||||
}
|
||||
|
||||
/** Avoid regressions of b/21309102 where transaction time did not change on each retry. */
|
||||
@Test
|
||||
void testTransact_getsNewTimestampOnEachTry() {
|
||||
ofy()
|
||||
.transact(
|
||||
new Runnable() {
|
||||
|
||||
DateTime firstAttemptTime;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (firstAttemptTime == null) {
|
||||
// Sleep a bit to ensure that the next attempt is at a new millisecond.
|
||||
firstAttemptTime = ofy().getTransactionTime();
|
||||
sleepUninterruptibly(java.time.Duration.ofMillis(10));
|
||||
throw new ConcurrentModificationException();
|
||||
}
|
||||
assertThat(ofy().getTransactionTime()).isGreaterThan(firstAttemptTime);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void testTransact_transientFailureException_retries() {
|
||||
assertThat(
|
||||
ofy()
|
||||
.transact(
|
||||
new Supplier<Integer>() {
|
||||
|
||||
int count = 0;
|
||||
|
||||
@Override
|
||||
public Integer get() {
|
||||
count++;
|
||||
if (count == 3) {
|
||||
return count;
|
||||
}
|
||||
throw new TransientFailureException("");
|
||||
}
|
||||
}))
|
||||
.isEqualTo(3);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testTransact_datastoreTimeoutException_noManifest_retries() {
|
||||
assertThat(
|
||||
ofy()
|
||||
.transact(
|
||||
new Supplier<Integer>() {
|
||||
|
||||
int count = 0;
|
||||
|
||||
@Override
|
||||
public Integer get() {
|
||||
// We don't write anything in this transaction, so there is no commit log
|
||||
// manifest.
|
||||
// Therefore it's always safe to retry since nothing got written.
|
||||
count++;
|
||||
if (count == 3) {
|
||||
return count;
|
||||
}
|
||||
throw new DatastoreTimeoutException("");
|
||||
}
|
||||
}))
|
||||
.isEqualTo(3);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testTransact_datastoreTimeoutException_manifestNotWrittenToDatastore_retries() {
|
||||
assertThat(
|
||||
ofy()
|
||||
.transact(
|
||||
new Supplier<Integer>() {
|
||||
|
||||
int count = 0;
|
||||
|
||||
@Override
|
||||
public Integer get() {
|
||||
// There will be something in the manifest now, but it won't be committed if
|
||||
// we throw.
|
||||
auditedOfy().save().entity(someObject.asHistoryEntry());
|
||||
count++;
|
||||
if (count == 3) {
|
||||
return count;
|
||||
}
|
||||
throw new DatastoreTimeoutException("");
|
||||
}
|
||||
}))
|
||||
.isEqualTo(3);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testTransact_datastoreTimeoutException_manifestWrittenToDatastore_returnsSuccess() {
|
||||
// A work unit that throws if it is ever retried.
|
||||
Supplier work =
|
||||
new Supplier<Void>() {
|
||||
boolean firstCallToVrun = true;
|
||||
|
||||
@Override
|
||||
public Void get() {
|
||||
if (firstCallToVrun) {
|
||||
firstCallToVrun = false;
|
||||
auditedOfy().save().entity(someObject.asHistoryEntry());
|
||||
return null;
|
||||
}
|
||||
fail("Shouldn't have retried.");
|
||||
return null;
|
||||
}
|
||||
};
|
||||
// A commit logged work that throws on the first attempt to get its result.
|
||||
CommitLoggedWork<Void> commitLoggedWork =
|
||||
new CommitLoggedWork<Void>(work, new SystemClock()) {
|
||||
boolean firstCallToGetResult = true;
|
||||
|
||||
@Override
|
||||
public Void getResult() {
|
||||
if (firstCallToGetResult) {
|
||||
firstCallToGetResult = false;
|
||||
throw new DatastoreTimeoutException("");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
// Despite the DatastoreTimeoutException in the first call to getResult(), this should succeed
|
||||
// without retrying. If a retry is triggered, the test should fail due to the call to fail().
|
||||
auditedOfy().transactCommitLoggedWork(commitLoggedWork);
|
||||
}
|
||||
|
||||
void doReadOnlyRetryTest(final RuntimeException e) {
|
||||
assertThat(
|
||||
ofy()
|
||||
.transactNewReadOnly(
|
||||
new Supplier<Integer>() {
|
||||
|
||||
int count = 0;
|
||||
|
||||
@Override
|
||||
public Integer get() {
|
||||
count++;
|
||||
if (count == 3) {
|
||||
return count;
|
||||
}
|
||||
throw new TransientFailureException("");
|
||||
}
|
||||
}))
|
||||
.isEqualTo(3);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testTransactNewReadOnly_transientFailureException_retries() {
|
||||
doReadOnlyRetryTest(new TransientFailureException(""));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testTransactNewReadOnly_datastoreTimeoutException_retries() {
|
||||
doReadOnlyRetryTest(new DatastoreTimeoutException(""));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testTransactNewReadOnly_datastoreFailureException_retries() {
|
||||
doReadOnlyRetryTest(new DatastoreFailureException(""));
|
||||
}
|
||||
|
||||
@Test
|
||||
void test_getBaseEntityClassFromEntityOrKey_regularEntity() {
|
||||
Contact contact = newContact("testcontact");
|
||||
assertThat(getBaseEntityClassFromEntityOrKey(contact)).isEqualTo(Contact.class);
|
||||
assertThat(getBaseEntityClassFromEntityOrKey(Key.create(contact))).isEqualTo(Contact.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void test_getBaseEntityClassFromEntityOrKey_unregisteredEntity() {
|
||||
IllegalStateException thrown =
|
||||
assertThrows(
|
||||
IllegalStateException.class,
|
||||
() -> getBaseEntityClassFromEntityOrKey(new SystemClock()));
|
||||
assertThat(thrown).hasMessageThat().contains("SystemClock");
|
||||
}
|
||||
|
||||
@Test
|
||||
void test_getBaseEntityClassFromEntityOrKey_unregisteredEntityKey() {
|
||||
IllegalArgumentException thrown =
|
||||
assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() ->
|
||||
getBaseEntityClassFromEntityOrKey(
|
||||
Key.create(
|
||||
com.google.appengine.api.datastore.KeyFactory.createKey(
|
||||
"UnknownKind", 1))));
|
||||
assertThat(thrown).hasMessageThat().contains("UnknownKind");
|
||||
}
|
||||
|
||||
@Test
|
||||
void test_doWithFreshSessionCache() {
|
||||
auditedOfy().saveWithoutBackup().entity(someObject.asHistoryEntry()).now();
|
||||
final HistoryEntry modifiedObject =
|
||||
someObject.asBuilder().setModificationTime(END_OF_TIME).build();
|
||||
// Mutate the saved objected, bypassing the Objectify session cache.
|
||||
getDatastoreService()
|
||||
.put(auditedOfy().saveWithoutBackup().toEntity(modifiedObject.asHistoryEntry()));
|
||||
// Normal loading should come from the session cache and shouldn't reflect the mutation.
|
||||
assertThat(auditedOfy().load().entity(someObject).now()).isEqualTo(someObject.asHistoryEntry());
|
||||
// Loading inside doWithFreshSessionCache() should reflect the mutation.
|
||||
boolean ran =
|
||||
auditedOfy()
|
||||
.doWithFreshSessionCache(
|
||||
() -> {
|
||||
assertAboutImmutableObjects()
|
||||
.that(auditedOfy().load().entity(someObject).now())
|
||||
.isEqualExceptFields(modifiedObject, "contactBase");
|
||||
return true;
|
||||
});
|
||||
assertThat(ran).isTrue();
|
||||
// Test the normal loading again to verify that we've restored the original session unchanged.
|
||||
assertThat(auditedOfy().load().entity(someObject).now()).isEqualTo(someObject.asHistoryEntry());
|
||||
}
|
||||
}
|
||||
@@ -121,8 +121,7 @@ public class RdeRevisionTest extends EntityTestCase {
|
||||
}
|
||||
|
||||
public static void save(String tld, DateTime date, RdeMode mode, int revision) {
|
||||
String triplet = RdeNamingUtils.makePartialName(tld, date, mode);
|
||||
RdeRevision object = RdeRevision.create(triplet, tld, date.toLocalDate(), mode, revision);
|
||||
RdeRevision object = RdeRevision.create(tld, date.toLocalDate(), mode, revision);
|
||||
tm().transact(() -> tm().put(object));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,7 +49,8 @@ public class LockTest extends EntityTestCase {
|
||||
super(JpaEntityCoverageCheck.ENABLED);
|
||||
}
|
||||
|
||||
private Optional<Lock> acquire(String tld, Duration leaseLength, LockState expectedLockState) {
|
||||
private static Optional<Lock> acquire(
|
||||
String tld, Duration leaseLength, LockState expectedLockState) {
|
||||
Lock.lockMetrics = mock(LockMetrics.class);
|
||||
Optional<Lock> lock = Lock.acquire(RESOURCE_NAME, tld, leaseLength, requestStatusChecker, true);
|
||||
verify(Lock.lockMetrics).recordAcquire(RESOURCE_NAME, tld, expectedLockState);
|
||||
@@ -58,7 +59,7 @@ public class LockTest extends EntityTestCase {
|
||||
return lock;
|
||||
}
|
||||
|
||||
private void release(Lock lock, String expectedTld, long expectedMillis) {
|
||||
private static void release(Lock lock, String expectedTld, long expectedMillis) {
|
||||
Lock.lockMetrics = mock(LockMetrics.class);
|
||||
lock.release();
|
||||
verify(Lock.lockMetrics)
|
||||
|
||||
@@ -15,20 +15,16 @@
|
||||
package google.registry.persistence;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.model.common.EntityGroupRoot.getCrossTldKey;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
|
||||
import com.googlecode.objectify.Key;
|
||||
import com.googlecode.objectify.annotation.Entity;
|
||||
import com.googlecode.objectify.annotation.Id;
|
||||
import com.googlecode.objectify.annotation.Parent;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.common.EntityGroupRoot;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.domain.DomainHistory.DomainHistoryId;
|
||||
import google.registry.model.reporting.HistoryEntry;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import javax.persistence.Transient;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
@@ -74,7 +70,6 @@ class DomainHistoryVKeyTest {
|
||||
@Entity
|
||||
@javax.persistence.Entity(name = "TestEntity")
|
||||
private static class TestEntity extends ImmutableObject {
|
||||
@Transient @Parent Key<EntityGroupRoot> parent = getCrossTldKey();
|
||||
|
||||
@Id @javax.persistence.Id String id = "id";
|
||||
|
||||
|
||||
@@ -162,18 +162,14 @@ class VKeyTest {
|
||||
void testStringify_sqlAndOfyVKey() {
|
||||
assertThat(
|
||||
VKey.create(TestObject.class, "foo", Key.create(TestObject.create("foo"))).stringify())
|
||||
.isEqualTo(
|
||||
"kind:TestObject@sql:rO0ABXQAA2Zvbw@ofy:agR0ZXN0cjELEg9FbnRpdH"
|
||||
+ "lHcm91cFJvb3QiCWNyb3NzLXRsZAwLEgpUZXN0T2JqZWN0IgNmb28M");
|
||||
.isEqualTo("kind:TestObject@sql:rO0ABXQAA2Zvbw@ofy:agR0ZXN0chMLEgpUZXN0T2JqZWN0IgNmb28M");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testStringify_asymmetricVKey() {
|
||||
assertThat(
|
||||
VKey.create(TestObject.class, "test", Key.create(TestObject.create("foo"))).stringify())
|
||||
.isEqualTo(
|
||||
"kind:TestObject@sql:rO0ABXQABHRlc3Q@ofy:agR0ZXN0cjELEg9FbnRpd"
|
||||
+ "HlHcm91cFJvb3QiCWNyb3NzLXRsZAwLEgpUZXN0T2JqZWN0IgNmb28M");
|
||||
.isEqualTo("kind:TestObject@sql:rO0ABXQABHRlc3Q@ofy:agR0ZXN0chMLEgpUZXN0T2JqZWN0IgNmb28M");
|
||||
}
|
||||
|
||||
/** Test create() via different vkey string representations. */
|
||||
|
||||
@@ -44,7 +44,7 @@ final class LockHandlerImplTest {
|
||||
final AppEngineExtension appEngine = AppEngineExtension.builder().withCloudSql().build();
|
||||
|
||||
private static class CountingCallable implements Callable<Void> {
|
||||
int numCalled = 0;
|
||||
int numCalled;
|
||||
|
||||
@Override
|
||||
public Void call() {
|
||||
@@ -69,16 +69,11 @@ final class LockHandlerImplTest {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean executeWithLocks(Callable<Void> callable, final @Nullable Lock acquiredLock) {
|
||||
private boolean executeWithLocks(Callable<Void> callable, @Nullable final Lock acquiredLock) {
|
||||
return createTestLockHandler(acquiredLock)
|
||||
.executeWithLocks(callable, "tld", ONE_DAY, "resourceName");
|
||||
}
|
||||
|
||||
private boolean executeWithSqlLocks(Callable<Void> callable, final @Nullable Lock acquiredLock) {
|
||||
return createTestLockHandler(acquiredLock)
|
||||
.executeWithSqlLocks(callable, "tld", ONE_DAY, "resourceName");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testLockSucceeds() {
|
||||
Lock lock = mock(Lock.class);
|
||||
@@ -88,15 +83,6 @@ final class LockHandlerImplTest {
|
||||
verify(lock, times(1)).release();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSqlLockSucceeds() {
|
||||
Lock lock = mock(Lock.class);
|
||||
CountingCallable countingCallable = new CountingCallable();
|
||||
assertThat(executeWithSqlLocks(countingCallable, lock)).isTrue();
|
||||
assertThat(countingCallable.numCalled).isEqualTo(1);
|
||||
verify(lock, times(1)).release();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testLockSucceeds_uncheckedException() {
|
||||
Lock lock = mock(Lock.class);
|
||||
@@ -157,11 +143,6 @@ final class LockHandlerImplTest {
|
||||
assertThat(leaseLength).isEqualTo(ONE_DAY);
|
||||
return Optional.ofNullable(acquiredLock);
|
||||
}
|
||||
|
||||
@Override
|
||||
Optional<Lock> acquireSql(String resourceName, String tld, Duration leaseLength) {
|
||||
return acquire(resourceName, tld, leaseLength);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,7 +63,6 @@ import com.googlecode.objectify.Key;
|
||||
import google.registry.dns.writer.VoidDnsWriter;
|
||||
import google.registry.model.Buildable;
|
||||
import google.registry.model.EppResource;
|
||||
import google.registry.model.EppResource.ForeignKeyedEppResource;
|
||||
import google.registry.model.EppResourceUtils;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.billing.BillingEvent;
|
||||
@@ -91,7 +90,6 @@ import google.registry.model.eppcommon.Trid;
|
||||
import google.registry.model.host.Host;
|
||||
import google.registry.model.index.EppResourceIndex;
|
||||
import google.registry.model.index.EppResourceIndexBucket;
|
||||
import google.registry.model.index.ForeignKeyIndex;
|
||||
import google.registry.model.poll.PollMessage;
|
||||
import google.registry.model.pricing.StaticPremiumListPricingEngine;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
@@ -1011,9 +1009,6 @@ public class DatabaseHelper {
|
||||
.that(resource.getRepoId())
|
||||
.isNotEmpty();
|
||||
saver.accept(index);
|
||||
if (resource instanceof ForeignKeyedEppResource) {
|
||||
saver.accept(ForeignKeyIndex.create(resource, resource.getDeletionTime()));
|
||||
}
|
||||
}
|
||||
|
||||
/** Persists an object in the DB for tests. */
|
||||
|
||||
@@ -42,12 +42,6 @@ public class FakeLockHandler implements LockHandler {
|
||||
return execute(callable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean executeWithSqlLocks(
|
||||
Callable<Void> callable, @Nullable String tld, Duration leaseLength, String... lockNames) {
|
||||
return execute(callable);
|
||||
}
|
||||
|
||||
private boolean execute(Callable<Void> callable) {
|
||||
if (!lockSucceeds) {
|
||||
return false;
|
||||
|
||||
@@ -14,25 +14,18 @@
|
||||
|
||||
package google.registry.testing;
|
||||
|
||||
import static google.registry.model.common.EntityGroupRoot.getCrossTldKey;
|
||||
|
||||
import com.googlecode.objectify.Key;
|
||||
import com.googlecode.objectify.annotation.Entity;
|
||||
import com.googlecode.objectify.annotation.Id;
|
||||
import com.googlecode.objectify.annotation.Parent;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.annotations.VirtualEntity;
|
||||
import google.registry.model.common.EntityGroupRoot;
|
||||
import google.registry.persistence.VKey;
|
||||
import javax.persistence.Transient;
|
||||
|
||||
/** A test model object that can be persisted in any entity group. */
|
||||
@Entity
|
||||
@javax.persistence.Entity
|
||||
public class TestObject extends ImmutableObject {
|
||||
|
||||
@Parent @Transient Key<EntityGroupRoot> parent;
|
||||
|
||||
@Id @javax.persistence.Id String id;
|
||||
|
||||
String field;
|
||||
@@ -58,14 +51,9 @@ public class TestObject extends ImmutableObject {
|
||||
}
|
||||
|
||||
public static TestObject create(String id, String field) {
|
||||
return create(id, field, getCrossTldKey());
|
||||
}
|
||||
|
||||
public static TestObject create(String id, String field, Key<EntityGroupRoot> parent) {
|
||||
TestObject instance = new TestObject();
|
||||
instance.id = id;
|
||||
instance.field = field;
|
||||
instance.parent = parent;
|
||||
return instance;
|
||||
}
|
||||
|
||||
|
||||
@@ -28,13 +28,13 @@ import static org.joda.time.DateTimeZone.UTC;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.googlecode.objectify.Key;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.host.Host;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import java.util.Arrays;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Stream;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -119,19 +119,20 @@ public class MutatingCommandTest {
|
||||
@Test
|
||||
void testSuccess_create() throws Exception {
|
||||
ImmutableList<VKey<?>> keys =
|
||||
Arrays.asList(host1, host2, registrar1, registrar2).stream()
|
||||
.map(entity -> VKey.from(Key.create(entity)))
|
||||
Stream.of(host1, host2, registrar1, registrar2)
|
||||
.map(ImmutableObject::createVKey)
|
||||
.collect(toImmutableList());
|
||||
tm().transact(() -> tm().delete(keys));
|
||||
MutatingCommand command = new MutatingCommand() {
|
||||
@Override
|
||||
protected void init() {
|
||||
stageEntityChange(null, newHost1);
|
||||
stageEntityChange(null, newHost2);
|
||||
stageEntityChange(null, newRegistrar1);
|
||||
stageEntityChange(null, newRegistrar2);
|
||||
}
|
||||
};
|
||||
MutatingCommand command =
|
||||
new MutatingCommand() {
|
||||
@Override
|
||||
protected void init() {
|
||||
stageEntityChange(null, newHost1);
|
||||
stageEntityChange(null, newHost2);
|
||||
stageEntityChange(null, newRegistrar1);
|
||||
stageEntityChange(null, newRegistrar2);
|
||||
}
|
||||
};
|
||||
command.init();
|
||||
String changes = command.prompt();
|
||||
assertThat(changes)
|
||||
|
||||
@@ -366,7 +366,7 @@ class SetupOteCommandTest extends CommandTestCase<SetupOteCommand> {
|
||||
"--registrar=blobio",
|
||||
"--email=contact@email.com",
|
||||
"--certfile=" + getCertFilename()));
|
||||
assertThat(thrown).hasMessageThat().contains("VKey<Registrar>(sql:blobio-1,ofy:blobio-1)");
|
||||
assertThat(thrown).hasMessageThat().contains("VKey<Registrar>(sql:blobio-1)");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -1,45 +1,27 @@
|
||||
class google.registry.model.common.EntityGroupRoot {
|
||||
@Id java.lang.String id;
|
||||
}
|
||||
class google.registry.model.common.GaeUserIdConverter {
|
||||
@Id long id;
|
||||
com.google.appengine.api.users.User user;
|
||||
}
|
||||
class google.registry.model.contact.Contact {
|
||||
@Id java.lang.String repoId;
|
||||
google.registry.model.contact.ContactAuthInfo authInfo;
|
||||
google.registry.model.contact.ContactPhoneNumber fax;
|
||||
google.registry.model.contact.ContactPhoneNumber voice;
|
||||
google.registry.model.contact.Disclose disclose;
|
||||
google.registry.model.transfer.ContactTransferData transferData;
|
||||
java.lang.String contactId;
|
||||
java.lang.String creationClientId;
|
||||
java.lang.String currentSponsorClientId;
|
||||
java.lang.String email;
|
||||
java.lang.String lastEppUpdateClientId;
|
||||
java.lang.String searchName;
|
||||
java.util.Set<google.registry.model.eppcommon.StatusValue> status;
|
||||
org.joda.time.DateTime deletionTime;
|
||||
org.joda.time.DateTime lastEppUpdateTime;
|
||||
org.joda.time.DateTime lastTransferTime;
|
||||
}
|
||||
class google.registry.model.contact.ContactAuthInfo {
|
||||
google.registry.model.eppcommon.AuthInfo$PasswordAuth pw;
|
||||
}
|
||||
class google.registry.model.contact.ContactBase {
|
||||
@Id java.lang.String repoId;
|
||||
google.registry.model.contact.ContactAuthInfo authInfo;
|
||||
google.registry.model.contact.ContactPhoneNumber fax;
|
||||
google.registry.model.contact.ContactPhoneNumber voice;
|
||||
google.registry.model.contact.Disclose disclose;
|
||||
google.registry.model.transfer.ContactTransferData transferData;
|
||||
java.lang.String contactId;
|
||||
java.lang.String creationClientId;
|
||||
java.lang.String currentSponsorClientId;
|
||||
java.lang.String email;
|
||||
java.lang.String lastEppUpdateClientId;
|
||||
java.lang.String searchName;
|
||||
java.util.Set<google.registry.model.eppcommon.StatusValue> status;
|
||||
org.joda.time.DateTime deletionTime;
|
||||
org.joda.time.DateTime lastEppUpdateTime;
|
||||
org.joda.time.DateTime lastTransferTime;
|
||||
@@ -50,46 +32,19 @@ class google.registry.model.contact.ContactHistory {
|
||||
boolean bySuperuser;
|
||||
byte[] xmlBytes;
|
||||
google.registry.model.contact.ContactBase contactBase;
|
||||
google.registry.model.domain.Period period;
|
||||
google.registry.model.eppcommon.Trid trid;
|
||||
google.registry.model.reporting.HistoryEntry$Type type;
|
||||
java.lang.Boolean requestedByRegistrar;
|
||||
java.lang.String clientId;
|
||||
java.lang.String otherClientId;
|
||||
java.lang.String reason;
|
||||
java.util.Set<google.registry.model.reporting.DomainTransactionRecord> domainTransactionRecords;
|
||||
org.joda.time.DateTime modificationTime;
|
||||
}
|
||||
class google.registry.model.contact.ContactPhoneNumber {
|
||||
java.lang.String extension;
|
||||
java.lang.String phoneNumber;
|
||||
}
|
||||
class google.registry.model.contact.Disclose {
|
||||
google.registry.model.eppcommon.PresenceMarker email;
|
||||
google.registry.model.eppcommon.PresenceMarker fax;
|
||||
google.registry.model.eppcommon.PresenceMarker voice;
|
||||
java.lang.Boolean flag;
|
||||
java.util.List<google.registry.model.contact.Disclose$PostalInfoChoice> addr;
|
||||
java.util.List<google.registry.model.contact.Disclose$PostalInfoChoice> name;
|
||||
java.util.List<google.registry.model.contact.Disclose$PostalInfoChoice> org;
|
||||
}
|
||||
class google.registry.model.contact.Disclose$PostalInfoChoice {
|
||||
google.registry.model.contact.PostalInfo$Type type;
|
||||
}
|
||||
enum google.registry.model.contact.PostalInfo$Type {
|
||||
INTERNATIONALIZED;
|
||||
LOCALIZED;
|
||||
}
|
||||
class google.registry.model.domain.Domain {
|
||||
@Id java.lang.String repoId;
|
||||
google.registry.model.domain.DomainAuthInfo authInfo;
|
||||
google.registry.model.domain.launch.LaunchNotice launchNotice;
|
||||
google.registry.model.transfer.DomainTransferData transferData;
|
||||
google.registry.persistence.VKey<google.registry.model.contact.Contact> adminContact;
|
||||
google.registry.persistence.VKey<google.registry.model.contact.Contact> billingContact;
|
||||
google.registry.persistence.VKey<google.registry.model.contact.Contact> registrantContact;
|
||||
google.registry.persistence.VKey<google.registry.model.contact.Contact> techContact;
|
||||
google.registry.persistence.VKey<google.registry.model.domain.token.AllocationToken> currentPackageToken;
|
||||
google.registry.persistence.VKey<google.registry.model.poll.PollMessage$Autorenew> autorenewPollMessage;
|
||||
google.registry.persistence.VKey<google.registry.model.poll.PollMessage$OneTime> deletePollMessage;
|
||||
java.lang.String creationClientId;
|
||||
@@ -99,9 +54,6 @@ class google.registry.model.domain.Domain {
|
||||
java.lang.String lastEppUpdateClientId;
|
||||
java.lang.String smdId;
|
||||
java.lang.String tld;
|
||||
java.util.Set<google.registry.model.domain.GracePeriod> gracePeriods;
|
||||
java.util.Set<google.registry.model.domain.secdns.DelegationSignerData> dsData;
|
||||
java.util.Set<google.registry.model.eppcommon.StatusValue> status;
|
||||
java.util.Set<google.registry.persistence.VKey<google.registry.model.host.Host>> nsHosts;
|
||||
java.util.Set<java.lang.String> subordinateHosts;
|
||||
org.joda.time.DateTime autorenewEndTime;
|
||||
@@ -110,19 +62,12 @@ class google.registry.model.domain.Domain {
|
||||
org.joda.time.DateTime lastTransferTime;
|
||||
org.joda.time.DateTime registrationExpirationTime;
|
||||
}
|
||||
class google.registry.model.domain.DomainAuthInfo {
|
||||
google.registry.model.eppcommon.AuthInfo$PasswordAuth pw;
|
||||
}
|
||||
class google.registry.model.domain.DomainBase {
|
||||
@Id java.lang.String repoId;
|
||||
google.registry.model.domain.DomainAuthInfo authInfo;
|
||||
google.registry.model.domain.launch.LaunchNotice launchNotice;
|
||||
google.registry.model.transfer.DomainTransferData transferData;
|
||||
google.registry.persistence.VKey<google.registry.model.contact.Contact> adminContact;
|
||||
google.registry.persistence.VKey<google.registry.model.contact.Contact> billingContact;
|
||||
google.registry.persistence.VKey<google.registry.model.contact.Contact> registrantContact;
|
||||
google.registry.persistence.VKey<google.registry.model.contact.Contact> techContact;
|
||||
google.registry.persistence.VKey<google.registry.model.domain.token.AllocationToken> currentPackageToken;
|
||||
google.registry.persistence.VKey<google.registry.model.poll.PollMessage$Autorenew> autorenewPollMessage;
|
||||
google.registry.persistence.VKey<google.registry.model.poll.PollMessage$OneTime> deletePollMessage;
|
||||
java.lang.String creationClientId;
|
||||
@@ -132,9 +77,6 @@ class google.registry.model.domain.DomainBase {
|
||||
java.lang.String lastEppUpdateClientId;
|
||||
java.lang.String smdId;
|
||||
java.lang.String tld;
|
||||
java.util.Set<google.registry.model.domain.GracePeriod> gracePeriods;
|
||||
java.util.Set<google.registry.model.domain.secdns.DelegationSignerData> dsData;
|
||||
java.util.Set<google.registry.model.eppcommon.StatusValue> status;
|
||||
java.util.Set<google.registry.persistence.VKey<google.registry.model.host.Host>> nsHosts;
|
||||
java.util.Set<java.lang.String> subordinateHosts;
|
||||
org.joda.time.DateTime autorenewEndTime;
|
||||
@@ -149,132 +91,14 @@ class google.registry.model.domain.DomainHistory {
|
||||
boolean bySuperuser;
|
||||
byte[] xmlBytes;
|
||||
google.registry.model.domain.DomainBase domainBase;
|
||||
google.registry.model.domain.Period period;
|
||||
google.registry.model.eppcommon.Trid trid;
|
||||
google.registry.model.reporting.HistoryEntry$Type type;
|
||||
java.lang.Boolean requestedByRegistrar;
|
||||
java.lang.String clientId;
|
||||
java.lang.String otherClientId;
|
||||
java.lang.String reason;
|
||||
java.util.Set<google.registry.model.domain.GracePeriod$GracePeriodHistory> gracePeriodHistories;
|
||||
java.util.Set<google.registry.model.domain.secdns.DomainDsDataHistory> dsDataHistories;
|
||||
java.util.Set<google.registry.model.reporting.DomainTransactionRecord> domainTransactionRecords;
|
||||
java.util.Set<google.registry.persistence.VKey<google.registry.model.host.Host>> nsHosts;
|
||||
org.joda.time.DateTime modificationTime;
|
||||
}
|
||||
class google.registry.model.domain.GracePeriod {
|
||||
google.registry.model.domain.rgp.GracePeriodStatus type;
|
||||
java.lang.String clientId;
|
||||
long gracePeriodId;
|
||||
org.joda.time.DateTime expirationTime;
|
||||
}
|
||||
class google.registry.model.domain.GracePeriod$GracePeriodHistory {
|
||||
google.registry.model.domain.rgp.GracePeriodStatus type;
|
||||
java.lang.Long domainHistoryRevisionId;
|
||||
java.lang.Long gracePeriodHistoryRevisionId;
|
||||
java.lang.String clientId;
|
||||
long gracePeriodId;
|
||||
org.joda.time.DateTime expirationTime;
|
||||
}
|
||||
class google.registry.model.domain.Period {
|
||||
google.registry.model.domain.Period$Unit unit;
|
||||
java.lang.Integer value;
|
||||
}
|
||||
enum google.registry.model.domain.Period$Unit {
|
||||
MONTHS;
|
||||
YEARS;
|
||||
}
|
||||
class google.registry.model.domain.launch.LaunchNotice {
|
||||
google.registry.model.domain.launch.LaunchNotice$NoticeIdType noticeId;
|
||||
org.joda.time.DateTime acceptedTime;
|
||||
org.joda.time.DateTime expirationTime;
|
||||
}
|
||||
class google.registry.model.domain.launch.LaunchNotice$NoticeIdType {
|
||||
java.lang.String tcnId;
|
||||
java.lang.String validatorId;
|
||||
}
|
||||
enum google.registry.model.domain.rgp.GracePeriodStatus {
|
||||
ADD;
|
||||
AUTO_RENEW;
|
||||
PENDING_DELETE;
|
||||
PENDING_RESTORE;
|
||||
REDEMPTION;
|
||||
RENEW;
|
||||
TRANSFER;
|
||||
}
|
||||
class google.registry.model.domain.secdns.DelegationSignerData {
|
||||
byte[] digest;
|
||||
int algorithm;
|
||||
int digestType;
|
||||
int keyTag;
|
||||
}
|
||||
class google.registry.model.domain.secdns.DomainDsDataHistory {
|
||||
byte[] digest;
|
||||
int algorithm;
|
||||
int digestType;
|
||||
int keyTag;
|
||||
java.lang.Long domainHistoryRevisionId;
|
||||
java.lang.Long dsDataHistoryRevisionId;
|
||||
}
|
||||
class google.registry.model.domain.token.AllocationToken {
|
||||
@Id java.lang.String token;
|
||||
boolean discountPremiums;
|
||||
double discountFraction;
|
||||
google.registry.model.common.TimedTransitionProperty<google.registry.model.domain.token.AllocationToken$TokenStatus> tokenStatusTransitions;
|
||||
google.registry.model.domain.token.AllocationToken$RegistrationBehavior registrationBehavior;
|
||||
google.registry.model.domain.token.AllocationToken$TokenType tokenType;
|
||||
google.registry.persistence.DomainHistoryVKey redemptionHistoryEntry;
|
||||
int discountYears;
|
||||
java.lang.String domainName;
|
||||
java.util.Set<java.lang.String> allowedClientIds;
|
||||
java.util.Set<java.lang.String> allowedTlds;
|
||||
}
|
||||
enum google.registry.model.domain.token.AllocationToken$RegistrationBehavior {
|
||||
ANCHOR_TENANT;
|
||||
BYPASS_TLD_STATE;
|
||||
DEFAULT;
|
||||
}
|
||||
enum google.registry.model.domain.token.AllocationToken$TokenStatus {
|
||||
CANCELLED;
|
||||
ENDED;
|
||||
NOT_STARTED;
|
||||
VALID;
|
||||
}
|
||||
enum google.registry.model.domain.token.AllocationToken$TokenType {
|
||||
PACKAGE;
|
||||
SINGLE_USE;
|
||||
UNLIMITED_USE;
|
||||
}
|
||||
class google.registry.model.eppcommon.AuthInfo$PasswordAuth {
|
||||
java.lang.String repoId;
|
||||
java.lang.String value;
|
||||
}
|
||||
class google.registry.model.eppcommon.PresenceMarker {
|
||||
boolean marked;
|
||||
}
|
||||
enum google.registry.model.eppcommon.StatusValue {
|
||||
CLIENT_DELETE_PROHIBITED;
|
||||
CLIENT_HOLD;
|
||||
CLIENT_RENEW_PROHIBITED;
|
||||
CLIENT_TRANSFER_PROHIBITED;
|
||||
CLIENT_UPDATE_PROHIBITED;
|
||||
INACTIVE;
|
||||
LINKED;
|
||||
OK;
|
||||
PENDING_CREATE;
|
||||
PENDING_DELETE;
|
||||
PENDING_TRANSFER;
|
||||
PENDING_UPDATE;
|
||||
SERVER_DELETE_PROHIBITED;
|
||||
SERVER_HOLD;
|
||||
SERVER_RENEW_PROHIBITED;
|
||||
SERVER_TRANSFER_PROHIBITED;
|
||||
SERVER_UPDATE_PROHIBITED;
|
||||
}
|
||||
class google.registry.model.eppcommon.Trid {
|
||||
java.lang.String clientTransactionId;
|
||||
java.lang.String serverTransactionId;
|
||||
}
|
||||
class google.registry.model.host.Host {
|
||||
@Id java.lang.String repoId;
|
||||
google.registry.persistence.VKey<google.registry.model.domain.Domain> superordinateDomain;
|
||||
@@ -282,7 +106,6 @@ class google.registry.model.host.Host {
|
||||
java.lang.String currentSponsorClientId;
|
||||
java.lang.String fullyQualifiedHostName;
|
||||
java.lang.String lastEppUpdateClientId;
|
||||
java.util.Set<google.registry.model.eppcommon.StatusValue> status;
|
||||
java.util.Set<java.net.InetAddress> inetAddresses;
|
||||
org.joda.time.DateTime deletionTime;
|
||||
org.joda.time.DateTime lastEppUpdateTime;
|
||||
@@ -296,7 +119,6 @@ class google.registry.model.host.HostBase {
|
||||
java.lang.String currentSponsorClientId;
|
||||
java.lang.String fullyQualifiedHostName;
|
||||
java.lang.String lastEppUpdateClientId;
|
||||
java.util.Set<google.registry.model.eppcommon.StatusValue> status;
|
||||
java.util.Set<java.net.InetAddress> inetAddresses;
|
||||
org.joda.time.DateTime deletionTime;
|
||||
org.joda.time.DateTime lastEppUpdateTime;
|
||||
@@ -308,15 +130,12 @@ class google.registry.model.host.HostHistory {
|
||||
@Parent com.googlecode.objectify.Key<? extends google.registry.model.EppResource> parent;
|
||||
boolean bySuperuser;
|
||||
byte[] xmlBytes;
|
||||
google.registry.model.domain.Period period;
|
||||
google.registry.model.eppcommon.Trid trid;
|
||||
google.registry.model.host.HostBase hostBase;
|
||||
google.registry.model.reporting.HistoryEntry$Type type;
|
||||
java.lang.Boolean requestedByRegistrar;
|
||||
java.lang.String clientId;
|
||||
java.lang.String otherClientId;
|
||||
java.lang.String reason;
|
||||
java.util.Set<google.registry.model.reporting.DomainTransactionRecord> domainTransactionRecords;
|
||||
org.joda.time.DateTime modificationTime;
|
||||
}
|
||||
class google.registry.model.index.EppResourceIndex {
|
||||
@@ -328,119 +147,16 @@ class google.registry.model.index.EppResourceIndex {
|
||||
class google.registry.model.index.EppResourceIndexBucket {
|
||||
@Id long bucketId;
|
||||
}
|
||||
class google.registry.model.index.ForeignKeyIndex$ForeignKeyContactIndex {
|
||||
@Id java.lang.String foreignKey;
|
||||
google.registry.persistence.VKey<E> topReference;
|
||||
org.joda.time.DateTime deletionTime;
|
||||
}
|
||||
class google.registry.model.index.ForeignKeyIndex$ForeignKeyDomainIndex {
|
||||
@Id java.lang.String foreignKey;
|
||||
google.registry.persistence.VKey<E> topReference;
|
||||
org.joda.time.DateTime deletionTime;
|
||||
}
|
||||
class google.registry.model.index.ForeignKeyIndex$ForeignKeyHostIndex {
|
||||
@Id java.lang.String foreignKey;
|
||||
google.registry.persistence.VKey<E> topReference;
|
||||
org.joda.time.DateTime deletionTime;
|
||||
}
|
||||
class google.registry.model.rde.RdeRevision {
|
||||
@Id java.lang.String id;
|
||||
int revision;
|
||||
}
|
||||
class google.registry.model.registrar.Registrar {
|
||||
@Id java.lang.String clientIdentifier;
|
||||
@Parent com.googlecode.objectify.Key<google.registry.model.common.EntityGroupRoot> parent;
|
||||
boolean blockPremiumNames;
|
||||
boolean contactsRequireSyncing;
|
||||
boolean registryLockAllowed;
|
||||
google.registry.model.registrar.Registrar$State state;
|
||||
google.registry.model.registrar.Registrar$Type type;
|
||||
java.lang.Long ianaIdentifier;
|
||||
java.lang.String clientCertificate;
|
||||
java.lang.String clientCertificateHash;
|
||||
java.lang.String driveFolderId;
|
||||
java.lang.String emailAddress;
|
||||
java.lang.String failoverClientCertificate;
|
||||
java.lang.String failoverClientCertificateHash;
|
||||
java.lang.String faxNumber;
|
||||
java.lang.String icannReferralEmail;
|
||||
java.lang.String passwordHash;
|
||||
java.lang.String phoneNumber;
|
||||
java.lang.String phonePasscode;
|
||||
java.lang.String poNumber;
|
||||
java.lang.String registrarName;
|
||||
java.lang.String salt;
|
||||
java.lang.String url;
|
||||
java.lang.String whoisServer;
|
||||
java.util.List<google.registry.util.CidrAddressBlock> ipAddressWhitelist;
|
||||
java.util.Map<org.joda.money.CurrencyUnit, java.lang.String> billingAccountMap;
|
||||
java.util.Set<java.lang.String> allowedTlds;
|
||||
java.util.Set<java.lang.String> rdapBaseUrls;
|
||||
org.joda.time.DateTime lastCertificateUpdateTime;
|
||||
org.joda.time.DateTime lastExpiringCertNotificationSentDate;
|
||||
org.joda.time.DateTime lastExpiringFailoverCertNotificationSentDate;
|
||||
}
|
||||
enum google.registry.model.registrar.Registrar$State {
|
||||
ACTIVE;
|
||||
DISABLED;
|
||||
PENDING;
|
||||
SUSPENDED;
|
||||
}
|
||||
enum google.registry.model.registrar.Registrar$Type {
|
||||
EXTERNAL_MONITORING;
|
||||
INTERNAL;
|
||||
MONITORING;
|
||||
OTE;
|
||||
PDT;
|
||||
REAL;
|
||||
TEST;
|
||||
}
|
||||
class google.registry.model.reporting.DomainTransactionRecord {
|
||||
google.registry.model.reporting.DomainTransactionRecord$TransactionReportField reportField;
|
||||
java.lang.Integer reportAmount;
|
||||
java.lang.String tld;
|
||||
org.joda.time.DateTime reportingTime;
|
||||
}
|
||||
enum google.registry.model.reporting.DomainTransactionRecord$TransactionReportField {
|
||||
DELETED_DOMAINS_GRACE;
|
||||
DELETED_DOMAINS_NOGRACE;
|
||||
NET_ADDS_10_YR;
|
||||
NET_ADDS_1_YR;
|
||||
NET_ADDS_2_YR;
|
||||
NET_ADDS_3_YR;
|
||||
NET_ADDS_4_YR;
|
||||
NET_ADDS_5_YR;
|
||||
NET_ADDS_6_YR;
|
||||
NET_ADDS_7_YR;
|
||||
NET_ADDS_8_YR;
|
||||
NET_ADDS_9_YR;
|
||||
NET_RENEWS_10_YR;
|
||||
NET_RENEWS_1_YR;
|
||||
NET_RENEWS_2_YR;
|
||||
NET_RENEWS_3_YR;
|
||||
NET_RENEWS_4_YR;
|
||||
NET_RENEWS_5_YR;
|
||||
NET_RENEWS_6_YR;
|
||||
NET_RENEWS_7_YR;
|
||||
NET_RENEWS_8_YR;
|
||||
NET_RENEWS_9_YR;
|
||||
RESTORED_DOMAINS;
|
||||
TRANSFER_NACKED;
|
||||
TRANSFER_SUCCESSFUL;
|
||||
}
|
||||
class google.registry.model.reporting.HistoryEntry {
|
||||
@Id java.lang.Long id;
|
||||
@Parent com.googlecode.objectify.Key<? extends google.registry.model.EppResource> parent;
|
||||
boolean bySuperuser;
|
||||
byte[] xmlBytes;
|
||||
google.registry.model.domain.Period period;
|
||||
google.registry.model.eppcommon.Trid trid;
|
||||
google.registry.model.reporting.HistoryEntry$Type type;
|
||||
java.lang.Boolean requestedByRegistrar;
|
||||
java.lang.String clientId;
|
||||
java.lang.String otherClientId;
|
||||
java.lang.String reason;
|
||||
java.util.Set<google.registry.model.reporting.DomainTransactionRecord> domainTransactionRecords;
|
||||
org.joda.time.DateTime modificationTime;
|
||||
}
|
||||
enum google.registry.model.reporting.HistoryEntry$Type {
|
||||
@@ -472,48 +188,3 @@ enum google.registry.model.reporting.HistoryEntry$Type {
|
||||
RDE_IMPORT;
|
||||
SYNTHETIC;
|
||||
}
|
||||
class google.registry.model.server.Lock {
|
||||
@Id java.lang.String lockId;
|
||||
java.lang.String requestLogId;
|
||||
java.lang.String resourceName;
|
||||
java.lang.String tld;
|
||||
org.joda.time.DateTime acquiredTime;
|
||||
org.joda.time.DateTime expirationTime;
|
||||
}
|
||||
class google.registry.model.server.ServerSecret {
|
||||
@Id long id;
|
||||
@Parent com.googlecode.objectify.Key<google.registry.model.common.EntityGroupRoot> parent;
|
||||
long leastSignificant;
|
||||
long mostSignificant;
|
||||
}
|
||||
class google.registry.model.transfer.ContactTransferData {
|
||||
google.registry.model.eppcommon.Trid transferRequestTrid;
|
||||
google.registry.model.transfer.TransferStatus transferStatus;
|
||||
java.lang.String gainingClientId;
|
||||
java.lang.String losingClientId;
|
||||
org.joda.time.DateTime pendingTransferExpirationTime;
|
||||
org.joda.time.DateTime transferRequestTime;
|
||||
}
|
||||
class google.registry.model.transfer.DomainTransferData {
|
||||
google.registry.model.domain.Period transferPeriod;
|
||||
google.registry.model.eppcommon.Trid transferRequestTrid;
|
||||
google.registry.model.transfer.TransferStatus transferStatus;
|
||||
google.registry.persistence.VKey<google.registry.model.poll.PollMessage$Autorenew> serverApproveAutorenewPollMessage;
|
||||
java.lang.String gainingClientId;
|
||||
java.lang.String losingClientId;
|
||||
org.joda.time.DateTime pendingTransferExpirationTime;
|
||||
org.joda.time.DateTime transferRequestTime;
|
||||
org.joda.time.DateTime transferredRegistrationExpirationTime;
|
||||
}
|
||||
enum google.registry.model.transfer.TransferStatus {
|
||||
CLIENT_APPROVED;
|
||||
CLIENT_CANCELLED;
|
||||
CLIENT_REJECTED;
|
||||
PENDING;
|
||||
SERVER_APPROVED;
|
||||
SERVER_CANCELLED;
|
||||
}
|
||||
class google.registry.persistence.DomainHistoryVKey {
|
||||
java.lang.Long historyRevisionId;
|
||||
java.lang.String repoId;
|
||||
}
|
||||
|
||||
@@ -261,7 +261,7 @@ td.section {
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="property_name">generated on</td>
|
||||
<td class="property_value">2022-08-30 20:29:57.165769</td>
|
||||
<td class="property_value">2022-09-01 15:31:59.206925</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="property_name">last flyway file</td>
|
||||
@@ -284,7 +284,7 @@ td.section {
|
||||
generated on
|
||||
</text>
|
||||
<text text-anchor="start" x="3835.5" y="-10.8" font-family="Helvetica,sans-Serif" font-size="14.00">
|
||||
2022-08-30 20:29:57.165769
|
||||
2022-09-01 15:31:59.206925
|
||||
</text>
|
||||
<polygon fill="none" stroke="#888888" points="3748,-4 3748,-44 4013,-44 4013,-4 3748,-4" /> <!-- allocationtoken_a08ccbef -->
|
||||
<g id="node1" class="node">
|
||||
|
||||
@@ -261,7 +261,7 @@ td.section {
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="property_name">generated on</td>
|
||||
<td class="property_value">2022-08-30 20:29:55.057361</td>
|
||||
<td class="property_value">2022-09-01 15:31:54.876473</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="property_name">last flyway file</td>
|
||||
@@ -284,7 +284,7 @@ td.section {
|
||||
generated on
|
||||
</text>
|
||||
<text text-anchor="start" x="4519.5" y="-10.8" font-family="Helvetica,sans-Serif" font-size="14.00">
|
||||
2022-08-30 20:29:55.057361
|
||||
2022-09-01 15:31:54.876473
|
||||
</text>
|
||||
<polygon fill="none" stroke="#888888" points="4432,-4 4432,-44 4697,-44 4697,-4 4432,-4" /> <!-- allocationtoken_a08ccbef -->
|
||||
<g id="node1" class="node">
|
||||
|
||||
@@ -742,7 +742,8 @@
|
||||
);
|
||||
|
||||
create table "User" (
|
||||
id int8 not null,
|
||||
id bigserial not null,
|
||||
update_timestamp timestamptz,
|
||||
email_address text not null,
|
||||
gaia_id text not null,
|
||||
registry_lock_password_hash text,
|
||||
|
||||
@@ -28,7 +28,9 @@ import java.lang.reflect.Modifier;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/** Utilities methods related to reflection. */
|
||||
public class TypeUtils {
|
||||
public final class TypeUtils {
|
||||
|
||||
private TypeUtils() {}
|
||||
|
||||
/** A {@code TypeToken} that removes an ugly cast in the common cases of getting a known type. */
|
||||
public static class TypeInstantiator<T> extends TypeToken<T> {
|
||||
@@ -47,7 +49,8 @@ public class TypeUtils {
|
||||
}
|
||||
|
||||
public static <T> T instantiate(Class<? extends T> clazz) {
|
||||
checkArgument(Modifier.isPublic(clazz.getModifiers()),
|
||||
checkArgument(
|
||||
Modifier.isPublic(clazz.getModifiers()),
|
||||
"AppEngine's custom security manager won't let us reflectively access non-public types");
|
||||
try {
|
||||
return clazz.getConstructor().newInstance();
|
||||
@@ -59,14 +62,15 @@ public class TypeUtils {
|
||||
/**
|
||||
* Instantiate a class with the specified constructor argument.
|
||||
*
|
||||
* <p>Because we use arg1's type to lookup the constructor, this only works if arg1's class is
|
||||
* exactly the same type as the constructor argument. Subtypes are not allowed.
|
||||
* <p>Because we use {@code arg}'s type to look up the constructor, this only works if arg1's
|
||||
* class is exactly the same type as the constructor argument. Subtypes are not allowed.
|
||||
*/
|
||||
public static <T, U> T instantiate(Class<? extends T> clazz, U arg1) {
|
||||
checkArgument(Modifier.isPublic(clazz.getModifiers()),
|
||||
public static <T, U> T instantiate(Class<? extends T> clazz, U arg) {
|
||||
checkArgument(
|
||||
Modifier.isPublic(clazz.getModifiers()),
|
||||
"AppEngine's custom security manager won't let us reflectively access non-public types");
|
||||
try {
|
||||
return clazz.getConstructor(arg1.getClass()).newInstance(arg1);
|
||||
return clazz.getConstructor(arg.getClass()).newInstance(arg);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
@@ -106,8 +110,10 @@ public class TypeUtils {
|
||||
T enumField = (T) field.get(null);
|
||||
builder.put(field.getName(), enumField);
|
||||
} catch (IllegalArgumentException | IllegalAccessException e) {
|
||||
throw new RuntimeException(String.format(
|
||||
"Could not retrieve static final field mapping for %s", clazz.getName()), e);
|
||||
throw new RuntimeException(
|
||||
String.format(
|
||||
"Could not retrieve static final field mapping for %s", clazz.getName()),
|
||||
e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -115,8 +121,7 @@ public class TypeUtils {
|
||||
}
|
||||
|
||||
/** Returns a predicate that tests whether classes are annotated with the given annotation. */
|
||||
public static Predicate<Class<?>> hasAnnotation(
|
||||
final Class<? extends Annotation> annotation) {
|
||||
public static Predicate<Class<?>> hasAnnotation(final Class<? extends Annotation> annotation) {
|
||||
return clazz -> clazz.isAnnotationPresent(annotation);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user