private final ImmutableProjectReactor reactor; | private final ImmutableProjectReactor reactor; | ||||
private final BatchComponentCache resourceCache; | private final BatchComponentCache resourceCache; | ||||
private final AnalysisMode analysisMode; | private final AnalysisMode analysisMode; | ||||
private final InputPathCache inputPathCache; | |||||
public ServerIssueRepository(Caches caches, ServerIssuesLoader previousIssuesLoader, ImmutableProjectReactor reactor, BatchComponentCache resourceCache, | public ServerIssueRepository(Caches caches, ServerIssuesLoader previousIssuesLoader, ImmutableProjectReactor reactor, BatchComponentCache resourceCache, | ||||
AnalysisMode analysisMode, InputPathCache inputPathCache) { | |||||
AnalysisMode analysisMode) { | |||||
this.caches = caches; | this.caches = caches; | ||||
this.previousIssuesLoader = previousIssuesLoader; | this.previousIssuesLoader = previousIssuesLoader; | ||||
this.reactor = reactor; | this.reactor = reactor; | ||||
this.resourceCache = resourceCache; | this.resourceCache = resourceCache; | ||||
this.analysisMode = analysisMode; | this.analysisMode = analysisMode; | ||||
this.inputPathCache = inputPathCache; | |||||
} | } | ||||
public void load() { | public void load() { | ||||
} | } | ||||
} | } | ||||
private void stopDebug(Profiler profiler, String msg, boolean fromCache) { | |||||
private static void stopDebug(Profiler profiler, String msg, boolean fromCache) { | |||||
if (fromCache) { | if (fromCache) { | ||||
profiler.stopDebug(msg + " (done from cache)"); | profiler.stopDebug(msg + " (done from cache)"); | ||||
} else { | } else { |
} | } | ||||
private static void parseIssues(ByteSource input, Function<ServerIssue, Void> consumer) { | 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); | ServerIssue previousIssue = ServerIssue.parseDelimitedFrom(is); | ||||
while (previousIssue != null) { | while (previousIssue != null) { | ||||
consumer.apply(previousIssue); | consumer.apply(previousIssue); |
} | } | ||||
private Collection<Rule> byRepository(RuleQuery query) { | 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 | @Override | ||||
public Rule apply(@Nonnull org.sonar.api.batch.rule.Rule input) { | public Rule apply(@Nonnull org.sonar.api.batch.rule.Rule input) { | ||||
return toRule(input); | return toRule(input); | ||||
} | } | ||||
private Collection<Rule> byInternalKey(RuleQuery query) { | 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 | @CheckForNull |
/* | |||||
* 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); | |||||
} | |||||
} |
package org.sonar.batch.repository; | package org.sonar.batch.repository; | ||||
import org.sonar.batch.bootstrap.WSLoaderResult; | import org.sonar.batch.bootstrap.WSLoaderResult; | ||||
import com.google.common.io.ByteSource; | import com.google.common.io.ByteSource; | ||||
import org.sonar.batch.bootstrap.WSLoader; | import org.sonar.batch.bootstrap.WSLoader; | ||||
import com.google.common.base.Function; | import com.google.common.base.Function; | ||||
import java.io.ByteArrayInputStream; | import java.io.ByteArrayInputStream; | ||||
import java.io.ByteArrayOutputStream; | import java.io.ByteArrayOutputStream; | ||||
import java.io.IOException; | |||||
import java.util.ArrayList; | import java.util.ArrayList; | ||||
import java.util.List; | import java.util.List; | ||||
ServerIssue.newBuilder().setKey("ab2").build() | ServerIssue.newBuilder().setKey("ab2").build() | ||||
.writeDelimitedTo(bos); | .writeDelimitedTo(bos); | ||||
when(bs.openStream()).thenReturn(new ByteArrayInputStream(bos.toByteArray())); | |||||
when(bs.openBufferedStream()).thenReturn(new ByteArrayInputStream(bos.toByteArray())); | |||||
final List<ServerIssue> result = new ArrayList<>(); | final List<ServerIssue> result = new ArrayList<>(); | ||||
loader.load("foo", new Function<BatchInput.ServerIssue, Void>() { | loader.load("foo", new Function<BatchInput.ServerIssue, Void>() { | ||||
assertThat(result).extracting("key").containsExactly("ab1", "ab2"); | 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); | |||||
} | |||||
} | } |
*/ | */ | ||||
package org.sonar.batch.repository.user; | 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 com.google.common.io.ByteSource; | ||||
import org.sonar.batch.bootstrap.WSLoader; | import org.sonar.batch.bootstrap.WSLoader; | ||||
import org.junit.Test; | import org.junit.Test; | ||||
import java.io.ByteArrayInputStream; | import java.io.ByteArrayInputStream; | ||||
import java.io.ByteArrayOutputStream; | import java.io.ByteArrayOutputStream; | ||||
import java.io.IOException; | import java.io.IOException; | ||||
import java.io.InputStream; | |||||
import java.util.Arrays; | import java.util.Arrays; | ||||
import static org.assertj.core.api.Assertions.assertThat; | import static org.assertj.core.api.Assertions.assertThat; | ||||
import static org.mockito.Mockito.when; | import static org.mockito.Mockito.when; | ||||
public class UserRepositoryTest { | public class UserRepositoryTest { | ||||
@Rule | |||||
public final ExpectedException exception = ExpectedException.none(); | |||||
@Test | @Test | ||||
public void testLoad() throws IOException { | public void testLoad() throws IOException { | ||||
builder.setLogin("sbrandhof").setName("Simon").build().writeDelimitedTo(out); | builder.setLogin("sbrandhof").setName("Simon").build().writeDelimitedTo(out); | ||||
ByteSource source = mock(ByteSource.class); | 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())); | 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")); | 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")); | |||||
} | |||||
} | } |
assertThat(loader.loadedFromCache()).isTrue(); | assertThat(loader.loadedFromCache()).isTrue(); | ||||
} | } | ||||
@Test(expected = IllegalStateException.class) | |||||
public void testGetLoadedFromCacheBefore() { | |||||
DefaultRulesLoader loader = new DefaultRulesLoader(mock(WSLoader.class)); | |||||
loader.loadedFromCache(); | |||||
} | |||||
} | } |
@Mock | @Mock | ||||
private AnalysisMode mode; | private AnalysisMode mode; | ||||
private WSLoaderProjectProvider loaderProvider; | |||||
private ProjectWSLoaderProvider loaderProvider; | |||||
private Map<String, String> propMap; | private Map<String, String> propMap; | ||||
private AnalysisProperties props; | private AnalysisProperties props; | ||||
@Before | @Before | ||||
public void setUp() { | public void setUp() { | ||||
MockitoAnnotations.initMocks(this); | MockitoAnnotations.initMocks(this); | ||||
loaderProvider = new WSLoaderProjectProvider(); | |||||
loaderProvider = new ProjectWSLoaderProvider(); | |||||
propMap = new HashMap<>(); | propMap = new HashMap<>(); | ||||
} | } | ||||
@CheckForNull | @CheckForNull | ||||
public synchronized String getString(@Nonnull String obj, @Nullable final PersistentCacheLoader<String> valueLoader) throws IOException { | 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) { | if (cached == null) { | ||||
return null; | return null; | ||||
} | } | ||||
} | } | ||||
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> { | private static class DirectoryClearFilter implements DirectoryStream.Filter<Path> { | ||||
@Override | @Override | ||||
public boolean accept(Path entry) throws IOException { | public boolean accept(Path entry) throws IOException { |