com.nextep.datadesigner.vcs.services.VCSFiles.java Source code

Java tutorial

Introduction

Here is the source code for com.nextep.datadesigner.vcs.services.VCSFiles.java

Source

/*******************************************************************************
 * Copyright (c) 2011 neXtep Software and contributors.
 * All rights reserved.
 *
 * This file is part of neXtep designer.
 *
 * NeXtep designer is free software: you can redistribute it 
 * and/or modify it under the terms of the GNU General Public 
 * License as published by the Free Software Foundation, either 
 * version 3 of the License, or any later version.
 *
 * NeXtep designer 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Contributors:
 *     neXtep Softwares - initial API and implementation
 *******************************************************************************/
package com.nextep.datadesigner.vcs.services;

import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.StringWriter;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import oracle.sql.BLOB;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.HibernateException;
import com.nextep.datadesigner.exception.ErrorException;
import com.nextep.datadesigner.vcs.impl.RepositoryFile;
import com.nextep.designer.core.CorePlugin;
import com.nextep.designer.core.model.IConnection;
import com.nextep.designer.core.services.IConnectionService;
import com.nextep.designer.core.services.IRepositoryService;
import com.nextep.designer.vcs.VCSMessages;
import com.nextep.designer.vcs.model.IRepositoryFile;

/**
 * This service provides helper methods to manipulate repository files.
 * 
 * @author Christophe Fondacci
 * @author Bruno Gautier
 */
public class VCSFiles {

    private static final Log LOGGER = LogFactory.getLog(VCSFiles.class);
    private static final IRepositoryService repoService = CorePlugin.getRepositoryService();
    private static final IConnectionService connService = CorePlugin.getConnectionService();
    private static VCSFiles instance;

    private VCSFiles() {
    }

    public static VCSFiles getInstance() {
        if (instance == null) {
            instance = new VCSFiles();
        }
        return instance;
    }

    /**
     * Create a repository file from the given local file. The specified file must exist.
     * 
     * @param filePath path to the local file (must exist, else exception)
     * @return the generated repository file
     */
    public IRepositoryFile createFromLocalFile(String filePath) {
        final File file = new File(filePath);
        if (!file.exists()) {
            throw new ErrorException(VCSMessages.getString("fileMustExist")); //$NON-NLS-1$
        }
        IRepositoryFile repFile = new RepositoryFile();
        repFile.setName(file.getName());
        // Saving properties
        CorePlugin.getIdentifiableDao().save(repFile);

        final IConnection repoConn = repoService.getRepositoryConnection();
        // Generating BLOB
        Connection jdbcConn = null;
        try {
            jdbcConn = connService.connect(repoConn);
            switch (repoConn.getDBVendor()) {
            case ORACLE:
                writeOracleBlob(jdbcConn, repFile, file);
                break;
            case MYSQL:
                writeMySQLBlob(jdbcConn, repFile, file);
                break;
            }
            return repFile;
        } catch (SQLException sqle) {
            throw new ErrorException(sqle);
        } finally {
            try {
                if (jdbcConn != null) {
                    jdbcConn.close();
                }
            } catch (SQLException sqle) {
                throw new ErrorException(VCSMessages.getString("files.closeProblem")); //$NON-NLS-1$
            }
        }
    }

    private void writeMySQLBlob(Connection conn, IRepositoryFile file, File localFile) throws SQLException {
        file.setFileSizeKB((localFile.length() / 1024) + 1);
        PreparedStatement stmt = null;
        InputStream is = null;
        try {
            /*
             * Columns names in the SET clause cannot be qualified with an alias name because it
             * would fail in Postgres.
             */
            stmt = conn.prepareStatement("UPDATE rep_files rf " //$NON-NLS-1$
                    + "  SET file_content = ? " //$NON-NLS-1$
                    + "    , filesize = ? " //$NON-NLS-1$
                    + "WHERE rf.file_id = ? "); //$NON-NLS-1$
            is = new FileInputStream(localFile);
            stmt.setBinaryStream(1, is);
            stmt.setLong(2, file.getFileSizeKB());
            stmt.setLong(3, file.getUID().rawId());
            stmt.execute();
        } catch (IOException e) {
            throw new ErrorException(e);
        } finally {
            if (stmt != null) {
                stmt.close();
            }
            safeClose(is);
        }
    }

