001/*
002 * SonarQube
003 * Copyright (C) 2009-2017 SonarSource SA
004 * mailto:info AT sonarsource DOT com
005 *
006 * This program is free software; you can redistribute it and/or
007 * modify it under the terms of the GNU Lesser General Public
008 * License as published by the Free Software Foundation; either
009 * version 3 of the License, or (at your option) any later version.
010 *
011 * This program is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014 * Lesser General Public License for more details.
015 *
016 * You should have received a copy of the GNU Lesser General Public License
017 * along with this program; if not, write to the Free Software Foundation,
018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
019 */
020package org.sonar.api.utils;
021
022import java.net.URL;
023import java.time.Clock;
024import java.util.Date;
025import java.util.Map;
026import java.util.Properties;
027import java.util.TimeZone;
028import javax.annotation.CheckForNull;
029import org.apache.commons.lang.SystemUtils;
030import org.sonar.api.batch.ScannerSide;
031import org.sonar.api.ce.ComputeEngineSide;
032import org.sonar.api.server.ServerSide;
033
034/**
035 * Proxy over {@link java.lang.System}. It aims to improve testability of classes
036 * that interact with low-level system methods, for example :
037 * <br>
038 * <pre>
039 * public class MyClass {
040 *   private final System2 system;
041 *
042 *   public MyClass(System2 s) {
043 *     this.system = s;
044 *   }
045 *
046 *   public long xxx() {
047 *     return system.now();
048 *   }
049 * }
050 *
051 * {@literal @}Test
052 * public void should_return_xxx() {
053 *   // using Mockito
054 *   System2 system = mock(System2.class);
055 *   long now = 123456789L;
056 *   doReturn(now).when(system).now();
057 *   assertThat(new MyClass(system).xxx()).isEqualTo(now);
058 * }
059 * </pre>
060 * <br>
061 * Note that the name System2 was chosen to not conflict with {@link java.lang.System}.
062 * <br>
063 * An instance is available in IoC container since 4.3.
064 * 
065 * Since 6.4 you can also inject {@link Clock} instead of {@link System2} if you are only interested by date/time operations
066 *
067 * @since 4.2
068 */
069@ScannerSide
070@ServerSide
071@ComputeEngineSide
072public class System2 {
073
074  public static final System2 INSTANCE = new System2();
075
076  /**
077   * Shortcut for {@link System#currentTimeMillis()}
078   * Since 6.4 you can also inject {@link Clock} instead of {@link System2}
079   */
080  public long now() {
081    return System.currentTimeMillis();
082  }
083
084  /**
085   * Shortcut for {@link System#getProperties()}
086   */
087  public Properties properties() {
088    return System.getProperties();
089  }
090
091  /**
092   * Shortcut for {@link System#getProperty(String)}
093   */
094  @CheckForNull
095  public String property(String key) {
096    return System.getProperty(key);
097  }
098
099  /**
100   * Shortcut for {@code System{@link #setProperty(String, String)}}
101   * @since 6.4
102   */
103  public System2 setProperty(String key, String value) {
104    System.setProperty(key, value);
105    return this;
106  }
107
108  /**
109   * Shortcut for {@link System#getenv()}
110   */
111  public Map<String, String> envVariables() {
112    return System.getenv();
113  }
114
115  /**
116   * Shortcut for {@link System#getenv(String)}
117   */
118  @CheckForNull
119  public String envVariable(String key) {
120    return System.getenv(key);
121  }
122
123  /**
124   * True if this is MS Windows.
125   */
126  public boolean isOsWindows() {
127    return SystemUtils.IS_OS_WINDOWS;
128  }
129
130  /**
131   * True if Java 7 or Java 8 runtime environment
132   * @since 4.3
133   * @deprecated in 6.4. Java 8+ is required, so this method always returns {@code true}.
134   */
135  @Deprecated
136  public boolean isJavaAtLeast17() {
137    return true;
138  }
139
140  public void println(String obj) {
141    System.out.print(obj);
142  }
143
144  /**
145   * @deprecated in 5.2. Please use {@link #now()}
146   */
147  @Deprecated
148  public Date newDate() {
149    return new Date();
150  }
151
152  /**
153   * @since 5.1
154   * @return the JVM's default time zone
155   */
156  public TimeZone getDefaultTimeZone() {
157    return TimeZone.getDefault();
158  }
159
160  /**
161   * @since 5.5
162   * @see Class#getResource(String)
163   */
164  public URL getResource(String name) {
165    return getClass().getResource(name);
166  }
167
168  /**
169   * Closes the object and throws an {@link java.lang.IllegalStateException} on error.
170   * @since 5.1
171   */
172  public void close(AutoCloseable closeable) {
173    try {
174      closeable.close();
175    } catch (Exception e) {
176      throw new IllegalStateException("Fail to close " + closeable, e);
177    }
178  }
179}