[SDC-18] Tosca Parser conformance level - initial

Change-Id: I0d8d27f4b8085d918ecc94aace423d3216337f2d
Signed-off-by: Pavel Aharoni <pa0916@att.com>
diff --git a/jtosca/pom.xml b/jtosca/pom.xml
index f74988b..ce50fec 100644
--- a/jtosca/pom.xml
+++ b/jtosca/pom.xml
@@ -9,7 +9,7 @@
 	</parent>
 	
 	<artifactId>jtosca</artifactId>
-	<version>0.1.2-SNAPSHOT</version>
+	<version>0.1.3-SNAPSHOT</version>
 	
 	<dependencies>
 	
@@ -34,5 +34,10 @@
 			<scope>test</scope>
 		</dependency> -->
 
-	</dependencies>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>4.12</version>
+		</dependency>
+    </dependencies>
 </project>
\ No newline at end of file
diff --git a/jtosca/src/main/java/org/openecomp/sdc/toscaparser/api/ToscaTemplate.java b/jtosca/src/main/java/org/openecomp/sdc/toscaparser/api/ToscaTemplate.java
index 942ca96..d1b0179 100644
--- a/jtosca/src/main/java/org/openecomp/sdc/toscaparser/api/ToscaTemplate.java
+++ b/jtosca/src/main/java/org/openecomp/sdc/toscaparser/api/ToscaTemplate.java
@@ -82,8 +82,9 @@
     private ArrayList<TopologyTemplate> nestedToscaTemplatesWithTopology;
     private ToscaGraph graph;
     private String csarTempDir;
