blob: bfe2bfe9f5a870313273fec08d49d04d2b9691b5 [file] [log] [blame]
/*
* Copyright 2017-present Open Networking Laboratory
*
* 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.onosproject.yang.web;
import org.apache.commons.io.IOUtils;
import org.glassfish.jersey.media.multipart.FormDataBodyPart;
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
import org.glassfish.jersey.media.multipart.FormDataMultiPart;
import org.onosproject.rest.AbstractWebResource;
import org.onosproject.yang.compiler.api.YangCompilationParam;
import org.onosproject.yang.compiler.api.YangCompilerService;
import org.onosproject.yang.compiler.datamodel.YangNode;
import org.onosproject.yang.model.YangModel;
import org.onosproject.yang.runtime.DefaultModelRegistrationParam;
import org.onosproject.yang.runtime.ModelRegistrationParam;
import org.onosproject.yang.runtime.YangModelRegistry;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import static org.onosproject.yang.compiler.datamodel.utils.DataModelUtils.deSerializeDataModel;
import static org.onosproject.yang.compiler.utils.io.impl.YangIoUtils.deleteDirectory;
import static org.onosproject.yang.runtime.helperutils.YangApacheUtils.processYangModel;
//import org.onosproject.yang.compiler.tool.DefaultYangCompilationParam;
/**
* Yang files upload resource.
*/
@Path("live-compiler")
public class YangWebResource extends AbstractWebResource {
private static final String YANG_FILE_EXTENSION = ".yang";
private static final String SER_FILE_EXTENSION = ".ser";
private static final String REGISTER = "register";
private static final String UNREGISTER = "unregister";
private static final String CODE_GEN_DIR = "target/generated-sources/";
private static final String META_DATA_DIR = "target/yang/resources/";
private static final String SERIALIZED_FILE_NAME = "YangMetaData.ser";
private static final String UNKNOWN_KEY = "Key must be either register " +
"or unregister.";
/**
* Compiles and registers the given yang files.
*
* @param formData YANG files or ser files
* @return 200 OK
* @throws IOException when fails to generate a file
*/
@Path("upload")
@POST
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Response upload(FormDataMultiPart formData) throws IOException {
Map<String, List<File>> input = parseInputData(formData);
for (Map.Entry<String, List<File>> entry : input.entrySet()) {
deleteDirectory(CODE_GEN_DIR);
deleteDirectory(META_DATA_DIR);
YangCompilerService liveCompiler = get(YangCompilerService.class);
liveCompiler.compileYangFiles(createCompilationParam(
entry.getValue()));
YangModelRegistry modelRegistry = get(YangModelRegistry.class);
String key = entry.getKey();
if (key.equalsIgnoreCase(REGISTER)) {
modelRegistry.registerModel(getModelRegParam());
} else if (key.equalsIgnoreCase(UNREGISTER)) {
modelRegistry.unregisterModel(getModelRegParam());
} else {
return Response.serverError().entity(UNKNOWN_KEY).build();
}
}
// TODO : create bundles
return Response.status(200).build();
}
private File getInputFile(InputStream stream, String fileName)
throws IOException {
byte[] content = IOUtils.toByteArray(stream);
File file = new File(fileName);
if (!file.exists()) {
file.createNewFile();
}
FileOutputStream fop = new FileOutputStream(file);
fop.write(content);
fop.flush();
fop.close();
return file;
}
private Map<String, List<File>> parseInputData(FormDataMultiPart formData)
throws IOException {
Map<String, List<File>> input = new HashMap<>();
Map<String, List<FormDataBodyPart>> fieldsByName = formData.getFields();
for (Map.Entry<String, List<FormDataBodyPart>> entry :
fieldsByName.entrySet()) {
List<File> inputFiles = new LinkedList<>();
for (FormDataBodyPart field : entry.getValue()) {
InputStream stream = field.getEntityAs(InputStream.class);
FormDataContentDisposition content = field
.getFormDataContentDisposition();
String fileName = content.getFileName();
inputFiles.add(getInputFile(stream, fileName));
}
input.put(entry.getKey(), inputFiles);
}
return input;
}
private YangCompilationParam createCompilationParam(List<File> inputFiles)
throws IOException {
// TODO : uncomment when yang tools new verison is released.
/*YangCompilationParam param = new DefaultYangCompilationParam();
for (File file : inputFiles) {
if (file.getName().endsWith(YANG_FILE_EXTENSION)) {
param.addYangFile(Paths.get(file.getAbsolutePath()));
} else if (file.getName().endsWith(SER_FILE_EXTENSION)) {
param.addDependentSchema(Paths.get(file.getAbsolutePath()));
}
}
param.setCodeGenDir(Paths.get(CODE_GEN_DIR));
param.setMetadataGenDir(Paths.get(META_DATA_DIR));
return param;*/
return null;
}
private ModelRegistrationParam getModelRegParam() throws IOException {
String metaPath = META_DATA_DIR + SERIALIZED_FILE_NAME;
List<YangNode> curNodes = getYangNodes(metaPath);
if (curNodes != null && !curNodes.isEmpty()) {
YangModel model = processYangModel(metaPath, curNodes);
return DefaultModelRegistrationParam.builder()
.setYangModel(model).build();
}
return null;
}
private List<YangNode> getYangNodes(String path) throws IOException {
List<YangNode> nodes = new LinkedList<YangNode>();
File file = new File(path);
if (file.getName().endsWith(SER_FILE_EXTENSION)) {
nodes.addAll(deSerializeDataModel(file.toString()));
}
return nodes;
}
}