001/* 002 * Copyright 2018 Anyware Services 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.ametys.core.minimize.js; 017 018import java.io.ByteArrayOutputStream; 019import java.io.IOException; 020import java.io.OutputStream; 021import java.io.Serializable; 022import java.nio.charset.StandardCharsets; 023import java.util.Map; 024 025import org.apache.avalon.framework.parameters.Parameters; 026import org.apache.avalon.framework.service.ServiceException; 027import org.apache.avalon.framework.service.ServiceManager; 028import org.apache.cocoon.ProcessingException; 029import org.apache.cocoon.environment.ObjectModelHelper; 030import org.apache.excalibur.source.Source; 031import org.apache.excalibur.source.SourceException; 032 033import org.ametys.core.DevMode; 034import org.ametys.core.DevMode.DEVMODE; 035import org.ametys.core.resources.JSResourceHandler; 036 037/** 038 * Resource handler for minimized javascript file 039 */ 040public class MinimizedJSResourceHandler extends JSResourceHandler 041{ 042 /** JS minimize manager */ 043 protected MinimizeJSManager _jSMinimizeManager; 044 045 private String _realFileUri; 046 047 @Override 048 public void service(ServiceManager manager) throws ServiceException 049 { 050 super.service(manager); 051 _jSMinimizeManager = (MinimizeJSManager) manager.lookup(MinimizeJSManager.ROLE); 052 } 053 054 @Override 055 public Source setup(String location, Map objectModel, Parameters par, boolean readForDownload) throws IOException, ProcessingException 056 { 057 _requestedLocation = location; 058 _objectModel = objectModel; 059 060 // Cached 061 _setExpiresToNoCache = false; 062 063 Source source = null; 064 try 065 { 066 source = _resolver.resolveURI(location); 067 } 068 catch (SourceException e) 069 { 070 // Nothing 071 } 072 073 if (source == null || !source.exists()) 074 { 075 // If the file does not exists at the original location, but it is a .min.js file, retrieve the .js file instead to process it 076 _resolver.release(source); 077 078 String realLocation = location.substring(0, location.length() - ".min.js".length()) + ".js"; 079 source = super.setup(realLocation, objectModel, par, readForDownload); 080 081 // The .js location 082 _realFileUri = realLocation; 083 } 084 085 _source = source; 086 return _source; 087 } 088 089 @Override 090 public Serializable getKey() 091 { 092 Serializable key = super.getKey(); 093 return key + "*" + _requestedLocation; 094 } 095 096 @Override 097 public void generate(OutputStream out) throws IOException, ProcessingException 098 { 099 if (_realFileUri == null) 100 { 101 _jSMinimizeManager.validateAndOutputMinimizedFile(_source, out, _requestedLocation); 102 return; 103 } 104 105 // Retrieve the .js file and minimize it to serve a .min.js generated on the fly 106 try (ByteArrayOutputStream bos = new ByteArrayOutputStream()) 107 { 108 super.generate(bos); 109 110 String code = bos.toString("UTF-8"); 111 String locale = getLocale(); 112 113 // when lazy loading the source map, wait for the .map to be directly called to generate it 114 boolean lazyLoadSourceMap = DEVMODE.PRODUCTION.equals(DevMode.getDeveloperMode(ObjectModelHelper.getRequest(_objectModel))); 115 String result; 116 if (lazyLoadSourceMap) 117 { 118 result = _jSMinimizeManager.minimizeJS(code, _realFileUri); 119 } 120 else 121 { 122 result = _jSMinimizeManager.minimizeJS(code, _realFileUri, _realFileUri + ".map" + (locale != null ? "#" + locale : ""), _source.getLastModified()); 123 } 124 125 out.write(result.getBytes(StandardCharsets.UTF_8)); 126 } 127 } 128}