/asadmin-java/src/main/java/org/n0pe/asadmin/AsAdmin.java
Java | 375 lines | 301 code | 23 blank | 51 comment | 50 complexity | 68fbed96621a507679c0bba210139159 MD5 | raw file
Possible License(s): Apache-2.0
- /*
- * Copyright (c) 2010, Paul Merlin.
- * Copyright (c) 2010, Christophe Souvignier.
- * Copyright (c) 2010, Jean-Michel Tonneau.
- * Copyright (c) 2011, J. Francis.
- *
- * Licensed 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 org.n0pe.asadmin;
- import java.io.BufferedReader;
- import java.io.File;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.InputStreamReader;
- import java.util.ArrayList;
- import java.util.Arrays;
- import java.util.HashMap;
- import java.util.Iterator;
- import java.util.List;
- import java.util.Map;
- import org.apache.commons.lang.StringUtils;
- import org.apache.commons.lang.SystemUtils;
- import org.n0pe.asadmin.commands.Database;
- import org.n0pe.asadmin.commands.Deployment;
- import org.n0pe.asadmin.commands.Domain;
- /**
- * asadmin command execution facility built as a multipleton which discriminator is a configuration provider.
- *
- * TODO : allows AsAdminCommands to provide input lines for stdin, implements this command :
- * echo y | asadmin generate-diagnostic-report --outputfile report-dosadi.jar domainName
- *
- * TODO : handle asadmin invocation return codes with exceptions
- */
- public class AsAdmin
- {
- private static final String OUTPUT_PREFIX = "[ASADMIN] ";
- private static Map<IAsAdminConfig, AsAdmin> instances;
- public static final String HOST_OPT = "--host";
- public static final String PORT_OPT = "--port";
- public static final String SECURE_OPT = "--secure";
- public static final String USER_OPT = "--user";
- public static final String PASSWORDFILE_OPT = "--passwordfile";
- public static String ASADMIN_COMMAND_NAME;
- static
- {
- ASADMIN_COMMAND_NAME = SystemUtils.IS_OS_WINDOWS ? "asadmin.bat" : "asadmin";
- }
- private IAsAdminConfig config;
- /**
- * Get a asadmin instance configured with the given configuration provider.
- *
- * @param config
- * @return
- */
- public static AsAdmin getInstance( final IAsAdminConfig config )
- {
- if( instances == null )
- {
- instances = new HashMap<IAsAdminConfig, AsAdmin>( 1 );
- }
- AsAdmin instance = instances.get( config );
- if( instance == null )
- {
- instance = new AsAdmin( config );
- instances.put( config, instance );
- }
- return instance;
- }
- private AsAdmin( final IAsAdminConfig config )
- {
- this.config = config;
- }
- /**
- * Run the given list of AsAdmin command.
- *
- * @param cmdList AsAdmin commands to be run
- * @throws org.n0pe.asadmin.AsAdminException AsAdminException
- */
- public void run( final AsAdminCmdList cmdList )
- throws AsAdminException
- {
- final Iterator<IAsAdminCmd> it = cmdList.iterator();
- while( it.hasNext() )
- {
- run( it.next() );
- }
- }
- /**
- * Run the given AsAdmin command.
- *
- * @param cmd AsAdmin command to be run
- * @throws org.n0pe.asadmin.AsAdminException AsAdminException
- */
- public void run( final IAsAdminCmd cmd )
- throws AsAdminException
- {
- try
- {
- final File gfBinPath = new File( config.getGlassfishHome() + File.separator + "bin" );
- final String[] cmds = buildProcessParams( cmd, config );
- cmds[0] = gfBinPath + File.separator + cmds[0];
- int exitCode;
- final Process proc;
- String[] env = buildEnvironmentStrings( config.getEnvironmentVariables() );
- if( SystemUtils.IS_OS_WINDOWS )
- {
- // Windows
- final String command = "\"\"" + StringUtils.join( cmds, "\" \"" ) + "\"\"";
- final String[] windowsCommand;
- if( SystemUtils.IS_OS_WINDOWS_95 || SystemUtils.IS_OS_WINDOWS_98 || SystemUtils.IS_OS_WINDOWS_ME )
- {
- windowsCommand = new String[]
- {
- "command.com", "/C", command
- };
- }
- else
- {
- windowsCommand = new String[]
- {
- "cmd.exe", "/C", command
- };
- }
- outPrintln( "Will run the following command: " + StringUtils.join( windowsCommand, " " ) );
- if( env.length > 0 )
- {
- proc = Runtime.getRuntime().exec( windowsCommand, env );
- }
- else
- {
- proc = Runtime.getRuntime().exec( windowsCommand );
- }
- }
- else
- {
- // Non Windows
- outPrintln( "Will run the following command: " + StringUtils.join( cmds, " " ) );
- proc = Runtime.getRuntime().exec( cmds, env );
- }
- final ProcessStreamGobbler errorGobbler = new ProcessStreamGobbler( cmd,
- proc.getErrorStream(),
- ProcessStreamGobbler.ERROR );
- final ProcessStreamGobbler outputGobbler = new ProcessStreamGobbler( cmd,
- proc.getInputStream(),
- ProcessStreamGobbler.OUTPUT );
- errorGobbler.start();
- outputGobbler.start();
- exitCode = proc.waitFor();
- if( exitCode != 0 )
- {
- if( cmd.failOnNonZeroExit() )
- {
- throw new AsAdminException( "asadmin invocation failed and returned : " + String.valueOf( exitCode ) );
- }
- errPrintln( "Ignoring accpetable asadmin error" );
- }
- }
- catch( final InterruptedException ex )
- {
- throw new AsAdminException( "AsAdmin error occurred: " + ex.getMessage(), ex );
- }
- catch( final IOException ex )
- {
- throw new AsAdminException( "AsAdmin error occurred: " + ex.getMessage(), ex );
- }
- }
- public static String[] buildProcessParams( final IAsAdminCmd cmd, final IAsAdminConfig config )
- throws AsAdminException
- {
- final List<String> pbParams = new ArrayList<String>();
- pbParams.add( ASADMIN_COMMAND_NAME );
- if( !Deployment.UNDEPLOY.equals( cmd.getActionCommand() )
- && !Deployment.DEPLOY.equals( cmd.getActionCommand() )
- && !Deployment.REDEPLOY.equals( cmd.getActionCommand() )
- && !"add-resources".equals( cmd.getActionCommand() ) )
- {
- pbParams.add( cmd.getActionCommand() );
- }
- if( !StringUtils.isEmpty( config.getHost() )
- && !Domain.START.equals( cmd.getActionCommand() )
- && !Domain.STOP.equals( cmd.getActionCommand() )
- && !Database.STOP.equals( cmd.getActionCommand() )
- && !Database.START.equals( cmd.getActionCommand() ) )
- {
- pbParams.add( HOST_OPT );
- pbParams.add( config.getHost() );
- }
- if( !StringUtils.isEmpty( config.getPort() )
- && !Domain.START.equals( cmd.getActionCommand() )
- && !Domain.STOP.equals( cmd.getActionCommand() )
- && !Database.STOP.equals( cmd.getActionCommand() )
- && !Database.START.equals( cmd.getActionCommand() ) )
- {
- pbParams.add( PORT_OPT );
- pbParams.add( config.getPort() );
- }
- if( config.isSecure() )
- {
- pbParams.add( SECURE_OPT );
- }
- if( cmd.needCredentials() )
- {
- pbParams.add( USER_OPT );
- pbParams.add( config.getUser() );
- pbParams.add( PASSWORDFILE_OPT );
- pbParams.add( cmd.handlePasswordFile( config.getPasswordFile() ) );
- }
- if( Deployment.UNDEPLOY.equals( cmd.getActionCommand() )
- || Deployment.DEPLOY.equals( cmd.getActionCommand() )
- || Deployment.REDEPLOY.equals( cmd.getActionCommand() )
- || "add-resources".equals( cmd.getActionCommand() ) )
- {
- pbParams.add( cmd.getActionCommand() );
- }
- pbParams.addAll( Arrays.asList( cmd.getParameters() ) );
- return pbParams.toArray( new String[ pbParams.size() ] );
- }
- private static void outPrintln( final String message )
- {
- System.out.print( OUTPUT_PREFIX );
- System.out.println( message );
- }
- private static void errPrintln( final String message )
- {
- System.out.print( OUTPUT_PREFIX );
- System.out.println( message );
- }
- /**
- * Ensure variable names do not contains spaces and quote their values if needed.
- */
- /* package */ static String[] buildEnvironmentStrings( Map<String, String> envVariables )
- {
- if( envVariables == null || envVariables.isEmpty() )
- {
- return new String[]
- {
- };
- }
- String[] array = new String[ envVariables.size() ];
- int idx = 0;
- for( Map.Entry<String, String> eachEntry : envVariables.entrySet() )
- {
- String key = eachEntry.getKey().trim();
- if( !key.matches( "^\\S+$" ) )
- {
- throw new IllegalArgumentException( "Environment variable names cannot contain spaces: " + key );
- }
- String value = eachEntry.getValue();
- array[idx] = key + "=" + quoteArgument( value );
- idx++;
- }
- return array;
- }
- private static final String SINGLE_QUOTE = "\'";
- private static final String DOUBLE_QUOTE = "\"";
- private static String quoteArgument( final String argument )
- {
- String cleanedArgument = argument.trim();
- // strip the quotes from both ends
- while( cleanedArgument.startsWith( SINGLE_QUOTE ) || cleanedArgument.startsWith( DOUBLE_QUOTE ) )
- {
- cleanedArgument = cleanedArgument.substring( 1 );
- }
- while( cleanedArgument.endsWith( SINGLE_QUOTE ) || cleanedArgument.endsWith( DOUBLE_QUOTE ) )
- {
- cleanedArgument = cleanedArgument.substring( 0, cleanedArgument.length() - 1 );
- }
- final StringBuffer sb = new StringBuffer();
- if( cleanedArgument.indexOf( DOUBLE_QUOTE ) > -1 )
- {
- if( cleanedArgument.indexOf( SINGLE_QUOTE ) > -1 )
- {
- throw new IllegalArgumentException( "Can't handle single and double quotes in same argument" );
- }
- else
- {
- return sb.append( SINGLE_QUOTE ).append( cleanedArgument ).append( SINGLE_QUOTE ).toString();
- }
- }
- else if( cleanedArgument.indexOf( SINGLE_QUOTE ) > -1 || cleanedArgument.indexOf( " " ) > -1 )
- {
- return sb.append( DOUBLE_QUOTE ).append( cleanedArgument ).append( DOUBLE_QUOTE ).toString();
- }
- else
- {
- return cleanedArgument;
- }
- }
- /**
- * TODO : take a logger as constructor parameter and remove type
- */
- private static class ProcessStreamGobbler
- extends Thread
- {
- private static final int OUTPUT = 0;
- private static final int ERROR = 1;
- private AbstractAsAdminCmd cmd;
- private InputStream is;
- private int type = OUTPUT;
- private ProcessStreamGobbler( final IAsAdminCmd cmd, InputStream is, int type )
- {
- this.is = is;
- this.type = type;
- if( AbstractAsAdminCmd.class.isAssignableFrom( cmd.getClass() ) )
- {
- this.cmd = (AbstractAsAdminCmd) cmd;
- }
- }
- @Override
- @SuppressWarnings( "CallToThreadDumpStack" )
- public void run()
- {
- try
- {
- InputStreamReader isr = new InputStreamReader( is );
- BufferedReader br = new BufferedReader( isr );
- String line;
- while( ( line = br.readLine() ) != null )
- {
- switch( type )
- {
- case OUTPUT:
- if( cmd != null )
- {
- cmd.appendStandardOutputLine( line );
- }
- outPrintln( "[OUTPUT] " + line );
- break;
- case ERROR:
- if( cmd != null )
- {
- cmd.appendErrorOutputLine( line );
- }
- errPrintln( "[ERROR] " + line );
- }
- }
- }
- catch( IOException ioe )
- {
- ioe.printStackTrace();
- }
- }
- }
- }