RegisterDerby.java :  » IDE-Netbeans » derby » org » netbeans » modules » derby » Java Open Source

Java Open Source » IDE Netbeans » derby 
derby » org » netbeans » modules » derby » RegisterDerby.java
/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
 *
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common
 * Development and Distribution License("CDDL") (collectively, the
 * "License"). You may not use this file except in compliance with the
 * License. You can obtain a copy of the License at
 * http://www.netbeans.org/cddl-gplv2.html
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
 * specific language governing permissions and limitations under the
 * License.  When distributing the software, include this License Header
 * Notice in each file and include the License file at
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the GPL Version 2 section of the License file that
 * accompanied this code. If applicable, add the following below the
 * License Header, with the fields enclosed by brackets [] replaced by
 * your own identifying information:
 * "Portions Copyrighted [year] [name of copyright owner]"
 *
 * Contributor(s):
 *
 * The Original Software is NetBeans. The Initial Developer of the Original
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
 * Microsystems, Inc. All Rights Reserved.
 *
 * If you wish your version of this file to be governed by only the CDDL
 * or only the GPL Version 2, indicate your decision by adding
 * "[Contributor] elects to include this software in this distribution
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
 * single choice of license, a recipient has the option to distribute
 * your version of this file under either the CDDL, the GPL Version 2 or
 * to extend the choice of license to its licensees as provided above.
 * However, if you add GPL Version 2 code and therefore, elected the GPL
 * Version 2 license, then the option applies only if the new code is
 * made subject to such option by the copyright holder.
 */

package org.netbeans.modules.derby;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.netbeans.api.db.explorer.JDBCDriver;
import org.netbeans.api.db.explorer.JDBCDriverManager;
import org.netbeans.api.java.platform.JavaPlatform;
import org.netbeans.api.java.platform.JavaPlatformManager;
import org.netbeans.api.progress.ProgressHandle;
import org.netbeans.api.progress.ProgressHandleFactory;
import org.netbeans.modules.derby.api.DerbyDatabases;
import org.netbeans.spi.db.explorer.DatabaseRuntime;
import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor;
import org.openide.execution.NbProcessDescriptor;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.util.NbBundle;
import org.openide.util.RequestProcessor;
import org.openide.util.Utilities;


/**
 *
 * @author  Ludo, Petr Jiricka
 */
public class RegisterDerby implements DatabaseRuntime {
    
    // XXX this class does too much. Should maybe be split into 
    // DatabaseRuntimeImpl, DerbyStartStop and the rest.
    
    // XXX refactor this soon, it is full of race conditions!
    
    private static final Logger LOGGER = Logger.getLogger(RegisterDerby.class.getName());
    private static final boolean LOG = LOGGER.isLoggable(Level.FINE);
    
    private static final int START_TIMEOUT = 5; // seconds
    
    private static RegisterDerby reg=null;
    
    /** Derby server process */
    static Process process = null;
    
    /** Creates a new instance of RegisterDerby */
    private RegisterDerby() {
    }
    
    public static synchronized RegisterDerby getDefault(){
        if (reg==null)
            reg= new RegisterDerby();
        return reg;
    }
    
    /**
     * Whether this runtime accepts this connection string.
     */
    public boolean acceptsDatabaseURL(String url){
        return url.trim().startsWith("jdbc:derby://localhost"); // NOI18N
    }
    
    /**
     * Is database server up and running.
     */
    public boolean isRunning(){
        if (process!=null){
            try{
                int e = process.exitValue();
                process=null;
            } catch (IllegalThreadStateException e){
                //not exited yet...it's ok
                
            }
        }
        return (process!=null);
        
    }
    
    public String getJDBCDriverClass() {
        return DerbyOptions.DRIVER_CLASS_NET;
    }
    
    /**
     * Can the database be started from inside the IDE?
     */
    public boolean canStart(){
        // issue 81619: should only try to start if the location is set
        return DerbyOptions.getDefault().getLocation().length() > 0;
    }
    
    /**
     * Start the database server.
     */
    public void start(){
        start(START_TIMEOUT);
    }
    
    private String getNetworkServerClasspath() {
        return 
            Util.getDerbyFile("lib/derby.jar").getAbsolutePath() + File.pathSeparator +
            Util.getDerbyFile("lib/derbytools.jar").getAbsolutePath() + File.pathSeparator +
            Util.getDerbyFile("lib/derbynet.jar").getAbsolutePath(); // NOI18N
    }
    
