import com.google.common.base.Strings;
import com.google.common.collect.Collections2;
import com.google.common.collect.Lists;
+import java.time.Clock;
+import java.time.OffsetDateTime;
+import java.time.Period;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
import org.apache.commons.lang.BooleanUtils;
-import org.joda.time.DateTime;
-import org.joda.time.format.ISOPeriodFormat;
import org.sonar.api.resources.Qualifiers;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.server.ServerSide;
-import org.sonar.api.utils.System2;
import org.sonar.api.web.UserRole;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
private static final ComponentDto UNKNOWN_COMPONENT = new ComponentDto().setUuid(UNKNOWN).setProjectUuid(UNKNOWN);
private final DbClient dbClient;
- private final System2 system;
+ private final Clock clock;
private final UserSession userSession;
- public IssueQueryFactory(DbClient dbClient, System2 system, UserSession userSession) {
+ public IssueQueryFactory(DbClient dbClient, Clock clock, UserSession userSession) {
this.dbClient = dbClient;
- this.system = system;
+ this.clock = clock;
this.userSession = userSession;
}
Date actualCreatedAfter = createdAfter;
if (createdInLast != null) {
- actualCreatedAfter = new DateTime(system.now()).minus(
- ISOPeriodFormat.standard().parsePeriod("P" + createdInLast.toUpperCase(Locale.ENGLISH))).toDate();
+ actualCreatedAfter = Date.from(
+ OffsetDateTime.now(clock)
+ .minus(Period.parse("P" + createdInLast.toUpperCase(Locale.ENGLISH)))
+ .toInstant());
}
return actualCreatedAfter;
}
return mainBranchProjectUuid == null ? componentDto.projectUuid() : mainBranchProjectUuid;
}
- private static void setBranch(IssueQuery.Builder builder, ComponentDto component, @Nullable String branch){
+ private static void setBranch(IssueQuery.Builder builder, ComponentDto component, @Nullable String branch) {
builder.branchUuid(branch == null ? null : component.projectUuid());
builder.mainBranch(branch == null || !branch.equals(component.getBranch()));
}
*/
package org.sonar.server.platform.platformlevel;
+import java.time.Clock;
import java.util.Properties;
import javax.annotation.Nullable;
import org.sonar.NetworkUtils;
TempFolderCleaner.class,
new TempFolderProvider(),
System2.INSTANCE,
+ Clock.systemDefaultZone(),
// user session
ThreadLocalUserSession.class,
*/
package org.sonar.server.issue;
+import java.time.Clock;
+import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.Date;
import org.junit.Rule;
import org.sonar.api.resources.Qualifiers;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.utils.DateUtils;
-import org.sonar.api.utils.System2;
import org.sonar.db.DbTester;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.component.SnapshotDto;
@Rule
public DbTester db = DbTester.create();
- private System2 system = mock(System2.class);
- private IssueQueryFactory underTest = new IssueQueryFactory(db.getDbClient(), system, userSession);
+ private Clock clock = mock(Clock.class);
+ private IssueQueryFactory underTest = new IssueQueryFactory(db.getDbClient(), clock, userSession);
@Test
public void create_from_parameters() {
assertThat(query.createdBefore()).isEqualTo(DateUtils.parseDate("2013-04-18"));
}
+ @Test
+ public void creation_date_support_localdate() {
+ SearchWsRequest request = new SearchWsRequest()
+ .setCreatedAt("2013-04-16");
+
+ IssueQuery query = underTest.create(request);
+
+ assertThat(query.createdAt()).isEqualTo(DateUtils.parseDate("2013-04-16"));
+ }
+
+ @Test
+ public void creation_date_support_zoneddatetime() {
+ SearchWsRequest request = new SearchWsRequest()
+ .setCreatedAt("2013-04-16T09:08:24+0200");
+
+ IssueQuery query = underTest.create(request);
+
+ assertThat(query.createdAt()).isEqualTo(DateUtils.parseDateTime("2013-04-16T09:08:24+0200"));
+ }
+
@Test
public void add_unknown_when_no_component_found() {
SearchWsRequest request = new SearchWsRequest()
.setComponentKeys(singletonList(file.getKey()))
.setBranch(branch.getBranch())
.setOnComponentOnly(true)))
- .extracting(IssueQuery::branchUuid, query -> new ArrayList<>(query.componentUuids()), IssueQuery::isMainBranch)
- .containsOnly(branch.uuid(), singletonList(file.uuid()), false);
+ .extracting(IssueQuery::branchUuid, query -> new ArrayList<>(query.componentUuids()), IssueQuery::isMainBranch)
+ .containsOnly(branch.uuid(), singletonList(file.uuid()), false);
}
@Test
assertThat(underTest.create(new SearchWsRequest()
.setProjectKeys(singletonList(project.getKey()))
.setBranch("master")))
- .extracting(IssueQuery::branchUuid, query -> new ArrayList<>(query.projectUuids()), IssueQuery::isMainBranch)
- .containsOnly(project.uuid(), singletonList(project.uuid()), true);
+ .extracting(IssueQuery::branchUuid, query -> new ArrayList<>(query.projectUuids()), IssueQuery::isMainBranch)
+ .containsOnly(project.uuid(), singletonList(project.uuid()), true);
assertThat(underTest.create(new SearchWsRequest()
.setComponentKeys(singletonList(project.getKey()))
.setBranch("master")))
- .extracting(IssueQuery::branchUuid, query -> new ArrayList<>(query.projectUuids()), IssueQuery::isMainBranch)
- .containsOnly(project.uuid(), singletonList(project.uuid()), true);
+ .extracting(IssueQuery::branchUuid, query -> new ArrayList<>(query.projectUuids()), IssueQuery::isMainBranch)
+ .containsOnly(project.uuid(), singletonList(project.uuid()), true);
}
@Test
@Test
public void set_created_after_from_created_since() {
Date now = DateUtils.parseDateTime("2013-07-25T07:35:00+0100");
- when(system.now()).thenReturn(now.getTime());
+ when(clock.instant()).thenReturn(now.toInstant());
+ when(clock.getZone()).thenReturn(ZoneOffset.UTC);
SearchWsRequest request = new SearchWsRequest()
.setCreatedInLast("1y2m3w4d");
assertThat(underTest.create(request).createdAfter()).isEqualTo(DateUtils.parseDateTime("2012-04-30T07:35:00+0100"));
package org.sonar.server.issue.ws;
import java.io.IOException;
+import java.time.Clock;
import java.util.Arrays;
import java.util.Date;
import org.junit.Rule;
private IssueIndex issueIndex = new IssueIndex(es.client(), System2.INSTANCE, userSession, new AuthorizationTypeSupport(userSession));
private IssueIndexer issueIndexer = new IssueIndexer(es.client(), dbClient, new IssueIteratorFactory(dbClient));
private ViewIndexer viewIndexer = new ViewIndexer(dbClient, es.client());
- private IssueQueryFactory issueQueryFactory = new IssueQueryFactory(dbClient, System2.INSTANCE, userSession);
+ private IssueQueryFactory issueQueryFactory = new IssueQueryFactory(dbClient, Clock.systemUTC(), userSession);
private IssueFieldsSetter issueFieldsSetter = new IssueFieldsSetter();
private IssueWorkflow issueWorkflow = new IssueWorkflow(new FunctionExecutor(issueFieldsSetter), issueFieldsSetter);
private SearchResponseLoader searchResponseLoader = new SearchResponseLoader(userSession, dbClient, new ActionFinder(userSession),
*/
package org.sonar.server.issue.ws;
+import java.time.Clock;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
private DbSession session = db.getSession();
private IssueIndex issueIndex = new IssueIndex(es.client(), System2.INSTANCE, userSessionRule, new AuthorizationTypeSupport(userSessionRule));
private IssueIndexer issueIndexer = new IssueIndexer(es.client(), dbClient, new IssueIteratorFactory(dbClient));
- private IssueQueryFactory issueQueryFactory = new IssueQueryFactory(dbClient, System2.INSTANCE, userSessionRule);
+ private IssueQueryFactory issueQueryFactory = new IssueQueryFactory(dbClient, Clock.systemUTC(), userSessionRule);
private IssueFieldsSetter issueFieldsSetter = new IssueFieldsSetter();
private IssueWorkflow issueWorkflow = new IssueWorkflow(new FunctionExecutor(issueFieldsSetter), issueFieldsSetter);
- private SearchResponseLoader searchResponseLoader = new SearchResponseLoader(userSessionRule, dbClient, new ActionFinder(userSessionRule), new TransitionService(userSessionRule, issueWorkflow));
+ private SearchResponseLoader searchResponseLoader = new SearchResponseLoader(userSessionRule, dbClient, new ActionFinder(userSessionRule),
+ new TransitionService(userSessionRule, issueWorkflow));
private Languages languages = new Languages();
private SearchResponseFormat searchResponseFormat = new SearchResponseFormat(new Durations(), new WsResponseCommonFormat(languages), languages, new AvatarResolverImpl());
private WsActionTester ws = new WsActionTester(new SearchAction(userSessionRule, issueIndex, issueQueryFactory, searchResponseLoader, searchResponseFormat));
import org.junit.rules.ExpectedException;
import org.sonar.api.rule.RuleStatus;
import org.sonar.api.utils.DateUtils;
-import org.sonar.api.utils.SonarException;
import static java.util.Arrays.asList;
import static org.assertj.core.api.Assertions.assertThat;
@Test
public void toDate_bad_format() {
- throwable.expect(SonarException.class);
+ throwable.expect(RuntimeException.class);
RubyUtils.toDate("01/02/2013");
}
import javax.annotation.Nullable;
import org.apache.commons.lang.StringUtils;
import org.sonar.api.utils.DateUtils;
-import org.sonar.api.utils.SonarException;
import static com.google.common.base.Preconditions.checkArgument;
import static java.lang.String.format;
try {
return DateUtils.parseDate(s);
- } catch (SonarException notDateException) {
+ } catch (RuntimeException notDateException) {
throw new IllegalArgumentException(notDateException);
}
}
*/
package org.sonar.api.utils;
-import java.io.NotSerializableException;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-import java.lang.ref.Reference;
-import java.lang.ref.SoftReference;
-import java.text.DateFormat;
-import java.text.FieldPosition;
-import java.text.ParsePosition;
-import java.text.SimpleDateFormat;
+import java.time.Instant;
+import java.time.LocalDate;
+import java.time.OffsetDateTime;
+import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeParseException;
+import java.time.temporal.ChronoUnit;
import java.util.Date;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
public static final String DATE_FORMAT = "yyyy-MM-dd";
public static final String DATETIME_FORMAT = "yyyy-MM-dd'T'HH:mm:ssZ";
- private static final ThreadSafeDateFormat THREAD_SAFE_DATE_FORMAT = new ThreadSafeDateFormat(DATE_FORMAT);
- private static final ThreadSafeDateFormat THREAD_SAFE_DATETIME_FORMAT = new ThreadSafeDateFormat(DATETIME_FORMAT);
+ private static final DateTimeFormatter DATETIME_FORMATTER = DateTimeFormatter.ofPattern(DATETIME_FORMAT);
private DateUtils() {
}
+ /**
+ * Warning: relies on default timezone!
+ */
public static String formatDate(Date d) {
- return THREAD_SAFE_DATE_FORMAT.format(d);
+ return d.toInstant().atZone(ZoneId.systemDefault()).toLocalDate().toString();
}
+ /**
+ * Warning: relies on default timezone!
+ */
public static String formatDateTime(Date d) {
- return THREAD_SAFE_DATETIME_FORMAT.format(d);
+ return formatDateTime(OffsetDateTime.ofInstant(d.toInstant(), ZoneId.systemDefault()));
}
+ /**
+ * Warning: relies on default timezone!
+ */
public static String formatDateTime(long ms) {
- return THREAD_SAFE_DATETIME_FORMAT.format(new Date(ms));
+ return formatDateTime(OffsetDateTime.ofInstant(Instant.ofEpochMilli(ms), ZoneId.systemDefault()));
+ }
+
+ /**
+ * @since 6.6
+ */
+ public static String formatDateTime(OffsetDateTime dt) {
+ return DATETIME_FORMATTER.format(dt);
}
+ /**
+ * Warning: relies on default timezone!
+ */
public static String formatDateTimeNullSafe(@Nullable Date date) {
- return date == null ? "" : THREAD_SAFE_DATETIME_FORMAT.format(date);
+ return date == null ? "" : formatDateTime(date);
}
@CheckForNull
}
/**
+ * Return a date at the start of day.
* @param s string in format {@link #DATE_FORMAT}
* @throws SonarException when string cannot be parsed
*/
public static Date parseDate(String s) {
- ParsePosition pos = new ParsePosition(0);
- Date result = THREAD_SAFE_DATE_FORMAT.parse(s, pos);
- if (pos.getIndex() != s.length()) {
- throw new SonarException("The date '" + s + "' does not respect format '" + DATE_FORMAT + "'");
- }
- return result;
+ return Date.from(parseLocalDate(s).atStartOfDay(ZoneId.systemDefault()).toInstant());
}
/**
return date;
}
+ /**
+ * @since 6.6
+ */
+ public static LocalDate parseLocalDate(String s) {
+ try {
+ return LocalDate.parse(s);
+ } catch (DateTimeParseException e) {
+ throw MessageException.of("The date '" + s + "' does not respect format '" + DATE_FORMAT + "'", e);
+ }
+ }
+
+ /**
+ * Parse format {@link #DATE_FORMAT}. This method never throws exception.
+ *
+ * @param s any string
+ * @return the date, {@code null} if parsing error or if parameter is {@code null}
+ * @since 6.6
+ */
+ @CheckForNull
+ public static LocalDate parseLocalDateQuietly(@Nullable String s) {
+ LocalDate date = null;
+ if (s != null) {
+ try {
+ date = parseLocalDate(s);
+ } catch (RuntimeException e) {
+ // ignore
+ }
+
+ }
+ return date;
+ }
+
/**
* @param s string in format {@link #DATETIME_FORMAT}
* @throws SonarException when string cannot be parsed
*/
-
public static Date parseDateTime(String s) {
- ParsePosition pos = new ParsePosition(0);
- Date result = THREAD_SAFE_DATETIME_FORMAT.parse(s, pos);
- if (pos.getIndex() != s.length()) {
- throw new SonarException("The date '" + s + "' does not respect format '" + DATETIME_FORMAT + "'");
+ return Date.from(parseOffsetDateTime(s).toInstant());
+ }
+
+ /**
+ * @param s string in format {@link #DATETIME_FORMAT}
+ * @throws SonarException when string cannot be parsed
+ * @since 6.6
+ */
+ public static OffsetDateTime parseOffsetDateTime(String s) {
+ try {
+ return OffsetDateTime.parse(s, DATETIME_FORMATTER);
+ } catch (DateTimeParseException e) {
+ throw MessageException.of("The date '" + s + "' does not respect format '" + DATETIME_FORMAT + "'", e);
}
- return result;
}
/**
}
/**
+ * Parse format {@link #DATETIME_FORMAT}. This method never throws exception.
+ *
+ * @param s any string
+ * @return the datetime, {@code null} if parsing error or if parameter is {@code null}
+ * @since 6.6
+ */
+ @CheckForNull
+ public static OffsetDateTime parseOffsetDateTimeQuietly(@Nullable String s) {
+ OffsetDateTime datetime = null;
+ if (s != null) {
+ try {
+ datetime = parseOffsetDateTime(s);
+ } catch (RuntimeException e) {
+ // ignore
+ }
+
+ }
+ return datetime;
+ }
+
+ /**
+ * Warning: may rely on default timezone!
* @throws IllegalArgumentException if stringDate is not a correctly formed date or datetime
* @return the datetime, {@code null} if stringDate is null
* @since 6.1
return null;
}
- Date date = parseDateTimeQuietly(stringDate);
- if (date != null) {
- return date;
+ OffsetDateTime odt = parseOffsetDateTimeQuietly(stringDate);
+ if (odt != null) {
+ return Date.from(odt.toInstant());
}
- date = parseDateQuietly(stringDate);
- checkArgument(date != null, "Date '%s' cannot be parsed as either a date or date+time", stringDate);
+ LocalDate ld = parseLocalDateQuietly(stringDate);
+ checkArgument(ld != null, "Date '%s' cannot be parsed as either a date or date+time", stringDate);
- return date;
+ return Date.from(ld.atStartOfDay(ZoneId.systemDefault()).toInstant());
}
/**
+ * Warning: may rely on default timezone!
* @see #parseDateOrDateTime(String)
*/
@CheckForNull
/**
* Return the datetime if @param stringDate is a datetime, date + 1 day if stringDate is a date.
- * So '2016-09-01' would return a date equivalent to '2016-09-02T00:00:00+0000' in GMT
+ * So '2016-09-01' would return a date equivalent to '2016-09-02T00:00:00+0000' in GMT (Warning: relies on default timezone!)
* @see #parseDateOrDateTime(String)
* @throws IllegalArgumentException if stringDate is not a correctly formed date or datetime
* @return the datetime, {@code null} if stringDate is null
* @return the new date object with the amount added
*/
public static Date addDays(Date date, int numberOfDays) {
- return org.apache.commons.lang.time.DateUtils.addDays(date, numberOfDays);
+ return Date.from(date.toInstant().plus(numberOfDays, ChronoUnit.DAYS));
}
- static class ThreadSafeDateFormat extends DateFormat {
- private final String format;
- private final ThreadLocal<Reference<DateFormat>> cache = new ThreadLocal<Reference<DateFormat>>() {
- @Override
- public Reference<DateFormat> get() {
- Reference<DateFormat> softRef = super.get();
- if (softRef == null || softRef.get() == null) {
- SimpleDateFormat sdf = new SimpleDateFormat(format);
- sdf.setLenient(false);
- softRef = new SoftReference<>(sdf);
- super.set(softRef);
- }
- return softRef;
- }
- };
-
- ThreadSafeDateFormat(String format) {
- this.format = format;
- }
-
- private DateFormat getDateFormat() {
- return cache.get().get();
- }
-
- @Override
- public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition) {
- return getDateFormat().format(date, toAppendTo, fieldPosition);
- }
-
- @Override
- public Date parse(String source, ParsePosition pos) {
- return getDateFormat().parse(source, pos);
- }
-
- private void readObject(ObjectInputStream ois) throws NotSerializableException {
- throw new NotSerializableException();
- }
-
- private void writeObject(ObjectOutputStream ois) throws NotSerializableException {
- throw new NotSerializableException();
- }
- }
}
package org.sonar.api.utils;
import java.net.URL;
+import java.time.Clock;
import java.util.Date;
import java.util.Map;
import java.util.Properties;
/**
* Shortcut for {@link System#currentTimeMillis()}
+ * @deprecated since 6.6 use {@link Clock} that is available in pico.
*/
+ @Deprecated
public long now() {
return System.currentTimeMillis();
}
import com.tngtech.java.junit.dataprovider.DataProvider;
import com.tngtech.java.junit.dataprovider.DataProviderRunner;
import com.tngtech.java.junit.dataprovider.UseDataProvider;
-import java.util.ArrayList;
import java.util.Date;
-import java.util.List;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Fail.fail;
import static org.sonar.api.utils.DateUtils.parseDate;
import static org.sonar.api.utils.DateUtils.parseDateOrDateTime;
import static org.sonar.api.utils.DateUtils.parseDateTime;
@Test
public void parseDate_not_valid_format() {
- expectedException.expect(SonarException.class);
+ expectedException.expect(MessageException.class);
DateUtils.parseDate("2010/05/18");
}
@Test
public void parseDate_not_lenient() {
- expectedException.expect(SonarException.class);
+ expectedException.expect(MessageException.class);
DateUtils.parseDate("2010-13-18");
}
@Test
public void parseDate_fail_if_additional_characters() {
- expectedException.expect(SonarException.class);
+ expectedException.expect(MessageException.class);
DateUtils.parseDate("1986-12-04foo");
}
@Test
public void parseDateTime_not_valid_format() {
- expectedException.expect(SonarException.class);
+ expectedException.expect(MessageException.class);
DateUtils.parseDate("2010/05/18 10:55");
}
@Test
public void parseDateTime_fail_if_additional_characters() {
- expectedException.expect(SonarException.class);
+ expectedException.expect(MessageException.class);
DateUtils.parseDateTime("1986-12-04T01:02:03+0300foo");
}
@Test
public void shouldFormatDate() {
assertThat(DateUtils.formatDate(new Date())).startsWith("20");
- assertThat(DateUtils.formatDate(new Date()).length()).isEqualTo(10);
+ assertThat(DateUtils.formatDate(new Date())).hasSize(10);
}
@Test
parseEndingDateOrDateTime("polop");
}
- /**
- * Cordially copied from XStream unit test
- * See http://koders.com/java/fid8A231D75F2C6E6909FB26BCA11C12D08AD05FB50.aspx?s=ThreadSafeDateFormatTest
- */
- @Test
- public void shouldBeThreadSafe() throws Exception {
- final DateUtils.ThreadSafeDateFormat format = new DateUtils.ThreadSafeDateFormat("yyyy-MM-dd'T'HH:mm:ss,S z");
- final Date now = new Date();
- final List<Throwable> throwables = new ArrayList<>();
-
- final ThreadGroup tg = new ThreadGroup("shouldBeThreadSafe") {
- @Override
- public void uncaughtException(Thread t, Throwable e) {
- throwables.add(e);
- super.uncaughtException(t, e);
- }
- };
-
- final int[] counter = new int[1];
- counter[0] = 0;
- final Thread[] threads = new Thread[10];
- for (int i = 0; i < threads.length; ++i) {
- threads[i] = new Thread(tg, "JUnit Thread " + i) {
-
- @Override
- public void run() {
- int i = 0;
- try {
- synchronized (this) {
- notifyAll();
- wait();
- }
- while (i < 1000 && !interrupted()) {
- String formatted = format.format(now);
- Thread.yield();
- assertThat(now).isEqualTo(format.parse(formatted));
- ++i;
- }
- } catch (Exception e) {
- fail("Unexpected exception: " + e);
- }
- synchronized (counter) {
- counter[0] += i;
- }
- }
-
- };
- }
-
- for (int i = 0; i < threads.length; ++i) {
- synchronized (threads[i]) {
- threads[i].start();
- threads[i].wait();
- }
- }
-
- for (int i = 0; i < threads.length; ++i) {
- synchronized (threads[i]) {
- threads[i].notifyAll();
- }
- }
-
- Thread.sleep(1000);
-
- for (int i = 0; i < threads.length; ++i) {
- threads[i].interrupt();
- }
- for (int i = 0; i < threads.length; ++i) {
- synchronized (threads[i]) {
- threads[i].join();
- }
- }
-
- assertThat(throwables).isEmpty();
- assertThat(counter[0]).isGreaterThanOrEqualTo(threads.length);
- }
}
*/
package org.sonar.scanner;
+import java.time.Clock;
import java.util.Date;
import java.util.Optional;
-
import org.picocontainer.Startable;
import org.sonar.api.CoreProperties;
import org.sonar.api.batch.ScannerSide;
import org.sonar.api.config.Configuration;
import org.sonar.api.utils.DateUtils;
-import org.sonar.api.utils.SonarException;
-import org.sonar.api.utils.System2;
/**
* @since 6.3
*/
@ScannerSide
public class ProjectAnalysisInfo implements Startable {
- private final System2 system2;
+ private final Clock clock;
private Configuration settings;
private Date analysisDate;
private String analysisVersion;
- public ProjectAnalysisInfo(Configuration settings, System2 system2) {
+ public ProjectAnalysisInfo(Configuration settings, Clock clock) {
this.settings = settings;
- this.system2 = system2;
+ this.clock = clock;
}
public Date analysisDate() {
private Date loadAnalysisDate() {
Optional<String> value = settings.get(CoreProperties.PROJECT_DATE_PROPERTY);
if (!value.isPresent()) {
- return new Date(system2.now());
+ return Date.from(clock.instant());
}
- Date date;
try {
// sonar.projectDate may have been specified as a time
return DateUtils.parseDateTime(value.get());
- } catch (SonarException e) {
+ } catch (RuntimeException e) {
// this is probably just a date
+ }
+ try {
+ // sonar.projectDate may have been specified as a date
return DateUtils.parseDate(value.get());
+ } catch (RuntimeException e) {
+ throw new IllegalArgumentException("Illegal value for '" + CoreProperties.PROJECT_DATE_PROPERTY + "'", e);
}
}
*/
package org.sonar.scanner.bootstrap;
+import java.time.Clock;
import java.util.List;
import java.util.Map;
import org.sonar.api.Plugin;
UriReader.class,
new FileCacheProvider(),
System2.INSTANCE,
+ Clock.systemDefaultZone(),
new MetricsRepositoryProvider(),
UuidFactoryImpl.INSTANCE);
addIfMissing(ScannerPluginInstaller.class, PluginInstaller.class);
*/
package org.sonar.scanner;
+import java.time.Clock;
import java.time.LocalDate;
+import java.time.OffsetDateTime;
import java.time.ZoneId;
+import java.time.ZoneOffset;
import java.util.Date;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.ExpectedException;
import org.sonar.api.CoreProperties;
import org.sonar.api.config.internal.MapSettings;
-import org.sonar.api.utils.System2;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
public class ProjectAnalysisInfoTest {
+
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ @Test
+ public void testSimpleDateTime() {
+ MapSettings settings = new MapSettings();
+ settings.appendProperty(CoreProperties.PROJECT_DATE_PROPERTY, "2017-01-01T12:13:14+0200");
+ settings.appendProperty(CoreProperties.PROJECT_VERSION_PROPERTY, "version");
+ Clock clock = mock(Clock.class);
+ ProjectAnalysisInfo info = new ProjectAnalysisInfo(settings.asConfig(), clock);
+ info.start();
+ OffsetDateTime date = OffsetDateTime.of(2017, 1, 1, 12, 13, 14, 0, ZoneOffset.ofHours(2));
+
+ assertThat(info.analysisDate()).isEqualTo(Date.from(date.toInstant()));
+ assertThat(info.analysisVersion()).isEqualTo("version");
+ }
+
@Test
public void testSimpleDate() {
MapSettings settings = new MapSettings();
settings.appendProperty(CoreProperties.PROJECT_DATE_PROPERTY, "2017-01-01");
- settings.appendProperty(CoreProperties.PROJECT_VERSION_PROPERTY, "version");
- System2 system = mock(System2.class);
- ProjectAnalysisInfo info = new ProjectAnalysisInfo(settings.asConfig(), system);
+ Clock clock = mock(Clock.class);
+ ProjectAnalysisInfo info = new ProjectAnalysisInfo(settings.asConfig(), clock);
info.start();
LocalDate date = LocalDate.of(2017, 1, 1);
assertThat(info.analysisDate()).isEqualTo(Date.from(date.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant()));
- assertThat(info.analysisVersion()).isEqualTo("version");
+ }
+
+ @Test
+ public void emptyDate() {
+ MapSettings settings = new MapSettings();
+ settings.appendProperty(CoreProperties.PROJECT_DATE_PROPERTY, "");
+ settings.appendProperty(CoreProperties.PROJECT_VERSION_PROPERTY, "version");
+ Clock clock = mock(Clock.class);
+ ProjectAnalysisInfo info = new ProjectAnalysisInfo(settings.asConfig(), clock);
+
+ thrown.expect(RuntimeException.class);
+
+ info.start();
}
}
import com.google.common.collect.ImmutableMap;
import java.util.ArrayList;
+import java.util.Date;
import java.util.List;
import org.junit.Before;
import org.junit.Rule;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.sonar.api.batch.bootstrap.ProjectKey;
+import org.sonar.api.utils.DateUtils;
import org.sonar.api.utils.log.LogTester;
import org.sonar.api.utils.log.LoggerLevel;
import org.sonar.scanner.analysis.AnalysisProperties;
when(projectRepo.exists()).thenReturn(true);
response = new ArrayList<>(1);
- response.add(QualityProfile.newBuilder().setKey("profile").setName("profile").setLanguage("lang").build());
+ response.add(QualityProfile.newBuilder().setKey("profile").setName("profile").setLanguage("lang").setRulesUpdatedAt(DateUtils.formatDateTime(new Date())).build());
}
@Test
package org.sonar.scanner.rule;
import com.google.common.collect.ImmutableList;
+import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import org.junit.Before;
import org.mockito.MockitoAnnotations;
import org.sonar.api.batch.rule.ActiveRules;
import org.sonar.api.rule.RuleKey;
+import org.sonar.api.utils.DateUtils;
import org.sonarqube.ws.QualityProfiles.SearchWsResponse.QualityProfile;
import static org.assertj.core.api.Assertions.assertThat;
List<QualityProfile> profiles = new LinkedList<>();
for (String k : keys) {
- QualityProfile p = QualityProfile.newBuilder().setKey(k).setLanguage(k).build();
+ QualityProfile p = QualityProfile.newBuilder().setKey(k).setLanguage(k).setRulesUpdatedAt(DateUtils.formatDateTime(new Date())).build();
profiles.add(p);
}