/*
* Copyright 2012 Red Hat, Inc. and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.guvnor.m2repo.backend.server;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import javax.enterprise.inject.Instance;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemHeaders;
import org.eclipse.aether.artifact.Artifact;
import org.guvnor.common.services.project.model.GAV;
import org.guvnor.m2repo.backend.server.helpers.FormData;
import org.guvnor.m2repo.backend.server.helpers.HttpPostHelper;
import org.guvnor.m2repo.model.JarListPageRequest;
import org.guvnor.m2repo.model.JarListPageRow;
import org.guvnor.m2repo.preferences.ArtifactRepositoryPreference;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.mockito.Matchers;
import org.mockito.Mockito;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.uberfire.paging.PageResponse;
import static org.guvnor.m2repo.model.HTMLFileManagerFields.UPLOAD_OK;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.*;
public class M2RepositoryServiceImplTest {
private static final Logger log = LoggerFactory.getLogger( M2RepositoryServiceImplTest.class );
private static GAV gavBackend;
private static GAV gavBackend1;
private static GAV gavBackend2;
private static GAV gavArquillian;
private GuvnorM2Repository repo;
private M2RepoServiceImpl service;
private HttpPostHelper helper;
private java.lang.reflect.Method helperMethod;
@Rule
public final ExpectedException exception = ExpectedException.none();
@BeforeClass
public static void setupClass() {
gavBackend = new GAV( "org.kie.guvnor",
"guvnor-m2repo-editor-backend",
"0.0.1-SNAPSHOT" );
gavBackend1 = new GAV( "org.kie.guvnor",
"guvnor-m2repo-editor-backend1",
"0.0.1-SNAPSHOT" );
gavBackend2 = new GAV( "org.kie.guvnor",
"guvnor-m2repo-editor-backend2",
"0.0.1-SNAPSHOT" );
gavArquillian = new GAV( "org.jboss.arquillian.core",
"arquillian-core-api",
"1.0.2.Final" );
}
@Before
public void setup() throws Exception {
log.info( "Deleting existing Repositories instance.." );
File dir = new File( "repositories" );
log.info( "DELETING test repo: " + dir.getAbsolutePath() );
deleteDir( dir );
log.info( "TEST repo was deleted." );
ArtifactRepositoryPreference pref = mock( ArtifactRepositoryPreference.class );
when(pref.getDefaultM2RepoDir()).thenReturn( "repositories/kie" );
repo = new GuvnorM2Repository( pref );
repo.init();
//Create a shell M2RepoService and set the M2Repository
service = new M2RepoServiceImpl();
java.lang.reflect.Field repositoryField = M2RepoServiceImpl.class.getDeclaredField( "repository" );
repositoryField.setAccessible( true );
repositoryField.set( service, repo );
//Make private method accessible for testing
helper = new HttpPostHelper();
helperMethod = HttpPostHelper.class.getDeclaredMethod( "upload", FormData.class );
helperMethod.setAccessible( true );
//Set the repository service created above in the HttpPostHelper
java.lang.reflect.Field m2RepoServiceField = HttpPostHelper.class.getDeclaredField( "m2RepoService" );
m2RepoServiceField.setAccessible( true );
m2RepoServiceField.set( helper, service );
}
@AfterClass
public static void tearDown() throws Exception {
log.info( "Deleting all Repository instances.." );
File dir = new File( "repositories" );
log.info( "DELETING test repo: " + dir.getAbsolutePath() );
deleteDir( dir );
log.info( "TEST repo was deleted." );
}
public static boolean deleteDir( File dir ) {
if ( dir.isDirectory() ) {
String[] children = dir.list();
for ( int i = 0; i < children.length; i++ ) {
if ( !deleteDir( new File( dir,
children[ i ] ) ) ) {
return false;
}
}
}
// The directory is now empty so delete it
return dir.delete();
}
@Test
public void testDeployArtifact() throws Exception {
deployArtifact( gavBackend );
Collection<File> files = repo.listFiles();
boolean found = false;
for ( File file : files ) {
String fileName = file.getName();
if ( fileName.startsWith( "guvnor-m2repo-editor-backend-0.0.1" ) && fileName.endsWith( ".jar" ) ) {
found = true;
String path = file.getPath();
String jarPath = path.substring( GuvnorM2Repository.M2_REPO_DIR.length() + 1 );
String pom = GuvnorM2Repository.getPomText( jarPath );
assertNotNull( pom );
break;
}
}
assertTrue( "Did not find expected file after calling M2Repository.addFile()",
found );
// Test get artifact file
File file = repo.getArtifactFileFromRepository( gavBackend );
assertNotNull( "Empty file for artifact", file );
JarFile jarFile = new JarFile( file );
int count = 0;
String lastEntryName = null;
for ( Enumeration<JarEntry> entries = jarFile.entries(); entries.hasMoreElements(); ) {
++count;
JarEntry entry = entries.nextElement();
assertNotEquals( "Endless loop.", lastEntryName, entry.getName() );
}
assertTrue( "Empty jar file!", count > 0 );
}
@Test
public void testDeployPom() throws Exception {
InputStream is = this.getClass().getResourceAsStream( "guvnor-m2repo-editor-backend-test-pom.xml" );
repo.deployPom( is,
gavBackend );
Collection<File> files = repo.listFiles();
boolean found = false;
for ( File file : files ) {
String fileName = file.getName();
if ( fileName.startsWith( "guvnor-m2repo-editor-backend-0.0.1" ) && fileName.endsWith( ".pom" ) ) {
found = true;
String path = file.getPath();
String jarPath = path.substring( GuvnorM2Repository.M2_REPO_DIR.length() + 1 );
String pom = GuvnorM2Repository.getPomText( jarPath );
assertNotNull( pom );
break;
}
}
assertTrue( "Did not find expected file after calling M2Repository.addFile()",
found );
}
@Test
public void testListFiles() throws Exception {
deployArtifact( gavBackend );
deployArtifact( gavArquillian );
Collection<File> files = repo.listFiles();
boolean found1 = false;
boolean found2 = false;
for ( File file : files ) {
String fileName = file.getName();
if ( fileName.startsWith( "guvnor-m2repo-editor-backend-0.0.1" ) && fileName.endsWith( ".jar" ) ) {
found1 = true;
}
if ( fileName.startsWith( "arquillian-core-api-1.0.2.Final" ) && fileName.endsWith( ".jar" ) ) {
found2 = true;
}
}
assertTrue( "Did not find expected file after calling M2Repository.addFile()",
found1 );
assertTrue( "Did not find expected file after calling M2Repository.addFile()",
found2 );
}
@Test
public void testListFilesWithFilter() throws Exception {
deployArtifact( gavBackend );
deployArtifact( gavArquillian );
//filter with version number
boolean found1 = false;
Collection<File> files = repo.listFiles( "1.0.2" );
final String VERSION_NUMBER_SEARCH_FILTER = "arquillian-core-api-1.0.2";
for ( File file : files ) {
String fileName = file.getName();
if ( fileName.startsWith( VERSION_NUMBER_SEARCH_FILTER ) && fileName.endsWith( ".jar" ) ) {
found1 = true;
}
}
assertTrue( "Did not find expected file after calling M2Repository.addFile()",
found1 );
for ( File file : files ) {
String fileName = file.getName();
if ( !fileName.contains( VERSION_NUMBER_SEARCH_FILTER ) ) {
Assert.fail( fileName + " doesn't match the filter " + VERSION_NUMBER_SEARCH_FILTER );
}
}
//filter with artifact id
found1 = false;
files = repo.listFiles( "arquillian-core-api" );
final String ARTIFACT_SEARCH_FILTER = "arquillian-core-api";
for ( File file : files ) {
String fileName = file.getName();
if ( fileName.startsWith( ARTIFACT_SEARCH_FILTER ) && fileName.endsWith( ".jar" ) ) {
found1 = true;
}
}
assertTrue( "Did not find expected file after calling M2Repository.addFile()",
found1 );
for ( File file : files ) {
String fileName = file.getName();
if ( !fileName.contains( ARTIFACT_SEARCH_FILTER ) ) {
Assert.fail( fileName + " doesn't match the filter " + ARTIFACT_SEARCH_FILTER );
}
}
}
@Test
public void testUploadJARWithPOM() throws Exception {
FormData uploadItem = new FormData();
FileItem file = new MockFileItem( "guvnor-m2repo-editor-backend-test-with-pom.jar",
this.getClass().getResourceAsStream( "guvnor-m2repo-editor-backend-test-with-pom.jar" ) );
uploadItem.setFile( file );
assert ( helperMethod.invoke( helper,
uploadItem ).equals( UPLOAD_OK ) );
}
@Test
public void testUploadKJARWithPOM() throws Exception {
FormData uploadItem = new FormData();
FileItem file = new MockFileItem( "guvnor-m2repo-editor-backend-test-with-pom.kjar",
this.getClass().getResourceAsStream( "guvnor-m2repo-editor-backend-test-with-pom.jar" ) );
uploadItem.setFile( file );
assert ( helperMethod.invoke( helper,
uploadItem ).equals( UPLOAD_OK ) );
}
@Test
public void testUploadJARWithManualGAV() throws Exception {
FormData uploadItem = new FormData();
uploadItem.setGav( gavBackend );
FileItem file = new MockFileItem( "guvnor-m2repo-editor-backend-test-without-pom.jar",
this.getClass().getResourceAsStream( "guvnor-m2repo-editor-backend-test-without-pom.jar" ) );
uploadItem.setFile( file );
assert ( helperMethod.invoke( helper,
uploadItem ).equals( UPLOAD_OK ) );
}
@Test
public void testUploadKJARWithManualGAV() throws Exception {
FormData uploadItem = new FormData();
uploadItem.setGav( gavBackend );
FileItem file = new MockFileItem( "guvnor-m2repo-editor-backend-test.kjar",
this.getClass().getResourceAsStream( "guvnor-m2repo-editor-backend-test-without-pom.jar" ) );
uploadItem.setFile( file );
assert ( helperMethod.invoke( helper,
uploadItem ).equals( UPLOAD_OK ) );
}
/**
* Verify that
* {@link M2RepoServiceImpl#listArtifacts(org.guvnor.m2repo.model.JarListPageRequest) M2RepoServiceImpl.listFiles()}
* returns correct PageResponse.
* @throws java.lang.Exception
*/
@Test
public void testListArtifacts() throws Exception {
List<Artifact> artifacts = new ArrayList<Artifact>();
final int TOTAL = 5;
final int PAGE_START = 1;
final int PAGE_SIZE = 2;
for ( int i = 0; i < TOTAL; i++ ) {
final ArtifactImpl artifact = new ArtifactImpl( new File( repo.M2_REPO_DIR, "path/x" + i ) );
final HashMap<String, String> map = new HashMap<String, String>();
map.put( "repository","guvnor-m2-repo" );
artifact.setProperties( map );
artifacts.add( artifact );
}
// Create a mock repository to make the test independent on any project deployment
GuvnorM2Repository mockRepo = mock( GuvnorM2Repository.class );
Mockito.when( mockRepo.listArtifacts( Mockito.anyString(), Matchers.<List<String>>any() ) )
.thenReturn( artifacts );
// Create a shell M2RepoService with injected mock M2Repository
M2RepoServiceImpl m2service = new M2RepoServiceImpl();
java.lang.reflect.Field repositoryField = M2RepoServiceImpl.class.getDeclaredField( "repository" );
repositoryField.setAccessible( true );
repositoryField.set( m2service,
mockRepo );
// Verify PageResponse
JarListPageRequest request = new JarListPageRequest( PAGE_START, PAGE_SIZE, null, null, null, false );
PageResponse<JarListPageRow> response = m2service.listArtifacts( request );
assertEquals( PAGE_SIZE, response.getPageRowList().size() );
assertEquals( TOTAL, response.getTotalRowSize() );
int i = PAGE_START;
for ( JarListPageRow row : response.getPageRowList() ) {
assertEquals( "x" + i, row.getName() );
assertEquals( "path/x" + i, row.getPath() );
i += 1;
}
}
@Test
public void testUploadPOM() throws Exception {
FormData uploadItem = new FormData();
FileItem file = new MockFileItem( "pom.xml",
this.getClass().getResourceAsStream( "guvnor-m2repo-editor-backend-test-pom.xml" ) );
uploadItem.setFile( file );
assert ( helperMethod.invoke( helper,
uploadItem ).equals( UPLOAD_OK ) );
assertFilesCount( null, null, null, false, 1 );
}
@Test
public void testListFilesWithSortOnNameAscending() throws Exception {
deployArtifact( gavBackend1 );
deployArtifact( gavBackend2 );
//Sort by Name ascending
final PageResponse<JarListPageRow> response = assertFilesCount( null,
null,
JarListPageRequest.COLUMN_NAME,
true,
4 );
final List<JarListPageRow> files = response.getPageRowList();
final String fileName0 = files.get( 0 ).getName();
final String fileName2 = files.get( 2 ).getName();
assertTrue( fileName0.startsWith( "guvnor-m2repo-editor-backend1" ) );
assertTrue( fileName2.startsWith( "guvnor-m2repo-editor-backend2" ) );
}
@Test
public void testListFilesWithSortOnNameDescending() throws Exception {
deployArtifact( gavBackend1 );
deployArtifact( gavBackend2 );
//Sort by Name descending
final PageResponse<JarListPageRow> response = assertFilesCount( null,
null,
JarListPageRequest.COLUMN_NAME,
false,
4 );
final List<JarListPageRow> files = response.getPageRowList();
final String fileName0 = files.get( 0 ).getName();
final String fileName2 = files.get( 2 ).getName();
assertTrue( fileName0.startsWith( "guvnor-m2repo-editor-backend2" ) );
assertTrue( fileName2.startsWith( "guvnor-m2repo-editor-backend1" ) );
}
@Test
public void testListFilesWithSortOnPathAscending() throws Exception {
deployArtifact( gavBackend1 );
deployArtifact( gavBackend2 );
//Sort by Path ascending
final PageResponse<JarListPageRow> response = assertFilesCount( null,
null,
JarListPageRequest.COLUMN_PATH,
true,
4 );
final List<JarListPageRow> files = response.getPageRowList();
final String filePath0 = files.get( 0 ).getPath();
final String filePath2 = files.get( 2 ).getPath();
assertTrue( filePath0.contains( "guvnor-m2repo-editor-backend1" ) );
assertTrue( filePath2.contains( "guvnor-m2repo-editor-backend2" ) );
}
@Test
public void testListFilesWithSortOnPathDescending() throws Exception {
deployArtifact( gavBackend1 );
deployArtifact( gavBackend2 );
//Sort by Path descending
final PageResponse<JarListPageRow> response = assertFilesCount( null,
null,
JarListPageRequest.COLUMN_PATH,
false,
4 );
final List<JarListPageRow> files = response.getPageRowList();
final String filePath0 = files.get( 0 ).getPath();
final String filePath2 = files.get( 2 ).getPath();
assertTrue( filePath0.contains( "guvnor-m2repo-editor-backend2" ) );
assertTrue( filePath2.contains( "guvnor-m2repo-editor-backend1" ) );
}
@Test
public void testListFilesWithSortOnGavAscending() throws Exception {
deployArtifact( gavBackend1 );
deployArtifact( gavBackend2 );
//Sort by GAV ascending
final PageResponse<JarListPageRow> response = assertFilesCount( null,
null,
JarListPageRequest.COLUMN_GAV,
true,
4 );
final List<JarListPageRow> files = response.getPageRowList();
final GAV gav0 = files.get( 0 ).getGav();
final GAV gav2 = files.get( 2 ).getGav();
assertEquals( "guvnor-m2repo-editor-backend1",
gav0.getArtifactId() );
assertEquals( "guvnor-m2repo-editor-backend2",
gav2.getArtifactId() );
}
@Test
public void testListFilesWithSortOnGavDescending() throws Exception {
deployArtifact( gavBackend1 );
deployArtifact( gavBackend2 );
//Sort by GAV descending
final PageResponse<JarListPageRow> response = assertFilesCount( null,
null,
JarListPageRequest.COLUMN_GAV,
false,
4 );
final List<JarListPageRow> files = response.getPageRowList();
final GAV gav0 = files.get( 0 ).getGav();
final GAV gav2 = files.get( 2 ).getGav();
assertEquals( "guvnor-m2repo-editor-backend2",
gav0.getArtifactId() );
assertEquals( "guvnor-m2repo-editor-backend1",
gav2.getArtifactId() );
}
@Test
public void testListFilesWithSortOnLastModifiedAscending() throws Exception {
deployArtifact( gavBackend1 );
//Wait a bit before deploying other file (to ensure different Last Modified times)
Thread.sleep( 2000 );
//This installs a JAR and a POM
deployArtifact( gavBackend2 );
//Sort by Last Modified ascending
final PageResponse<JarListPageRow> response = assertFilesCount( null,
null,
JarListPageRequest.COLUMN_LAST_MODIFIED,
true,
4 );
final List<JarListPageRow> files = response.getPageRowList();
final Long fileTime0 = files.get( 0 ).getLastModified().getTime();
final Long fileTime2 = files.get( 2 ).getLastModified().getTime();
assertTrue( fileTime0.compareTo( fileTime2 ) < 0 );
}
@Test
public void testListFilesWithSortOnLastModifiedDescending() throws Exception {
deployArtifact( gavBackend1 );
//Wait a bit before deploying other file (to ensure different Last Modified times)
Thread.sleep( 2000 );
deployArtifact( gavBackend2 );
//Sort by Last Modified descending
final PageResponse<JarListPageRow> response = assertFilesCount( null,
null,
JarListPageRequest.COLUMN_LAST_MODIFIED,
false,
4 );
final List<JarListPageRow> files = response.getPageRowList();
final Long fileTime0 = files.get( 0 ).getLastModified().getTime();
final Long fileTime2 = files.get( 2 ).getLastModified().getTime();
assertTrue( fileTime0.compareTo( fileTime2 ) > 0 );
}
@Test
public void testListFilesIncludingPom() throws Exception {
deployArtifact( gavBackend );
//This installs a POM
GAV gavBackendParent = new GAV( "org.kie.guvnor",
"guvnor-m2repo-editor-backend-parent",
"0.0.1-SNAPSHOT" );
InputStream is = this.getClass().getResourceAsStream( "guvnor-m2repo-editor-backend-test-pom.xml" );
repo.deployPom( is,
gavBackendParent );
assertFilesCount( null, null, null, false, 3 );
}
@Test
public void testListFilesWhenNoneExist() throws Exception {
assertFilesCount( null,
null,
JarListPageRequest.COLUMN_GAV,
false,
0 );
}
@Test
public void testListFilesWithPageSize() throws Exception {
//Deploy 2 files (equating to 4 files)
deployArtifact( gavBackend1 );
deployArtifact( gavBackend2 );
final JarListPageRequest request = new JarListPageRequest( 0,
10,
null,
null,
null,
true );
final PageResponse<JarListPageRow> response = service.listArtifacts( request );
assertEquals( 4,
response.getPageRowList().size() );
}
@Test
public void testListFilesWithStartBeyondMaximum() throws Exception {
//Deploy 2 files (equating to 4 files)
deployArtifact( gavBackend1 );
deployArtifact( gavBackend2 );
final JarListPageRequest request = new JarListPageRequest( 10,
10,
null,
null,
null,
true );
final PageResponse<JarListPageRow> response = service.listArtifacts( request );
assertEquals( 0,
response.getPageRowList().size() );
}
@Test
public void testCheckArtifactExistsReturnsTrueForExistingArtifact() {
deployArtifact( gavBackend );
assertTrue( repo.containsArtifact( gavBackend ) );
}
@Test
public void testCheckArtifactExistsReturnsFalseForNonExistingArtifact() {
assertFalse( repo.containsArtifact( new GAV( "org.guvnor:non-existing-jar:1.0.Final" ) ) );
}
@Test
public void testGetPomTextRejectsTraversingPaths() {
service.getPomText( "dir/name.jar" );
service.getPomText( "dir/name.kjar" );
service.getPomText( "dir/name.pom" );
exception.expect( RuntimeException.class );
service.getPomText( "path/../file.pom" );
}
@Test
public void testLoadGAVFromJarRejectsTraversingPaths() {
exception.expect( RuntimeException.class );
service.loadGAVFromJar( "path/../file.jar" );
}
private PageResponse<JarListPageRow> assertFilesCount( final String filters,
final List<String> fileFormats,
final String dataSourceName,
final boolean isAscending,
final int filesCount ) {
final JarListPageRequest request = new JarListPageRequest( 0,
null,
filters,
fileFormats,
dataSourceName,
isAscending );
final PageResponse<JarListPageRow> response = service.listArtifacts( request );
assertEquals( filesCount,
response.getPageRowList().size() );
return response;
}
private void deployArtifact( GAV gav ) {
//This installs a JAR and a POM
InputStream is = this.getClass().getResourceAsStream( "guvnor-m2repo-editor-backend-test-without-pom.jar" );
repo.deployArtifact( is,
gav,
false );
}
//Create a mock FileItem setting an InputStream to test with
@SuppressWarnings("serial")
class MockFileItem implements FileItem {
private final String fileName;
private final InputStream fileStream;
MockFileItem( final String fileName,
final InputStream fileStream ) {
this.fileName = fileName;
this.fileStream = fileStream;
}
@Override
public InputStream getInputStream() throws IOException {
return fileStream;
//return this.getClass().getResourceAsStream( "guvnor-m2repo-editor-backend-test-without-pom.jar" );
}
@Override
public String getContentType() {
return null;
}
@Override
public String getName() {
return fileName;
}
@Override
public boolean isInMemory() {
return false;
}
@Override
public long getSize() {
return 0;
}
@Override
public byte[] get() {
return null;
}
@Override
public String getString( String encoding ) throws UnsupportedEncodingException {
return null;
}
@Override
public String getString() {
return null;
}
@Override
public void write( File file ) throws Exception {
}
@Override
public void delete() {
}
@Override
public String getFieldName() {
return null;
}
@Override
public void setFieldName( String name ) {
}
@Override
public boolean isFormField() {
return false;
}
@Override
public void setFormField( boolean state ) {
}
@Override
public OutputStream getOutputStream() throws IOException {
return null;
}
@Override
public FileItemHeaders getHeaders() {
return null;
}
@Override
public void setHeaders( FileItemHeaders fileItemHeaders ) {
}
}
}