From f5f7e2b29bab1712d889247ed5e1b7942a3cee61 Mon Sep 17 00:00:00 2001 From: kedzie Date: Tue, 22 Dec 2015 17:06:14 -0600 Subject: [PATCH] extractDuplicates bugfixes. -also extract duplicates from output folder, not just 3rd party deps -Handle multiple 3rd party deps with the same basename, i.e. classes.jar. --- .../android/phase09package/ApkMojo.java | 115 ++++++++++++++++-- .../phase09package/ExtractDuplicatesIT.java | 21 +--- ...jayway.maven.plugins.android.TestInterface | 1 + .../src/main/resources/resourceC | 1 + .../src/main/resources/resourceC | 1 + 5 files changed, 113 insertions(+), 26 deletions(-) rename src/test/java/com/{jayway => simpligility}/maven/plugins/android/phase09package/ExtractDuplicatesIT.java (88%) create mode 100644 src/test/projects/duplicates/duplicates-app/src/main/resources/META-INF/services/com.jayway.maven.plugins.android.TestInterface create mode 100644 src/test/projects/duplicates/duplicates-app/src/main/resources/resourceC create mode 100644 src/test/projects/duplicates/duplicates-lib-b/src/main/resources/resourceC diff --git a/src/main/java/com/simpligility/maven/plugins/android/phase09package/ApkMojo.java b/src/main/java/com/simpligility/maven/plugins/android/phase09package/ApkMojo.java index 7d47bc200..7e6396977 100644 --- a/src/main/java/com/simpligility/maven/plugins/android/phase09package/ApkMojo.java +++ b/src/main/java/com/simpligility/maven/plugins/android/phase09package/ApkMojo.java @@ -21,6 +21,7 @@ import com.android.sdklib.build.DuplicateFileException; import com.android.sdklib.build.SealedApkException; import com.simpligility.maven.plugins.android.AbstractAndroidMojo; +import com.google.common.io.Files; import com.simpligility.maven.plugins.android.AndroidNdk; import com.simpligility.maven.plugins.android.AndroidSigner; import com.simpligility.maven.plugins.android.IncludeExcludeSet; @@ -51,6 +52,7 @@ import java.io.File; import java.io.FileFilter; +import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FilenameFilter; @@ -566,7 +568,27 @@ private void computeDuplicateFiles( File jar ) throws IOException } } - private void extractDuplicateFiles( List jarFiles ) throws IOException + private void computeDuplicateFilesInSource( File folder ) + { + String rPath = folder.getAbsolutePath(); + for ( File file : Files.fileTreeTraverser().breadthFirstTraversal( folder ).toList() ) + { + String lPath = file.getAbsolutePath(); + if ( lPath.equals( rPath ) ) + { + continue; //skip the root + } + lPath = lPath.substring( rPath.length() + 1 ); //strip root folder to make relative path + + if ( jars.get( lPath ) == null ) + { + jars.put( lPath, new ArrayList() ); + } + jars.get( lPath ).add( folder ); + } + } + + private void extractDuplicateFiles( List jarFiles, Collection sourceFolders ) throws IOException { getLog().debug( "Extracting duplicates" ); List duplicates = new ArrayList(); @@ -600,12 +622,20 @@ private void extractDuplicateFiles( List jarFiles ) throws IOException for ( File file : jarToModify ) { - final File newJar = removeDuplicatesFromJar( file, duplicates, duplicatesAdded, zos ); - getLog().debug( "Removed duplicates from " + newJar ); - if ( newJar != null ) + final int index = jarFiles.indexOf( file ); + if ( index != -1 ) { - final int index = jarFiles.indexOf( file ); - jarFiles.set( index, newJar ); + final File newJar = removeDuplicatesFromJar( file, duplicates, duplicatesAdded, zos, index ); + getLog().debug( "Removed duplicates from " + newJar ); + if ( newJar != null ) + { + jarFiles.set( index, newJar ); + } + } + else + { + removeDuplicatesFromFolder( file, file, duplicates, duplicatesAdded, zos ); + getLog().debug( "Removed duplicates from " + file ); } } //add transformed resources to duplicate-resources.jar @@ -666,12 +696,17 @@ private void doAPKWithAPKBuilder( File outputFile, File dexFile, File zipArchive jarFiles.add( artifact.getFile() ); } + for ( File src : sourceFolders ) + { + computeDuplicateFilesInSource( src ); + } + // Check duplicates. if ( extractDuplicates ) { try { - extractDuplicateFiles( jarFiles ); + extractDuplicateFiles( jarFiles, sourceFolders ); } catch ( IOException e ) { @@ -799,12 +834,14 @@ private String getNextDexFileName( int dexNumber ) } private File removeDuplicatesFromJar( File in, List duplicates, - Set duplicatesAdded, ZipOutputStream duplicateZos ) + Set duplicatesAdded, ZipOutputStream duplicateZos, int num ) { String target = targetDirectory.getAbsolutePath(); File tmp = new File( target, "unpacked-embedded-jars" ); tmp.mkdirs(); - File out = new File( tmp, in.getName() ); + String jarName = String.format( "%s-%d.%s", + Files.getNameWithoutExtension( in.getName() ), num, Files.getFileExtension( in.getName() ) ); + File out = new File( tmp, jarName ); if ( out.exists() ) { @@ -910,6 +947,66 @@ private File removeDuplicatesFromJar( File in, List duplicates, return out; } + private void removeDuplicatesFromFolder( File root, File in, List duplicates, + Set duplicatesAdded, ZipOutputStream duplicateZos ) + { + String rPath = root.getAbsolutePath(); + try + { + for ( File f : in.listFiles() ) + { + if ( f.isDirectory() ) + { + removeDuplicatesFromFolder( root, f, duplicates, duplicatesAdded, duplicateZos ); + } + else + { + String lName = f.getAbsolutePath(); + lName = lName.substring( rPath.length() + 1 ); //make relative path + if ( duplicates.contains( lName ) ) + { + boolean resourceTransformed = false; + if ( transformers != null ) + { + for ( ResourceTransformer transformer : transformers ) + { + if ( transformer.canTransformResource( lName ) ) + { + getLog().info( "Transforming " + lName + + " using " + transformer.getClass().getName() ); + InputStream currIn = new FileInputStream( f ); + transformer.processResource( lName, currIn, null ); + currIn.close(); + resourceTransformed = true; + break; + } + } + } + //if not handled by transformer, add (once) to duplicates jar + if ( !resourceTransformed ) + { + if ( !duplicatesAdded.contains( lName ) ) + { + duplicatesAdded.add( lName ); + ZipEntry entry = new ZipEntry( lName ); + duplicateZos.putNextEntry( entry ); + InputStream currIn = new FileInputStream( f ); + copyStreamWithoutClosing( currIn, duplicateZos ); + currIn.close(); + duplicateZos.closeEntry(); + } + } + f.delete(); + } + } + } + } + catch ( IOException e ) + { + getLog().error( "Cannot removing duplicates : " + e.getMessage() ); + } + } + /** * Copies an input stream into an output stream but does not close the streams. * diff --git a/src/test/java/com/jayway/maven/plugins/android/phase09package/ExtractDuplicatesIT.java b/src/test/java/com/simpligility/maven/plugins/android/phase09package/ExtractDuplicatesIT.java similarity index 88% rename from src/test/java/com/jayway/maven/plugins/android/phase09package/ExtractDuplicatesIT.java rename to src/test/java/com/simpligility/maven/plugins/android/phase09package/ExtractDuplicatesIT.java index 9793fc9a8..b370843eb 100644 --- a/src/test/java/com/jayway/maven/plugins/android/phase09package/ExtractDuplicatesIT.java +++ b/src/test/java/com/simpligility/maven/plugins/android/phase09package/ExtractDuplicatesIT.java @@ -1,19 +1,4 @@ -/* - * Copyright (C) 2014 simpligility technologies inc. - * - * 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 com.jayway.maven.plugins.android.phase09package; +package com.simpligility.maven.plugins.android.phase09package; import io.takari.maven.testing.TestResources; import io.takari.maven.testing.executor.MavenExecutionResult; @@ -58,15 +43,17 @@ public void buildDeployAndRun() throws Exception { result.assertErrorFreeLog(); result.assertLogText( "Duplicate file resourceA" ); result.assertLogText( "Duplicate file resourceB" ); + result.assertLogText( "Duplicate file resourceC" ); File apk = new File(result.getBasedir().getAbsolutePath()+"/duplicates-app/target", "duplicates-app.apk"); assertNotNull("APK Not Null", apk); ZipFile apkFile = new ZipFile(apk); assertNotNull(apkFile.getEntry("resourceA")); assertNotNull(apkFile.getEntry("resourceB")); + assertNotNull(apkFile.getEntry("resourceC")); //test services assertEntryContents(apkFile, "META-INF/services/com.jayway.maven.plugins.android.TestInterface", - "ImplementationA\nImplementationB\nImplementationC"); + "ImplementationA\nImplementationB\nImplementationC\nImplementationApp"); //test xpath xml assertEntryContents( apkFile, "META-INF/kmodule.xml", expectedKmodule ); diff --git a/src/test/projects/duplicates/duplicates-app/src/main/resources/META-INF/services/com.jayway.maven.plugins.android.TestInterface b/src/test/projects/duplicates/duplicates-app/src/main/resources/META-INF/services/com.jayway.maven.plugins.android.TestInterface new file mode 100644 index 000000000..307d6a626 --- /dev/null +++ b/src/test/projects/duplicates/duplicates-app/src/main/resources/META-INF/services/com.jayway.maven.plugins.android.TestInterface @@ -0,0 +1 @@ +ImplementationApp \ No newline at end of file diff --git a/src/test/projects/duplicates/duplicates-app/src/main/resources/resourceC b/src/test/projects/duplicates/duplicates-app/src/main/resources/resourceC new file mode 100644 index 000000000..08cf61014 --- /dev/null +++ b/src/test/projects/duplicates/duplicates-app/src/main/resources/resourceC @@ -0,0 +1 @@ +test content \ No newline at end of file diff --git a/src/test/projects/duplicates/duplicates-lib-b/src/main/resources/resourceC b/src/test/projects/duplicates/duplicates-lib-b/src/main/resources/resourceC new file mode 100644 index 000000000..08cf61014 --- /dev/null +++ b/src/test/projects/duplicates/duplicates-lib-b/src/main/resources/resourceC @@ -0,0 +1 @@ +test content \ No newline at end of file