diff --git a/common/src/main/java/org/treblereel/j2cl/processors/common/resources/ClientBundle.java b/common/src/main/java/org/treblereel/j2cl/processors/common/resources/ClientBundle.java index 79ef36d..27ee797 100644 --- a/common/src/main/java/org/treblereel/j2cl/processors/common/resources/ClientBundle.java +++ b/common/src/main/java/org/treblereel/j2cl/processors/common/resources/ClientBundle.java @@ -60,5 +60,7 @@ public interface ClientBundle { String path(); String copyTo() default ""; + + boolean unzip() default false; } } diff --git a/processor/src/main/java/org/treblereel/j2cl/processors/generator/resources/MavenArtifact.java b/processor/src/main/java/org/treblereel/j2cl/processors/generator/resources/MavenArtifact.java index 3f40d00..ff6c5ae 100644 --- a/processor/src/main/java/org/treblereel/j2cl/processors/generator/resources/MavenArtifact.java +++ b/processor/src/main/java/org/treblereel/j2cl/processors/generator/resources/MavenArtifact.java @@ -86,8 +86,8 @@ public String getRepositoryUrl() { return repositoryUrl; } - void copyResourceTo(String path, FileObject dst) { - mavenArtifactDownloader.copyResourceTo(path, dst); + void copyResourceTo(String path, FileObject dst, boolean unzip) { + mavenArtifactDownloader.copyResourceTo(path, dst, unzip); } @Override diff --git a/processor/src/main/java/org/treblereel/j2cl/processors/generator/resources/MavenArtifactDownloader.java b/processor/src/main/java/org/treblereel/j2cl/processors/generator/resources/MavenArtifactDownloader.java index fa7e2f9..14cbf29 100644 --- a/processor/src/main/java/org/treblereel/j2cl/processors/generator/resources/MavenArtifactDownloader.java +++ b/processor/src/main/java/org/treblereel/j2cl/processors/generator/resources/MavenArtifactDownloader.java @@ -19,9 +19,13 @@ import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; +import java.io.IOException; +import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStreamWriter; +import java.io.PushbackInputStream; import java.util.Collections; +import java.util.zip.GZIPInputStream; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import javax.tools.FileObject; @@ -58,19 +62,26 @@ class MavenArtifactDownloader { this.mavenArtifact = mavenArtifact; } - public void copyResourceTo(String path, FileObject dst) { + void copyResourceTo(String path, FileObject dst, boolean unzip) { if (artifact == null) { download(); } try (ZipFile zipFile = new ZipFile(artifact.getFile())) { ZipEntry entry = zipFile.getEntry(path); if (entry != null) { + if (unzip && !checkIfZip(zipFile.getInputStream(entry))) { + throw new GenerationException("Resource with a path " + path + " isn't a GZIP"); + } try (BufferedReader reader = - new BufferedReader(new InputStreamReader(zipFile.getInputStream(entry))); + new BufferedReader( + new InputStreamReader( + unzip + ? new GZIPInputStream(zipFile.getInputStream(entry)) + : zipFile.getInputStream(entry))); BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(dst.openOutputStream()))) { - char[] buffer = new char[1024]; // a buffer to hold chunks of characters + char[] buffer = new char[1024]; int charsRead; while ((charsRead = reader.read(buffer)) != -1) { bufferedWriter.write(buffer, 0, charsRead); @@ -85,6 +96,21 @@ public void copyResourceTo(String path, FileObject dst) { } } + private boolean checkIfZip(InputStream inputStream) { + if (!(inputStream instanceof PushbackInputStream)) { + inputStream = new PushbackInputStream(inputStream, 2); + } + + byte[] signature = new byte[2]; + try { + int bytesRead = inputStream.read(signature); + ((PushbackInputStream) inputStream).unread(signature, 0, bytesRead); + return bytesRead == 2 && signature[0] == (byte) 0x1f && signature[1] == (byte) 0x8b; + } catch (IOException e) { + throw new GenerationException(e); + } + } + private void download() { RepositorySystem system = newRepositorySystem(); RepositorySystemSession session = newSession(system); diff --git a/processor/src/main/java/org/treblereel/j2cl/processors/generator/resources/MavenArtifactSourceProcessor.java b/processor/src/main/java/org/treblereel/j2cl/processors/generator/resources/MavenArtifactSourceProcessor.java index 9df82e5..7a9232e 100644 --- a/processor/src/main/java/org/treblereel/j2cl/processors/generator/resources/MavenArtifactSourceProcessor.java +++ b/processor/src/main/java/org/treblereel/j2cl/processors/generator/resources/MavenArtifactSourceProcessor.java @@ -17,13 +17,8 @@ package org.treblereel.j2cl.processors.generator.resources; import com.google.common.io.Files; -import java.io.BufferedReader; -import java.io.BufferedWriter; import java.io.File; import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.OutputStreamWriter; import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -103,8 +98,7 @@ private void copyResources(Map> mavenArtif StandardLocation.CLASS_OUTPUT, "", // no package copyTo); - mavenArtifactSetEntry.getKey().copyResourceTo(path, resource); - // copy(is, os); + mavenArtifactSetEntry.getKey().copyResourceTo(path, resource, artifactSource.unzip()); } catch (IOException e) { throw new RuntimeException(e); } @@ -120,7 +114,7 @@ private void checkPath(String path, String type, ExecutableElement method) { if (!pattern.matcher(pkg).matches()) { throw new GenerationException( - "Wring " + type + " at " + method.getEnclosingElement() + "." + method.getSimpleName()); + "Wrong " + type + " at " + method.getEnclosingElement() + "." + method.getSimpleName()); } } @@ -145,18 +139,4 @@ private void delete(File dir) { } } } - - public void copy(InputStreamReader reader, OutputStream outStream) throws IOException { - try (BufferedReader bufferedReader = new BufferedReader(reader); - BufferedWriter bufferedWriter = - new BufferedWriter(new OutputStreamWriter(outStream, reader.getEncoding()))) { - - char[] buffer = new char[1024]; // a buffer to hold chunks of characters - int charsRead; - while ((charsRead = bufferedReader.read(buffer)) != -1) { - bufferedWriter.write(buffer, 0, charsRead); - } - bufferedWriter.flush(); - } - } } diff --git a/tests/resources/src/test/java/org/treblereel/j2cl/processors/test/TextResourcesTest.java b/tests/resources/src/test/java/org/treblereel/j2cl/processors/test/TextResourcesTest.java index 7a3bceb..67c538f 100644 --- a/tests/resources/src/test/java/org/treblereel/j2cl/processors/test/TextResourcesTest.java +++ b/tests/resources/src/test/java/org/treblereel/j2cl/processors/test/TextResourcesTest.java @@ -104,4 +104,10 @@ public void testExternalResourceWebJarRename() { String content = readFileAsString("original_support.js"); assertEquals(content, TextTestResourceImpl.INSTANCE.externalResourceWebJarRename().getText()); } + + @Test + public void testExternalResourceWebJarGZIP() { + String content = readFileAsString("bootstrap.min.js.back"); + assertEquals(content, TextTestResourceImpl.INSTANCE.externalResourceWebJarGZIP().getText()); + } } diff --git a/tests/resources/src/test/java/org/treblereel/j2cl/processors/test/TextTestResource.java b/tests/resources/src/test/java/org/treblereel/j2cl/processors/test/TextTestResource.java index 0b27d8e..dafd63a 100644 --- a/tests/resources/src/test/java/org/treblereel/j2cl/processors/test/TextTestResource.java +++ b/tests/resources/src/test/java/org/treblereel/j2cl/processors/test/TextTestResource.java @@ -77,4 +77,13 @@ interface TextTestResource extends ClientBundle { path = "META-INF/resources/webjars/jquery/3.7.1/src/css/support.js", copyTo = "org/test/support-old.js.back") TextResource externalResourceWebJarRenameDashInFile(); + + @MavenArtifactSource( + group = "org.webjars", + artifact = "bootstrap", + version = "3.4.1", + path = "META-INF/resources/webjars/bootstrap/3.4.1/js/bootstrap.min.js.gz", + copyTo = "org/test/bootstrap.min.js.back", + unzip = true) + TextResource externalResourceWebJarGZIP(); } diff --git a/tests/resources/src/test/java/org/treblereel/j2cl/processors/test/bootstrap.min.js.back b/tests/resources/src/test/java/org/treblereel/j2cl/processors/test/bootstrap.min.js.back new file mode 100644 index 0000000..eb0a8b4 --- /dev/null +++ b/tests/resources/src/test/java/org/treblereel/j2cl/processors/test/bootstrap.min.js.back @@ -0,0 +1,6 @@ +/*! + * Bootstrap v3.4.1 (https://getbootstrap.com/) + * Copyright 2011-2019 Twitter, Inc. + * Licensed under the MIT license + */ +if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");!function(t){"use strict";var e=jQuery.fn.jquery.split(" ")[0].split(".");if(e[0]<2&&e[1]<9||1==e[0]&&9==e[1]&&e[2]<1||3this.$items.length-1||t<0))return this.sliding?this.$element.one("slid.bs.carousel",function(){e.to(t)}):i==t?this.pause().cycle():this.slide(idocument.documentElement.clientHeight;this.$element.css({paddingLeft:!this.bodyIsOverflowing&&t?this.scrollbarWidth:"",paddingRight:this.bodyIsOverflowing&&!t?this.scrollbarWidth:""})},s.prototype.resetAdjustments=function(){this.$element.css({paddingLeft:"",paddingRight:""})},s.prototype.checkScrollbar=function(){var t=window.innerWidth;if(!t){var e=document.documentElement.getBoundingClientRect();t=e.right-Math.abs(e.left)}this.bodyIsOverflowing=document.body.clientWidth
',trigger:"hover focus",title:"",delay:0,html:!1,container:!1,viewport:{selector:"body",padding:0},sanitize:!0,sanitizeFn:null,whiteList:t},m.prototype.init=function(t,e,i){if(this.enabled=!0,this.type=t,this.$element=g(e),this.options=this.getOptions(i),this.$viewport=this.options.viewport&&g(document).find(g.isFunction(this.options.viewport)?this.options.viewport.call(this,this.$element):this.options.viewport.selector||this.options.viewport),this.inState={click:!1,hover:!1,focus:!1},this.$element[0]instanceof document.constructor&&!this.options.selector)throw new Error("`selector` option must be specified when initializing "+this.type+" on the window.document object!");for(var o=this.options.trigger.split(" "),n=o.length;n--;){var s=o[n];if("click"==s)this.$element.on("click."+this.type,this.options.selector,g.proxy(this.toggle,this));else if("manual"!=s){var a="hover"==s?"mouseenter":"focusin",r="hover"==s?"mouseleave":"focusout";this.$element.on(a+"."+this.type,this.options.selector,g.proxy(this.enter,this)),this.$element.on(r+"."+this.type,this.options.selector,g.proxy(this.leave,this))}}this.options.selector?this._options=g.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},m.prototype.getDefaults=function(){return m.DEFAULTS},m.prototype.getOptions=function(t){var e=this.$element.data();for(var i in e)e.hasOwnProperty(i)&&-1!==g.inArray(i,o)&&delete e[i];return(t=g.extend({},this.getDefaults(),e,t)).delay&&"number"==typeof t.delay&&(t.delay={show:t.delay,hide:t.delay}),t.sanitize&&(t.template=n(t.template,t.whiteList,t.sanitizeFn)),t},m.prototype.getDelegateOptions=function(){var i={},o=this.getDefaults();return this._options&&g.each(this._options,function(t,e){o[t]!=e&&(i[t]=e)}),i},m.prototype.enter=function(t){var e=t instanceof this.constructor?t:g(t.currentTarget).data("bs."+this.type);if(e||(e=new this.constructor(t.currentTarget,this.getDelegateOptions()),g(t.currentTarget).data("bs."+this.type,e)),t instanceof g.Event&&(e.inState["focusin"==t.type?"focus":"hover"]=!0),e.tip().hasClass("in")||"in"==e.hoverState)e.hoverState="in";else{if(clearTimeout(e.timeout),e.hoverState="in",!e.options.delay||!e.options.delay.show)return e.show();e.timeout=setTimeout(function(){"in"==e.hoverState&&e.show()},e.options.delay.show)}},m.prototype.isInStateTrue=function(){for(var t in this.inState)if(this.inState[t])return!0;return!1},m.prototype.leave=function(t){var e=t instanceof this.constructor?t:g(t.currentTarget).data("bs."+this.type);if(e||(e=new this.constructor(t.currentTarget,this.getDelegateOptions()),g(t.currentTarget).data("bs."+this.type,e)),t instanceof g.Event&&(e.inState["focusout"==t.type?"focus":"hover"]=!1),!e.isInStateTrue()){if(clearTimeout(e.timeout),e.hoverState="out",!e.options.delay||!e.options.delay.hide)return e.hide();e.timeout=setTimeout(function(){"out"==e.hoverState&&e.hide()},e.options.delay.hide)}},m.prototype.show=function(){var t=g.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(t);var e=g.contains(this.$element[0].ownerDocument.documentElement,this.$element[0]);if(t.isDefaultPrevented()||!e)return;var i=this,o=this.tip(),n=this.getUID(this.type);this.setContent(),o.attr("id",n),this.$element.attr("aria-describedby",n),this.options.animation&&o.addClass("fade");var s="function"==typeof this.options.placement?this.options.placement.call(this,o[0],this.$element[0]):this.options.placement,a=/\s?auto?\s?/i,r=a.test(s);r&&(s=s.replace(a,"")||"top"),o.detach().css({top:0,left:0,display:"block"}).addClass(s).data("bs."+this.type,this),this.options.container?o.appendTo(g(document).find(this.options.container)):o.insertAfter(this.$element),this.$element.trigger("inserted.bs."+this.type);var l=this.getPosition(),h=o[0].offsetWidth,d=o[0].offsetHeight;if(r){var p=s,c=this.getPosition(this.$viewport);s="bottom"==s&&l.bottom+d>c.bottom?"top":"top"==s&&l.top-dc.width?"left":"left"==s&&l.left-ha.top+a.height&&(n.top=a.top+a.height-l)}else{var h=e.left-s,d=e.left+s+i;ha.right&&(n.left=a.left+a.width-d)}return n},m.prototype.getTitle=function(){var t=this.$element,e=this.options;return t.attr("data-original-title")||("function"==typeof e.title?e.title.call(t[0]):e.title)},m.prototype.getUID=function(t){for(;t+=~~(1e6*Math.random()),document.getElementById(t););return t},m.prototype.tip=function(){if(!this.$tip&&(this.$tip=g(this.options.template),1!=this.$tip.length))throw new Error(this.type+" `template` option must consist of exactly 1 top-level element!");return this.$tip},m.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},m.prototype.enable=function(){this.enabled=!0},m.prototype.disable=function(){this.enabled=!1},m.prototype.toggleEnabled=function(){this.enabled=!this.enabled},m.prototype.toggle=function(t){var e=this;t&&((e=g(t.currentTarget).data("bs."+this.type))||(e=new this.constructor(t.currentTarget,this.getDelegateOptions()),g(t.currentTarget).data("bs."+this.type,e))),t?(e.inState.click=!e.inState.click,e.isInStateTrue()?e.enter(e):e.leave(e)):e.tip().hasClass("in")?e.leave(e):e.enter(e)},m.prototype.destroy=function(){var t=this;clearTimeout(this.timeout),this.hide(function(){t.$element.off("."+t.type).removeData("bs."+t.type),t.$tip&&t.$tip.detach(),t.$tip=null,t.$arrow=null,t.$viewport=null,t.$element=null})},m.prototype.sanitizeHtml=function(t){return n(t,this.options.whiteList,this.options.sanitizeFn)};var e=g.fn.tooltip;g.fn.tooltip=function i(o){return this.each(function(){var t=g(this),e=t.data("bs.tooltip"),i="object"==typeof o&&o;!e&&/destroy|hide/.test(o)||(e||t.data("bs.tooltip",e=new m(this,i)),"string"==typeof o&&e[o]())})},g.fn.tooltip.Constructor=m,g.fn.tooltip.noConflict=function(){return g.fn.tooltip=e,this}}(jQuery),function(n){"use strict";var s=function(t,e){this.init("popover",t,e)};if(!n.fn.tooltip)throw new Error("Popover requires tooltip.js");s.VERSION="3.4.1",s.DEFAULTS=n.extend({},n.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:''}),((s.prototype=n.extend({},n.fn.tooltip.Constructor.prototype)).constructor=s).prototype.getDefaults=function(){return s.DEFAULTS},s.prototype.setContent=function(){var t=this.tip(),e=this.getTitle(),i=this.getContent();if(this.options.html){var o=typeof i;this.options.sanitize&&(e=this.sanitizeHtml(e),"string"===o&&(i=this.sanitizeHtml(i))),t.find(".popover-title").html(e),t.find(".popover-content").children().detach().end()["string"===o?"html":"append"](i)}else t.find(".popover-title").text(e),t.find(".popover-content").children().detach().end().text(i);t.removeClass("fade top bottom left right in"),t.find(".popover-title").html()||t.find(".popover-title").hide()},s.prototype.hasContent=function(){return this.getTitle()||this.getContent()},s.prototype.getContent=function(){var t=this.$element,e=this.options;return t.attr("data-content")||("function"==typeof e.content?e.content.call(t[0]):e.content)},s.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")};var t=n.fn.popover;n.fn.popover=function e(o){return this.each(function(){var t=n(this),e=t.data("bs.popover"),i="object"==typeof o&&o;!e&&/destroy|hide/.test(o)||(e||t.data("bs.popover",e=new s(this,i)),"string"==typeof o&&e[o]())})},n.fn.popover.Constructor=s,n.fn.popover.noConflict=function(){return n.fn.popover=t,this}}(jQuery),function(s){"use strict";function n(t,e){this.$body=s(document.body),this.$scrollElement=s(t).is(document.body)?s(window):s(t),this.options=s.extend({},n.DEFAULTS,e),this.selector=(this.options.target||"")+" .nav li > a",this.offsets=[],this.targets=[],this.activeTarget=null,this.scrollHeight=0,this.$scrollElement.on("scroll.bs.scrollspy",s.proxy(this.process,this)),this.refresh(),this.process()}function e(o){return this.each(function(){var t=s(this),e=t.data("bs.scrollspy"),i="object"==typeof o&&o;e||t.data("bs.scrollspy",e=new n(this,i)),"string"==typeof o&&e[o]()})}n.VERSION="3.4.1",n.DEFAULTS={offset:10},n.prototype.getScrollHeight=function(){return this.$scrollElement[0].scrollHeight||Math.max(this.$body[0].scrollHeight,document.documentElement.scrollHeight)},n.prototype.refresh=function(){var t=this,o="offset",n=0;this.offsets=[],this.targets=[],this.scrollHeight=this.getScrollHeight(),s.isWindow(this.$scrollElement[0])||(o="position",n=this.$scrollElement.scrollTop()),this.$body.find(this.selector).map(function(){var t=s(this),e=t.data("target")||t.attr("href"),i=/^#./.test(e)&&s(e);return i&&i.length&&i.is(":visible")&&[[i[o]().top+n,e]]||null}).sort(function(t,e){return t[0]-e[0]}).each(function(){t.offsets.push(this[0]),t.targets.push(this[1])})},n.prototype.process=function(){var t,e=this.$scrollElement.scrollTop()+this.options.offset,i=this.getScrollHeight(),o=this.options.offset+i-this.$scrollElement.height(),n=this.offsets,s=this.targets,a=this.activeTarget;if(this.scrollHeight!=i&&this.refresh(),o<=e)return a!=(t=s[s.length-1])&&this.activate(t);if(a&&e=n[t]&&(n[t+1]===undefined||e .active"),n=i&&r.support.transition&&(o.length&&o.hasClass("fade")||!!e.find("> .fade").length);function s(){o.removeClass("active").find("> .dropdown-menu > .active").removeClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!1),t.addClass("active").find('[data-toggle="tab"]').attr("aria-expanded",!0),n?(t[0].offsetWidth,t.addClass("in")):t.removeClass("fade"),t.parent(".dropdown-menu").length&&t.closest("li.dropdown").addClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!0),i&&i()}o.length&&n?o.one("bsTransitionEnd",s).emulateTransitionEnd(a.TRANSITION_DURATION):s(),o.removeClass("in")};var t=r.fn.tab;r.fn.tab=e,r.fn.tab.Constructor=a,r.fn.tab.noConflict=function(){return r.fn.tab=t,this};var i=function(t){t.preventDefault(),e.call(r(this),"show")};r(document).on("click.bs.tab.data-api",'[data-toggle="tab"]',i).on("click.bs.tab.data-api",'[data-toggle="pill"]',i)}(jQuery),function(l){"use strict";var h=function(t,e){this.options=l.extend({},h.DEFAULTS,e);var i=this.options.target===h.DEFAULTS.target?l(this.options.target):l(document).find(this.options.target);this.$target=i.on("scroll.bs.affix.data-api",l.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",l.proxy(this.checkPositionWithEventLoop,this)),this.$element=l(t),this.affixed=null,this.unpin=null,this.pinnedOffset=null,this.checkPosition()};function i(o){return this.each(function(){var t=l(this),e=t.data("bs.affix"),i="object"==typeof o&&o;e||t.data("bs.affix",e=new h(this,i)),"string"==typeof o&&e[o]()})}h.VERSION="3.4.1",h.RESET="affix affix-top affix-bottom",h.DEFAULTS={offset:0,target:window},h.prototype.getState=function(t,e,i,o){var n=this.$target.scrollTop(),s=this.$element.offset(),a=this.$target.height();if(null!=i&&"top"==this.affixed)return n