001/* 002 * Copyright 2012-2018 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.boot.maven; 018 019import java.io.IOException; 020import java.io.InputStream; 021import java.util.List; 022import java.util.Properties; 023import java.util.jar.JarEntry; 024import java.util.jar.JarOutputStream; 025 026import org.apache.maven.plugins.shade.relocation.Relocator; 027import org.apache.maven.plugins.shade.resource.ResourceTransformer; 028 029/** 030 * Extension for the <a href="http://maven.apache.org/plugins/maven-shade-plugin/">Maven 031 * shade plugin</a> to allow properties files (e.g. {@literal META-INF/spring.factories}) 032 * to be merged without losing any information. 033 * 034 * @author Dave Syer 035 * @author Andy Wilkinson 036 */ 037public class PropertiesMergingResourceTransformer implements ResourceTransformer { 038 039 // Set this in pom configuration with <resource>...</resource> 040 private String resource; 041 042 private final Properties data = new Properties(); 043 044 /** 045 * Return the data the properties being merged. 046 * @return the data 047 */ 048 public Properties getData() { 049 return this.data; 050 } 051 052 @Override 053 public boolean canTransformResource(String resource) { 054 if (this.resource != null && this.resource.equalsIgnoreCase(resource)) { 055 return true; 056 } 057 return false; 058 } 059 060 @Override 061 public void processResource(String resource, InputStream inputStream, 062 List<Relocator> relocators) throws IOException { 063 Properties properties = new Properties(); 064 properties.load(inputStream); 065 inputStream.close(); 066 properties.forEach((name, value) -> process((String) name, (String) value)); 067 } 068 069 private void process(String name, String value) { 070 String existing = this.data.getProperty(name); 071 this.data.setProperty(name, (existing != null) ? existing + "," + value : value); 072 } 073 074 @Override 075 public boolean hasTransformedResource() { 076 return !this.data.isEmpty(); 077 } 078 079 @Override 080 public void modifyOutputStream(JarOutputStream os) throws IOException { 081 os.putNextEntry(new JarEntry(this.resource)); 082 this.data.store(os, "Merged by PropertiesMergingResourceTransformer"); 083 os.flush(); 084 this.data.clear(); 085 } 086 087 public String getResource() { 088 return this.resource; 089 } 090 091 public void setResource(String resource) { 092 this.resource = resource; 093 } 094 095}