java.time features it's own halted clock, called a fixed clock, we can
use that one.

On top of that the watcher xcontent parser does not need a clock at all,
just a timestamp when parsing happened.

Original commit: elastic/x-pack-elasticsearch@2061aeffe1
This commit is contained in:
Alexander Reelsen 2018-02-08 09:24:08 +01:00 committed by GitHub
parent 3102b94946
commit 064a0819d9
6 changed files with 29 additions and 92 deletions

View File

@ -1,47 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
package org.elasticsearch.xpack.common.time;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import java.time.Clock;
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZoneOffset;
public class HaltedClock extends Clock {
private final DateTime now;
public HaltedClock(DateTime now) {
this.now = now.toDateTime(DateTimeZone.UTC);
}
@Override
public ZoneId getZone() {
return ZoneOffset.UTC;
}
@Override
public Clock withZone(ZoneId zoneId) {
if (zoneId.equals(ZoneOffset.UTC)) {
return this;
}
throw new IllegalArgumentException("Halted clock time zone cannot be changed");
}
@Override
public long millis() {
return now.getMillis();
}
@Override
public Instant instant() {
return Instant.ofEpochMilli(now.getMillis());
}
}

View File

@ -15,6 +15,7 @@ import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.xpack.core.watcher.common.secret.Secret;
import org.elasticsearch.xpack.core.watcher.crypto.CryptoService;
import org.joda.time.DateTime;
import java.io.IOException;
import java.time.Clock;
@ -59,24 +60,17 @@ public class WatcherXContentParser implements XContentParser {
return new Secret(chars);
}
public static Clock clock(XContentParser parser) {
if (parser instanceof WatcherXContentParser) {
return ((WatcherXContentParser) parser).getClock();
}
return Clock.systemUTC();
}
private final Clock clock;
private final DateTime parseTime;
private final XContentParser parser;
@Nullable private final CryptoService cryptoService;
public WatcherXContentParser(XContentParser parser, Clock clock, @Nullable CryptoService cryptoService) {
this.clock = clock;
public WatcherXContentParser(XContentParser parser, DateTime parseTime, @Nullable CryptoService cryptoService) {
this.parseTime = parseTime;
this.parser = parser;
this.cryptoService = cryptoService;
}
public Clock getClock() { return clock; }
public DateTime getParseDateTime() { return parseTime; }
@Override
public XContentType contentType() {

View File

@ -22,7 +22,6 @@ import org.elasticsearch.xpack.core.watcher.support.xcontent.WatcherXContentPars
import org.joda.time.DateTime;
import java.io.IOException;
import java.time.Clock;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
@ -273,7 +272,7 @@ public class WatchStatus implements ToXContentObject, Streamable {
return builder.endObject();
}
public static WatchStatus parse(String watchId, XContentParser parser, Clock clock) throws IOException {
public static WatchStatus parse(String watchId, WatcherXContentParser parser) throws IOException {
State state = null;
ExecutionState executionState = null;
DateTime lastChecked = null;
@ -289,7 +288,7 @@ public class WatchStatus implements ToXContentObject, Streamable {
currentFieldName = parser.currentName();
} else if (Field.STATE.match(currentFieldName)) {
try {
state = State.parse(parser, clock);
state = State.parse(parser);
} catch (ElasticsearchParseException e) {
throw new ElasticsearchParseException("could not parse watch status for [{}]. failed to parse field [{}]",
e, watchId, currentFieldName);
@ -348,7 +347,7 @@ public class WatchStatus implements ToXContentObject, Streamable {
// this is to support old watches that weren't upgraded yet to
// contain the state
if (state == null) {
state = new State(true, new DateTime(WatcherXContentParser.clock(parser).millis(), UTC));
state = new State(true, parser.getParseDateTime());
}
actions = actions == null ? emptyMap() : unmodifiableMap(actions);
@ -381,12 +380,12 @@ public class WatchStatus implements ToXContentObject, Streamable {
return builder.endObject();
}
public static State parse(XContentParser parser, Clock clock) throws IOException {
public static State parse(XContentParser parser) throws IOException {
if (parser.currentToken() != XContentParser.Token.START_OBJECT) {
throw new ElasticsearchParseException("expected an object but found [{}] instead", parser.currentToken());
}
boolean active = true;
DateTime timestamp = new DateTime(clock.millis(), UTC);
DateTime timestamp = DateTime.now(UTC);
String currentFieldName = null;
XContentParser.Token token;
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {

View File

@ -6,11 +6,10 @@
package org.elasticsearch.xpack.security.authc.saml;
import java.time.Clock;
import java.time.Instant;
import java.time.ZoneOffset;
import org.elasticsearch.xpack.common.time.HaltedClock;
import org.hamcrest.Matchers;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.junit.Before;
import org.opensaml.saml.common.xml.SAMLConstants;
import org.opensaml.saml.saml2.core.LogoutRequest;
@ -67,8 +66,8 @@ public class SamlLogoutRequestMessageBuilderTests extends SamlTestCase {
"http://idp.example.com/saml/logout/artifact");
idpRole.getSingleLogoutServices().add(sloArtifact);
final DateTime now = DateTime.now(DateTimeZone.UTC);
final SamlLogoutRequestMessageBuilder builder = new SamlLogoutRequestMessageBuilder(new HaltedClock(now), sp, idp, nameId, session);
Clock fixedClock = Clock.fixed(Instant.now(), ZoneOffset.UTC);
final SamlLogoutRequestMessageBuilder builder = new SamlLogoutRequestMessageBuilder(fixedClock, sp, idp, nameId, session);
final LogoutRequest logoutRequest = builder.build();
assertThat(logoutRequest, notNullValue());
assertThat(logoutRequest.getReason(), nullValue());
@ -82,7 +81,7 @@ public class SamlLogoutRequestMessageBuilderTests extends SamlTestCase {
assertThat(logoutRequest.getConsent(), nullValue());
assertThat(logoutRequest.getNotOnOrAfter(), nullValue());
assertThat(logoutRequest.getIssueInstant(), notNullValue());
assertThat(logoutRequest.getIssueInstant(), equalTo(now));
assertThat(logoutRequest.getIssueInstant().getMillis(), equalTo(fixedClock.millis()));
assertThat(logoutRequest.getSessionIndexes(), iterableWithSize(1));
assertThat(logoutRequest.getSessionIndexes().get(0).getSessionIndex(), equalTo(session));
assertThat(logoutRequest.getDestination(), equalTo("http://idp.example.com/saml/logout/redirect"));

View File

@ -32,7 +32,6 @@ import org.elasticsearch.xpack.watcher.condition.InternalAlwaysCondition;
import org.elasticsearch.xpack.watcher.input.InputRegistry;
import org.elasticsearch.xpack.watcher.input.none.ExecutableNoneInput;
import org.elasticsearch.xpack.watcher.trigger.TriggerService;
import org.elasticsearch.xpack.common.time.HaltedClock;
import org.joda.time.DateTime;
import java.io.IOException;
@ -53,23 +52,22 @@ public class WatchParser extends AbstractComponent {
private final ActionRegistry actionRegistry;
private final InputRegistry inputRegistry;
private final CryptoService cryptoService;
private final Clock clock;
private final ExecutableInput defaultInput;
private final ExecutableCondition defaultCondition;
private final List<ActionWrapper> defaultActions;
private final Clock clock;
public WatchParser(Settings settings, TriggerService triggerService, ActionRegistry actionRegistry, InputRegistry inputRegistry,
@Nullable CryptoService cryptoService, Clock clock) {
super(settings);
this.triggerService = triggerService;
this.actionRegistry = actionRegistry;
this.inputRegistry = inputRegistry;
this.cryptoService = cryptoService;
this.clock = clock;
this.defaultInput = new ExecutableNoneInput(logger);
this.defaultCondition = InternalAlwaysCondition.INSTANCE;
this.defaultActions = Collections.emptyList();
this.clock = clock;
}
public Watch parse(String name, boolean includeStatus, BytesReference source, XContentType xContentType) throws IOException {
@ -102,23 +100,17 @@ public class WatchParser extends AbstractComponent {
if (logger.isTraceEnabled()) {
logger.trace("parsing watch [{}] ", source.utf8ToString());
}
XContentParser parser = null;
try {
// EMPTY is safe here because we never use namedObject
parser = new WatcherXContentParser(xContentType.xContent().createParser(NamedXContentRegistry.EMPTY, source),
new HaltedClock(now), withSecrets ? cryptoService : null);
// EMPTY is safe here because we never use namedObject
try (WatcherXContentParser parser = new WatcherXContentParser(xContentType.xContent().createParser(NamedXContentRegistry.EMPTY,
source), now, withSecrets ? cryptoService : null)) {
parser.nextToken();
return parse(id, includeStatus, parser);
} catch (IOException ioe) {
throw ioException("could not parse watch [{}]", ioe, id);
} finally {
if (parser != null) {
parser.close();
}
}
}
public Watch parse(String id, boolean includeStatus, XContentParser parser) throws IOException {
public Watch parse(String id, boolean includeStatus, WatcherXContentParser parser) throws IOException {
Trigger trigger = null;
ExecutableInput input = defaultInput;
ExecutableCondition condition = defaultCondition;
@ -161,7 +153,7 @@ public class WatchParser extends AbstractComponent {
metatdata = parser.map();
} else if (WatchField.STATUS.match(currentFieldName)) {
if (includeStatus) {
status = WatchStatus.parse(id, parser, clock);
status = WatchStatus.parse(id, parser);
} else {
parser.skipChildren();
}
@ -185,11 +177,10 @@ public class WatchParser extends AbstractComponent {
} else {
// we need to create the initial statuses for the actions
Map<String, ActionStatus> actionsStatuses = new HashMap<>();
DateTime now = new DateTime(WatcherXContentParser.clock(parser).millis(), UTC);
for (ActionWrapper action : actions) {
actionsStatuses.put(action.id(), new ActionStatus(now));
actionsStatuses.put(action.id(), new ActionStatus(parser.getParseDateTime()));
}
status = new WatchStatus(now, unmodifiableMap(actionsStatuses));
status = new WatchStatus(parser.getParseDateTime(), unmodifiableMap(actionsStatuses));
}
return new Watch(id, trigger, input, condition, transform, throttlePeriod, actions, metatdata, status);

View File

@ -122,6 +122,8 @@ import org.junit.Before;
import java.io.IOException;
import java.time.Clock;
import java.time.Instant;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@ -179,9 +181,8 @@ public class WatchTests extends ESTestCase {
}
public void testParserSelfGenerated() throws Exception {
DateTime now = new DateTime(UTC);
ClockMock clock = ClockMock.frozen();
clock.setTime(now);
Clock clock = Clock.fixed(Instant.now(), ZoneOffset.UTC);
DateTime now = new DateTime(clock.millis(), UTC);
TransformRegistry transformRegistry = transformRegistry();
boolean includeStatus = randomBoolean();
Schedule schedule = randomSchedule();
@ -207,7 +208,7 @@ public class WatchTests extends ESTestCase {
for (ActionWrapper action : actions) {
actionsStatuses.put(action.id(), new ActionStatus(now));
}
WatchStatus watchStatus = new WatchStatus(new DateTime(clock.millis()), unmodifiableMap(actionsStatuses));
WatchStatus watchStatus = new WatchStatus(now, unmodifiableMap(actionsStatuses));
TimeValue throttlePeriod = randomBoolean() ? null : TimeValue.timeValueSeconds(randomIntBetween(5, 10000));