    /**
     * Write the specified file to the given repository file with Oracle-specific Blob support.
     * 
     * @param conn Oracle connection
     * @param file repository file which must have been created
     * @param localFile local file to dump into the repository file
     * @throws SQLException when any database connection problems occurs
     */
    private void writeOracleBlob(Connection conn, IRepositoryFile file, File localFile) throws SQLException {
        PreparedStatement stmt = null;
        long size = 0;

        try {
            /*
             * Columns names in the SET clause cannot be qualified with an alias name because it
             * would fail in Postgres.
             */
            stmt = conn.prepareStatement("UPDATE rep_files rf " //$NON-NLS-1$
                    + "  SET file_content = ? " //$NON-NLS-1$
                    + "    , filesize = ? " //$NON-NLS-1$
                    + "WHERE rf.file_id = ? "); //$NON-NLS-1$

            OutputStream os = null;
            FileInputStream is = null;
            BLOB tempBlob = null;

            try {
                // Get the oracle connection class for checking
                Class<?> oracleConnectionClass = Class.forName("oracle.jdbc.OracleConnection"); //$NON-NLS-1$

                // Make sure connection object is right type
                if (!oracleConnectionClass.isAssignableFrom(conn.getClass())) {
                    throw new HibernateException(VCSMessages.getString("files.invalidOracleConnection") //$NON-NLS-1$
                            + VCSMessages.getString("files.invalidOracleConnection.2") //$NON-NLS-1$
                            + conn.getClass().getName());
                }

                // Create our temp BLOB
                tempBlob = BLOB.createTemporary(conn, true, BLOB.DURATION_SESSION);
                tempBlob.open(BLOB.MODE_READWRITE);
                os = tempBlob.getBinaryOutputStream();
                is = new FileInputStream(localFile);

                // Large 10K buffer for efficient read
                byte[] buffer = new byte[10240];
                int bytesRead = 0;

                while ((bytesRead = is.read(buffer)) >= 0) {
                    os.write(buffer, 0, bytesRead);
                    size += bytesRead;
                }
            } catch (ClassNotFoundException cnfe) {
                // could not find the class with reflection
                throw new ErrorException(VCSMessages.getString("files.classUnresolved") //$NON-NLS-1$
                        + cnfe.getMessage());
            } catch (FileNotFoundException fnfe) {
                throw new ErrorException(VCSMessages.getString("files.fileUnresolved")); //$NON-NLS-1$
            } catch (IOException ioe) {
                throw new ErrorException(VCSMessages.getString("files.readProblem"), ioe); //$NON-NLS-1$
            } finally {
                safeClose(os);
                safeClose(is);
                if (tempBlob != null) {
                    tempBlob.close();
                }
            }
            stmt.setBlob(1, tempBlob);
            stmt.setLong(2, size);
            stmt.setLong(3, file.getUID().rawId());
            stmt.execute();
        } finally {
            if (stmt != null) {
                stmt.close();
            }
            file.setFileSizeKB(size / 1024);
        }
    }

    /**
     * Generates the specified repository file back to the local file system path. The given path
     * must point to the file to create (and not to its owning directory)
     * 
     * @param file repository file to generate
     * @param path file path to the local file to generate
     */
    public void generateFile(IRepositoryFile file, String path) {
        final IConnection repoConn = repoService.getRepositoryConnection();

        Connection jdbcConn = null;
        try {
            jdbcConn = connService.connect(repoConn);
            generateOracleFile(jdbcConn, file, path);
        } catch (SQLException sqle) {
            throw new ErrorException(sqle);
        } finally {
            try {
                if (jdbcConn != null) {
                    jdbcConn.close();
                }
            } catch (SQLException sqle) {
                throw new ErrorException(VCSMessages.getString("files.closeProblem")); //$NON-NLS-1$
            }
        }
    }

