blob: 471e891bbee0e1503ed1c9f6598f040ee6ec02bb [file] [log] [blame]
Vidyashree Rama3c503612017-05-10 13:55:34 +05301/*
2 * Copyright 2017-present Open Networking Laboratory
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package org.onosproject.yang.web;
18
19import org.apache.commons.io.IOUtils;
20import org.glassfish.jersey.media.multipart.FormDataBodyPart;
21import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
22import org.glassfish.jersey.media.multipart.FormDataMultiPart;
23import org.onosproject.rest.AbstractWebResource;
24import org.onosproject.yang.compiler.api.YangCompilationParam;
25import org.onosproject.yang.compiler.api.YangCompilerService;
26import org.onosproject.yang.compiler.datamodel.YangNode;
Vidyashree Rama0c49b9a2017-06-02 11:54:19 +053027import org.onosproject.yang.compiler.tool.DefaultYangCompilationParam;
Vidyashree Rama3c503612017-05-10 13:55:34 +053028import org.onosproject.yang.model.YangModel;
29import org.onosproject.yang.runtime.DefaultModelRegistrationParam;
30import org.onosproject.yang.runtime.ModelRegistrationParam;
31import org.onosproject.yang.runtime.YangModelRegistry;
32
33import javax.ws.rs.Consumes;
34import javax.ws.rs.POST;
35import javax.ws.rs.Path;
36import javax.ws.rs.core.MediaType;
37import javax.ws.rs.core.Response;
38import java.io.File;
39import java.io.FileOutputStream;
40import java.io.IOException;
41import java.io.InputStream;
Vidyashree Rama0c49b9a2017-06-02 11:54:19 +053042import java.nio.file.Paths;
Vidyashree Rama00449232017-06-21 09:41:07 +053043import java.util.Enumeration;
Vidyashree Rama3c503612017-05-10 13:55:34 +053044import java.util.HashMap;
45import java.util.LinkedList;
46import java.util.List;
47import java.util.Map;
Vidyashree Rama00449232017-06-21 09:41:07 +053048import java.util.zip.ZipEntry;
49import java.util.zip.ZipFile;
Vidyashree Rama3c503612017-05-10 13:55:34 +053050
51import static org.onosproject.yang.compiler.datamodel.utils.DataModelUtils.deSerializeDataModel;
52import static org.onosproject.yang.compiler.utils.io.impl.YangIoUtils.deleteDirectory;
53import static org.onosproject.yang.runtime.helperutils.YangApacheUtils.processYangModel;
54
Vidyashree Rama3c503612017-05-10 13:55:34 +053055/**
56 * Yang files upload resource.
57 */
Vidyashree Rama00449232017-06-21 09:41:07 +053058@Path("models")
Vidyashree Rama3c503612017-05-10 13:55:34 +053059public class YangWebResource extends AbstractWebResource {
60 private static final String YANG_FILE_EXTENSION = ".yang";
61 private static final String SER_FILE_EXTENSION = ".ser";
Vidyashree Rama00449232017-06-21 09:41:07 +053062 private static final String JAR_FILE_EXTENSION = ".jar";
63 private static final String ZIP_FILE_EXTENSION = ".zip";
Vidyashree Rama3c503612017-05-10 13:55:34 +053064 private static final String REGISTER = "register";
65 private static final String UNREGISTER = "unregister";
66 private static final String CODE_GEN_DIR = "target/generated-sources/";
Vidyashree Rama00449232017-06-21 09:41:07 +053067 private static final String YANG_RESOURCES = "target/yang/resources/";
Vidyashree Rama3c503612017-05-10 13:55:34 +053068 private static final String SERIALIZED_FILE_NAME = "YangMetaData.ser";
69 private static final String UNKNOWN_KEY = "Key must be either register " +
70 "or unregister.";
Vidyashree Rama00449232017-06-21 09:41:07 +053071 private static final String SLASH = "/";
Vidyashree Rama3c503612017-05-10 13:55:34 +053072
73 /**
74 * Compiles and registers the given yang files.
75 *
76 * @param formData YANG files or ser files
77 * @return 200 OK
78 * @throws IOException when fails to generate a file
79 */
Vidyashree Rama3c503612017-05-10 13:55:34 +053080 @POST
81 @Consumes(MediaType.MULTIPART_FORM_DATA)
82 public Response upload(FormDataMultiPart formData) throws IOException {
83 Map<String, List<File>> input = parseInputData(formData);
84
85 for (Map.Entry<String, List<File>> entry : input.entrySet()) {
86 deleteDirectory(CODE_GEN_DIR);
Vidyashree Rama00449232017-06-21 09:41:07 +053087 deleteDirectory(YANG_RESOURCES);
Vidyashree Rama3c503612017-05-10 13:55:34 +053088
89 YangCompilerService liveCompiler = get(YangCompilerService.class);
90 liveCompiler.compileYangFiles(createCompilationParam(
91 entry.getValue()));
92
93 YangModelRegistry modelRegistry = get(YangModelRegistry.class);
94 String key = entry.getKey();
95 if (key.equalsIgnoreCase(REGISTER)) {
96 modelRegistry.registerModel(getModelRegParam());
97 } else if (key.equalsIgnoreCase(UNREGISTER)) {
98 modelRegistry.unregisterModel(getModelRegParam());
99 } else {
100 return Response.serverError().entity(UNKNOWN_KEY).build();
101 }
102 }
103
104 // TODO : create bundles
105
106 return Response.status(200).build();
107 }
108
109 private File getInputFile(InputStream stream, String fileName)
110 throws IOException {
111 byte[] content = IOUtils.toByteArray(stream);
112 File file = new File(fileName);
113 if (!file.exists()) {
114 file.createNewFile();
115 }
116 FileOutputStream fop = new FileOutputStream(file);
117 fop.write(content);
118 fop.flush();
119 fop.close();
120 return file;
121 }
122
123 private Map<String, List<File>> parseInputData(FormDataMultiPart formData)
124 throws IOException {
125 Map<String, List<File>> input = new HashMap<>();
126 Map<String, List<FormDataBodyPart>> fieldsByName = formData.getFields();
127 for (Map.Entry<String, List<FormDataBodyPart>> entry :
128 fieldsByName.entrySet()) {
129 List<File> inputFiles = new LinkedList<>();
130 for (FormDataBodyPart field : entry.getValue()) {
131 InputStream stream = field.getEntityAs(InputStream.class);
132 FormDataContentDisposition content = field
133 .getFormDataContentDisposition();
134 String fileName = content.getFileName();
135 inputFiles.add(getInputFile(stream, fileName));
136 }
137 input.put(entry.getKey(), inputFiles);
138 }
139 return input;
140 }
141
142 private YangCompilationParam createCompilationParam(List<File> inputFiles)
143 throws IOException {
Vidyashree Rama0c49b9a2017-06-02 11:54:19 +0530144 YangCompilationParam param = new DefaultYangCompilationParam();
Vidyashree Rama3c503612017-05-10 13:55:34 +0530145 for (File file : inputFiles) {
Vidyashree Rama00449232017-06-21 09:41:07 +0530146 if (file.getName().endsWith(JAR_FILE_EXTENSION)
147 || file.getName().endsWith(ZIP_FILE_EXTENSION)) {
148 List<File> files = decompressFile(file);
149
150 for (File f : files) {
151 param = addToParam(param, f);
152 }
153 } else {
154 param = addToParam(param, file);
Vidyashree Rama3c503612017-05-10 13:55:34 +0530155 }
156 }
157 param.setCodeGenDir(Paths.get(CODE_GEN_DIR));
Vidyashree Rama00449232017-06-21 09:41:07 +0530158 param.setMetadataGenDir(Paths.get(YANG_RESOURCES));
159 return param;
160 }
161
162 private YangCompilationParam addToParam(YangCompilationParam param,
163 File file) {
164 if (file.getName().endsWith(YANG_FILE_EXTENSION)) {
165 param.addYangFile(Paths.get(file.getAbsolutePath()));
166 } else if (file.getName().endsWith(SER_FILE_EXTENSION)) {
167 param.addDependentSchema(Paths.get(file.getAbsolutePath()));
168 }
Vidyashree Rama0c49b9a2017-06-02 11:54:19 +0530169 return param;
Vidyashree Rama3c503612017-05-10 13:55:34 +0530170 }
171
172 private ModelRegistrationParam getModelRegParam() throws IOException {
Vidyashree Rama00449232017-06-21 09:41:07 +0530173 String metaPath = YANG_RESOURCES + SERIALIZED_FILE_NAME;
Vidyashree Rama3c503612017-05-10 13:55:34 +0530174 List<YangNode> curNodes = getYangNodes(metaPath);
175 if (curNodes != null && !curNodes.isEmpty()) {
176 YangModel model = processYangModel(metaPath, curNodes);
177 return DefaultModelRegistrationParam.builder()
178 .setYangModel(model).build();
179 }
180 return null;
181 }
182
183 private List<YangNode> getYangNodes(String path) throws IOException {
Vidyashree Rama00449232017-06-21 09:41:07 +0530184 List<YangNode> nodes = new LinkedList<>();
Vidyashree Rama3c503612017-05-10 13:55:34 +0530185 File file = new File(path);
186 if (file.getName().endsWith(SER_FILE_EXTENSION)) {
187 nodes.addAll(deSerializeDataModel(file.toString()));
188 }
189 return nodes;
190 }
Vidyashree Rama00449232017-06-21 09:41:07 +0530191
192 private static List<File> decompressFile(File jarFile)
193 throws IOException {
194 ZipFile zip = new ZipFile(jarFile);
195 final List<File> unzipedFiles = new LinkedList<>();
196
197 // first get all directories,
198 // then make those directory on the destination Path
199 for (Enumeration<? extends ZipEntry> enums = zip.entries();
200 enums.hasMoreElements();) {
201 ZipEntry entry = enums.nextElement();
202
203 String fileName = YANG_RESOURCES + entry.getName();
204 File f = new File(fileName);
205
206 if (fileName.endsWith(SLASH)) {
207 f.mkdirs();
208 }
209 }
210
211 //now create all files
212 for (Enumeration<? extends ZipEntry> enums = zip.entries();
213 enums.hasMoreElements();) {
214 ZipEntry entry = enums.nextElement();
215 String fileName = YANG_RESOURCES + entry.getName();
216 File f = new File(fileName);
217
218 if (!fileName.endsWith(SLASH)) {
219 InputStream is = zip.getInputStream(entry);
220 FileOutputStream fos = new FileOutputStream(f);
221
222 // write contents of 'is' to 'fos'
223 while (is.available() > 0) {
224 fos.write(is.read());
225 }
226 unzipedFiles.add(f);
227 fos.close();
228 is.close();
229 }
230 }
231 return unzipedFiles;
232 }
Vidyashree Rama3c503612017-05-10 13:55:34 +0530233}