/* * Copyright 2011 Future Systems, Inc. * * 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.krakenapps.confdb.file; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.net.Inet4Address; import java.net.Inet6Address; import java.nio.charset.Charset; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Map; import org.json.JSONException; import org.json.JSONWriter; import org.krakenapps.codec.Base64; import org.krakenapps.codec.UnsupportedTypeException; import org.krakenapps.confdb.ConfigCollection; import org.krakenapps.confdb.ConfigIterator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class Exporter { private final Logger logger = LoggerFactory.getLogger(Exporter.class.getName()); private FileConfigDatabase db; /** * CAUTION: thread unsafe for performance reason. */ private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ssZ"); public Exporter(FileConfigDatabase db) { this.db = db; } public void exportData(OutputStream os) throws IOException { if (os == null) throw new IllegalArgumentException("export output stream cannot be null"); logger.debug("kraken confdb: start export data"); db.lock(); try { OutputStreamWriter writer = new OutputStreamWriter(os, Charset.forName("utf-8")); JSONWriter jw = new JSONWriter(writer); jw.object(); jw.key("metadata"); jw.object(); jw.key("version").value(1); jw.key("date").value(sdf.format(new Date())); jw.endObject(); jw.key("collections"); jw.object(); for (String name : db.getCollectionNames()) { ConfigCollection col = db.getCollection(name); // collection name jw.key(name); // typed doc list jw.array(); jw.value("list"); // doc list begin jw.array(); ConfigIterator it = col.findAll(); try { while (it.hasNext()) { Object doc = it.next().getDocument(); jw.value(insertType(doc)); } } finally { it.close(); } // end of doc list jw.endArray(); // end of typed list jw.endArray(); } // end of collection jw.endObject(); // end of master doc jw.endObject(); writer.flush(); logger.debug("kraken confdb: export complete"); } catch (JSONException e) { throw new IOException(e); } finally { db.unlock(); } } private Object insertType(Object doc) { if (doc instanceof String) { return createList("string", doc); } else if (doc instanceof Integer) { return createList("int", doc); } else if (doc instanceof Boolean) { return createList("bool", doc); } else if (doc instanceof Long) { return createList("long", doc); } else if (doc instanceof Inet4Address) { return createList("ip4", ((Inet4Address) doc).getHostAddress()); } else if (doc instanceof Inet6Address) { return createList("ip6", ((Inet6Address) doc).getHostAddress()); } else if (doc instanceof Double) { return createList("double", doc); } else if (doc instanceof Float) { return createList("float", doc); } else if (doc instanceof Date) { Date docDate = (Date) doc; return createList("date", sdf.format(docDate)); } else if (doc instanceof Short) { return createList("short", doc); } else if (doc == null) { return createList("null", doc); } else if (doc instanceof Map) { @SuppressWarnings("unchecked") Map<String, Object> m = (Map<String, Object>) doc; for (String name : m.keySet()) { m.put(name, insertType(m.get(name))); } return createList("map", m); } else if (doc instanceof List) { @SuppressWarnings("unchecked") List<Object> l = (List<Object>) doc; List<Object> newList = new ArrayList<Object>(); for (Object o : l) { newList.add(insertType(o)); } return createList("list", newList); } else if (doc.getClass().isArray()) { return insertArrayType(doc); } else { throw new UnsupportedTypeException("unsupported value [" + doc + "], type [" + doc.getClass().getName() + "]"); } } private List<Object> createList(String type, Object doc) { List<Object> l = new ArrayList<Object>(2); l.add(type); l.add(doc); return l; } private Object insertArrayType(Object doc) { Class<?> c = doc.getClass().getComponentType(); if (c == byte.class) { byte[] arr = (byte[]) doc; return createList("blob", new String(Base64.encode(arr))); } else if (c == int.class || c == double.class || c == float.class || c == long.class || c == short.class || c == boolean.class) { return createList("list", doc); } else if (c == char.class) { throw new UnsupportedTypeException("unsupported data type [" + c.getName() + "]"); } else { Object[] os = (Object[]) doc; Object[] newOs = new Object[os.length]; for (int index = 0; index < os.length; index++) { newOs[index] = insertType(os[index]); } return createList("list", newOs); } } }