2 * Copyright (c) 2018 Pantheon Technologies, s.r.o. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.yangtools.yang2sources.plugin;
10 import static java.util.Objects.requireNonNull;
11 import static org.opendaylight.yangtools.yang.common.YangConstants.RFC6020_YANG_FILE_EXTENSION;
12 import static org.opendaylight.yangtools.yang2sources.plugin.YangToSourcesProcessor.META_INF_YANG_STRING;
13 import static org.opendaylight.yangtools.yang2sources.plugin.YangToSourcesProcessor.META_INF_YANG_STRING_JAR;
15 import com.google.common.annotations.VisibleForTesting;
16 import com.google.common.collect.ImmutableList;
17 import com.google.common.collect.ImmutableSet;
18 import com.google.common.io.ByteSource;
19 import com.google.common.io.ByteStreams;
21 import java.io.IOException;
22 import java.nio.charset.StandardCharsets;
23 import java.util.ArrayList;
24 import java.util.Arrays;
25 import java.util.List;
26 import java.util.zip.ZipEntry;
27 import java.util.zip.ZipFile;
28 import org.apache.maven.artifact.Artifact;
29 import org.apache.maven.project.MavenProject;
30 import org.eclipse.jdt.annotation.NonNullByDefault;
31 import org.opendaylight.yangtools.yang.model.spi.source.YangTextSource;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
36 abstract class ScannedDependency {
37 private static final class Single extends ScannedDependency {
38 Single(final File file) {
43 ImmutableList<YangTextSource> sources() {
44 return ImmutableList.of(YangTextSource.forPath(file().toPath()));
48 private static final class Zip extends ScannedDependency {
49 private final ImmutableSet<String> entryNames;
51 Zip(final File file, final ImmutableSet<String> entryNames) {
53 this.entryNames = requireNonNull(entryNames);
57 ImmutableList<YangTextSource> sources() throws IOException {
58 final var builder = ImmutableList.<YangTextSource>builderWithExpectedSize(entryNames.size());
60 try (ZipFile zip = new ZipFile(file())) {
61 for (String entryName : entryNames) {
62 final ZipEntry entry = requireNonNull(zip.getEntry(entryName));
64 builder.add(YangTextSource.delegateForByteSource(
65 entryName.substring(entryName.lastIndexOf('/') + 1),
66 // FIXME: can we reasonable make this a CharSource?
67 ByteSource.wrap(ByteStreams.toByteArray(zip.getInputStream(entry))),
68 StandardCharsets.UTF_8));
72 return builder.build();
76 private static final Logger LOG = LoggerFactory.getLogger(ScannedDependency.class);
78 private final File file;
80 ScannedDependency(final File file) {
81 this.file = requireNonNull(file);
84 static List<ScannedDependency> scanDependencies(final MavenProject project) throws IOException {
85 final List<File> filesOnCp = getClassPath(project);
86 LOG.debug("{} Searching for YANG files in dependencies: {}", YangToSourcesProcessor.LOG_PREFIX, filesOnCp);
87 LOG.debug("{} Searching for YANG files in {} dependencies", YangToSourcesProcessor.LOG_PREFIX,
90 final var result = new ArrayList<ScannedDependency>();
91 for (File file : filesOnCp) {
92 // is it jar file or directory?
93 if (file.isDirectory()) {
94 final File yangDir = new File(file, META_INF_YANG_STRING);
95 if (yangDir.exists() && yangDir.isDirectory()) {
96 result.addAll(scanDirectory(yangDir));
99 result.addAll(scanZipFile(file));
105 private static ImmutableList<ScannedDependency> scanDirectory(final File yangDir) {
106 return Arrays.stream(yangDir.listFiles(
107 (dir, name) -> name.endsWith(RFC6020_YANG_FILE_EXTENSION) && new File(dir, name).isFile()))
109 .collect(ImmutableList.toImmutableList());
112 private static ImmutableList<ScannedDependency> scanZipFile(final File zipFile) throws IOException {
113 final ImmutableSet<String> entryNames;
114 try (ZipFile zip = new ZipFile(zipFile)) {
115 entryNames = zip.stream()
117 final String entryName = entry.getName();
118 return entryName.startsWith(META_INF_YANG_STRING_JAR) && !entry.isDirectory()
119 && entryName.endsWith(RFC6020_YANG_FILE_EXTENSION);
121 .map(ZipEntry::getName)
122 .collect(ImmutableSet.toImmutableSet());
125 return entryNames.isEmpty() ? ImmutableList.of() : ImmutableList.of(new Zip(zipFile, entryNames));
128 // FIXME: java.nio.file.Path
133 abstract ImmutableList<YangTextSource> sources() throws IOException;
136 static List<File> getClassPath(final MavenProject project) {
137 return project.getArtifacts().stream()
138 .map(Artifact::getFile)
139 .filter(file -> file.isFile() && file.getName().endsWith(".jar") || file.isDirectory())