001// Copyright 2013-2014 The Apache Software Foundation 002// 003// Licensed under the Apache License, Version 2.0 (the "License"); 004// you may not use this file except in compliance with the License. 005// You may obtain a copy of the License at 006// 007// http://www.apache.org/licenses/LICENSE-2.0 008// 009// Unless required by applicable law or agreed to in writing, software 010// distributed under the License is distributed on an "AS IS" BASIS, 011// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 012// See the License for the specific language governing permissions and 013// limitations under the License. 014 015package org.apache.tapestry5.internal.webresources; 016 017import org.apache.commons.io.IOUtils; 018import org.apache.tapestry5.annotations.Path; 019import org.apache.tapestry5.ioc.OperationTracker; 020import org.apache.tapestry5.ioc.Resource; 021import org.apache.tapestry5.ioc.internal.util.CollectionFactory; 022import org.apache.tapestry5.ioc.internal.util.InternalUtils; 023import org.apache.tapestry5.services.assets.ResourceDependencies; 024import org.apache.tapestry5.services.assets.ResourceTransformer; 025import org.mozilla.javascript.NativeObject; 026 027import java.io.IOException; 028import java.io.InputStream; 029import java.nio.charset.Charset; 030import java.util.List; 031 032public class CoffeeScriptCompiler implements ResourceTransformer 033{ 034 private final static Charset UTF8 = Charset.forName("utf-8"); 035 036 private final RhinoExecutorPool executorPool; 037 038 public String getTransformedContentType() 039 { 040 return "text/javascript"; 041 } 042 043 public CoffeeScriptCompiler(@Path("classpath:org/apache/tapestry5/webresources/internal/coffee-script.js") 044 Resource mainCompiler, 045 @Path("classpath:org/apache/tapestry5/webresources/internal/invoke-coffeescript.js") 046 Resource shim, 047 OperationTracker tracker) 048 { 049 050 executorPool = new RhinoExecutorPool(tracker, toList(mainCompiler, shim)); 051 } 052 053 private List<Resource> toList(Resource... resources) 054 { 055 List<Resource> list = CollectionFactory.newList(); 056 057 for (Resource r : resources) 058 { 059 list.add(r); 060 } 061 062 return list; 063 } 064 065 066 private String getString(NativeObject object, String key) 067 { 068 return object.get(key).toString(); 069 } 070 071 072 public InputStream transform(Resource source, ResourceDependencies dependencies) throws IOException 073 { 074 InputStream is = null; 075 String content; 076 077 try 078 { 079 is = source.openStream(); 080 content = IOUtils.toString(is, UTF8); 081 } finally 082 { 083 InternalUtils.close(is); 084 } 085 086 RhinoExecutor executor = executorPool.get(); 087 088 try 089 { 090 091 NativeObject result = (NativeObject) executor.invokeFunction("compileCoffeeScriptSource", content, source.toString()); 092 093 if (result.containsKey("exception")) 094 { 095 throw new RuntimeException(getString(result, "exception")); 096 } 097 098 return IOUtils.toInputStream(getString(result, "output"), UTF8); 099 100 } finally 101 { 102 executor.discard(); 103 } 104 105 106 } 107}