blob: e835452e904046c90bc9f80e2e2a4af489470eb2 [file] [log] [blame]
/*
* 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.maven.plugins.assembly.filter;
import javax.inject.Named;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
import java.nio.file.Files;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.io.input.XmlStreamReader;
import org.apache.commons.io.output.XmlStreamWriter;
import org.codehaus.plexus.archiver.Archiver;
import org.codehaus.plexus.archiver.ArchiverException;
import org.codehaus.plexus.archiver.ResourceIterator;
import org.codehaus.plexus.archiver.UnArchiver;
import org.codehaus.plexus.components.io.fileselectors.FileInfo;
import org.codehaus.plexus.util.xml.Xpp3Dom;
import org.codehaus.plexus.util.xml.Xpp3DomBuilder;
import org.codehaus.plexus.util.xml.Xpp3DomWriter;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
/**
* <code>plexus</code>: Plexus Components XML file filter <code>META-INF/plexus/components.xml</code>.
*
* @author <a href="mailto:brett@apache.org">Brett Porter</a>
*
*/
@Named("plexus")
public class ComponentsXmlArchiverFileFilter implements ContainerDescriptorHandler {
public static final String COMPONENTS_XML_PATH = "META-INF/plexus/components.xml";
// [jdcasey] Switched visibility to protected to allow testing. Also, because this class isn't final, it should
// allow
// some minimal access to the components accumulated for extending classes.
Map<String, Xpp3Dom> components;
private boolean excludeOverride = false;
void addComponentsXml(final Reader componentsReader) throws XmlPullParserException, IOException {
Xpp3Dom newDom = Xpp3DomBuilder.build(componentsReader);
if (newDom != null) {
newDom = newDom.getChild("components");
}
if (newDom != null) {
final Xpp3Dom[] children = newDom.getChildren();
for (final Xpp3Dom component : children) {
if (components == null) {
components = new LinkedHashMap<>();
}
final String role = component.getChild("role").getValue();
final Xpp3Dom child = component.getChild("role-hint");
final String roleHint = child != null ? child.getValue() : "";
final String key = role + roleHint;
if (!components.containsKey(key)) {
components.put(key, component);
}
}
}
}
private void addToArchive(final Archiver archiver) throws IOException {
if (components != null) {
final File f = Files.createTempFile("maven-assembly-plugin", "tmp").toFile();
f.deleteOnExit();
try (Writer fileWriter = XmlStreamWriter.builder()
.setOutputStream(Files.newOutputStream(f.toPath()))
.get()) {
final Xpp3Dom dom = new Xpp3Dom("component-set");
final Xpp3Dom componentDom = new Xpp3Dom("components");
dom.addChild(componentDom);
for (final Xpp3Dom component : components.values()) {
componentDom.addChild(component);
}
Xpp3DomWriter.write(fileWriter, dom);
}
excludeOverride = true;
archiver.addFile(f, COMPONENTS_XML_PATH);
excludeOverride = false;
}
}
@Override
public void finalizeArchiveCreation(final Archiver archiver) {
// this will prompt the isSelected() call, below, for all resources added to the archive.
// FIXME: This needs to be corrected in the AbstractArchiver, where
// runArchiveFinalizers() is called before regular resources are added...
// which is done because the manifest needs to be added first, and the
// manifest-creation component is a finalizer in the assembly plugin...
for (final ResourceIterator it = archiver.getResources(); it.hasNext(); ) {
it.next();
}
try {
addToArchive(archiver);
} catch (final IOException e) {
throw new ArchiverException("Error finalizing component-set for archive. Reason: " + e.getMessage(), e);
}
}
@Override
public List<String> getVirtualFiles() {
if ((components != null) && !components.isEmpty()) {
return Collections.singletonList(COMPONENTS_XML_PATH);
}
return null;
}
@Override
public boolean isSelected(final FileInfo fileInfo) throws IOException {
if (fileInfo.isFile()) {
if (excludeOverride) {
return true;
}
String entry = fileInfo.getName().replace('\\', '/');
if (entry.startsWith("/")) {
entry = entry.substring(1);
}
if (ComponentsXmlArchiverFileFilter.COMPONENTS_XML_PATH.equals(entry)) {
try (Reader reader = new BufferedReader(XmlStreamReader.builder()
.setInputStream(fileInfo.getContents())
.get())) {
addComponentsXml(reader);
} catch (final XmlPullParserException e) {
throw new IOException("Error finalizing component-set for archive. Reason: " + e.getMessage(), e);
}
return false;
} else {
return true;
}
} else {
return true;
}
}
@Override
public void finalizeArchiveExtraction(final UnArchiver unarchiver) {}
}