/*
* Created on 12-Sep-2005
* Created by Paul Gardner
* Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
*
* This program 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 2
* 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 General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* AELITIS, SAS au capital de 46,603.30 euros
* 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
*
*/
package org.gudy.azureus2.pluginsimpl.local.launch;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.security.SecureRandom;
import org.gudy.azureus2.core3.util.RandomUtils;
import org.gudy.azureus2.core3.util.SystemProperties;
import org.gudy.azureus2.plugins.PluginManagerArgumentHandler;
import org.gudy.azureus2.plugins.logging.LoggerChannel;
import org.gudy.azureus2.plugins.logging.LoggerChannelListener;
public class
PluginSingleInstanceHandler
{
private static boolean active;
private static int port;
private static PluginManagerArgumentHandler handler;
public static void
initialise(
int _port,
PluginManagerArgumentHandler _handler )
{
port = _port;
handler = _handler;
String multi_instance = System.getProperty( "MULTI_INSTANCE");
if ( multi_instance != null && multi_instance.equalsIgnoreCase( "true" )){
return;
}
active = true;
}
public static boolean
initialiseAndProcess(
int _port,
PluginManagerArgumentHandler _handler,
String[] _args )
{
initialise( _port, _handler );
return( process( null, _args ));
}
protected static boolean
process(
LoggerChannelListener log,
String[] args )
{
if ( active ){
if ( startListener( log )){
return( false );
}else{
sendArguments( log, args );
return( true );
}
}else{
return( false );
}
}
protected static boolean
startListener(
final LoggerChannelListener log )
{
try{
final ServerSocket server_socket = new ServerSocket( port, 50, InetAddress.getByName("127.0.0.1"));
if ( log != null ){
log.messageLogged(
LoggerChannel.LT_INFORMATION,
"SingleInstanceHandler: listening on 127.0.0.1:" + port + " for passed arguments");
}
Thread t =
new Thread("Single Instance Handler")
{
public void
run()
{
while ( true ){
Socket socket = null;
ObjectInputStream ois = null;
try{
socket = server_socket.accept();
String address = socket.getInetAddress().getHostAddress();
if ( !( address.equals("localhost") || address.equals("127.0.0.1"))){
socket.close();
continue;
}
ois = new ObjectInputStream( socket.getInputStream());
ois.readInt(); // version
String header = (String)ois.readObject();
if ( !header.equals( getHeader())){
if ( log != null ){
log.messageLogged(
LoggerChannel.LT_ERROR,
"SingleInstanceHandler: invalid header - " + header );
}
continue;
}
String[] args = (String[])ois.readObject();
String config_dir = System.getProperty( SystemProperties.SYS_PROP_CONFIG_OVERRIDE, null );
if ( config_dir != null ){
// caller will have written args to a file
String config_path = (String)ois.readObject();
String file_name = (String)ois.readObject();
if ( !config_path.equals( config_dir )){
throw( new Exception( "Called supplied incorrect config path: " + config_path ));
}
File cmd_file = new File( new File( config_dir, "tmp" ), file_name ).getCanonicalFile();
if ( !cmd_file.getParentFile().getParentFile().equals( new File( config_dir ))){
throw( new Exception( "Called supplied invalid file name: " + file_name ));
}
ObjectInputStream ois2 = new ObjectInputStream( new FileInputStream( cmd_file ));
try{
args = (String[])ois2.readObject();
}finally{
ois2.close();
cmd_file.delete();
}
}
handler.processArguments( args );
}catch( Throwable e ){
if ( log != null ){
log.messageLogged( "SingleInstanceHandler: receive error", e );
}
}finally{
if ( ois != null ){
try{
ois.close();
}catch( Throwable e ){
}
}
if ( socket != null ){
try{
socket.close();
}catch( Throwable e ){
}
}
}
}
}
};
t.setDaemon( true );
t.start();
return( true );
}catch( Throwable e ){
return( false );
}
}
protected static void
sendArguments(
LoggerChannelListener log,
String[] args )
{
Socket socket = null;
try{
socket = new Socket( "127.0.0.1", port );
ObjectOutputStream oos = new ObjectOutputStream( socket.getOutputStream());
oos.writeInt( 0 );
oos.writeObject( getHeader());
oos.writeObject( args );
// if we know the config dir then use more secure mechanism to pass args by writing
// to a file (this proving we have write access to the directory at least)
String config_dir = System.getProperty( SystemProperties.SYS_PROP_CONFIG_OVERRIDE, null );
if ( config_dir != null ){
File file = new File( config_dir, "tmp" );
file.mkdirs();
file = File.createTempFile( "AZU" + RandomUtils.nextSecureAbsoluteLong(), ".tmp", file );
ObjectOutputStream oos2 = new ObjectOutputStream( new FileOutputStream( file ));
try{
oos2.writeObject( args );
}finally{
oos2.close();
}
oos.writeObject( config_dir );
oos.writeObject( file.getName());
}
oos.flush();
if ( log != null ){
log.messageLogged( LoggerChannel.LT_INFORMATION, "SingleInstanceHandler: arguments passed to existing process" );
}
}catch( Throwable e ){
if ( log != null ){
log.messageLogged( "SingleInstanceHandler: send error", e );
}
}finally{
if ( socket != null ){
try{
socket.close();
}catch( Throwable e ){
}
}
}
}
protected static String
getHeader()
{
return( SystemProperties.getApplicationName() + " Single Instance Handler" );
}
}