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}