-    private int nestingLoopCounter; 
-  
+    private int nestingLoopCounter;
+	private LinkedHashMap<String, LinkedHashMap<String, Object>> metaProperties;
+
 	@SuppressWarnings("unchecked")
 	public ToscaTemplate(String _path,
 			 			 LinkedHashMap<String,Object> _parsedParams,
@@ -480,6 +481,7 @@
 			if (csar.validate()) {
 				try {
 					csar.decompress();
+					metaProperties = csar.getMetaProperties();
 				} 
 				catch (IOException e) {
 					log.error("ToscaTemplate - _getPath - IOException trying to decompress {}", _path);
@@ -554,6 +556,10 @@
 	public ArrayList<NodeTemplate> getNodeTemplates() {
 		return nodeTemplates;
 	}
+
+	public LinkedHashMap<String, Object> getMetaProperties(String propertiesFile) {
+		return metaProperties.get(propertiesFile);
+	}
 	
 	private boolean _isSubMappedNode(NodeTemplate nt,LinkedHashMap<String,Object> toscaTpl) {
 		// Return True if the nodetemple is substituted
diff --git a/jtosca/src/main/java/org/openecomp/sdc/toscaparser/api/prereq/CSAR.java b/jtosca/src/main/java/org/openecomp/sdc/toscaparser/api/prereq/CSAR.java
index 159ad66..2ab5d26 100644
--- a/jtosca/src/main/java/org/openecomp/sdc/toscaparser/api/prereq/CSAR.java
+++ b/jtosca/src/main/java/org/openecomp/sdc/toscaparser/api/prereq/CSAR.java
@@ -12,10 +12,7 @@
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.nio.file.StandardCopyOption;
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.LinkedHashMap;
-import java.util.Map;
+import java.util.*;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipFile;
 import java.util.zip.ZipInputStream;
@@ -31,6 +28,7 @@
 public class CSAR {
 
 	private static Logger log = LoggerFactory.getLogger(CSAR.class.getName());
+	private static final ArrayList<String> META_PROPERTIES_FILES = new ArrayList<>(Arrays.asList("TOSCA-Metadata/TOSCA.meta", "csar.meta"));
 
 	private String path;
     private boolean isFile;
@@ -38,9 +36,10 @@
     private boolean errorCaught;
     private String csar;
     private String tempDir;
-    private Metadata metaData;
+//    private Metadata metaData;
     private File tempFile;
-	
+	private LinkedHashMap<String, LinkedHashMap<String, Object>> metaProperties;
+
 	public CSAR(String csarPath, boolean aFile) {
 		path = csarPath;
 		isFile = aFile;
@@ -49,8 +48,9 @@
         csar = null;
         tempDir = null;
         tempFile = null;
+		metaProperties = new LinkedHashMap<>();
 	}
-	
+
 	@SuppressWarnings("unchecked")
 	public boolean validate() {
 		isValidated = true;
@@ -89,86 +89,8 @@
 			return false;
 		}
 		
-		ZipFile zf = null;
-        
-		try {
+		_parseAndValidateMetaProperties();
 
-			// validate that it is a valid zip file
-			RandomAccessFile raf = new RandomAccessFile(csar, "r");
-			long n = raf.readInt();
-			raf.close();
-			// check if Zip's magic number
-			if (n != 0x504B0304) {
-			    throw new IOException(String.format("\"%s\" is not a valid zip file", csar));
-			}
-			
-			// validate that it contains the metadata file in the correct location
-			zf = new ZipFile(csar);
-			ZipEntry ze = zf.getEntry("TOSCA-Metadata/TOSCA.meta");
-			if(ze == null) {
-				throw new IOException(String.format(
-						"\"%s\" is not a valid CSAR as it does not contain the " +
-			            "required file \"TOSCA.meta\" in the folder \"TOSCA-Metadata\"", csar));
-			}
-	        
-			// verify it has "Entry-Definition"
-			ZipInputStream zipIn = new ZipInputStream(new FileInputStream(csar));
-	        byte ba[] = new byte[4096];
-			while ((ze = zipIn.getNextEntry()) != null) {
-			    if (ze.getName().equals("TOSCA-Metadata/TOSCA.meta")) {
-					n = zipIn.read(ba,0,4096);
-					zipIn.close();
-			        break;
-			    }
-			}
-
-	        String md = new String(ba);
-	        md = md.substring(0, (int)n);
-	        Yaml yaml = new Yaml();
-	        Object mdo = yaml.load(md);
-	        if(!(mdo instanceof LinkedHashMap)) {
-	        	throw new IOException(String.format(
-	        			"The file \"TOSCA-Metadata/TOSCA.meta\" in the" +
-	        			" CSAR \"%s\" does not contain valid YAML content",csar));
-	        }
-	        
-			metaData = new Metadata((Map<String, Object>) mdo);
-	        String edf = metaData.getValue("Entry-Definitions");
-	        if(edf == null) {
-	        	throw new IOException(String.format(
-	        			"The CSAR \"%s\" is missing the required metadata " +
-	        			"\"Entry-Definitions\" in \"TOSCA-Metadata/TOSCA.meta\"",csar));
-	        }
-	        
-	        //validate that "Entry-Definitions' metadata value points to an existing file in the CSAR
-	        boolean foundEDF = false;
-	        Enumeration<? extends ZipEntry> entries = zf.entries();
-	        while (entries.hasMoreElements()) {
-	            ze = entries.nextElement();
-	            if (ze.getName().equals(edf)) {
-	                foundEDF = true;
-	                break;
-	            }
-	        }
-	        if(!foundEDF) {
-	        	throw new IOException(String.format(
-	        			"The \"Entry-Definitions\" file defined in the CSAR \"%s\" does not exist",csar));
-	        }
-			
-		}
-		catch(Exception e) {
-			ExceptionCollector.appendException("ValidationError: " + e.getMessage());
-			errorCaught = true;;
-		}
-		
-		try {
-			if(zf != null) {
-				zf.close();
-			}
-		}
-		catch(IOException e) {
-		}
-		
 		if(errorCaught) {
 			return false;
 		}
@@ -179,6 +101,93 @@
         return !errorCaught;
 
 	}
+
+	private void _parseAndValidateMetaProperties() {
+
+		ZipFile zf = null;
+
+		try {
+
+			// validate that it is a valid zip file
+			RandomAccessFile raf = new RandomAccessFile(csar, "r");
+			long n = raf.readInt();
+			raf.close();
+			// check if Zip's magic number
+			if (n != 0x504B0304) {
+				throw new IOException(String.format("\"%s\" is not a valid zip file", csar));
+			}
+
+			// validate that it contains the metadata file in the correct location
+			zf = new ZipFile(csar);
+			ZipEntry ze = zf.getEntry("TOSCA-Metadata/TOSCA.meta");
+			if (ze == null) {
+				throw new IOException(String.format(
+						"\"%s\" is not a valid CSAR as it does not contain the " +
+								"required file \"TOSCA.meta\" in the folder \"TOSCA-Metadata\"", csar));
+			}
+
+			//Going over expected metadata files and parsing them
+			for (String metaFile: META_PROPERTIES_FILES) {
+
+				byte ba[] = new byte[4096];
+				ze = zf.getEntry(metaFile);
+				if (ze != null) {
+					InputStream inputStream = zf.getInputStream(ze);
+					n = inputStream.read(ba, 0, 4096);
+
+					String md = new String(ba);
+					md = md.substring(0, (int) n);
+					Yaml yaml = new Yaml();
+					Object mdo = yaml.load(md);
+					if (!(mdo instanceof LinkedHashMap)) {
+						throw new IOException(String.format(
+								"The file \"%s\" in the" +
+										" CSAR \"%s\" does not contain valid YAML content", ze.getName(), csar));
+					}
+
+					String[] split = ze.getName().split("/");
+                    String fileName = split[split.length - 1];
+
+					if (!metaProperties.containsKey(fileName)) {
+						metaProperties.put(fileName, (LinkedHashMap<String, Object>) mdo);
+					}
+				}
+			}
+
+			// verify it has "Entry-Definition"
+			String edf = _getMetadata("Entry-Definitions");
+			if (edf == null) {
+				throw new IOException(String.format(
+						"The CSAR \"%s\" is missing the required metadata " +
+								"\"Entry-Definitions\" in \"TOSCA-Metadata/TOSCA.meta\"", csar));
+			}
+
+			//validate that "Entry-Definitions' metadata value points to an existing file in the CSAR
+			boolean foundEDF = false;
+			Enumeration<? extends ZipEntry> entries = zf.entries();
+			while (entries.hasMoreElements()) {
+				ze = entries.nextElement();
+				if (ze.getName().equals(edf)) {
+					foundEDF = true;
+					break;
+				}
+			}
+			if (!foundEDF) {
+				throw new IOException(String.format(
+						"The \"Entry-Definitions\" file defined in the CSAR \"%s\" does not exist", csar));
+			}
+		} catch (Exception e) {
+			ExceptionCollector.appendException("ValidationError: " + e.getMessage());
+			errorCaught = true;
+		}
+
+		try {
+			if (zf != null) {
+				zf.close();
+			}
+		} catch (IOException e) {
+		}
+	}
 	
 	public void cleanup() {
 		try {
@@ -190,15 +199,12 @@
 		}
 	}
 	
-	public Metadata getMetadata() {
-		return metaData;
-	}
-	
     private String _getMetadata(String key) {
     	if(!isValidated) {
     		validate();
     	}
-    	return metaData.getValue(key);
+    	Object value = _getMetaProperty("TOSCA.meta").get(key);
+    	return value != null ? value.toString() : null;
     }
 
     public String getAuthor() {
@@ -208,8 +214,16 @@
     public String getVersion() {
         return _getMetadata("CSAR-Version");
     }
-    
-    public String getMainTemplate() {
+
+	public LinkedHashMap<String, LinkedHashMap<String, Object>> getMetaProperties() {
+		return metaProperties;
+	}
+
+	private LinkedHashMap<String, Object> _getMetaProperty(String propertiesFile) {
+		return metaProperties.get(propertiesFile);
+	}
+
+	public String getMainTemplate() {
     	String entryDef = _getMetadata("Entry-Definitions");
     	ZipFile zf;
     	boolean ok = false;
@@ -259,8 +273,10 @@
         if(desc != null) {
             return desc;
         }
-        metaData.setValue("Description",(String)getMainTemplateYaml().get("description"));
-        return metaData.getValue("Description");
+
+		Map<String, Object> metaData = metaProperties.get("TOSCA.meta");
+		metaData.put("Description", getMainTemplateYaml().get("description"));
+		return _getMetadata("Description");
     }
 
     public String getTempDir() {
diff --git a/jtosca/src/test/java/org.openecomp.sdc.toscaparser/JToscaMetadataParse.java b/jtosca/src/test/java/org.openecomp.sdc.toscaparser/JToscaMetadataParse.java
new file mode 100644
index 0000000..584a0fd
--- /dev/null
+++ b/jtosca/src/test/java/org.openecomp.sdc.toscaparser/JToscaMetadataParse.java
@@ -0,0 +1,26 @@
+package org.openecomp.sdc.toscaparser;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.io.File;
+import java.util.LinkedHashMap;
+
+import org.junit.Test;
+import org.openecomp.sdc.toscaparser.api.ToscaTemplate;
+import org.openecomp.sdc.toscaparser.api.common.JToscaException;
+
+public class JToscaMetadataParse {
+
+    @Test
+    public void testMetadataParsedCorrectly() throws JToscaException {
+        String fileStr = JToscaMetadataParse.class.getClassLoader().getResource("csars/csar_hello_world.csar").getFile();
+        File file = new File(fileStr);
+        ToscaTemplate toscaTemplate = new ToscaTemplate(file.getAbsolutePath(), null, true, null);
+        LinkedHashMap<String, Object> metadataProperties = toscaTemplate.getMetaProperties("TOSCA.meta");
+        assertNotNull(metadataProperties);
+        Object entryDefinition = metadataProperties.get("Entry-Definitions");
+        assertNotNull(entryDefinition);
+        assertEquals("tosca_helloworld.yaml", entryDefinition);
+    }
+}
diff --git a/jtosca/src/test/resources/csars/csar_hello_world.csar b/jtosca/src/test/resources/csars/csar_hello_world.csar
new file mode 100644
index 0000000..43ffbbc
--- /dev/null
+++ b/jtosca/src/test/resources/csars/csar_hello_world.csar
Binary files differ