/**************************************************************
 * 
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 com.sun.star.comp.helper;

import com.sun.star.bridge.UnoUrlResolver;
import com.sun.star.bridge.XUnoUrlResolver;
import com.sun.star.comp.loader.JavaLoader;
import com.sun.star.container.XSet;
import com.sun.star.lang.XInitialization;
import com.sun.star.lang.XMultiServiceFactory;
import com.sun.star.lang.XMultiComponentFactory;
import com.sun.star.lang.XSingleComponentFactory;
import com.sun.star.lib.util.NativeLibraryLoader;
import com.sun.star.loader.XImplementationLoader;
import com.sun.star.uno.UnoRuntime;
import com.sun.star.uno.XComponentContext;

import java.io.BufferedReader;
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Random;

/** Bootstrap offers functionality to obtain a context or simply
	a service manager.
	The service manager can create a few basic services, whose implementations  are:
	<ul>
	<li>com.sun.star.comp.loader.JavaLoader</li>
	<li>com.sun.star.comp.urlresolver.UrlResolver</li>
	<li>com.sun.star.comp.bridgefactory.BridgeFactory</li>
	<li>com.sun.star.comp.connections.Connector</li>
	<li>com.sun.star.comp.connections.Acceptor</li>
	<li>com.sun.star.comp.servicemanager.ServiceManager</li>
	</ul>

	Other services can be inserted into the service manager by
	using its XSet interface:
	<pre>
		XSet xSet = UnoRuntime.queryInterface( XSet.class, aMultiComponentFactory );
		// insert the service manager
		xSet.insert( aSingleComponentFactory );
	</pre>
*/	
public class Bootstrap {
    
    private static void insertBasicFactories(
        XSet xSet, XImplementationLoader xImpLoader )
        throws Exception
    {
		// insert the factory of the loader        
		xSet.insert( xImpLoader.activate(
            "com.sun.star.comp.loader.JavaLoader", null, null, null ) );
		
		// insert the factory of the URLResolver        
		xSet.insert( xImpLoader.activate(
            "com.sun.star.comp.urlresolver.UrlResolver", null, null, null ) );
        
		// insert the bridgefactory
		xSet.insert( xImpLoader.activate(
            "com.sun.star.comp.bridgefactory.BridgeFactory", null, null, null ) );
        
		// insert the connector
        xSet.insert( xImpLoader.activate(
            "com.sun.star.comp.connections.Connector", null, null, null ) );
        
		// insert the acceptor
        xSet.insert( xImpLoader.activate(
            "com.sun.star.comp.connections.Acceptor", null, null, null ) );
    }
    
	/** Bootstraps an initial component context with service manager and basic
        jurt components inserted.
		@param context_entries the hash table contains mappings of entry names (type string) to
		context entries (type class ComponentContextEntry).
		@return a new context.
		@throws java.lang.Exception
    */
	static public XComponentContext createInitialComponentContext( Hashtable context_entries )
        throws Exception
    {
		XImplementationLoader xImpLoader = UnoRuntime.queryInterface(
            XImplementationLoader.class, new JavaLoader() );
		
		// Get the factory of the ServiceManager
		XSingleComponentFactory smgr_fac = UnoRuntime.queryInterface(
            XSingleComponentFactory.class, xImpLoader.activate(
                "com.sun.star.comp.servicemanager.ServiceManager", null, null, null ) );
        
		// Create an instance of the ServiceManager
		XMultiComponentFactory xSMgr = UnoRuntime.queryInterface(
            XMultiComponentFactory.class, smgr_fac.createInstanceWithContext( null ) );
        
		// post init loader
		XInitialization xInit = UnoRuntime.queryInterface(
            XInitialization.class, xImpLoader );
		Object[] args = new Object [] { xSMgr };
		xInit.initialize( args );
        
        // initial component context
        if (context_entries == null)
            context_entries = new Hashtable( 1 );
        // add smgr
        context_entries.put(
            "/singletons/com.sun.star.lang.theServiceManager",
            new ComponentContextEntry( null, xSMgr ) );
        // ... xxx todo: add standard entries
        XComponentContext xContext = new ComponentContext( context_entries, null );
        
        // post init smgr
		xInit = UnoRuntime.queryInterface(
            XInitialization.class, xSMgr );
		args = new Object [] { null, xContext }; // no registry, default context
		xInit.initialize( args );
        
		XSet xSet = UnoRuntime.queryInterface( XSet.class, xSMgr );
		// insert the service manager
		xSet.insert( smgr_fac );
        // and basic jurt factories
        insertBasicFactories( xSet, xImpLoader );
        
		return xContext;
	}
    
