package com.sonatype.buildserver.eclipse.ui;
import java.net.MalformedURLException;
import java.net.NoRouteToHostException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.UnknownHostException;
import java.nio.channels.UnresolvedAddressException;
import java.text.MessageFormat;
import java.util.Collections;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jdt.internal.junit.model.JUnitModel;
import org.eclipse.jdt.internal.junit.model.TestRunSession;
import org.eclipse.jdt.internal.junit.ui.TestRunnerViewPart;
import org.eclipse.jdt.junit.model.ITestRunSession;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.browser.IWebBrowser;
import org.eclipse.ui.browser.IWorkbenchBrowserSupport;
import org.eclipse.ui.console.ConsolePlugin;
import org.eclipse.ui.console.IConsole;
import org.eclipse.ui.console.IConsoleManager;
import org.eclipse.ui.progress.UIJob;
import org.eclipse.ui.statushandlers.StatusManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.sonatype.buildserver.eclipse.console.HudsonConsole;
import com.sonatype.buildserver.eclipse.test.HudsonTestSession;
import com.sonatype.buildserver.eclipse.ui.job.view.SingleJobView;
import com.sonatype.buildserver.hudsonclient.HudsonRestFactory;
import com.sonatype.buildserver.monitor.HudsonJob;
import com.sonatype.buildserver.monitor.HudsonManager;
import com.sonatype.buildserver.monitor.HudsonMonitor;
import com.sonatype.buildserver.monitor.CompositeMonitor;
import com.sonatype.buildserver.monitor.ErrorJob;
import org.hudsonci.rest.client.HandshakeFailedException;
import org.hudsonci.rest.client.InvalidResponseException;
import org.hudsonci.rest.model.build.BuildDTO;
import org.hudsonci.rest.model.build.BuildResultDTO;
import org.hudsonci.rest.model.build.TestsDTO;
import org.hudsonci.rest.model.project.ProjectDTO;
import com.sun.jersey.api.client.ClientHandlerException;
@SuppressWarnings( "restriction" )
{
private static Logger log = LoggerFactory.getLogger( HudsonUtils.class );
public static final void openJob( HudsonJob o )
{
if ( o.getJobDetails() instanceof ErrorJob )
{
ProjectDTO det = o.getJobDetails();
if ( det != null && det.getUrl() != null )
{
openUrl( det.getUrl() );
}
return;
}
SingleJobView.openEditor( o );
}
public static final void openUrl( String url )
{
try
{
log.debug( "Opening URL: " + url );
IWorkbenchBrowserSupport support = PlatformUI.getWorkbench().getBrowserSupport();
IWebBrowser browser =
support.isInternalWebBrowserAvailable() ? support.createBrowser( IWorkbenchBrowserSupport.AS_EDITOR
| IWorkbenchBrowserSupport.LOCATION_BAR | IWorkbenchBrowserSupport.NAVIGATION_BAR
| IWorkbenchBrowserSupport.STATUS, null, url, url ) : support.getExternalBrowser();
browser.openURL( new URL( url ) );
}
catch ( PartInitException partInitException )
{
StatusManager.getManager().handle( partInitException, HudsonUIActivator.PLUGIN_ID );
}
catch ( MalformedURLException malformedURLException )
{
StatusManager.getManager().handle( new Status( IStatus.ERROR, HudsonUIActivator.PLUGIN_ID,
Messages.HudsonUtils_error_open_url + url,
malformedURLException ) );
}
}
{
Class pluginClass = null;
try
{
pluginClass = Class.forName( "org.eclipse.jdt.internal.junit.JUnitCorePlugin" );
}
catch ( ClassNotFoundException cnf1 )
{
try
{
pluginClass = Class.forName( "org.eclipse.jdt.internal.junit.ui.JUnitPlugin" );
}
catch ( ClassNotFoundException cnf2 )
{
log.error( "Could not find JUnit plugin class." );
}
}
Object pluginObject;
try
{
pluginObject = pluginClass.getDeclaredMethod( "getDefault", null ).invoke( pluginClass, null );
return (JUnitModel) pluginObject.getClass().getDeclaredMethod( "getModel", null ).invoke( pluginObject,
null );
}
catch ( Exception e )
{
log.error( "Could not find junit related methods.", e );
}
return null;
}
public static final void openTests(
final HudsonJob job,
final BuildDTO build )
{
assert job != null && build != null;
Job jb = new Job( NLS.bind( Messages.background_retrieve_tests, job.getJobName(), build.getNumber() ) )
{
@Override
protected IStatus run( IProgressMonitor monitor )
{
log.debug( "Getting test results for job {} / build {} from server {}", new Object[] { job.getJobName(), build.getId(), job.getServerName() } );
try
{
HudsonJob selected = job;
BuildDTO bld = build;
List<HudsonJob> descs = job.loadDescendants();
if ( descs.size() > 0 )
{
boolean failed =
build.getResult() == BuildResultDTO.FAILURE || build.getResult() == BuildResultDTO.UNSTABLE;
for ( HudsonJob bj : descs )
{
BuildDTO b = bj.loadBuild( build.getNumber() );
if ( b != null )
{
if ( failed )
{
if ( b.getResult() == BuildResultDTO.FAILURE || b.getResult() == BuildResultDTO.UNSTABLE )
{
selected = bj;
bld = b;
log.debug( "Picked job {} failed configuration {}", new Object[] { job.getJobName(), selected.getJobName() } );
break;
}
}
else
{
log.debug( "Picked job {} configuration {}", new Object[] { job.getJobName(), selected.getJobName() } );
selected = bj;
bld = b;
break;
}
}
}
}
final TestsDTO tests = selected.getTests( bld );
final HudsonJob fSelected = selected;
final BuildDTO fBld = bld;
Display.getDefault().asyncExec( new Runnable()
{
public void run()
{
JUnitModel model = getJUnitModel();
String sessionName =
Messages.HudsonUtils_test_name_prefix + HudsonUtils.getJobTitle( fSelected, fBld );
for ( Object session : model.getTestRunSessions() )
{
if ( ( (ITestRunSession) session ).getTestRunName().equals( sessionName ) )
{
model.removeTestRunSession( (TestRunSession) session );
break;
}
}
model.addTestRunSession( new HudsonTestSession( sessionName, tests ) );
IWorkbenchPage workbench =
PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
try
{
workbench.showView( TestRunnerViewPart.NAME );
}
catch ( PartInitException e )
{
UIJob.errorStatus( e );
}
}
} );
}
catch ( Exception e )
{
StatusManager.getManager().handle( new Status( IStatus.ERROR, HudsonUIActivator.PLUGIN_ID,
"Failed to retrieve tests for job '"
+ job.getJobName() + "' build #"
+ build.getNumber(), e ), StatusManager.LOG );
}
return Status.OK_STATUS;
}
};
jb.schedule();
}
public static final void openConsole(
final HudsonJob job,
final BuildDTO build )
{
assert job != null && build != null;
Job jb =
new Job( NLS.bind( "Retrieve console output for Hodson job {0} #{1}", job.getJobName(), build.getNumber() ) )
{
@Override
protected IStatus run( IProgressMonitor monitor )
{
IConsoleManager consoleManager = ConsolePlugin.getDefault().getConsoleManager();
HudsonJob selected = job;
BuildDTO bld = build;
List<HudsonJob> descs = job.loadDescendants();
if ( descs.size() > 0 )
{
boolean failed =
build.getResult() == BuildResultDTO.FAILURE || build.getResult() == BuildResultDTO.UNSTABLE;
for ( HudsonJob bj : descs )
{
BuildDTO b = bj.loadBuild( build.getNumber() );
if ( b != null )
{
if ( failed )
{
if ( b.getResult() == BuildResultDTO.FAILURE || b.getResult() == BuildResultDTO.UNSTABLE )
{
selected = bj;
bld = b;
log.debug( "Picked job {} failed configuration {}", new Object[] { job.getJobName(), selected.getJobName() } );
break;
}
}
else
{
log.debug( "Picked job {} configuration {}", new Object[] { job.getJobName(), selected.getJobName() } );
selected = bj;
bld = b;
break;
}
}
}
}
IConsole[] allConsoles = consoleManager.getConsoles();
String name = HudsonUtils.getJobTitle( selected, bld );
for ( int i = 0; i < allConsoles.length; i++ )
{
if ( HudsonConsole.HUDSON_TYPE.equals( allConsoles[i].getType() )
&& allConsoles[i].getName().equals( name ) )
{
consoleManager.showConsoleView( allConsoles[i] );
HudsonConsole c = (HudsonConsole)allConsoles[i];
c.checkForUpdates();
consoleManager.refresh( allConsoles[i] );
return Status.OK_STATUS;
}
}
HudsonConsole hc = new HudsonConsole( selected, bld );
consoleManager.addConsoles( new IConsole[] { hc } );
consoleManager.showConsoleView( hc );
return Status.OK_STATUS;
}
};
jb.schedule();
}
public static String
getJobTitle( HudsonJob job, BuildDTO bld )
{
if ( bld == null )
{
return job.getJobName();
}
return job.getJobName() + Messages.HudsonUtils_build_prefix + bld.getNumber();
}
private static long SECOND = 1000;
private static long MINUTE = 60 * SECOND;
private static long HOUR = 60 * MINUTE;
private static long DAY = 24 * HOUR;
private static long WEEK = 7 * DAY;
private static long MONTH = 30 * DAY;
{
if ( job.getJobDetails() == null || job.getJobDetails().getLastBuild() == null )
return Messages.jobPopup_not_run;
BuildDTO last = job.getJobDetails().getLastBuild();
long before = last.getTimeStamp() + ( last.getDuration() != null ? last.getDuration() : 0 );
long time = System.currentTimeMillis() - before;
if ( time <= 2 * MINUTE )
{
return Messages.jobPopup_a_minute_ago;
}
else if ( time <= HOUR )
{
return NLS.bind( Messages.jobPopup_minutes_ago, ( time / MINUTE ) );
}
else if ( time <= 2 * HOUR )
{
return Messages.jobPopup_hour_ago;
}
else if ( time <= DAY )
{
return NLS.bind( Messages.jobPopup_hours_ago, ( time / HOUR ) );
}
else if ( time <= 2 * DAY )
{
return Messages.jobPopup_day_ago;
}
else if ( time <= WEEK )
{
return NLS.bind( Messages.jobPopup_days_ago, ( time / DAY ) );
}
else if ( time <= 2 * WEEK )
{
return Messages.jobPopup_week_ago;
}
else if ( time <= MONTH )
{
return NLS.bind( Messages.jobPopup_weeks_ago, ( time / WEEK ) );
}
else if ( time <= 2 * MONTH )
{
return Messages.jobPopup_month_ago;
}
return NLS.bind( Messages.jobPopup_months_ago, ( time / MONTH ) );
}
public static void runBuild(
final HudsonJob job )
{
org.eclipse.core.runtime.jobs.Job jb =
new org.eclipse.core.runtime.jobs.Job( NLS.bind( Messages.background_build_job, job.getJobName() ) )
{
@Override
protected IStatus
run( IProgressMonitor monitor )
{
log.debug( "Triggering build job {} from server {}.", job.getJobName(), job.getServerName() );
IStatus status = job.build();
if ( !status.isOK() )
{
StatusManager.getManager().handle( status, StatusManager.SHOW | StatusManager.LOG );
} else {
job.refresh();
}
return Status.OK_STATUS;
}
};
jb.schedule();
}
{
long time = build.getDuration();
long hours = time / HOUR;
time = time - hours * HOUR;
long minutes = time / MINUTE;
time = time - minutes * MINUTE;
long seconds = time / SECOND;
if ( hours > 0 )
{
return NLS.bind( Messages.HudsonUtils_hour_minute, hours, minutes );
}
else if ( minutes > 0 )
{
return NLS.bind( Messages.HudsonUtils_minute_second, minutes, seconds );
}
else
{
if ( seconds < 5 )
{
double secs = (double) time / (double) SECOND;
return NLS.bind( Messages.HudsonUtils_second, MessageFormat.format( "{0,number,#.##}", secs ) );
}
return NLS.bind( Messages.HudsonUtils_second, seconds );
}
}
{
Image im = HudsonImages.getHealthImage( job );
if ( im == HudsonImages.HEALTH_81_PLUS_IMAGE )
{
return Messages.HudsonUtils_no_recent_fail;
}
if ( im == HudsonImages.HEALTH_61_TO_80_IMAGE )
{
return Messages.HudsonUtils_minority_fail;
}
if ( im == HudsonImages.HEALTH_41_TO_60_IMAGE )
{
return Messages.HudsonUtils_some_fail;
}
if ( im == HudsonImages.HEALTH_21_TO_40_IMAGE )
{
return Messages.HudsonUtils_majority_fail;
}
if ( im == HudsonImages.HEALTH_00_TO_20_IMAGE )
{
return Messages.HudsonUtils_all_fail;
}
return Messages.HudsonUtils_unknown_health;
}
{
return "hudson.matrix.MatrixProject".equals( type.getType() );
}
{
return "hudson.matrix.MatrixConfiguration".equals( type.getType() );
}
{
boolean isHandshake = false;
if ( e instanceof HandshakeFailedException )
{
isHandshake = true;
HandshakeFailedException ex = (HandshakeFailedException) e;
for ( Throwable t : ex.getFailures() )
{
e = t;
}
}
if (e instanceof InvalidResponseException) {
InvalidResponseException ie = (InvalidResponseException)e;
if ( isHandshake && ie.getResponse().getStatus() == 404 ) {
return "Hudson REST plugin not found at given URL.";
}
if (ie.getResponse().getStatus() == 404 && notFound404Message != null) {
return notFound404Message;
}
if ( isHandshake && ie.getResponse().getStatus() == 409) {
return "Incompatible REST plugin on Hudson server. Client version is " + HudsonRestFactory.getClient().getVersion();
}
if ( isHandshake && ie.getResponse().getStatus() == 400) {
return "Server REST plugin indicated the client sent bad request. Client version is " + HudsonRestFactory.getClient().getVersion();
}
if ( isHandshake && ie.getResponse().getStatus() == 503) {
return "Server REST plugin is not yet fully initiated. Please try again later.";
}
if (ie.getResponse().getStatus() == 302) {
String url = ie.getResponse().getHeaders().getFirst( "Location" );
if (url.endsWith( "/rest/handshake" )) {
url = url.substring( 0, url.lastIndexOf( "/rest/handshake" ) );
}
return "Please use following URL instead: " + url;
}
if (ie.getResponse().getStatus() == 401) {
StatusManager.getManager().handle(new Status(IStatus.ERROR, HudsonUIActivator.PLUGIN_ID, "Unauthorized\n" + ie.getResponse().getEntity(String.class), ie), StatusManager.LOG);
return "Unauthorized";
}
String m = "Http error code " + ie.getResponse().getStatus();
String mes = ie.getResponse().getEntity(String.class);
if (mes != null && mes.length() > 0) {
m = m + " : " + mes;
}
return m;
}
if ( e instanceof ClientHandlerException )
{
while ( e.getCause() != null )
{
e = e.getCause();
}
}
if ( e instanceof UnknownHostException )
{
return Messages.error_unknown_host;
}
if ( e instanceof UnresolvedAddressException )
{
return Messages.error_unresolved_address;
}
if ( e instanceof NoRouteToHostException )
{
return Messages.error_no_route_to_host;
}
return e.getMessage();
}
public static String
stripHtml( String source )
{
String regex =
"</?(a|b|big|body|br|center|dd|dl|dt|em|embed|font|form|h1|h2|h3|h4|h5|h6|head|hr|html|i|it|img|input|li|link|menu|meta|ol|option|p|small|strike|strong|table|td|th|title|tr|tt|u|ul).*?>";
Pattern p = Pattern.compile( regex, Pattern.DOTALL | Pattern.CASE_INSENSITIVE );
return p.matcher( source ).replaceAll( "" );
}
{
String serverName = null;
String jobName = null;
Pattern p = Pattern.compile( "(.*)/job/([^/]*)/*.*" );
Matcher m = p.matcher( jobURL );
if ( !m.find() )
return null;
serverName = m.group( 1 );
jobName = m.group( 2 );
Pattern viewPattern = Pattern.compile( "(.*)/view.*" );
Matcher m2 = viewPattern.matcher( m.group( 1 ) );
if ( m2.find() )
serverName = m2.group( 1 );
return new String[] { serverName, jobName };
}
{
return HudsonManager.getDefaultMonitor();
}
public static boolean startMonitoringJob( String jobURL, CompositeMonitor monitor )
throws URISyntaxException
{
String[] jobInfo = parseHudsonWebURL( jobURL );
if ( jobInfo == null )
{
log.debug( "Could not parse job URL {}", jobURL );
return false;
}
HudsonMonitor serverMonitor = monitor.getMonitor( jobInfo[0] );
if ( serverMonitor == null )
{
serverMonitor = HudsonManager.addHudsonMonitor( new URI( jobInfo[0] ), null);
monitor.addMonitor( serverMonitor );
}
serverMonitor.addMonitoredJobs( Collections.singletonList( jobInfo[1] ) ).iterator().next().refresh();
monitor.save();
return true;
}
}