/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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.apache.usergrid.chop.plugin; import java.io.File; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.TimeZone; import org.codehaus.plexus.archiver.zip.ZipArchiver; import org.codehaus.plexus.archiver.zip.ZipUnArchiver; import org.codehaus.plexus.logging.console.ConsoleLogger; import org.codehaus.plexus.util.FileUtils; import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.Status; import org.eclipse.jgit.internal.storage.file.FileRepository; import org.eclipse.jgit.lib.Config; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.lib.RepositoryBuilder; import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.revwalk.RevWalk; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.versioning.DefaultArtifactVersion; import org.apache.maven.model.Resource; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.project.MavenProject; public class Utils { private final static Logger LOG = LoggerFactory.getLogger( Utils.class ); /** * @param jarFile Jar file to be extracted * @param destinationFolder Folder which the jarFile will be extracted to. Jar file's root will be this folder once * it is extracted. */ public static void extractJar( File jarFile, String destinationFolder ) throws MojoExecutionException { try { ZipUnArchiver unArchiver = new ZipUnArchiver( jarFile ); unArchiver.enableLogging( new ConsoleLogger( org.codehaus.plexus.logging.Logger.LEVEL_INFO, "console" ) ); unArchiver.setDestDirectory( new File( destinationFolder ) ); unArchiver.extract(); } catch ( Exception e ) { throw new MojoExecutionException( "Error while extracting JAR file", e ); } } /** * @param jarFile Jar file to be created * @param sourceFolder Jar file will be created out of the contents of this folder. This corresponds to the root * folder of the jar file once it is created. */ public static void archiveWar( File jarFile, String sourceFolder ) throws MojoExecutionException { try { ZipArchiver archiver = new ZipArchiver(); archiver.enableLogging( new ConsoleLogger( org.codehaus.plexus.logging.Logger.LEVEL_INFO, "console" ) ); archiver.setDestFile( jarFile ); archiver.addDirectory( new File( sourceFolder ), "", new String[] { "**/*" }, null ); archiver.createArchive(); } catch ( Exception e ) { throw new MojoExecutionException( "Error while creating WAR file", e ); } } /** * Gets all dependency jars of the project specified by 'project' parameter from the local mirror and copies them * under targetFolder * * @param targetFolder The folder which the dependency jars will be copied to */ public static void copyArtifactsTo( MavenProject project, String targetFolder ) throws MojoExecutionException { File targetFolderFile = new File( targetFolder ); for ( Iterator it = project.getArtifacts().iterator(); it.hasNext(); ) { Artifact artifact = ( Artifact ) it.next(); File f = artifact.getFile(); LOG.info( "Artifact {} found.", f.getAbsolutePath() ); if ( f == null ) { throw new MojoExecutionException( "Cannot locate artifact file of " + artifact.getArtifactId() ); } // Check already existing artifacts and replace them if they are of a lower version try { List<String> existing = FileUtils.getFileNames( targetFolderFile, artifact.getArtifactId() + "-*.jar", null, false ); if ( existing.size() != 0 ) { String version = existing.get( 0 ).split( "(" + artifact.getArtifactId() + "-)" )[1].split( "(.jar)" )[0]; DefaultArtifactVersion existingVersion = new DefaultArtifactVersion( version ); DefaultArtifactVersion artifactVersion = new DefaultArtifactVersion( artifact.getVersion() ); if ( existingVersion.compareTo( artifactVersion ) < 0 ) { // Remove existing version FileUtils.forceDelete( targetFolder + existing.get( 0 ) ); } else { LOG.info( "Artifact " + artifact.getArtifactId() + " with the same or higher " + "version already exists in lib folder, skipping copy" ); continue; } } LOG.info( "Copying {} to {}", f.getName(), targetFolder ); FileUtils.copyFileToDirectory( f.getAbsolutePath(), targetFolder ); } catch ( IOException e ) { throw new MojoExecutionException( "Error while copying artifact file of " + artifact.getArtifactId(), e ); } } } /** * Copies all found resource files, including test resources to the <code>targetFolder</code>. * <p> * Resource files to be copied are filtered or included according to the configurations inside * <code>project</code>'s pom.xml file. * * @param project project whose resource files to be copied * @param targetFolder matching resource files are stored in this directory * @return */ public static boolean copyResourcesTo( MavenProject project, String targetFolder ) { File targetFolderFile = new File( targetFolder ); String includes; String excludes; List allResources = project.getResources(); allResources.addAll( project.getTestResources() ); // If there is no resource folder under project, mvn chop:runner goal should fail if ( ! hasResourceFolders( project ) ){ return false; } else{ LOG.info( "Copying resource files to runner.jar" ); for( Object res: allResources ) { if( ! ( res instanceof Resource ) ) { continue; } Resource resource = ( Resource ) res; try { File baseDir = new File( resource.getDirectory() ); includes = resource.getIncludes().toString().replace( "[", "" ).replace( "]", "" ).replace( " ", "" ); excludes = resource.getExcludes().toString().replace( "[", "" ).replace( "]", "" ).replace( " ", "" ); List<String> resFiles = FileUtils.getFileNames( baseDir, includes, excludes, true, true ); for( String resFile: resFiles ) { File resourceFile = new File( resFile ); LOG.info( "Copying {} to {}", resourceFile.getName(), targetFolder ); FileUtils.copyFileToDirectory( resourceFile, targetFolderFile ); } } catch ( IOException e ){ LOG.info( "Error while trying to copy resource files.", e ); } catch ( IllegalStateException e ) { String path = resource.getDirectory(); path = path.substring( 0, path.lastIndexOf( "/" ) ); LOG.info( "There is no resource folder under {} folder.", path ); } } return true; } } /** * Returns true if there is at least one resource folder inside the project. * * @param project * @return */ public static boolean hasResourceFolders( MavenProject project ){ List<Resource> resources = project.getResources(); for ( Resource res : resources ){ if ( FileUtils.fileExists( res.getDirectory() ) ){ return true; } } return false; } /** * @param projectPath * @return * @throws MojoExecutionException */ public static String getGitConfigFolder( String projectPath ) throws MojoExecutionException { projectPath = forceNoSlashOnDir( projectPath ); while ( !FileUtils.fileExists( projectPath + File.separator + ".git" ) ) { int lastSlashIndex = projectPath.lastIndexOf( File.separator ); if ( lastSlashIndex < 1 ) { throw new MojoExecutionException( "There are no local git repository associated with this project" ); } projectPath = projectPath.substring( 0, lastSlashIndex ); } return projectPath + File.separator + ".git"; } /** * @param gitConfigFolder e.g. /your/project/root/.git * * @return Returns last commit's UUID, "nocommit" if there are no commits and returns null if an exception occured */ public static String getLastCommitUuid( String gitConfigFolder ) throws MojoExecutionException { try { Repository repo = new RepositoryBuilder().setGitDir( new File( gitConfigFolder ) ).readEnvironment().findGitDir() .build(); RevWalk walk = new RevWalk( repo ); ObjectId head = repo.resolve( "HEAD" ); if ( head != null ) { RevCommit lastCommit = walk.parseCommit( head ); return lastCommit.getId().getName(); } else { return "nocommit"; } } catch ( Exception e ) { throw new MojoExecutionException( "Error trying to get the last git commit uuid", e ); } } /** * @param gitConfigFolder e.g. /your/project/root/.git * * @return Returns git config remote.origin.url field of the repository located at gitConfigFolder */ public static String getGitRemoteUrl( String gitConfigFolder ) throws MojoExecutionException { try { Repository repo = new RepositoryBuilder().setGitDir( new File( gitConfigFolder ) ).readEnvironment().findGitDir() .build(); Config config = repo.getConfig(); return config.getString( "remote", "origin", "url" ); } catch ( Exception e ) { throw new MojoExecutionException( "Error trying to get remote origin url of git repository", e ); } } /** * @param gitConfigFolder e.g. /your/project/root/.git * * @return Returns true if 'git status' has modified files inside the 'Changes to be committed' section */ public static boolean isCommitNecessary( String gitConfigFolder ) throws MojoExecutionException { try { Repository repo = new FileRepository( gitConfigFolder ); Git git = new Git( repo ); Status status = git.status().call(); Set<String> modified = status.getModified(); return ( modified.size() != 0 ); } catch ( Exception e ) { throw new MojoExecutionException( "Error trying to find out if git commit is needed", e ); } } /** * Concatenates provided timestamp and commitUUID strings and returns their calculated MD5 in hexadecimal format * * @return Returns the hexadecimal representation of calculated MD5 * * @throws MojoExecutionException This will probably never thrown, cause UTF-8 encoding and MD5 is defined in each * system */ public static String getMD5( String timestamp, String commitUUID ) throws MojoExecutionException { try { MessageDigest digest = MessageDigest.getInstance( "MD5" ); byte[] hash = digest.digest( ( timestamp + commitUUID ).getBytes( "UTF-8" ) ); StringBuilder result = new StringBuilder( hash.length * 2 ); for ( int i = 0; i < hash.length; i++ ) { result.append( String.format( "%02x", hash[i] & 0xff ) ); } return result.toString(); } catch ( NoSuchAlgorithmException e ) { throw new MojoExecutionException( "MD5 algorithm could not be found", e ); } catch ( UnsupportedEncodingException e ) { throw new MojoExecutionException( "UTF-8 encoding is not supported", e ); } } /** @return Returns the given date in a 'yyyy.MM.dd.HH.mm.ss' format, UTC timezone */ public static String getTimestamp( Date date ) { SimpleDateFormat dateFormat = new SimpleDateFormat( "yyyy.MM.dd.HH.mm.ss" ); dateFormat.setTimeZone( TimeZone.getTimeZone( "UTC" ) ); return dateFormat.format( date ); } /** * @param directory * @return */ public static String forceSlashOnDir( String directory ) { return directory.endsWith( File.separator ) ? directory : directory + File.separator; } /** * @param directory * @return */ public static String forceNoSlashOnDir( String directory ) { return directory.endsWith( File.separator ) ? directory.substring( 0, directory.length() - 1 ) : directory; } }