001    /**
002     * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.tools;
016    
017    import com.liferay.portal.kernel.util.FastDateFormatFactoryUtil;
018    import com.liferay.portal.kernel.util.FileUtil;
019    import com.liferay.portal.kernel.util.PortalClassLoaderUtil;
020    import com.liferay.portal.kernel.util.PropsUtil;
021    import com.liferay.portal.kernel.util.StringPool;
022    import com.liferay.portal.kernel.util.StringUtil;
023    import com.liferay.portal.kernel.util.Validator;
024    import com.liferay.portal.model.ModelHintsConstants;
025    import com.liferay.portal.servlet.filters.dynamiccss.RTLCSSUtil;
026    import com.liferay.portal.tools.sass.SassExecutorUtil;
027    import com.liferay.portal.util.FastDateFormatFactoryImpl;
028    import com.liferay.portal.util.FileImpl;
029    import com.liferay.portal.util.PortalImpl;
030    import com.liferay.portal.util.PortalUtil;
031    import com.liferay.portal.util.PropsImpl;
032    
033    import java.io.File;
034    
035    import java.util.ArrayList;
036    import java.util.List;
037    import java.util.Map;
038    
039    import org.apache.tools.ant.DirectoryScanner;
040    
041    /**
042     * @author Brian Wing Shun Chan
043     * @author Raymond Aug??
044     * @author Eduardo Lundgren
045     * @author Shuyang Zhou
046     */
047    public class SassToCssBuilder {
048    
049            public static File getCacheFile(String fileName) {
050                    return getCacheFile(fileName, StringPool.BLANK);
051            }
052    
053            public static File getCacheFile(String fileName, String suffix) {
054                    return new File(getCacheFileName(fileName, suffix));
055            }
056    
057            public static String getCacheFileName(String fileName, String suffix) {
058                    String cacheFileName = StringUtil.replace(
059                            fileName, StringPool.BACK_SLASH, StringPool.SLASH);
060    
061                    int x = cacheFileName.lastIndexOf(StringPool.SLASH);
062                    int y = cacheFileName.lastIndexOf(StringPool.PERIOD);
063    
064                    return cacheFileName.substring(0, x + 1) + ".sass-cache/" +
065                            cacheFileName.substring(x + 1, y) + suffix +
066                                    cacheFileName.substring(y);
067            }
068    
069            public static String getRtlCustomFileName(String fileName) {
070                    int pos = fileName.lastIndexOf(StringPool.PERIOD);
071    
072                    return fileName.substring(0, pos) + "_rtl" + fileName.substring(pos);
073            }
074    
075            public static void main(String[] args) throws Exception {
076                    Map<String, String> arguments = ArgumentsUtil.parseArguments(args);
077    
078                    List<String> dirNames = new ArrayList<String>();
079    
080                    String dirName = arguments.get("sass.dir");
081    
082                    if (Validator.isNotNull(dirName)) {
083                            dirNames.add(dirName);
084                    }
085                    else {
086                            for (int i = 0;; i++ ) {
087                                    dirName = arguments.get("sass.dir." + i);
088    
089                                    if (Validator.isNotNull(dirName)) {
090                                            dirNames.add(dirName);
091                                    }
092                                    else {
093                                            break;
094                                    }
095                            }
096                    }
097    
098                    String docrootDirName = arguments.get("sass.docroot.dir");
099                    String portalCommonDirName = arguments.get("sass.portal.common.dir");
100    
101                    new SassToCssBuilder(dirNames, docrootDirName, portalCommonDirName);
102            }
103    
104            public static String parseStaticTokens(String content) {
105                    return StringUtil.replace(
106                            content,
107                            new String[] {
108                                    "@model_hints_constants_text_display_height@",
109                                    "@model_hints_constants_text_display_width@",
110                                    "@model_hints_constants_textarea_display_height@",
111                                    "@model_hints_constants_textarea_display_width@"
112                            },
113                            new String[] {
114                                    ModelHintsConstants.TEXT_DISPLAY_HEIGHT,
115                                    ModelHintsConstants.TEXT_DISPLAY_WIDTH,
116                                    ModelHintsConstants.TEXTAREA_DISPLAY_HEIGHT,
117                                    ModelHintsConstants.TEXTAREA_DISPLAY_WIDTH
118                            });
119            }
120    
121            public SassToCssBuilder(
122                            List<String> dirNames, String docrootDirName,
123                            String portalCommonDirName)
124                    throws Exception {
125    
126                    Class<?> clazz = getClass();
127    
128                    ClassLoader classLoader = clazz.getClassLoader();
129    
130                    _initUtil(classLoader);
131    
132                    List<String> fileNames = new ArrayList<String>();
133    
134                    for (String dirName : dirNames) {
135                            _collectSassFiles(fileNames, dirName, docrootDirName);
136                    }
137    
138                    SassExecutorUtil.init(docrootDirName, portalCommonDirName);
139    
140                    for (String fileName : fileNames) {
141                            SassExecutorUtil.execute(docrootDirName, fileName);
142                    }
143    
144                    SassExecutorUtil.persist();
145            }
146    
147            private void _collectSassFiles(
148                            List<String> fileNames, String dirName, String docrootDirName)
149                    throws Exception {
150    
151                    DirectoryScanner directoryScanner = new DirectoryScanner();
152    
153                    String basedir = docrootDirName.concat(dirName);
154    
155                    directoryScanner.setBasedir(basedir);
156    
157                    directoryScanner.setExcludes(
158                            new String[] {
159                                    "**\\_diffs\\**", "**\\.sass-cache*\\**",
160                                    "**\\.sass_cache_*\\**", "**\\_sass_cache_*\\**",
161                                    "**\\_styled\\**", "**\\_unstyled\\**"
162                            });
163                    directoryScanner.setIncludes(new String[] {"**\\*.css"});
164    
165                    directoryScanner.scan();
166    
167                    String[] fileNamesArray = directoryScanner.getIncludedFiles();
168    
169                    if (!_isModified(basedir, fileNamesArray)) {
170                            return;
171                    }
172    
173                    for (String fileName : fileNamesArray) {
174                            if (fileName.contains("_rtl")) {
175                                    continue;
176                            }
177    
178                            fileNames.add(_normalizeFileName(dirName, fileName));
179                    }
180            }
181    
182            private void _initUtil(ClassLoader classLoader) {
183                    FastDateFormatFactoryUtil fastDateFormatFactoryUtil =
184                            new FastDateFormatFactoryUtil();
185    
186                    fastDateFormatFactoryUtil.setFastDateFormatFactory(
187                            new FastDateFormatFactoryImpl());
188    
189                    FileUtil fileUtil = new FileUtil();
190    
191                    fileUtil.setFile(new FileImpl());
192    
193                    PortalClassLoaderUtil.setClassLoader(classLoader);
194    
195                    PortalUtil portalUtil = new PortalUtil();
196    
197                    portalUtil.setPortal(new PortalImpl());
198    
199                    PropsUtil.setProps(new PropsImpl());
200    
201                    RTLCSSUtil.init();
202            }
203    
204            private boolean _isModified(String dirName, String[] fileNames)
205                    throws Exception {
206    
207                    for (String fileName : fileNames) {
208                            if (fileName.contains("_rtl")) {
209                                    continue;
210                            }
211    
212                            fileName = _normalizeFileName(dirName, fileName);
213    
214                            File file = new File(fileName);
215                            File cacheFile = getCacheFile(fileName);
216    
217                            if (file.lastModified() != cacheFile.lastModified()) {
218                                    return true;
219                            }
220                    }
221    
222                    return false;
223            }
224    
225            private String _normalizeFileName(String dirName, String fileName) {
226                    return StringUtil.replace(
227                            dirName + StringPool.SLASH + fileName,
228                            new String[] {
229                                    StringPool.BACK_SLASH, StringPool.DOUBLE_SLASH
230                            },
231                            new String[] {
232                                    StringPool.SLASH, StringPool.SLASH
233                            }
234                    );
235            }
236    
237    }