View Javadoc

1   package com.atlassian.servlet;
2   
3   import java.io.IOException;
4   import java.util.Collection;
5   import java.util.Enumeration;
6   import java.util.HashMap;
7   import java.util.Iterator;
8   import java.util.Set;
9   import java.util.TreeSet;
10  
11  import javax.servlet.ServletConfig;
12  import javax.servlet.ServletException;
13  import javax.servlet.http.HttpServlet;
14  import javax.servlet.http.HttpServletRequest;
15  import javax.servlet.http.HttpServletResponse;
16  
17  import org.apache.commons.collections.MultiHashMap;
18  import org.apache.commons.collections.MultiMap;
19  import org.apache.log4j.Category;
20  
21  import com.atlassian.cache.servlet.handler.CacheExpirationHandler;
22  import com.atlassian.cache.servlet.resolver.ContentResolver;
23  
24  /**
25   * FQCN : com.atlassian.servlet.CombinedServlet
26   * @author BNP Paribas - ITP/ITGS/SFRI
27   * @author Kaamelot
28   * @since
29   * Description : Strongly duplicated from com.atlassian.cache.servlet.CombinedCachingServlet, 
30   * but with Optional Cache, and more protected methods !
31   *
32   */
33  public class CombinedServlet extends HttpServlet {
34  
35  	/** */
36  	private static final long serialVersionUID = 1L;
37  
38  	public static final String DEFAULT_ENCODING = "UTF-8";
39  
40  	private static final String DEFAULT_CONTENT_TYPE = "text/javascript";
41  
42  	private static final String CONTENT_RESOLVER_PREFIX = "content.resolver";
43  
44  	protected final Category log = Category.getInstance(getClass());
45  
46  	private String data = null;
47  
48  	private CacheExpirationHandler cacheExpirationHandler;
49  
50  	private String contentType;
51  
52  	private HashMap contentResolvers;
53  
54  	private MultiMap contentByResolver;
55  
56  	public synchronized void init(ServletConfig servletConfig) throws ServletException {
57  		super.init(servletConfig);
58  
59  //		initializeCacheExpirationHandler(servletConfig.getInitParameter("cache.expiration.handler.class"));
60  		initializeContentType(servletConfig.getInitParameter("content.type"));
61  		initializeContentResolvers(servletConfig);
62  		initializeContentParams();
63  	}
64  
65  	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
66  		// always set the content type as defined in the init params
67  		response.setContentType(contentType);
68  
69  //		// check to see if we need to do any work
70  //		if (getCacheExpirationHandler().checkRequest(request, response)) {
71  //			return;
72  //		}
73  
74  		response.getWriter().write(getDataToSend(request, response));
75  		response.getWriter().flush();
76  	}
77  
78  	protected String getDataToSend(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
79  //		if (isCacheDisabled())
80  			return makeData(request, response);
81  //		else
82  //			return getCachedData(request, response);
83  	}
84  
85  //	private synchronized String getCachedData(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
86  //		if (data == null)
87  //			data = makeData(request, response);
88  //
89  //		return data;
90  //	}
91  //
92  //	protected boolean isCacheDisabled() {
93  //		return "true".equals(System.getProperty("atlassian.disable.caches", "false"));
94  //	}
95  
96  	/** Build Final Stream from each defined ContentResolver and their resources
97  	 * @param request
98  	 * @param response
99  	 * @return
100 	 * @throws IOException
101 	 * @throws ServletException
102 	 */
103 	protected String makeData(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
104 		try {
105 			StringBuffer buffer = new StringBuffer();
106 
107 			// run through each contentResolver that is registered
108 			for (Iterator iterator = contentResolvers.keySet().iterator(); iterator.hasNext();) {
109 				String resolverKey = (String) iterator.next();
110 				// If we have content registered for this resolver
111 				if (contentByResolver.containsKey(resolverKey)) {
112 					// Run through all the registered content, asking the resolver to resolve it.
113 					for (Iterator iterator1 = ((Collection) contentByResolver.get(resolverKey)).iterator(); iterator1.hasNext();) {
114 						String path = (String) iterator1.next();
115 						ContentResolver resolver = (ContentResolver) contentResolvers.get(resolverKey);
116 						buffer.append(resolver.getContent(path, request, response));
117 					}
118 				}
119 			}
120 			return buffer.toString();
121 		} catch (IOException e) {
122 			log.error("Error building combined cached servlet data: " + request.getRequestURI() + " - " + e.toString(), e);
123 			throw e;
124 		} catch (ServletException e) {
125 			log.error("Error building combined cached servlet data: " + request.getRequestURI() + " - " + e.toString(), e);
126 			throw e;
127 		}
128 	}
129 
130 //	protected CacheExpirationHandler getCacheExpirationHandler() {
131 //		return cacheExpirationHandler;
132 //	}
133 
134 	/**
135 	 * Run through all the registered content resolver keys and then run through the init params looking for content entries for each resolver key. Store the content path with the resolver key.
136 	 */
137 	private void initializeContentParams() {
138 		contentByResolver = new MultiHashMap();
139 
140 		Enumeration e = getInitParameterNames();
141 		Set sortedNames = new TreeSet();
142 		while (e.hasMoreElements()) {
143 			sortedNames.add(e.nextElement());
144 		}
145 		// Run through all the contentResolvers that were registered
146 		for (Iterator iterator = contentResolvers.keySet().iterator(); iterator.hasNext();) {
147 			String resolverKey = (String) iterator.next();
148 			// Run through all the init params looking for the resolver key as a prefix
149 			for (Iterator i = sortedNames.iterator(); i.hasNext();) {
150 				String name = (String) i.next();
151 				if (name.startsWith(resolverKey)) {
152 					// store the path in the list associated with the resolver key
153 					contentByResolver.put(resolverKey, getInitParameter(name));
154 				}
155 			}
156 
157 		}
158 	}
159 
160 	/**
161 	 * Runs through all the init params looking for param names starting with CONTENT_RESOLVER_PREFIX. We will use the remainder of the name as the key (which is referenced in the content entries)
162 	 * which will be associated with the implementation of the content resolver (the class specified in the value of the param). If the class is not found then the resolver will not be added. <p/> ex.
163 	 * 
164 	 * <pre>
165 	 *  &lt;init-param&gt;
166 	 *    &lt;param-name&gt;content.resolver.dwr&lt;/param-name&gt;
167 	 *    &lt;param-value&gt;com.atlassian.cache.servlet.resolver.DwrContentResolver&lt;/param-value&gt;
168 	 *  &lt;/init-param&gt;
169 	 * </pre>
170 	 * 
171 	 * <p/> This will map the key: dwr to the implementation: com.atlassian.cache.servlet.resolver.DwrContentResolver
172 	 */
173 	private void initializeContentResolvers(ServletConfig config) throws ServletException {
174 		contentResolvers = new HashMap();
175 
176 		for (Enumeration e = getInitParameterNames(); e.hasMoreElements();) {
177 			String name = (String) e.nextElement();
178 			if (name.startsWith(CONTENT_RESOLVER_PREFIX)) {
179 				Object objResolver = getObjectForClass(getInitParameter(name));
180 				if (objResolver != null && objResolver instanceof ContentResolver) {
181 					ContentResolver resolver = (ContentResolver) objResolver;
182 					// always make sure to initialize the resolver
183 					resolver.init(config);
184 
185 					// Get the key to map this resolver from the name and add the impl to the resolvers map
186 					String key = name.substring(CONTENT_RESOLVER_PREFIX.length() + 1);
187 					contentResolvers.put(key, resolver);
188 				} else {
189 					log.warn("The class " + getInitParameter(name) + " does not implement ContentResolver.");
190 				}
191 			}
192 		}
193 	}
194 
195 	private void initializeContentType(String initParameter) {
196 		if (initParameter == null) {
197 			contentType = DEFAULT_CONTENT_TYPE;
198 		} else {
199 			contentType = initParameter;
200 		}
201 	}
202 
203 //	private void initializeCacheExpirationHandler(String cacheExpirationHandlerClass) {
204 //		Object objCacheExpirationHandler = getObjectForClass(cacheExpirationHandlerClass);
205 //
206 //		if (objCacheExpirationHandler != null && objCacheExpirationHandler instanceof CacheExpirationHandler) {
207 //			cacheExpirationHandler = (CacheExpirationHandler) objCacheExpirationHandler;
208 //		} else {
209 //			log.info("Unable to resolve class: " + cacheExpirationHandlerClass + " as an implementation of CacheExpirationHandler");
210 //			// fallback to the default implementation
211 //			cacheExpirationHandler = new LastModifiedCacheExpirationHandler();
212 //			log.info("Using the LastModifiedCacheExpirationHandler cache expiration handler");
213 //		}
214 //	}
215 
216 	private Object getObjectForClass(String clazz) {
217 		Object obj = null;
218 		try {
219 			if (clazz != null) {
220 				obj = Class.forName(clazz).newInstance();
221 			}
222 		} catch (Exception e) {
223 			log.warn("Unable to resolve class for className: " + clazz);
224 		}
225 		return obj;
226 	}
227 }