Package com.dotcms.csspreproc

Source Code of com.dotcms.csspreproc.CSSPreProcessServlet

package com.dotcms.csspreproc;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Date;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.dotcms.csspreproc.CachedCSS.ImportedAsset;
import com.dotcms.enterprise.csspreproc.CSSCompiler;
import com.dotcms.enterprise.csspreproc.LessCompiler;
import com.dotcms.enterprise.csspreproc.SassCompiler;
import com.dotcms.util.DownloadUtil;
import com.dotmarketing.beans.Host;
import com.dotmarketing.beans.Identifier;
import com.dotmarketing.business.APILocator;
import com.dotmarketing.business.CacheLocator;
import com.dotmarketing.business.PermissionAPI;
import com.dotmarketing.business.web.WebAPILocator;
import com.dotmarketing.cache.LiveCache;
import com.dotmarketing.cache.WorkingCache;
import com.dotmarketing.db.HibernateUtil;
import com.dotmarketing.exception.DotHibernateException;
import com.dotmarketing.exception.DotSecurityException;
import com.dotmarketing.portlets.contentlet.model.ContentletVersionInfo;
import com.dotmarketing.portlets.fileassets.business.FileAsset;
import com.dotmarketing.util.InodeUtils;
import com.dotmarketing.util.Logger;
import com.dotmarketing.util.UtilMethods;
import com.liferay.portal.model.User;

