Merge branch 'master' of ../controller
[yangtools.git] / yang / yang-maven-plugin / src / main / java / org / opendaylight / yangtools / yang2sources / plugin / ScannedDependency.java
1 /*
2  * Copyright (c) 2018 Pantheon Technologies, s.r.o. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.yangtools.yang2sources.plugin;
9
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;
14
15 import com.google.common.collect.ImmutableList;
16 import com.google.common.collect.ImmutableSet;
17 import com.google.common.io.ByteSource;
18 import com.google.common.io.ByteStreams;
19 import java.io.File;
20 import java.io.IOException;
21 import java.util.ArrayList;
22 import java.util.Arrays;
23 import java.util.Collection;
24 import java.util.List;
25 import java.util.Set;
26 import java.util.zip.ZipEntry;
27 import java.util.zip.ZipFile;
28 import org.apache.maven.project.MavenProject;
29 import org.eclipse.jdt.annotation.NonNullByDefault;
30 import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
33
34 @NonNullByDefault
35 abstract class ScannedDependency {
36     private static final class Single extends ScannedDependency {
37
38         Single(final File file) {
39             super(file);
40         }
41
42         @Override
43         Collection<YangTextSchemaSource> sources() {
44             return ImmutableList.of(YangTextSchemaSource.forFile(file()));
45         }
46     }
47
48     private static final class Zip extends ScannedDependency {
49         private final Set<String> entryNames;
50
51         Zip(final File file, final Collection<String> entryNames) {
52             super(file);
53             this.entryNames = ImmutableSet.copyOf(entryNames);
54         }
55
56         @Override
57         Collection<YangTextSchemaSource> sources() throws IOException {
58             final Collection<YangTextSchemaSource> result = new ArrayList<>(entryNames.size());
59
60             try (ZipFile zip = new ZipFile(file())) {
61                 for (String entryName : entryNames) {
62                     final ZipEntry entry = requireNonNull(zip.getEntry(entryName));
63
64                     result.add(YangTextSchemaSource.delegateForByteSource(
65                         entryName.substring(entryName.lastIndexOf('/') + 1),
66                         ByteSource.wrap(ByteStreams.toByteArray(zip.getInputStream(entry)))));
67                 }
68             }
69
70             return result;
71         }
72     }
73
74     private static final Logger LOG = LoggerFactory.getLogger(ScannedDependency.class);
75
76     private final File file;
77
78     ScannedDependency(final File file) {
79         this.file = requireNonNull(file);
80     }
81
82     static Collection<ScannedDependency> scanDependencies(final MavenProject project) throws IOException {
83         final Collection<File> filesOnCp = Util.getClassPath(project);
84         LOG.debug("{} Searching for YANG files in dependencies: {}", YangToSourcesProcessor.LOG_PREFIX, filesOnCp);
85         LOG.debug("{} Searching for YANG files in {} dependencies", YangToSourcesProcessor.LOG_PREFIX,
86             filesOnCp.size());
87
88         final List<ScannedDependency> result = new ArrayList<>();
89         for (File file : filesOnCp) {
90             // is it jar file or directory?
91             if (file.isDirectory()) {
92                 final File yangDir = new File(file, META_INF_YANG_STRING);
93                 if (yangDir.exists() && yangDir.isDirectory()) {
94                     result.addAll(scanDirectory(yangDir));
95                 }
96             } else {
97                 result.addAll(scanZipFile(file));
98             }
99         }
100         return result;
101     }
102
103     private static Collection<ScannedDependency> scanDirectory(final File yangDir) {
104         return Arrays.stream(yangDir.listFiles(
105             (dir, name) -> name.endsWith(RFC6020_YANG_FILE_EXTENSION) && new File(dir, name).isFile()))
106                 .map(Single::new).collect(ImmutableList.toImmutableList());
107     }
108
109     private static Collection<ScannedDependency> scanZipFile(final File zipFile) throws IOException {
110         final Collection<String> entryNames;
111         try (ZipFile zip = new ZipFile(zipFile)) {
112             entryNames = zip.stream().filter(entry -> {
113                 final String entryName = entry.getName();
114                 return entryName.startsWith(META_INF_YANG_STRING_JAR) && !entry.isDirectory()
115                         && entryName.endsWith(RFC6020_YANG_FILE_EXTENSION);
116             }).map(ZipEntry::getName).collect(ImmutableList.toImmutableList());
117         }
118
119         return entryNames.isEmpty() ? ImmutableList.of() : ImmutableList.of(new Zip(zipFile, entryNames));
120     }
121
122     final File file() {
123         return file;
124     }
125
126     abstract Collection<YangTextSchemaSource> sources() throws IOException;
127 }