    /**
     * Returns the registered Derby driver.
     */
    private JDBCDriver getRegisteredDerbyDriver() {
        JDBCDriver[] drvs = JDBCDriverManager.getDefault().getDrivers(DerbyOptions.DRIVER_CLASS_NET);
        if (drvs.length > 0) {
            return drvs[0];
        }
        return null;
    }
    
    public int getPort() {
        return 1527;
    }
    
    /** Posts the creation of the new database to request processor.
     */
    void postCreateNewDatabase(final String databaseName, final String user, final String password) throws Exception {
        RequestProcessor.getDefault().post(new Runnable() {
            public void run () {
                try {
                    // DerbyDatabases.createDatabase would start the database too, but
                    // doing it beforehand to avoid having two progress bars running
                    if (!ensureStarted(true)) {
                        return;
                    }
                    
                    ProgressHandle ph = ProgressHandleFactory.createHandle(NbBundle.getMessage(
                        RegisterDerby.class, "MSG_CreatingDBProgressLabel", databaseName));
                    ph.start();
                    try {
                        DerbyDatabases.createDatabase(databaseName, user, password);
                    } finally {
                        ph.finish();
                    }
               } catch (Exception e) {
                    LOGGER.log(Level.WARNING, null, e);
                    String message = NbBundle.getMessage(RegisterDerby.class, "ERR_CreateDatabase", e.getMessage());
                    Util.showInformation(message);
               }
           }
        });
    }
    
    private String getDerbySystemHome() {
        // return System.getProperty("netbeans.user") + File.separator + "derby";
        return DerbyOptions.getDefault().getSystemHome();
    }
    
    private void createDerbyPropertiesFile() {
        File derbyProperties = new File(getDerbySystemHome(), "derby.properties");
        if (derbyProperties.exists())
            return;
        Properties derbyProps = new Properties();
        // fill it
        if (Utilities.isMac()) {
            derbyProps.setProperty("derby.storage.fileSyncTransactionLog", "true");
        }

        // write it out
        OutputStream fileos = null; 
        try {
            File derbyPropertiesParent = derbyProperties.getParentFile();
            derbyPropertiesParent.mkdirs();
            fileos = new FileOutputStream(derbyProperties);
            derbyProps.store(fileos, NbBundle.getMessage(RegisterDerby.class, "MSG_DerbyPropsFile"));
        } catch (IOException ex) {
            LOGGER.log(Level.WARNING, null, ex);
        } finally {
            if (fileos != null) {
                try {
                    fileos.close();
                } catch (IOException ex) {
                    LOGGER.log(Level.WARNING, null, ex);
                }
            }
        }
        
    }
    
    private File getInstallLocation() {
        String location = DerbyOptions.getDefault().getLocation();
        if (location.equals("")) { // NOI18N
            return null;
        }
        return new File(location);
    }
            
    private String[] getEnvironment() {
        String location = DerbyOptions.getDefault().getLocation();
        if (location.equals("")) { // NOI18N
            return null;
        }
        return new String[] { "DERBY_INSTALL=" + location }; // NOI18N
    }
    
    private JavaPlatform getJavaPlatform() {
        JavaPlatformManager jpm = JavaPlatformManager.getDefault();
        return jpm.getDefaultPlatform(); 
    }
    
    /**
     * Start the database server, and wait some time (in milliseconds) to make sure the server is active.
     *
     * @param  waitTime the time to wait. If less than or equal to zero, do not
     *         wait at all.
     *
     * @return true if the server is definitely started, false otherwise (the server is
     *         not started or the status is unknown). If <code>waitTime</code> was
     *         less than or equal to zero, then always false.
     */
    private boolean start(int waitTime){
        if (process!=null){// seems to be already running?
            stop();
        }
        if (!Util.checkInstallLocation()) {
            return false;
        }
        try {
            ExecSupport ee= new ExecSupport();
            ee.setStringToLookFor("" + getPort());
            FileObject javaFO = getJavaPlatform().findTool("java");
            if (javaFO == null)
                throw new Exception (NbBundle.getMessage(RegisterDerby.class, "EXC_JavaExecutableNotFound"));
            String java = FileUtil.toFile(javaFO).getAbsolutePath();
            
            // create the derby.properties file
            createDerbyPropertiesFile();
            
            // java -Dderby.system.home="<userdir/derby>" -classpath  
            //     "<DERBY_INSTALL>/lib/derby.jar:<DERBY_INSTALL>/lib/derbytools.jar:<DERBY_INSTALL>/lib/derbynet.jar"
            //     org.apache.derby.drda.NetworkServerControl start
            NbProcessDescriptor desc = new NbProcessDescriptor(
              java,
              "-Dderby.system.home=\"" + getDerbySystemHome() + "\" " +
              "-classpath \"" + getNetworkServerClasspath() + "\"" + 
              " org.apache.derby.drda.NetworkServerControl start"
            );
            if (LOG) {
                LOGGER.log(Level.FINE, "Running " + desc.getProcessName() + " " + desc.getArguments());
            }
            process = desc.exec (
                null,
                getEnvironment(),
                true,
                getInstallLocation()
            );

            ee.displayProcessOutputs(process,NbBundle.getMessage(StartAction.class, "LBL_outputtab"));
            if (waitTime > 0) {
                // to make sure the server is up and running
                return waitStart(ee, waitTime);
            } else {
                return false;
            }
        } catch (Exception e) {
            Util.showInformation(e.getLocalizedMessage());
            return false;
        }
    }
    