	/**
	 * Bootstraps a servicemanager with the jurt base components registered.
	 * <p>
	 * @return     a freshly boostrapped service manager
	 * @see        "com.sun.star.lang.ServiceManager"
	 * @throws      java.lang.Exception
	 */
	static public XMultiServiceFactory createSimpleServiceManager() throws Exception
    {
        return UnoRuntime.queryInterface(
            XMultiServiceFactory.class, createInitialComponentContext( null ).getServiceManager() );
    }
    
    
    /**
     * Bootstraps the initial component context from a native UNO installation.
     * <p>
     * @return
     * @see defaultBootstrap_InitialComponentContext()
     */
    static public final XComponentContext defaultBootstrap_InitialComponentContext()
        throws Exception
    {
        return defaultBootstrap_InitialComponentContext( null, null );
    }
    /** Bootstraps the initial component context from a native UNO installation.
        
        @param ini_file
               ini_file (may be null: uno.rc besides cppuhelper lib)
        @param bootstrap_parameters
               bootstrap parameters (maybe null)
               
        @see defaultBootstrap_InitialComponentContext()
    */
    static public final XComponentContext defaultBootstrap_InitialComponentContext(
        String ini_file, Hashtable bootstrap_parameters )
        throws Exception
    {
        // jni convenience: easier to iterate over array than calling Hashtable
        String pairs [] = null;
        if (null != bootstrap_parameters)
        {
            pairs = new String [ 2 * bootstrap_parameters.size() ];
            Enumeration keys = bootstrap_parameters.keys();
            int n = 0;
            while (keys.hasMoreElements())
            {
                String name = (String)keys.nextElement();
                pairs[ n++ ] = name;
                pairs[ n++ ] = (String)bootstrap_parameters.get( name );
            }
        }
        
        if (! m_loaded_juh)
        {
            NativeLibraryLoader.loadLibrary( Bootstrap.class.getClassLoader(), "juh" );
            m_loaded_juh = true;
        }
        return UnoRuntime.queryInterface(
            XComponentContext.class,
            cppuhelper_bootstrap(
                ini_file, pairs, Bootstrap.class.getClassLoader() ) );
    }
    
    static private boolean m_loaded_juh = false;
    static private native Object cppuhelper_bootstrap(
        String ini_file, String bootstrap_parameters [], ClassLoader loader )
        throws Exception;

    /**
     * Bootstraps the component context from a UNO installation.
     *   
     * @return a bootstrapped component context.
	 * 
	 * @since UDK 3.1.0
     */    
    public static final XComponentContext bootstrap()
        throws BootstrapException {
        
        XComponentContext xContext = null;
        
        try {
            // create default local component context                
            XComponentContext xLocalContext =
                createInitialComponentContext( null );
            if ( xLocalContext == null )
                throw new BootstrapException( "no local component context!" );
            
            // find office executable relative to this class's class loader
            String sOffice =
                System.getProperty( "os.name" ).startsWith( "Windows" ) ?
                "soffice.exe" : "soffice";            
            File fOffice = NativeLibraryLoader.getResource(
                Bootstrap.class.getClassLoader(), sOffice );
            if ( fOffice == null )
                throw new BootstrapException( "no office executable found!" );

            // create random pipe name
            String sPipeName = "uno" +
                Long.toString( (new Random()).nextLong() & 0x7fffffffffffffffL );
            
            // create call with arguments
            String[] cmdArray = new String[7];
            cmdArray[0] = fOffice.getPath();
            cmdArray[1] = "-nologo";
            cmdArray[2] = "-nodefault";
            cmdArray[3] = "-norestore";
            cmdArray[4] = "-nocrashreport";
            cmdArray[5] = "-nolockcheck";
            cmdArray[6] = "-accept=pipe,name=" + sPipeName + ";urp;";
            
            // start office process
            Process p = Runtime.getRuntime().exec( cmdArray );
            pipe( p.getInputStream(), System.out, "CO> " );
            pipe( p.getErrorStream(), System.err, "CE> " );
            
            // initial service manager
            XMultiComponentFactory xLocalServiceManager =
                xLocalContext.getServiceManager();
            if ( xLocalServiceManager == null )
                throw new BootstrapException( "no initial service manager!" );
            
            // create a URL resolver
            XUnoUrlResolver xUrlResolver =
                UnoUrlResolver.create( xLocalContext );
            
            // connection string
            String sConnect = "uno:pipe,name=" + sPipeName +
                ";urp;StarOffice.ComponentContext";
            
            // wait until office is started
            for (int i = 0;; ++i) {
                try {
                    // try to connect to office
                    Object context = xUrlResolver.resolve( sConnect );
                    xContext = UnoRuntime.queryInterface(
                        XComponentContext.class, context);
                    if ( xContext == null )
                        throw new BootstrapException( "no component context!" );
                    break;
                } catch ( com.sun.star.connection.NoConnectException ex ) {
                    // Wait 500 ms, then try to connect again, but do not wait
                    // longer than 5 min (= 600 * 500 ms) total:
                    if (i == 600) {
                        throw new BootstrapException(ex.toString());
                    }
                    Thread.currentThread().sleep( 500 );
                }
            }
        } catch ( BootstrapException e ) {
            throw e;
        } catch ( java.lang.RuntimeException e ) {
            throw e;
        } catch ( java.lang.Exception e ) {
            throw new BootstrapException( e );
        }
        
		return xContext;
    }

    private static void pipe(
        final InputStream in, final PrintStream out, final String prefix ) {
        
        new Thread( "Pipe: " + prefix) {
            public void run() {
                BufferedReader r = new BufferedReader(
                    new InputStreamReader( in ) );
                try {
                    for ( ; ; ) {
                        String s = r.readLine();
                        if ( s == null ) {
                            break;
                        }
                        out.println( prefix + s );
                    }
                } catch ( java.io.IOException e ) {
                    e.printStackTrace( System.err );
                }
            }
        }.start();
    }
}
