net.autosauler.ballance.server.mongodb.Database.java Source code

Java tutorial

Introduction

Here is the source code for net.autosauler.ballance.server.mongodb.Database.java

Source

/*******************************************************************************
 * Copyright 2011 Alex 'Ript' Malyshev <alexript@gmail.com>
 * 
 * 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 net.autosauler.ballance.server.mongodb;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.net.UnknownHostException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import net.autosauler.ballance.server.model.AbstractCatalog;
import net.autosauler.ballance.server.model.AbstractDocument;
import net.autosauler.ballance.server.model.Currency;
import net.autosauler.ballance.server.model.GlobalSettings;
import net.autosauler.ballance.server.model.Scripts;
import net.autosauler.ballance.server.model.Structures;
import net.autosauler.ballance.server.model.UserList;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import com.allen_sauer.gwt.log.client.Log;
import com.mongodb.DB;
import com.mongodb.Mongo;
import com.mongodb.MongoException;

/**
 * The Class Database.
 */
public class Database {

    // TODO: all connect values must be configurable

    /** The Constant host. */
    private static final String host = "127.0.0.1";

    /** The Constant port. */
    private static final int port = 27017;

    /** The Constant database. */
    private static final String database = "blncatslrnt";

    /** The Constant user. */
    private static final String user = "user";

    /** The Constant password. */
    private static final String password = "user";

    /** The Constant adminuser. */
    private static final String adminuser = "root";

    /** The Constant adminpassword. */
    private static final String adminpassword = "root";

    /** The mongo. */
    private static Mongo mongo = null;
    /** The mongodatabase. */
    private static DB mongodatabase = null;

    /** The lockcounter. */
    private static Integer lockcounter = 0;

    /** The releaser. */
    private static Thread releaser = null;

    /** The retaintimeoutmin. */
    private static int retaintimeoutmin = 5;

    /** The settings. */
    private static GlobalSettings settings = null;

    /**
     * Close connection.
     */
    public static synchronized void close() {

        mongodatabase = null;
        if (mongo != null) {
            mongo.close();
            mongo = null;
        }

        if (releaser != null) {
            releaser = null;
        }
        lockcounter = 0;
        if (settings != null) {
            settings.save();
        }
    }

    public static void dumpdatabase(String domain, String username, String filename) {
        // TODO: return boolean, write to stream
        // TODO: add xml scheme
        // TODO: generate filename
        StringBuilder sb = new StringBuilder();

        sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
        sb.append("<dump date=\"" + new Date().getTime() + "\">\n");
        GlobalSettings settings = new GlobalSettings(domain);
        sb.append(settings.dump());

        sb.append(UserList.dump(domain));

        sb.append("<catalogs>\n");
        AbstractCatalog cat = new AbstractCatalog("paymethod", domain, username);
        sb.append(cat.dump());
        cat = new AbstractCatalog("partners", domain, username);
        sb.append(cat.dump());
        cat = new AbstractCatalog("tarifs", domain, username);
        sb.append(cat.dump());

        sb.append("</catalogs>\n<documents>\n");
        AbstractDocument doc = new AbstractDocument("inpay", domain, username);
        sb.append(doc.dump());
        doc = new AbstractDocument("ingoods", domain, username);
        sb.append(doc.dump());

        sb.append("</documents>\n");

        sb.append(Scripts.dump(domain));

        sb.append(Structures.dump(domain));

        sb.append("</dump>\n");

        String s = sb.toString();
        BufferedWriter out = null;
        try {
            out = new BufferedWriter(new FileWriter(filename));
            out.write(s);
            out.flush();
            out.close();
        } catch (IOException e) {
            if (out != null) {
                try {
                    out.flush();
                    out.close();
                } catch (IOException e1) {
                    Log.error(e1.getMessage());
                }
            }
            Log.error(e.getMessage());
        }

    }

    /**
     * Gets the database.
     * 
     * @return the dB
     */
    public static synchronized DB get(String domain) {
        if (mongodatabase == null) {
            try {
                initConnection(domain);
            } catch (UnknownHostException e) {
                close();
                Log.error(e.getMessage());
            } catch (MongoException e) {
                close();
                Log.error(e.getMessage());
            } catch (InterruptedException e) {
                close();
                Log.error(e.getMessage());
            }
        }

        return mongodatabase;
    }

    /**
     * Gets the all settings.
     * 
     * @return the all settings
     */
    public static HashMap<String, String> getAllSettings(String domain) {
        if (settings == null) {
            loadSettings(domain);
        }
        return settings.getAll();
    }

    /**
     * Gets the settings.
     * 
     * @return the settings
     */
    public static GlobalSettings getSettings() {
        return settings;
    }