    private boolean waitStart(ExecSupport execSupport, int waitTime) {
        boolean started = false;
        String waitMessage = NbBundle.getMessage(RegisterDerby.class, "MSG_StartingDerby");
        ProgressHandle progress = ProgressHandleFactory.createHandle(waitMessage);
        progress.start();
        try {
            while (!started) {
                started = execSupport.waitForMessage(waitTime * 1000);
                if (!started) {
                    String title = NbBundle.getMessage(RegisterDerby.class, "LBL_DerbyDatabase");
                    String message = NbBundle.getMessage(RegisterDerby.class, "MSG_WaitStart", waitTime);
                    NotifyDescriptor waitConfirmation = new NotifyDescriptor.Confirmation(message, title, NotifyDescriptor.YES_NO_OPTION);
                    if (DialogDisplayer.getDefault().notify(waitConfirmation) != NotifyDescriptor.YES_OPTION) {
                        break;
                    }
                }
            }
            if (!started) {
                LOGGER.log(Level.WARNING, "Derby server failed to start"); // NOI18N
            }
        } finally {
            progress.finish();
        }
        return started;
    }
    
    /**
     * Stop the database server.
     */
    public void stop(){
        try {
            if (process==null){//nothing to stop...
                return;
            }
            //BufferedWriter processIn = new BufferedWriter(new OutputStreamWriter(process.getOutputStream()));
            //processIn.write("q\ny\n");
            //processIn.flush();
            String java = FileUtil.toFile(getJavaPlatform().findTool("java")).getAbsolutePath();
            if (java == null)
                throw new Exception (NbBundle.getMessage(RegisterDerby.class, "EXC_JavaExecutableNotFound"));
            // java -Dderby.system.home="<userdir/derby>" -classpath  
            //     "<DERBY_INSTALL>/lib/derby.jar:<DERBY_INSTALL>/lib/derbytools.jar:<DERBY_INSTALL>/lib/derbynet.jar"
            //     org.apache.derby.drda.NetworkServerControl shutdown
            NbProcessDescriptor desc = new NbProcessDescriptor(
              java,
              "-Dderby.system.home=\"" + getDerbySystemHome() + "\" " +
              "-classpath \"" + getNetworkServerClasspath() + "\"" + 
              " org.apache.derby.drda.NetworkServerControl shutdown"
            );
            if (LOG) {
                LOGGER.log(Level.FINE, "Running " + desc.getProcessName() + " " + desc.getArguments());
            }
            Process shutwownProcess = desc.exec (
                null,
                getEnvironment(),
                true,
                getInstallLocation()
            );
            shutwownProcess.waitFor();

            process.destroy();
        } 
        catch (Exception e) {
            Util.showInformation(e.getMessage());
        }
        finally {
            process=null;
        }
    }
    
    /**
     * Starts the server if necessary, and can wait for it to start if it was
     * not already started.
     *
     * @param  waitIfNotStarted true if to wait for a certain period of time for the server to start 
     *         if it is not already started; false otherwise.
     *
     * @return true if the server is definitely known to be started, false otherwise.
     */
    public boolean ensureStarted(boolean waitIfNotStarted) {
        if (isRunning()) {
            return true;
        }
        if (!canStart()) {
            return false;
        }
        if (waitIfNotStarted) {
            return start(START_TIMEOUT);
        } else {
            start(0);
            return false;
        }
    }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.