Package net.sf.hajdbc.sync

Source Code of net.sf.hajdbc.sync.DumpRestoreSynchronizationStrategy$ConnectionPropertiesImpl

/*
* HA-JDBC: High-Availability JDBC
* Copyright (C) 2012  Paul Ferraro
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
package net.sf.hajdbc.sync;

import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.security.PrivilegedExceptionAction;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import java.util.regex.Matcher;

import net.sf.hajdbc.ConnectionProperties;
import net.sf.hajdbc.Database;
import net.sf.hajdbc.DatabaseCluster;
import net.sf.hajdbc.DumpRestoreSupport;
import net.sf.hajdbc.ExceptionType;
import net.sf.hajdbc.Messages;
import net.sf.hajdbc.SynchronizationStrategy;
import net.sf.hajdbc.dialect.Dialect;
import net.sf.hajdbc.util.Files;
import net.sf.hajdbc.util.Security;
import net.sf.hajdbc.util.Strings;

/**
* A synchronization strategy that uses dump/restore procedures.
* @author Paul Ferraro
*/
public class DumpRestoreSynchronizationStrategy implements SynchronizationStrategy
{
  private static final long serialVersionUID = 5743532034969216540L;
  private static final String DUMP_FILE_SUFFIX = ".dump";

  @Override
  public String getId()
  {
    return "dump-restore";
  }

  /**
   * {@inheritDoc}
   * @see net.sf.hajdbc.SynchronizationStrategy#init(net.sf.hajdbc.DatabaseCluster)
   */
  @Override
  public <Z, D extends Database<Z>> void init(DatabaseCluster<Z, D> cluster)
  {
  }

  /**
   * {@inheritDoc}
   * @see net.sf.hajdbc.SynchronizationStrategy#destroy(net.sf.hajdbc.DatabaseCluster)
   */
  @Override
  public <Z, D extends Database<Z>> void destroy(DatabaseCluster<Z, D> cluster)
  {
  }
 
  /**
   * {@inheritDoc}
   * @see net.sf.hajdbc.SynchronizationStrategy#synchronize(net.sf.hajdbc.sync.SynchronizationContext)
   */
  @Override
  public <Z, D extends Database<Z>> void synchronize(SynchronizationContext<Z, D> context) throws SQLException
  {
    Dialect dialect = context.getDialect();
    DumpRestoreSupport support = dialect.getDumpRestoreSupport();
   
    if (support == null)
    {
      throw new SQLException(Messages.DUMP_RESTORE_UNSUPPORTED.getMessage(dialect));
    }
   
    try
    {
      File file = Files.createTempFile(DUMP_FILE_SUFFIX);
     
      try
      {
        startProcess(support.createDumpProcess(new ConnectionPropertiesImpl<Z, D>(context, context.getSourceDatabase()), file));
       
        startProcess(support.createRestoreProcess(new ConnectionPropertiesImpl<Z, D>(context, context.getTargetDatabase()), file));
      }
      finally
      {
        Files.delete(file);
      }
    }
    catch (Exception e)
    {
      throw ExceptionType.SQL.<SQLException>getExceptionFactory().createException(e);
    }
  }
 
  private static void startProcess(final ProcessBuilder processBuilder) throws Exception
  {
    PrivilegedExceptionAction<Process> action = new PrivilegedExceptionAction<Process>()
    {
      @Override
      public Process run() throws Exception
      {
        return processBuilder.start();
      }
    };
   
    Process process = Security.run(action);
   
    try
    {
      int status = process.waitFor();
     
      if (status != 0)
      {
        StringBuilder builder = new StringBuilder();
        BufferedReader reader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
        String line = reader.readLine();
       
        while (line != null)
        {
          builder.append(line).append(Strings.NEW_LINE);
          line = reader.readLine();
        }
       
        throw new Exception(builder.toString());
      }
    }
    catch (InterruptedException e)
    {
      Thread.currentThread().interrupt();
     
      throw new Exception(processBuilder.toString(), e);
    }
  }
 
  private static class ConnectionPropertiesImpl<Z, D extends Database<Z>> implements ConnectionProperties
  {
    private final String host;
    private final String port;
    private final String database;
    private final String user;
    private final String password;
   
    ConnectionPropertiesImpl(SynchronizationContext<Z, D> context, D database) throws SQLException
    {
      DatabaseMetaData metaData = context.getConnection(database).getMetaData();
      String url = metaData.getURL();
     
      if (url == null)
      {
        throw new UnsupportedOperationException();
      }
       
      Matcher matcher = context.getDialect().getUrlPattern().matcher(url);
     
      if (!matcher.find() || (matcher.groupCount() != 3))
      {
        throw new UnsupportedOperationException(url);
      }
     
      this.host = matcher.group(1);
      this.port = matcher.group(2);
      this.database = matcher.group(3);
      this.user = metaData.getUserName();
      this.password = database.decodePassword(context.getDecoder());
    }

    /**
     * {@inheritDoc}
     * @see net.sf.hajdbc.ConnectionProperties#getHost()
     */
    @Override
    public String getHost()
    {
      return this.host;
    }

    /**
     * {@inheritDoc}
     * @see net.sf.hajdbc.ConnectionProperties#getPort()
     */
    @Override
    public String getPort()
    {
      return this.port;
    }

    /**
     * {@inheritDoc}
     * @see net.sf.hajdbc.ConnectionProperties#getDatabase()
     */
    @Override
    public String getDatabase()
    {
      return this.database;
    }

    /**
     * {@inheritDoc}
     * @see net.sf.hajdbc.ConnectionProperties#getUser()
     */
    @Override
    public String getUser()
    {
      return this.user;
    }

    /**
     * {@inheritDoc}
     * @see net.sf.hajdbc.ConnectionProperties#getPassword()
     */
    @Override
    public String getPassword()
    {
      return this.password;
    }
  }
}
TOP

Related Classes of net.sf.hajdbc.sync.DumpRestoreSynchronizationStrategy$ConnectionPropertiesImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.