001/*
002 * Copyright 2011 Atteo.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
005 * in compliance with the License. You may obtain a copy of the License at
006 *
007 * http://www.apache.org/licenses/LICENSE-2.0
008 *
009 * Unless required by applicable law or agreed to in writing, software distributed under the License
010 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
011 * or implied. See the License for the specific language governing permissions and limitations under
012 * the License.
013 */
014package org.atteo.classindex;
015
016import java.io.ByteArrayInputStream;
017import java.io.ByteArrayOutputStream;
018import java.io.IOException;
019import java.io.InputStream;
020import java.util.HashMap;
021import java.util.Iterator;
022import java.util.List;
023import java.util.Map;
024import java.util.jar.JarEntry;
025import java.util.jar.JarOutputStream;
026
027import org.apache.maven.plugins.shade.resource.ResourceTransformer;
028import org.codehaus.plexus.util.IOUtil;
029
030public class ClassIndexTransformer implements ResourceTransformer {
031    public static final String SUBCLASS_INDEX_PREFIX = "META-INF/services/";
032    public static final String ANNOTATED_INDEX_PREFIX = "META-INF/annotations/";
033    public static final String PACKAGE_INDEX_NAME = "jaxb.index";
034
035    private ByteArrayOutputStream data;
036
037    private Map serviceEntries = new HashMap();
038
039    @Override
040    public boolean canTransformResource(String resource) {
041        if (resource.startsWith(SUBCLASS_INDEX_PREFIX) || resource.startsWith(ANNOTATED_INDEX_PREFIX)
042                || resource.endsWith("/" + PACKAGE_INDEX_NAME)) {
043            data = (ByteArrayOutputStream) serviceEntries.get(resource);
044
045            if (data == null) {
046                data = new ByteArrayOutputStream();
047                serviceEntries.put(resource, data);
048            }
049            return true;
050        }
051
052        return false;
053    }
054
055    @Override
056    public void processResource(String resource, InputStream is, List relocators)
057            throws IOException {
058        IOUtil.copy(is, data);
059        is.close();
060    }
061
062    @Override
063    public boolean hasTransformedResource() {
064        return serviceEntries.size() > 0;
065    }
066
067    @Override
068    public void modifyOutputStream(JarOutputStream jos)
069            throws IOException {
070        for (Iterator i = serviceEntries.keySet().iterator(); i.hasNext();) {
071            String key = (String) i.next();
072            ByteArrayOutputStream stream = (ByteArrayOutputStream) serviceEntries.get(key);
073            jos.putNextEntry(new JarEntry(key));
074            IOUtil.copy(new ByteArrayInputStream(stream.toByteArray()), jos);
075            stream.reset();
076        }
077    }
078}