/*
* JBoss, Home of Professional Open Source
* Copyright 2013, Red Hat Middleware LLC, and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* 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 org.jboss.shrinkwrap.resolver.impl.maven.archive.importer;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.jar.Attributes;
import java.util.jar.Manifest;
import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.jboss.shrinkwrap.api.Archive;
import org.jboss.shrinkwrap.api.ArchivePath;
import org.jboss.shrinkwrap.api.ArchivePaths;
import org.jboss.shrinkwrap.api.Node;
import org.jboss.shrinkwrap.api.asset.Asset;
/**
* Represents Hamcrest matchers for validating content of an Archive
*
* @author <a href="kpiwko@redhat.com">Karel Piwko</a>
*
*/
public final class ArchiveContentMatchers {
public static ArchiveContentMatcher contains(String path) {
return new ArchiveContentMatcher(path);
}
public static ArchiveSizeMatcher size(int filesTotal) {
return new ArchiveSizeMatcher(filesTotal);
}
public static ManifestAssetMatcher hasManifestEntry(String section, String entry, String value) {
return new ManifestAssetMatcher(section, entry, value);
}
public static ManifestAssetMatcher hasManifestEntry(String entry) {
return new ManifestAssetMatcher(null, entry, null);
}
public static ManifestAssetMatcher hasManifestEntry(String entry, String value) {
return new ManifestAssetMatcher(null, entry, value);
}
/**
* Checks that archive {@link Asset}, that represents Manifest contains a manifest entry with specified value or at least
* entry itself
*
* @author <a href="kpiwko@redhat.com">Karel Piwko</a>
*
*/
public static class ManifestAssetMatcher extends BaseMatcher<Asset> implements Matcher<Asset> {
private final String section;
private final String name;
private final String value;
private ManifestAssetMatcher(String section, String entry, String value) {
this.section = section;
this.name = entry;
this.value = value;
}
@Override
public void describeTo(Description description) {
description.appendText("Archive manifest contains entry named: ").appendText(name);
if (value != null) {
description.appendText(" with value: ").appendText(value);
}
if (section != null) {
description.appendText("(in section ").appendText(section).appendText(")");
}
}
@Override
public boolean matches(Object item) {
if (item == null) {
return false;
} else if (item instanceof Asset) {
Manifest mf = getManifest((Asset) item);
String manifestValue = null;
if (section == null) {
manifestValue = mf.getMainAttributes().getValue(name);
} else {
Attributes attrs = mf.getAttributes(section);
if (attrs != null) {
manifestValue = attrs.getValue(name);
}
}
return value == null ? manifestValue != null : value.equals(manifestValue);
}
return false;
}
private Manifest getManifest(Asset asset) {
InputStream is = null;
try {
is = asset.openStream();
return new Manifest(is);
} catch (IOException e) {
} finally {
try {
if (is != null) {
is.close();
}
} catch (IOException e) {
}
}
return new Manifest();
}
}
/**
* Checks that an archive contains specific number of assets (directories are excluded)
*
* @author <a href="kpiwko@redhat.com">Karel Piwko</a>
*
*/
public static class ArchiveSizeMatcher extends BaseMatcher<Map<ArchivePath, Node>> implements
Matcher<Map<ArchivePath, Node>> {
private final int assetsTotal;
private ArchiveSizeMatcher(int assetsTotal) {
this.assetsTotal = assetsTotal;
}
@Override
public void describeTo(Description description) {
description.appendText("Archive contains ").appendText(String.valueOf(assetsTotal)).appendText(" assets.");
}
@Override
public boolean matches(Object item) {
if (item == null) {
return false;
} else if (item instanceof Map<?, ?>) {
@SuppressWarnings("unchecked")
Map<ArchivePath, Node> content = (Map<ArchivePath, Node>) item;
int assets = 0;
for (Map.Entry<ArchivePath, Node> entry : content.entrySet()) {
if (entry.getValue().getAsset() != null) {
assets++;
}
}
return assets == assetsTotal;
}
return false;
}
}
/**
* Checks that archive contains a node under given path
*
* @author <a href="kpiwko@redhat.com">Karel Piwko</a>
*
*/
public static class ArchiveContentMatcher extends BaseMatcher<Map<ArchivePath, Node>> implements
Matcher<Map<ArchivePath, Node>> {
private final String path;
private ArchiveContentMatcher(String path) {
this.path = path;
}
@Override
public void describeTo(Description description) {
description.appendText("Archive contains path ").appendText(path);
}
@Override
public boolean matches(Object item) {
if (item == null) {
return false;
} else if (item instanceof Map<?, ?>) {
@SuppressWarnings("unchecked")
Map<ArchivePath, Node> content = (Map<ArchivePath, Node>) item;
return content.containsKey(ArchivePaths.create(path));
}
else if (item instanceof Archive<?>) {
Archive<?> archive = (Archive<?>) item;
return archive.contains(path);
}
return false;
}
}
}