    private void generateOracleFile(Connection conn, IRepositoryFile file, String path) throws SQLException {
        PreparedStatement stmt = null;
        ResultSet rs = null;
        InputStream blobStream = null;
        OutputStream os = null;
        try {
            // Querying blob
            stmt = conn.prepareStatement("SELECT rf.file_content " //$NON-NLS-1$
                    + "FROM rep_files rf " //$NON-NLS-1$
                    + "WHERE rf.file_id = ? "); //$NON-NLS-1$
            stmt.setLong(1, file.getUID().rawId());
            rs = stmt.executeQuery();
            if (rs.next()) {
                // Retrieving blob input stream
                blobStream = rs.getBinaryStream(1);
                if (blobStream == null) {
                    return;
                }

                // Opening output file
                File f = new File(path);
                os = new FileOutputStream(f);

                // Large 10K buffer for efficient read
                byte[] buffer = new byte[10240];
                int bytesRead = 0;

                while ((bytesRead = blobStream.read(buffer)) >= 0) {
                    os.write(buffer, 0, bytesRead);
                }
            } else {
                throw new ErrorException(VCSMessages.getString("files.notFound")); //$NON-NLS-1$
            }
        } catch (IOException e) {
            throw new ErrorException(VCSMessages.getString("files.readRepositoryProblem"), //$NON-NLS-1$
                    e);
        } finally {
            safeClose(os);
            safeClose(blobStream);
            if (rs != null) {
                rs.close();
            }
            if (stmt != null) {
                stmt.close();
            }
        }
    }

    protected void safeClose(Closeable s) {
        if (s != null) {
            try {
                s.close();
            } catch (IOException e) {
                LOGGER.error(VCSMessages.getString("files.streamCloseProblem"), e); //$NON-NLS-1$
            }
        }
    }

    public String getResourceString(IRepositoryFile file) {
        final IConnection repoConn = repoService.getRepositoryConnection();

        Connection jdbcConn = null;
        try {
            jdbcConn = connService.connect(repoConn);
            return getFileAsString(jdbcConn, file);
        } catch (SQLException sqle) {
            throw new ErrorException(sqle);
        } finally {
            try {
                if (jdbcConn != null) {
                    jdbcConn.close();
                }
            } catch (SQLException sqle) {
                throw new ErrorException(VCSMessages.getString("files.closeProblem")); //$NON-NLS-1$
            }
        }
    }

    private String getFileAsString(Connection conn, IRepositoryFile file) throws SQLException {
        PreparedStatement stmt = null;
        ResultSet rs = null;
        InputStream blobStream = null;
        InputStreamReader reader = null;
        StringWriter os = null;
        try {
            // Querying blob
            stmt = conn.prepareStatement("SELECT rf.file_content " //$NON-NLS-1$
                    + "FROM rep_files rf " //$NON-NLS-1$
                    + "WHERE rf.file_id = ? "); //$NON-NLS-1$
            stmt.setLong(1, file.getUID().rawId());
            rs = stmt.executeQuery();
            if (rs.next()) {
                // Retrieving blob input stream
                blobStream = rs.getBinaryStream(1);
                if (blobStream == null) {
                    return ""; //$NON-NLS-1$
                }
                reader = new InputStreamReader(blobStream);

                // Opening output file
                os = new StringWriter(10240);

                // Large 10K buffer for efficient read
                char[] buffer = new char[10240];
                int bytesRead = 0;
                while ((bytesRead = reader.read(buffer)) >= 0) {
                    os.write(buffer, 0, bytesRead);
                }
                return os.toString();
            } else {
                throw new ErrorException(VCSMessages.getString("files.notFound")); //$NON-NLS-1$
            }
        } catch (IOException e) {
            throw new ErrorException(VCSMessages.getString("files.readRepositoryProblem"), //$NON-NLS-1$
                    e);
        } finally {
            safeClose(os);
            safeClose(blobStream);
            safeClose(reader);
            if (rs != null) {
                rs.close();
            }
            if (stmt != null) {
                stmt.close();
            }
        }
    }

}