1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * This library is free software; you can redistribute it and/or modify it under
5    * the terms of the GNU Lesser General Public License as published by the Free
6    * Software Foundation; either version 2.1 of the License, or (at your option)
7    * any later version.
8    *
9    * This library is distributed in the hope that it will be useful, but WITHOUT
10   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11   * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12   * details.
13   */
14  
15  package com.liferay.portal.servlet;
16  
17  import com.liferay.portal.kernel.cache.key.CacheKeyGenerator;
18  import com.liferay.portal.kernel.cache.key.CacheKeyGeneratorUtil;
19  import com.liferay.portal.kernel.nio.charset.CharsetEncoderUtil;
20  import com.liferay.portal.kernel.servlet.ServletContextUtil;
21  import com.liferay.portal.kernel.util.ContentTypes;
22  import com.liferay.portal.kernel.util.FileUtil;
23  import com.liferay.portal.kernel.util.ParamUtil;
24  import com.liferay.portal.kernel.util.StringBundler;
25  import com.liferay.portal.kernel.util.StringPool;
26  import com.liferay.portal.kernel.util.StringUtil;
27  import com.liferay.portal.kernel.util.Validator;
28  import com.liferay.portal.util.MinifierUtil;
29  import com.liferay.util.SystemProperties;
30  import com.liferay.util.servlet.ServletResponseUtil;
31  
32  import java.io.File;
33  import java.io.IOException;
34  
35  import java.nio.ByteBuffer;
36  
37  import java.util.Enumeration;
38  import java.util.Map;
39  
40  import javax.servlet.ServletContext;
41  import javax.servlet.http.HttpServlet;
42  import javax.servlet.http.HttpServletRequest;
43  import javax.servlet.http.HttpServletResponse;
44  
45  /**
46   * <a href="ComboServlet.java.html"><b><i>View Source</i></b></a>
47   *
48   * @author Eduardo Lundgren
49   */
50  public class ComboServlet extends HttpServlet {
51  
52      public void service(
53              HttpServletRequest request, HttpServletResponse response)
54          throws IOException {
55  
56          Map<String, String[]> parameterMap = request.getParameterMap();
57  
58          if (parameterMap.size() == 0) {
59              response.sendError(HttpServletResponse.SC_BAD_REQUEST);
60  
61              return;
62          }
63  
64          byte[] bytes = null;
65          int length = 0;
66  
67          File cacheFile = getCacheFile(request);
68  
69          if (cacheFile.exists()) {
70              bytes = FileUtil.getBytes(cacheFile);
71              length = bytes.length;
72          }
73          else {
74              StringBundler sb = new StringBundler(parameterMap.size());
75  
76              for (String modulePath : parameterMap.keySet()) {
77                  File file = getFile(modulePath);
78  
79                  if (file != null) {
80                      String moduleContent = FileUtil.read(file);
81  
82                      sb.append(moduleContent);
83                  }
84              }
85  
86              String content = sb.toString();
87  
88              if (Validator.isNotNull(content)) {
89                  String minifierType = ParamUtil.getString(
90                      request, "minifierType");
91  
92                  if (minifierType.equals("css")) {
93                      content = MinifierUtil.minifyCss(content);
94                  }
95                  else if (minifierType.equals("js")) {
96                      content = MinifierUtil.minifyJavaScript(content);
97                  }
98  
99                  ByteBuffer contentByteBuffer = CharsetEncoderUtil.encode(
100                     StringPool.UTF8, content);
101 
102                 bytes = contentByteBuffer.array();
103                 length = contentByteBuffer.limit();
104 
105                 FileUtil.write(cacheFile, bytes, 0, length);
106             }
107             else {
108                 bytes = new byte[0];
109             }
110         }
111 
112         String contentType = ContentTypes.TEXT_JAVASCRIPT;
113 
114         String firstModulePath =
115             (String)request.getParameterNames().nextElement();
116 
117         String extension = FileUtil.getExtension(firstModulePath);
118 
119         if (extension.equalsIgnoreCase(_CSS_EXTENSION)) {
120             contentType = ContentTypes.TEXT_CSS;
121         }
122 
123         response.setContentType(contentType);
124 
125         ServletResponseUtil.write(response, bytes, length);
126     }
127 
128     protected File getCacheFile(HttpServletRequest request) throws IOException {
129         StringBundler sb = new StringBundler(5);
130 
131         sb.append(request.getRequestURI());
132 
133         String queryString = request.getQueryString();
134 
135         if (queryString != null) {
136             sb.append(StringPool.QUESTION);
137             sb.append(queryString);
138         }
139 
140         long lastModified = 0;
141 
142         Enumeration<String> enu = request.getParameterNames();
143 
144         while (enu.hasMoreElements()) {
145             String modulePath = enu.nextElement();
146 
147             File file = getFile(modulePath);
148 
149             if (file != null) {
150                 lastModified += file.lastModified();
151             }
152         }
153 
154         if (lastModified > 0) {
155             sb.append(StringPool.AMPERSAND);
156             sb.append(lastModified);
157         }
158 
159         CacheKeyGenerator cacheKeyGenerator =
160             CacheKeyGeneratorUtil.getCacheKeyGenerator(
161                 ComboServlet.class.getName());
162 
163         String cacheFileName = _TEMP_DIR.concat(
164             cacheKeyGenerator.getCacheKey(sb));
165 
166         return new File(cacheFileName);
167     }
168 
169     protected File getFile(String path) throws IOException {
170         ServletContext servletContext = getServletContext();
171 
172         String basePath = ServletContextUtil.getRealPath(
173             servletContext, _JAVASCRIPT_DIR);
174 
175         if (basePath == null) {
176             return null;
177         }
178 
179         basePath = StringUtil.replace(
180             basePath, StringPool.BACK_SLASH, StringPool.SLASH);
181 
182         File baseDir = new File(basePath);
183 
184         if (!baseDir.exists()) {
185             return null;
186         }
187 
188         String filePath = ServletContextUtil.getRealPath(servletContext, path);
189 
190         if (filePath == null) {
191             return null;
192         }
193 
194         filePath = StringUtil.replace(
195             filePath, StringPool.BACK_SLASH, StringPool.SLASH);
196 
197         File file = new File(filePath);
198 
199         if (!file.exists()) {
200             return null;
201         }
202 
203         String baseCanonicalPath = baseDir.getCanonicalPath();
204         String fileCanonicalPath = file.getCanonicalPath();
205 
206         if (fileCanonicalPath.indexOf(baseCanonicalPath) == 0) {
207             return file;
208         }
209 
210         return null;
211     }
212 
213     private static final String _CSS_EXTENSION = "css";
214 
215     private static final String _JAVASCRIPT_DIR = "html/js";
216 
217     private static final String _TEMP_DIR =
218         SystemProperties.get(SystemProperties.TMP_DIR) + "/liferay/combo/";
219 
220 }