public class CSSPreProcessServlet extends HttpServlet {
    private static final long serialVersionUID = -3315180323197314439L;

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       
        try {
            Host host = WebAPILocator.getHostWebAPI().getCurrentHost(req);
            boolean live = !WebAPILocator.getUserWebAPI().isLoggedToBackend(req);
            User user = WebAPILocator.getUserWebAPI().getLoggedInUser(req);
            String reqURI=req.getRequestURI();
            String uri = reqURI.substring(reqURI.indexOf('/', 1));
           
            if(!reqURI.endsWith(".css")) {
                String path=live ? LiveCache.getPathFromCache(uri, host.getIdentifier()) : WorkingCache.getPathFromCache(uri, host.getIdentifier());
                if(UtilMethods.isSet(path)) {
                    req.getRequestDispatcher("/dotAsset?path=" + path).forward(req, resp);
                }
                else {
                    resp.sendError(404);
                }
                return;
            }
           
            // choose compiler based on the request URI
            Class<? extends CSSCompiler> compilerClass = reqURI.startsWith("/DOTSASS/") ? SassCompiler.class
                                           (reqURI.startsWith("/DOTLESS/") ? LessCompiler.class : null);
            CSSCompiler compiler = compilerClass.getConstructor(Host.class,String.class,boolean.class).newInstance(host,uri,live);
           
            // check if the asset exists
            String actualUri =  uri.substring(0, uri.lastIndexOf('.')) + "." + compiler.getDefaultExtension();
            Identifier ident = APILocator.getIdentifierAPI().find(host, actualUri);
            if(ident==null || !InodeUtils.isSet(ident.getId())) {
                resp.sendError(404);
                return;
            }
           
            // get the asset in order to build etag and check permissions
            long defLang=APILocator.getLanguageAPI().getDefaultLanguage().getId();
            FileAsset fileasset;
            try {
                fileasset = APILocator.getFileAssetAPI().fromContentlet(
                    APILocator.getContentletAPI().findContentletByIdentifier(ident.getId(), live, defLang, user, true));
            }
            catch(DotSecurityException ex) {
                resp.sendError(403);
                return;
            }
           
            boolean userHasEditPerms = false;
            if(!live) {
                userHasEditPerms = APILocator.getPermissionAPI().doesUserHavePermission(fileasset,PermissionAPI.PERMISSION_EDIT,user);
                if(req.getParameter("recompile")!=null && userHasEditPerms) {
                    CacheLocator.getCSSCache().remove(host.getIdentifier(), actualUri, false);
                    CacheLocator.getCSSCache().remove(host.getIdentifier(), actualUri, true);
                }
            }
           
            CachedCSS cache = CacheLocator.getCSSCache().get(host.getIdentifier(), actualUri, live, user);
           
            byte[] responseData=null;
            Date cacheMaxDate=null;
            CachedCSS cacheObject=null;
           
            if(cache==null || cache.data==null) {
                // do compile!
                synchronized(ident.getId().intern()) {
                    cache = CacheLocator.getCSSCache().get(host.getIdentifier(), actualUri, live, user);
                    if(cache==null || cache.data==null) {
                        Logger.debug(this, "compiling css data for "+host.getHostname()+":"+uri);
                       
                        try {
                            compiler.compile();
                        }
                        catch(Throwable ex) {
                            Logger.error(this, "Error compiling "+host.getHostname()+":"+uri, ex);
                            throw new Exception(ex);
                        }
                       
                        // build cache object
                        ContentletVersionInfo vinfo = APILocator.getVersionableAPI().getContentletVersionInfo(ident.getId(), defLang);
                        CachedCSS newcache = new CachedCSS();
                        newcache.data = compiler.getOutput();
                        newcache.hostId = host.getIdentifier();
                        newcache.uri = actualUri;
                        newcache.live = live;
                        newcache.modDate = vinfo.getVersionTs();
                        newcache.imported = new ArrayList<ImportedAsset>();
                        for(String importUri : compiler.getAllImportedURI()) {
                            // newcache entry for the imported asset
                            ImportedAsset asset = new ImportedAsset();
                            asset.uri = importUri;
                            Identifier ii;
                            if(importUri.startsWith("//")) {
                                importUri=importUri.substring(2);
                                String hn=importUri.substring(0, importUri.indexOf('/'));
                                String uu=importUri.substring(importUri.indexOf('/'));
                                ii = APILocator.getIdentifierAPI().find(APILocator.getHostAPI().findByName(hn, user, live),uu);
                            }
                            else {
                                ii = APILocator.getIdentifierAPI().find(host, importUri);
                            }
                            ContentletVersionInfo impInfo = APILocator.getVersionableAPI().getContentletVersionInfo(ii.getId(), defLang);
                            asset.modDate = impInfo.getVersionTs();
                            newcache.imported.add(asset);
                            Logger.debug(this, host.getHostname()+":"+actualUri+" imports-> "+importUri);
                           
                            // actual cache entry for the imported asset. If needed
                            synchronized(ii.getId().intern()) {
                                if(CacheLocator.getCSSCache().get(ii.getHostId(), importUri, live, user)==null) {
                                    CachedCSS entry = new CachedCSS();
                                    entry.data = null;
                                    entry.hostId = ii.getHostId();
                                    entry.imported = new ArrayList<ImportedAsset>();
                                    entry.live = live;
                                    entry.modDate = impInfo.getVersionTs();
                                    entry.uri = importUri;
                                    CacheLocator.getCSSCache().add(entry);
                                }
                            }
                        }
                        CacheLocator.getCSSCache().add(newcache);
                        cacheMaxDate = newcache.getMaxDate();
                        cacheObject = newcache;
                        responseData = compiler.getOutput();
                    }
                }
            }
           
            if(responseData==null) {
                if(cache!=null && cache.data!=null) {
                    // if css is cached an valid is used as response
                    responseData = cache.data;
                    cacheMaxDate = cache.getMaxDate();
                    cacheObject = cache;
                    Logger.debug(this, "using cached css data for "+host.getHostname()+":"+uri);
                }
                else {
                    resp.sendError(500, "no data!");
                    return;
                }
            }
           
           
            boolean doDownload = true;
           
            if(live) {
                // we use etag dot:inode:cacheMaxDate:filesize and lastMod:cacheMaxDate
                // so the browser downloads it if any of the imported files changes
                doDownload = DownloadUtil.isModifiedEtag(req, resp, fileasset.getInode(),
                        cacheMaxDate.getTime(), fileasset.getFileSize());
            }
           
            if(doDownload) {
                // write the actual response to the user
                resp.setContentType("text/css");
                resp.setHeader("Content-Disposition",
                        "inline; filename=\"" + uri.substring(uri.lastIndexOf('/'), uri.length()) + "\"");
               
                if(!live && userHasEditPerms && req.getParameter("debug")!=null) {
                    // debug information requested
                    PrintWriter out = resp.getWriter();
                    out.println("/*");
                    out.println("Cached CSS: "+host.getHostname()+":"+actualUri);
                    out.println("Size: "+cacheObject.data.length+" bytes");
                    out.println("Imported uris:");
                    for(ImportedAsset asset : cacheObject.imported) {
                        out.println("  "+asset.uri);
                    }
                    out.println("*/");
                    out.println(new String(responseData));
                }
                else {
                    resp.getOutputStream().write(responseData);
                }
            }
           
        }
        catch(Exception ex) {
            Logger.error(this, "Exception while serving compiled css file",ex);
        }
        finally {
            try {
                HibernateUtil.closeSession();
            } catch (DotHibernateException e) {
                Logger.warn(this, "Exception while hibernate session close",e);
            }
        }
    }
}
TOP

Related Classes of com.dotcms.csspreproc.CSSPreProcessServlet

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.