1. Project Clover database Tue Dec 20 2016 21:24:09 CET
  2. Package com.xpn.xwiki.web.sx

File AbstractSxAction.java

 

Coverage histogram

../../../../../img/srcFileCovDistChart9.png
38% of files have more coverage

Code metrics

16
32
2
1
157
78
12
0.38
16
2
6

Classes

Class Line # Actions
AbstractSxAction 45 32 0% 12 7
0.8686%
 

Contributing tests

No tests hitting this source file were found.

Source view

1    /*
2    * See the NOTICE file distributed with this work for additional
3    * information regarding copyright ownership.
4    *
5    * This is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU Lesser General Public License as
7    * published by the Free Software Foundation; either version 2.1 of
8    * the License, or (at your option) any later version.
9    *
10    * This software is distributed in the hope that it will be useful,
11    * but WITHOUT ANY WARRANTY; without even the implied warranty of
12    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13    * Lesser General Public License for more details.
14    *
15    * You should have received a copy of the GNU Lesser General Public
16    * License along with this software; if not, write to the Free
17    * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18    * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
19    */
20    package com.xpn.xwiki.web.sx;
21   
22    import java.io.IOException;
23    import java.util.Date;
24   
25    import javax.servlet.http.HttpServletResponse;
26   
27    import org.apache.commons.lang3.BooleanUtils;
28    import org.apache.commons.lang3.StringUtils;
29    import org.slf4j.Logger;
30   
31    import com.xpn.xwiki.XWikiContext;
32    import com.xpn.xwiki.XWikiException;
33    import com.xpn.xwiki.web.XWikiAction;
34    import com.xpn.xwiki.web.XWikiRequest;
35    import com.xpn.xwiki.web.XWikiResponse;
36    import com.xpn.xwiki.web.sx.SxSource.CachePolicy;
37   
38    /**
39    * Abstract Skin Extension action. Contains the logic to generate the response based on a extension source and a type of
40    * extension that implementing classes must provide.
41    *
42    * @version $Id: a1a3dc8bf2ec766e71d518dac3df88645eb95ae9 $
43    * @since 1.7M2
44    */
 
45    public abstract class AbstractSxAction extends XWikiAction
46    {
47    /** How many milliseconds a file should be cached for if it sets CachePolicy to LONG, hardcoded to 30 days. */
48    private static final long LONG_CACHE_DURATION = 30 * 24 * 3600 * 1000L;
49   
50    /** How many milliseconds a file should be cached for if it sets CachePolicy to SHORT, hardcoded to 1 day. */
51    private static final long SHORT_CACHE_DURATION = 1 * 24 * 3600 * 1000L;
52   
53    /** What http header parameter is used to specify when a file was last modified. */
54    private static final String LAST_MODIFIED_HEADER = "Last-Modified";
55   
56    /** What http header parameter is used to specify cache control. */
57    private static final String CACHE_CONTROL_HEADER = "Cache-Control";
58   
59    /** What http header parameter is used to specify when the cache should expire. */
60    private static final String CACHE_EXPIRES_HEADER = "Expires";
61   
62    /** The response will be sent to the browser as a byte array in this character set. */
63    private static final String RESPONSE_CHARACTER_SET = "UTF-8";
64   
65    /** If the user passes this parameter in the URL, we will look for the script in the jar files. */
66    private static final String JAR_RESOURCE_REQUEST_PARAMETER = "resource";
67   
68    /** If the user specifies this url parameter equals false, we will send uncompressed script content. */
69    private static final String COMPRESS_SCRIPT_REQUEST_PARAMETER = "minify";
70   
71    /** @return the logging object of the concrete subclass. */
72    protected abstract Logger getLogger();
73   
74    /**
75    * This method must be called by render(XWikiContext). Render is in charge of creating the proper source and
76    * extension type, and pass it as an argument to this method which will forge the proper response using those.
77    *
78    * @param sxSource the source of the extension.
79    * @param sxType the type of extension
80    * @param context the XWiki context when rendering the skin extension.
81    * @throws XWikiException when an error occurs when building the response.
82    */
 
83  486 toggle public void renderExtension(SxSource sxSource, Extension sxType, XWikiContext context)
84    throws XWikiException
85    {
86  489 XWikiRequest request = context.getRequest();
87  487 XWikiResponse response = context.getResponse();
88   
89  488 String extensionContent = sxSource.getContent();
90   
91  489 response.setContentType(sxType.getContentType());
92   
93  489 if (sxSource.getLastModifiedDate() > 0) {
94  489 response.setDateHeader(LAST_MODIFIED_HEADER, sxSource.getLastModifiedDate());
95    }
96   
97  489 CachePolicy cachePolicy = sxSource.getCachePolicy();
98   
99  489 if (cachePolicy != CachePolicy.FORBID) {
100  471 response.setHeader(CACHE_CONTROL_HEADER, "public");
101    }
102  489 if (cachePolicy == CachePolicy.LONG) {
103    // Cache for one month (30 days)
104  175 response.setDateHeader(CACHE_EXPIRES_HEADER, (new Date()).getTime() + LONG_CACHE_DURATION);
105  314 } else if (cachePolicy == CachePolicy.SHORT) {
106    // Cache for one day
107  0 response.setDateHeader(CACHE_EXPIRES_HEADER, (new Date()).getTime() + SHORT_CACHE_DURATION);
108  314 } else if (cachePolicy == CachePolicy.FORBID) {
109  18 response.setHeader(CACHE_CONTROL_HEADER, "no-cache, no-store, must-revalidate");
110    }
111   
112  489 if (BooleanUtils.toBoolean(StringUtils.defaultIfEmpty(
113    request.get(COMPRESS_SCRIPT_REQUEST_PARAMETER), "true"))) {
114  488 extensionContent = sxType.getCompressor().compress(extensionContent);
115    }
116   
117  489 try {
118  489 response.setContentLength(extensionContent.getBytes(RESPONSE_CHARACTER_SET).length);
119  489 response.getOutputStream().write(extensionContent.getBytes(RESPONSE_CHARACTER_SET));
120    } catch (IOException ex) {
121  0 getLogger().warn("Failed to send SX content: [{}]", ex.getMessage());
122    }
123   
124    }
125   
 
126  641 toggle @Override
127    public String render(XWikiContext context) throws XWikiException
128    {
129  641 SxSource sxSource;
130   
131  641 if (context.getRequest().getParameter(JAR_RESOURCE_REQUEST_PARAMETER) != null) {
132  0 sxSource = new SxResourceSource(context.getRequest().getParameter(JAR_RESOURCE_REQUEST_PARAMETER));
133    } else {
134  638 if (context.getDoc().isNew()) {
135  152 context.getResponse().setStatus(HttpServletResponse.SC_NOT_FOUND);
136  152 return "docdoesnotexist";
137    }
138  488 sxSource = new SxDocumentSource(context, getExtensionType());
139    }
140   
141  488 try {
142  488 renderExtension(sxSource, getExtensionType(), context);
143    } catch (IllegalArgumentException e) {
144    // Simply set a 404 status code and return null, so that no unneeded bytes are transfered
145  0 context.getResponse().setStatus(HttpServletResponse.SC_NOT_FOUND);
146    }
147  489 return null;
148    }
149   
150    /**
151    * Get the type of extension, depends on the type of action.
152    *
153    * @return a new object which extends Extension.
154    */
155    public abstract Extension getExtensionType();
156   
157    }