Skip to content
Permalink
Browse files

Another fix to how the UNC paths are handled (a workaround similar to…

… the one applied in SBT: sbt/sbt#564)

Build Monitor should load its LESS CSS assets correctly from a mapped network folder defined as a UNC path on Windows as long as:
- Build Monitor runs on Jenkins 1.598 or later (due to a bug in Jenkins prior to that version: http://jenkins-ci.org/changelog#v1.598)
- Jenkins runs on Java 7 u60 or later (due to a bug in Java prior to that version: http://bugs.java.com/view_bug.do?bug_id=8014394)

Fixes #183
  • Loading branch information...
jan-molak committed Nov 18, 2015
1 parent e05bc5d commit 22c6ca42454e485157c549228607911c2d44c068
@@ -5,7 +5,7 @@
import hudson.Plugin;
import hudson.util.PluginServletFilter;

import java.net.URI;
import java.io.File;
import java.net.URISyntaxException;
import java.net.URL;

@@ -31,7 +31,7 @@ private URL baseResourceURL() {
return getWrapper().parent.getPlugin("build-monitor-plugin").baseResourceURL;
}

private URI pathTo(String asset) throws URISyntaxException {
return new PathToAsset(baseResourceURL(), asset).toURI();
private File pathTo(String asset) throws URISyntaxException {
return new PathToAsset(baseResourceURL(), asset).toFile();
}
}
@@ -7,23 +7,47 @@
import static java.lang.String.format;

public class PathToAsset {
private final URL root;
private final String asset;
private static final String FILE_PROTOCOL = "file";
private final URI path;

public PathToAsset(URL root, String asset) {
this.root = root;
this.asset = asset;
this.path = validated(uriFrom(root, asset));
}

public URI toURI() {
public File toFile() {
/*
* The below workaround is required as the `uri` representing a UNC path on Windows
* has an `authority` component defined (//foo/bar/some/file.ext),
* however the File class constructor requires URIs with no defined authority
*
* https://github.com/jan-molak/jenkins-build-monitor-plugin/issues/183#issuecomment-157712010
*
* http://blogs.msdn.com/b/ie/archive/2006/12/06/file-uris-in-windows.aspx
* http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5086147
*
* fix as per: https://github.com/sbt/sbt/issues/564
*/

return (null == path.getAuthority())
? new File(path)
: new File(path.getSchemeSpecificPart());
}

// --

private URI uriFrom(URL root, String asset) {
try {
return new URL(root, asset).toURI();
} catch (Exception e) {
throw new RuntimeException(format("Sorry, I couldn't construct a path to asset '%s' using root: '%s", asset, root));
throw new IllegalArgumentException(format("Sorry, I couldn't construct a path to asset '%s' using root: '%s", asset, root));
}
}

public File toFile() {
return new File(toURI());
private URI validated(URI fileUri) {
if (! FILE_PROTOCOL.equals(fileUri.getScheme())) {
throw new IllegalArgumentException(format("Sorry, can't load the asset from '%s' using the '%s' protocol", fileUri, FILE_PROTOCOL));
}

return fileUri;
}
}
@@ -10,24 +10,23 @@
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;

public class LessCSS implements Filter {
private final File less;
private final File lessFile;
private final String pathToCSS;

private String compiledCSS;

public LessCSS(String pathToCSS, URI pathToLess) throws URISyntaxException {
public LessCSS(String pathToCSS, File pathToLess) throws URISyntaxException {
this.pathToCSS = pathToCSS;
this.less = new File(pathToLess);
this.lessFile = pathToLess;
}

@Override
public void init(FilterConfig filterConfig) throws ServletException {
try {
compiledCSS = cssFrom(less);
compiledCSS = cssFrom(lessFile);
} catch (Less4jException e) {
throw new ServletException("Couldn't compile the CSS from LESS sources", e);
}
@@ -1,37 +1,53 @@
package com.smartcodeltd.jenkinsci.plugin.assetbundler;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;

import java.net.MalformedURLException;
import java.net.URL;

import static com.smartcodeltd.jenkinsci.plugin.assetbundler.OsSpecific.isNotWindows;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;
import static org.junit.Assume.assumeTrue;

public class PathToAssetTest {
@Before
public void checkOS() {
// todo: Build Monitor should use Java 7 once its core dependency on Jenkins can be upgraded to 1.612
assumeTrue(isNotWindows());
}

@Test
public void combines_base_resource_url_given_by_jenkins_and_a_path_to_the_asset() throws Exception {
URL base = baseResourceUrlGivenByJenkins("/opt/jenkins/plugins/build-monitor-plugin/");
URL base = baseResourceUrlGivenByJenkins("file:///opt/jenkins/plugins/build-monitor-plugin/");

PathToAsset path = new PathToAsset(base, "less/index.less");

assertThat(absolute(path), is("/opt/jenkins/plugins/build-monitor-plugin/less/index.less"));
}

@Test
public void works_with_unc_paths_on_windows() throws Exception {
URL base = baseResourceUrlGivenByJenkins("file://server/jenkins/plugins/build-monitor-plugin/");

PathToAsset path = new PathToAsset(base, "less/index.less");

assertThat(absolute(path), is("/server/jenkins/plugins/build-monitor-plugin/less/index.less"));
}

@Rule public ExpectedException thrown = ExpectedException.none();

@Test
public void complains_when_given_a_non_file_base_resource_url() throws Exception {
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("Sorry, can't load the asset from 'http://google.com/less/index.less' using the 'file' protocol");

new PathToAsset(new URL("http://google.com"), "less/index.less");
}

// --

private String absolute(PathToAsset path) {
return path.toFile().getAbsolutePath();
}

private URL baseResourceUrlGivenByJenkins(String path) throws MalformedURLException {
return new URL("file://" + path);
// a pass-through method, only here for readability purposes
private URL baseResourceUrlGivenByJenkins(String url) throws MalformedURLException {
return new URL(url);
}
}

0 comments on commit 22c6ca4

Please sign in to comment.
You can’t perform that action at this time.