package org.safehaus.subutai.impl.packagemanager.storage;

import java.io.*;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import org.safehaus.subutai.api.packagemanager.PackageInfo;
import org.safehaus.subutai.api.packagemanager.storage.PackageInfoStorage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class FilePackageInfoStorage implements PackageInfoStorage {

    private static final Logger logger = LoggerFactory.getLogger(FilePackageInfoStorage.class);
    private final Path parent;

    public FilePackageInfoStorage(String parentDir) {
        File f = new File(parentDir);
        if(!f.exists()) f.mkdirs();
        else if(!f.isDirectory()) parentDir = "/tmp/subutai/packages";

        this.parent = Paths.get(parentDir);
    }

    @Override
    public Collection<PackageInfo> retrieve(String key) {
        try {
            return deserialize(key);
        } catch(IOException ex) {
            logger.error("Failed to deserialize", ex);
            return null;
        }
    }

    @Override
    public boolean persist(String key, Collection<PackageInfo> packages) {
        try {
            serialize(packages, key);
            return true;
        } catch(IOException ex) {
            logger.error("Failed to serialize", ex);
            return false;
        }
    }

    @Override
    public boolean delete(String key) {
        File f = parent.resolve(key).toFile();
        return f.exists() ? f.delete() : false;
    }

    private void serialize(Collection<PackageInfo> col, String filePath) throws IOException {
        File f = parent.resolve(filePath).toFile();
        if(!f.getParentFile().exists()) f.getParentFile().mkdirs();

        ObjectOutputStream out = null;
        try {
            FileOutputStream fos = new FileOutputStream(f);
            out = new ObjectOutputStream(fos);
            // wrap collection in list to ensure serializable collection
            ArrayList ls = new ArrayList(col);
            out.writeObject(ls);
        } finally {
            if(out != null) out.close();
        }
    }

    private List<PackageInfo> deserialize(String filePath) throws IOException {
        File f = parent.resolve(filePath).toFile();
        if(!f.exists()) return null;

        List<PackageInfo> res = null;
        ObjectInputStream in = null;
        try {
            FileInputStream fis = new FileInputStream(f);
            in = new ObjectInputStream(fis);
            res = (List<PackageInfo>)in.readObject();
        } catch(FileNotFoundException ex) {
            // failed to open specified file
            logger.warn("Failed to open file", ex);
        } catch(ClassNotFoundException ex) {
            // invalid data
            logger.warn("Invalid data", ex);
        } finally {
            if(in != null) in.close();
        }
        return res;
    }

}

@@ -63,17 +63,186 @@
 ort 
-java.io.*
+com.google.gson.Gson;%0Aimport com.google.gson.GsonBuilder;%0Aimport com.google.gson.JsonParseException;%0Aimport java.io.*;%0Aimport java.nio.charset.Charset;%0Aimport java.nio.file.Files
 ;%0Aim
@@ -449,16 +449,85 @@
 torage;%0A
+import org.safehaus.subutai.impl.packagemanager.info.DebPackageInfo;%0A
 import o
@@ -757,26 +757,238 @@
 ate 
-final Path parent;
+static final Gson gson;%0A    private final Path parent;%0A%0A    static %7B%0A        // do not use pretty-printing!!!%0A        // each item corresponds to one line in a file%0A        gson = new GsonBuilder().serializeNulls().create();%0A    %7D
 %0A%0A  
@@ -2036,38 +2036,41 @@
 ption %7B%0A        
-File f
+Path path
  = parent.resolv
@@ -2084,76 +2084,107 @@
 ath)
-.toFile();%0A        if(!f.getParentFile().exists()) f.getParentFile()
+;%0A        File parentDir = path.toFile().getParentFile();%0A        if(!parentDir.exists()) parentDir
 .mkd
@@ -2199,34 +2199,30 @@
         
-ObjectOutputStream
+BufferedWriter
  out = n
@@ -2256,255 +2256,195 @@
     
-FileOutputStream fos = new FileOutputStream(f);%0A            out = new ObjectOutputStream(fos);%0A            // wrap collection in list to ensure serializable collection%0A            ArrayList ls = new ArrayList(col);%0A            out.writeObject(ls);
+out = Files.newBufferedWriter(path, Charset.defaultCharset());%0A            for(PackageInfo p : col) %7B%0A                out.write(p.toString());%0A                out.newLine();%0A            %7D
 %0A   
@@ -2598,38 +2598,41 @@
 ption %7B%0A        
-File f
+Path path
  = parent.resolv
@@ -2642,25 +2642,16 @@
 ilePath)
-.toFile()
 ;%0A      
@@ -2648,33 +2648,45 @@
 h);%0A        if(!
-f
+path.toFile()
 .exists()) retur
@@ -2706,190 +2706,145 @@
     
-List%3CPackageInfo%3E res = null;%0A        ObjectInputStream in = null;%0A        try %7B%0A            FileInputStream fis = new FileInputStream(f);%0A            in = new ObjectInputStream(fis)
+BufferedReader in = null;%0A        try %7B%0A            in = Files.newBufferedReader(path, Charset.defaultCharset());%0A            String line
 ;%0A  
@@ -2857,15 +2857,8 @@
     
-res = (
 List
@@ -2874,165 +2874,293 @@
 nfo%3E
-)in.readObject();%0A        %7D catch(FileNotFoundException ex) %7B%0A            // failed to open specified file%0A            logger.warn(%22Failed to open file%22, ex)
+ res = new ArrayList%3C%3E();%0A            while((line = in.readLine()) != null) %7B%0A                if(line.isEmpty()) continue;%0A                DebPackageInfo deb = gson.fromJson(line, DebPackageInfo.class);%0A                if(deb != null) res.add(deb);%0A            %7D%0A            return res
 ;%0A  
@@ -3177,21 +3177,17 @@
 tch(
-ClassNotFound
+JsonParse
 Exce
@@ -3202,36 +3202,8 @@
 ) %7B%0A
-            // invalid data%0A
     
@@ -3221,12 +3221,13 @@
 ger.
-warn
+error
 (%22In
@@ -3236,12 +3236,19 @@
 lid 
-data
+source file
 %22, e
@@ -3331,26 +3331,27 @@
      return 
-res
+null
 ;%0A    %7D%0A%0A%7D%0A

store package info in text format instead of binary