/* * 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; } }