package org.codehaus.mojo.ruby; import java.io.IOException; import java.util.Iterator; import java.util.Map; import java.util.StringTokenizer; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.Mojo; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.codehaus.plexus.component.configurator.ComponentConfigurationException; import org.codehaus.plexus.component.jruby.JRubyInvoker; import org.codehaus.plexus.component.jruby.JRubyRuntimeInvoker; import org.codehaus.plexus.component.repository.ComponentRequirement; import org.codehaus.plexus.util.StringOutputStream; import org.jruby.exceptions.RaiseException; /** * This is the default implementation for the RubyMojo, which * uses the RubyInvoker. * @author Eric Redmond */ public class DefaultRubyMojo extends AbstractMojo implements RubyMojo { private JRubyInvoker jinvoker; private Object returned; public DefaultRubyMojo( JRubyInvoker invoker ) { this.jinvoker = invoker; } /** * Sets any string key with an object value. * @param key identifier for this object. * @param value some value object. */ public void set( String key, Object value ) { if ( "basedir".equals( key ) ) { jinvoker.setCurrentDirectory( value.toString() ); jinvoker.putGlobal( key, value ); } else if ( "libraryPaths".equals( key ) ) { // TODO: for future use // jinvoker.setLibraryPaths( (String[])value ); } else if ( "requires".equals( key ) ) { jinvoker.setRequires( (String[])value ); } else { jinvoker.putGlobal( key, value ); } } /** * Implementation of Mojo.execute. Invokes the underlying * Ruby script. * @throws MojoExecutionException satisfies Mojo contact, not used. * @throws MojoFailureException satisfies Mojo contact, not used. */ public void execute() throws MojoExecutionException, MojoFailureException { //jinvoker.setDebug( true ); StringOutputStream stdout = new StringOutputStream(); StringOutputStream stderr = new StringOutputStream(); try { returned = jinvoker.invoke( stdout, stderr ); // TODO: This is for future work. Returned object may be a Mojo, // to work like BeanShell if( returned instanceof Mojo ) { ((Mojo)returned).execute(); } } catch ( RaiseException e ) { JRubyRuntimeInvoker.printREStackTrace( e, stderr ); throw new MojoExecutionException( e.getMessage(), e ); } catch ( Throwable e ) { throw new MojoExecutionException( e.getMessage(), e ); } finally { try { stdout.flush(); logOutput( stdout.toString(), false ); stdout.close(); } catch( IOException e ) { e.printStackTrace(); } try { stderr.flush(); logOutput( stderr.toString(), true ); stderr.close(); } catch( IOException e ) { e.printStackTrace(); } } } public Object getReturned() { return returned; } /** * Outputs Strings as info or error to the mojo's log. * * @param out * @param error true if error */ private void logOutput( String output, boolean error ) { if ( output != null && output.length() > 0 ) { for ( StringTokenizer tokens = new StringTokenizer( output, "\n" ); tokens.hasMoreTokens(); ) { if ( error ) { getLog().error( tokens.nextToken() ); } else { getLog().info( tokens.nextToken() ); } } } } public void addComponentRequirement( ComponentRequirement componentrequirement, Object obj ) throws ComponentConfigurationException { set( componentrequirement.getFieldName(), obj ); } public void setComponentConfiguration( Map map ) throws ComponentConfigurationException { for( Iterator iter = map.entrySet().iterator(); iter.hasNext(); ) { Map.Entry entry = (Map.Entry)iter.next(); set( (String)entry.getKey(), entry.getValue() ); } } }