    /**
     * Inits the connection.
     * 
     * @throws UnknownHostException
     *             the unknown host exception
     * @throws MongoException
     *             the mongo exception
     * @throws InterruptedException
     *             the interrupted exception
     */
    private static synchronized void initConnection(String domain)
            throws UnknownHostException, MongoException, InterruptedException {
        try {
            if (mongo == null) {
                mongo = new Mongo(host, port);
            }
        } catch (com.mongodb.MongoInternalException e) {
            close();
            throw (e);
        }
        DB db = mongo.getDB("admin");
        boolean auth = db.authenticate(adminuser, adminpassword.toCharArray());
        if (auth) {
            List<String> databases = mongo.getDatabaseNames();
            db = mongo.getDB(database);

            if (!databases.contains(database)) {
                db.addUser(user, password.toCharArray());
            }

            auth = db.authenticate(user, password.toCharArray());
            if (auth) {
                mongodatabase = db;
                retain();
                // check settings and create new collection if not exists
                GlobalSettings.createDefaultRecords(db);
                // check users and if none - create admin
                UserList.createDefaultRecords(db);
                // check currency values. If none - load today values from cbr
                Currency.createDefaultRecords(db);

                release();

            } else {
                close();
            }
        } else {
            close();
        }

        loadSettings(domain);

    }

    private static void loadSettings(String domain) {
        if ((domain == null) || domain.isEmpty()) {
            domain = "127.0.0.1";
        }
        if (mongodatabase != null) {
            settings = new GlobalSettings(domain);
            retaintimeoutmin = settings.get("database.autoclose.timeout.min", retaintimeoutmin);
            settings.save();
        } else {
            settings = new GlobalSettings(false, domain);
        }
    }

    /**
     * Recreate database (drop and close connection).
     * 
     * @return true, if successful
     */
    public static synchronized boolean recreateDb() {

        if (mongodatabase == null) {
            return false;
        }

        try {
            Database.retain();
            mongodatabase.dropDatabase();
            close();
        } catch (MongoException e) {
            Log.error(e.getMessage());
            return false;
        }

        return true;
    }

    /**
     * Retain database lock counter.
     */
    public static synchronized void release() {
        lockcounter--;
        if ((lockcounter == 0) && (mongodatabase != null)) {
            mongodatabase.requestDone();
        }
        if (lockcounter < 0) {
            lockcounter = 0;
        }
    }

    /**
     * Restoredatabase.
     * 
     * @param domain
     *            the domain
     * @param username
     *            the username
     * @param filename
     *            the filename
     */
    public static void restoredatabase(String domain, String username, String filename) {
        // TODO: complete
        File dump = new File(filename);
        DocumentBuilder builder;
        try {
            builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
            Document doc = builder.parse(dump);

            NodeList rootnodes = doc.getElementsByTagName("dump");
            for (int i = 0; i < rootnodes.getLength(); i++) {
                Element rootelement = (Element) rootnodes.item(i);
                NodeList sections = rootelement.getChildNodes();
                for (int c = 0; c < sections.getLength(); c++) {
                    Node v = sections.item(c);
                    if (v.getNodeType() == Node.ELEMENT_NODE) {
                        Element val = (Element) v;
                        if (val.getNodeName().equals("settings")) {
                            GlobalSettings s = new GlobalSettings(domain);
                            s.restore(val);
                        } else if (val.getNodeName().equals("scripts")) {
                            Scripts s = new Scripts(domain, username);
                            s.restore(val);
                        } else if (val.getNodeName().equals("structures")) {
                            Structures s = new Structures(domain);
                            s.restore(val);
                        } else if (val.getNodeName().equals("users")) {
                            UserList.restore(domain, val);
                        } else if (val.getNodeName().equals("catalogs")) {
                            NodeList catnodes = val.getElementsByTagName("cat");
                            for (int j = 0; j < catnodes.getLength(); j++) {
                                Element cat = (Element) catnodes.item(j);
                                String catname = cat.getAttribute("name");
                                AbstractCatalog ac = new AbstractCatalog(catname, domain, username);
                                ac.restore(cat);
                            }
                        } else if (val.getNodeName().equals("documents")) {
                            NodeList docnodes = val.getElementsByTagName("doc");
                            for (int j = 0; j < docnodes.getLength(); j++) {
                                Element document = (Element) docnodes.item(j);
                                String docname = document.getAttribute("name");
                                if (docname.equals("inpay")) {
                                    AbstractDocument p = new AbstractDocument("inpay", domain, username);
                                    p.restore(document);
                                } else if (docname.equals("ingoods")) {
                                    AbstractDocument g = new AbstractDocument("ingoods", domain, username);
                                    g.restore(document);
                                }
                            }
                        }
                    }
                }
            }

        } catch (ParserConfigurationException e) {
            Log.error(e.getMessage());
        } catch (SAXException e) {
            Log.error(e.getMessage());
        } catch (IOException e) {
            Log.error(e.getMessage());
        }
    }

    /**
     * Retain database lock counter.
     */
    public static synchronized void retain() {
        lockcounter++;
        if ((lockcounter == 1) && (mongodatabase != null)) {
            mongodatabase.requestStart();
        }
        startReleaser();
    }

    /**
     * Sets the settings.
     * 
     * @param newvalues
     *            the newvalues
     */
    public static void setSettings(HashMap<String, String> newvalues) {
        settings.set(newvalues);
    }

    /**
     * Start releaser thread.
     */
    private static void startReleaser() {
        if (releaser == null) {
            releaser = new Thread(new Runnable() {

                @Override
                public void run() {
                    try {
                        while (lockcounter > 0) {
                            Thread.sleep(retaintimeoutmin * 60 * 1000);
                        }
                        close();
                    } catch (InterruptedException e) {
                        Log.error(e.getMessage());
                    }

                }
            });
            releaser.start();
        }
    }

    /**
     * Instantiates a new database.
     */
    public Database() {

    }
}