@@ -57,16 +57,14 @@ public class ServerIssueRepository { | |||
private final ImmutableProjectReactor reactor; | |||
private final BatchComponentCache resourceCache; | |||
private final AnalysisMode analysisMode; | |||
private final InputPathCache inputPathCache; | |||
public ServerIssueRepository(Caches caches, ServerIssuesLoader previousIssuesLoader, ImmutableProjectReactor reactor, BatchComponentCache resourceCache, | |||
AnalysisMode analysisMode, InputPathCache inputPathCache) { | |||
AnalysisMode analysisMode) { | |||
this.caches = caches; | |||
this.previousIssuesLoader = previousIssuesLoader; | |||
this.reactor = reactor; | |||
this.resourceCache = resourceCache; | |||
this.analysisMode = analysisMode; | |||
this.inputPathCache = inputPathCache; | |||
} | |||
public void load() { | |||
@@ -99,7 +97,7 @@ public class ServerIssueRepository { | |||
} | |||
} | |||
private void stopDebug(Profiler profiler, String msg, boolean fromCache) { | |||
private static void stopDebug(Profiler profiler, String msg, boolean fromCache) { | |||
if (fromCache) { | |||
profiler.stopDebug(msg + " (done from cache)"); | |||
} else { |
@@ -46,7 +46,7 @@ public class DefaultServerIssuesLoader implements ServerIssuesLoader { | |||
} | |||
private static void parseIssues(ByteSource input, Function<ServerIssue, Void> consumer) { | |||
try (InputStream is = input.openStream()) { | |||
try (InputStream is = input.openBufferedStream()) { | |||
ServerIssue previousIssue = ServerIssue.parseDelimitedFrom(is); | |||
while (previousIssue != null) { | |||
consumer.apply(previousIssue); |
@@ -95,10 +95,10 @@ public class RuleFinderCompatibility implements RuleFinder { | |||
} | |||
private Collection<Rule> byRepository(RuleQuery query) { | |||
return Collections2.transform(rules.findByRepository(query.getRepositoryKey()), RuleTransformer); | |||
return Collections2.transform(rules.findByRepository(query.getRepositoryKey()), ruleTransformer); | |||
} | |||
private static Function<org.sonar.api.batch.rule.Rule, Rule> RuleTransformer = new Function<org.sonar.api.batch.rule.Rule, Rule>() { | |||
private static Function<org.sonar.api.batch.rule.Rule, Rule> ruleTransformer = new Function<org.sonar.api.batch.rule.Rule, Rule>() { | |||
@Override | |||
public Rule apply(@Nonnull org.sonar.api.batch.rule.Rule input) { | |||
return toRule(input); | |||
@@ -111,7 +111,7 @@ public class RuleFinderCompatibility implements RuleFinder { | |||
} | |||
private Collection<Rule> byInternalKey(RuleQuery query) { | |||
return Collections2.transform(rules.findByInternalKey(query.getRepositoryKey(), query.getConfigKey()), RuleTransformer); | |||
return Collections2.transform(rules.findByInternalKey(query.getRepositoryKey(), query.getConfigKey()), ruleTransformer); | |||
} | |||
@CheckForNull |
@@ -1,58 +0,0 @@ | |||
/* | |||
* SonarQube, open source software quality management tool. | |||
* Copyright (C) 2008-2014 SonarSource | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* SonarQube is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* SonarQube is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.batch.scan; | |||
import org.picocontainer.injectors.ProviderAdapter; | |||
import java.util.Map; | |||
import org.sonar.batch.bootstrap.AnalysisProperties; | |||
import org.sonar.batch.bootstrap.ServerClient; | |||
import org.sonar.batch.bootstrap.WSLoader; | |||
import org.sonar.home.cache.PersistentCache; | |||
import org.sonar.api.batch.AnalysisMode; | |||
import org.sonar.batch.bootstrap.WSLoader.LoadStrategy; | |||
public class WSLoaderProjectProvider extends ProviderAdapter { | |||
private WSLoader wsLoader; | |||
public WSLoader provide(AnalysisProperties props, AnalysisMode mode, PersistentCache cache, ServerClient client) { | |||
if (wsLoader == null) { | |||
// recreate cache directory if needed for this analysis | |||
cache.reconfigure(); | |||
wsLoader = new WSLoader(isCacheEnabled(props.properties(), mode.isPreview()), cache, client); | |||
wsLoader.setStrategy(getStrategy(mode)); | |||
} | |||
return wsLoader; | |||
} | |||
private static LoadStrategy getStrategy(AnalysisMode mode) { | |||
if (mode.isQuick()) { | |||
return LoadStrategy.CACHE_FIRST; | |||
} | |||
return LoadStrategy.SERVER_FIRST; | |||
} | |||
private static boolean isCacheEnabled(Map<String, String> props, boolean isPreview) { | |||
String enableOffline = props.get("sonar.enableOffline"); | |||
return isPreview && "true".equals(enableOffline); | |||
} | |||
} |
@@ -20,7 +20,6 @@ | |||
package org.sonar.batch.repository; | |||
import org.sonar.batch.bootstrap.WSLoaderResult; | |||
import com.google.common.io.ByteSource; | |||
import org.sonar.batch.bootstrap.WSLoader; | |||
import com.google.common.base.Function; | |||
@@ -31,6 +30,7 @@ import org.sonar.batch.protocol.input.BatchInput.ServerIssue; | |||
import java.io.ByteArrayInputStream; | |||
import java.io.ByteArrayOutputStream; | |||
import java.io.IOException; | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
@@ -60,7 +60,7 @@ public class DefaultServerIssuesLoaderTest { | |||
ServerIssue.newBuilder().setKey("ab2").build() | |||
.writeDelimitedTo(bos); | |||
when(bs.openStream()).thenReturn(new ByteArrayInputStream(bos.toByteArray())); | |||
when(bs.openBufferedStream()).thenReturn(new ByteArrayInputStream(bos.toByteArray())); | |||
final List<ServerIssue> result = new ArrayList<>(); | |||
loader.load("foo", new Function<BatchInput.ServerIssue, Void>() { | |||
@@ -74,4 +74,12 @@ public class DefaultServerIssuesLoaderTest { | |||
assertThat(result).extracting("key").containsExactly("ab1", "ab2"); | |||
} | |||
@Test(expected = IllegalStateException.class) | |||
public void testError() throws IOException { | |||
ByteSource source = mock(ByteSource.class); | |||
when(source.openBufferedStream()).thenThrow(IOException.class); | |||
when(wsLoader.loadSource("/batch/issues?key=foo")).thenReturn(new WSLoaderResult<ByteSource>(source, true)); | |||
loader.load("foo", mock(Function.class), false); | |||
} | |||
} |
@@ -19,8 +19,11 @@ | |||
*/ | |||
package org.sonar.batch.repository.user; | |||
import org.sonar.batch.bootstrap.WSLoaderResult; | |||
import org.junit.rules.ExpectedException; | |||
import org.junit.Rule; | |||
import org.mockito.Mockito; | |||
import org.sonar.batch.bootstrap.WSLoaderResult; | |||
import com.google.common.io.ByteSource; | |||
import org.sonar.batch.bootstrap.WSLoader; | |||
import org.junit.Test; | |||
@@ -29,6 +32,7 @@ import org.sonar.batch.protocol.input.BatchInput; | |||
import java.io.ByteArrayInputStream; | |||
import java.io.ByteArrayOutputStream; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import java.util.Arrays; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
@@ -37,6 +41,8 @@ import static org.mockito.Mockito.mock; | |||
import static org.mockito.Mockito.when; | |||
public class UserRepositoryTest { | |||
@Rule | |||
public final ExpectedException exception = ExpectedException.none(); | |||
@Test | |||
public void testLoad() throws IOException { | |||
@@ -49,9 +55,26 @@ public class UserRepositoryTest { | |||
builder.setLogin("sbrandhof").setName("Simon").build().writeDelimitedTo(out); | |||
ByteSource source = mock(ByteSource.class); | |||
when(wsLoader.loadSource("/batch/users?logins=fmallet,sbrandhof")).thenReturn(new WSLoaderResult(source, true)); | |||
when(wsLoader.loadSource("/batch/users?logins=fmallet,sbrandhof")).thenReturn(new WSLoaderResult<>(source, true)); | |||
when(source.openStream()).thenReturn(new ByteArrayInputStream(out.toByteArray())); | |||
assertThat(userRepo.loadFromWs(Arrays.asList("fmallet", "sbrandhof"))).extracting("login", "name").containsOnly(tuple("fmallet", "Freddy Mallet"), tuple("sbrandhof", "Simon")); | |||
} | |||
@Test | |||
public void testInputStreamError() throws IOException { | |||
WSLoader wsLoader = mock(WSLoader.class); | |||
UserRepository userRepo = new UserRepository(wsLoader); | |||
ByteSource source = mock(ByteSource.class); | |||
when(wsLoader.loadSource("/batch/users?logins=fmallet,sbrandhof")).thenReturn(new WSLoaderResult<>(source, true)); | |||
InputStream errorInputStream = mock(InputStream.class); | |||
Mockito.doThrow(IOException.class).when(errorInputStream).read(); | |||
when(source.openStream()).thenReturn(errorInputStream); | |||
exception.expect(IllegalStateException.class); | |||
exception.expectMessage("Unable to get user details from server"); | |||
assertThat(userRepo.loadFromWs(Arrays.asList("fmallet", "sbrandhof"))).extracting("login", "name").containsOnly(tuple("fmallet", "Freddy Mallet"), tuple("sbrandhof", "Simon")); | |||
} | |||
} |
@@ -57,4 +57,10 @@ public class DefaultRulesLoaderTest { | |||
assertThat(loader.loadedFromCache()).isTrue(); | |||
} | |||
@Test(expected = IllegalStateException.class) | |||
public void testGetLoadedFromCacheBefore() { | |||
DefaultRulesLoader loader = new DefaultRulesLoader(mock(WSLoader.class)); | |||
loader.loadedFromCache(); | |||
} | |||
} |
@@ -47,14 +47,14 @@ public class WSLoaderProjectProviderTest { | |||
@Mock | |||
private AnalysisMode mode; | |||
private WSLoaderProjectProvider loaderProvider; | |||
private ProjectWSLoaderProvider loaderProvider; | |||
private Map<String, String> propMap; | |||
private AnalysisProperties props; | |||
@Before | |||
public void setUp() { | |||
MockitoAnnotations.initMocks(this); | |||
loaderProvider = new WSLoaderProjectProvider(); | |||
loaderProvider = new ProjectWSLoaderProvider(); | |||
propMap = new HashMap<>(); | |||
} | |||
@@ -77,16 +77,7 @@ public class PersistentCache { | |||
@CheckForNull | |||
public synchronized String getString(@Nonnull String obj, @Nullable final PersistentCacheLoader<String> valueLoader) throws IOException { | |||
byte[] cached = get(obj, new PersistentCacheLoader<byte[]>() { | |||
@Override | |||
public byte[] get() throws IOException { | |||
String s = valueLoader.get(); | |||
if (s != null) { | |||
return s.getBytes(ENCODING); | |||
} | |||
return null; | |||
} | |||
}); | |||
byte[] cached = get(obj, new ValueLoaderDecoder(valueLoader)); | |||
if (cached == null) { | |||
return null; | |||
@@ -229,6 +220,23 @@ public class PersistentCache { | |||
} | |||
} | |||
private static class ValueLoaderDecoder implements PersistentCacheLoader<byte[]> { | |||
PersistentCacheLoader<String> valueLoader; | |||
ValueLoaderDecoder(PersistentCacheLoader<String> valueLoader) { | |||
this.valueLoader = valueLoader; | |||
} | |||
@Override | |||
public byte[] get() throws IOException { | |||
String s = valueLoader.get(); | |||
if (s != null) { | |||
return s.getBytes(ENCODING); | |||
} | |||
return null; | |||
} | |||
} | |||
private static class DirectoryClearFilter implements DirectoryStream.Filter<Path> { | |||
@Override | |||
public boolean accept(Path entry) throws IOException { |