Project

General

Profile

Improvement #1547 » JDocFilter.java

Henning Blohm, 07.11.2013 14:39

 
1
/*
2
 * z2-Environment
3
 * 
4
 * Copyright(c) ZFabrik Software KG
5
 * 
6
 * contact@zfabrik.de
7
 * 
8
 * http://www.z2-environment.eu
9
 */
10
package com.zfabrik.impl.javadoc;
11

    
12
import java.io.File;
13
import java.io.FileInputStream;
14
import java.io.IOException;
15
import java.io.InputStream;
16
import java.io.OutputStream;
17
import java.util.Collection;
18
import java.util.TreeSet;
19

    
20
import javax.servlet.Filter;
21
import javax.servlet.FilterChain;
22
import javax.servlet.FilterConfig;
23
import javax.servlet.ServletException;
24
import javax.servlet.ServletRequest;
25
import javax.servlet.ServletResponse;
26
import javax.servlet.http.HttpServletRequest;
27
import javax.servlet.http.HttpServletResponse;
28

    
29
import com.zfabrik.components.IComponentDescriptor;
30
import com.zfabrik.components.IComponentsManager;
31
import com.zfabrik.components.java.IJavaComponent;
32
import com.zfabrik.components.java.JavaComponentUtil;
33
import com.zfabrik.util.expression.X;
34
import com.zfabrik.util.html.Escaper;
35

    
36
/**
37
 * Java Doc filter - serves and triggers on-demand creation of java component
38
 * java docs
39
 * 
40
 * @author hb
41
 * 
42
 */
43
public class JDocFilter implements Filter {
44
	private static final String LAST_MODIFIED = "Last-Modified";
45
	private static final String IF_MODIFIED_SINCE = "If-Modified-Since";
46
	private FilterConfig cfg;
47

    
48
	public void init(FilterConfig cfg) throws ServletException {
49
		this.cfg = cfg;
50
	}
51

    
52
	public void destroy() {
53
		this.cfg = null;
54
	}
55

    
56
	public void doFilter(ServletRequest req, ServletResponse res,FilterChain chain) throws IOException, ServletException {
57
		HttpServletRequest sreq = (HttpServletRequest) req;
58
		HttpServletResponse resp = (HttpServletResponse) res;
59

    
60
		// paths are /<component>/<api|impl>/<jdoc path>
61
		String path = sreq.getRequestURI().substring(sreq.getContextPath().length());
62
		if (path.length() > 1) {
63
			int p = path.indexOf('/', 1);
64
			if (p >= 0) {
65
				String component = Escaper.urlDecode(path.substring(1, p),'!');
66
				component = JavaComponentUtil.fixJavaComponentName(component);
67
				path = path.substring(p);
68
				if (path.length() > 1) {
69
					p = path.indexOf('/', 1);
70
					if (p >= 0) {
71
						String type = Escaper.urlDecode(path.substring(1, p),'!');
72
						File f = checkDocs(component, type);
73
						if (f != null) {
74
							path = path.substring(p);
75
							if (path.length()>0) {
76
								f = new File(f, path);
77
								if (f.exists()) {
78
									// check last modified request
79
									long ifModifiedSince = sreq	.getDateHeader(IF_MODIFIED_SINCE);
80
									if (ifModifiedSince >= 0) {
81
										// make sure to reduce to seconds precision!
82
										long cr = f.lastModified();
83
										if (((cr / 1000) * 1000) <= ifModifiedSince) {
84
											// nothing to do...
85
											resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
86
											return;
87
										}
88
									}
89
									// ok, write it out
90
									// headers
91
									// Important: set Last-Modified!
92
									resp.setDateHeader(LAST_MODIFIED, f.lastModified());
93
									resp.setContentType(this.cfg.getServletContext().getMimeType(f.getName()));
94
									resp.setContentLength((int) f.length());
95
	
96
									// stream out
97
									OutputStream out = resp.getOutputStream();
98
									InputStream in = new FileInputStream(f);
99
									try {
100
										byte[] buffer = new byte[16384];
101
										int l;
102
										while ((l = in.read(buffer)) >= 0) {
103
											out.write(buffer, 0, l);
104
										}
105
									} finally {
106
										in.close();
107
									}
108
									return;
109
								}
110
							} else {
111
								// url ends after type string. redirect
112
								redirect2Index(sreq,resp);
113
								return;
114
							}
115
						} else {
116
							// not found
117
							gotoList(sreq,resp,true);
118
							return;
119
						}
120
					} else {
121
						// url ends at type string. redirect
122
						redirect2Index(sreq,resp);
123
						return;
124
					}
125
				} else {
126
					// url ends at component
127
					redirect2Index(sreq,resp);
128
					return;
129
				}
130
			} else {
131
				// url ends at component
132
				redirect2Index(sreq,resp);
133
				return;
134
			}
135
		} else {
136
			// index
137
			gotoList(sreq,resp,false);
138
			return;
139
		}
140
		resp.setStatus(HttpServletResponse.SC_NOT_FOUND);
141
		chain.doFilter(req,res);
142
	}
143

    
144
	private void gotoList(HttpServletRequest sreq, HttpServletResponse resp,boolean notfound) throws IOException, ServletException {
145
		// present a choice of components
146
		sreq.setAttribute("notfound", notfound);
147
		Collection<String> cs = IComponentsManager.INSTANCE.findComponents(X.var(IComponentDescriptor.COMPONENT_TYPE).eq(X.val(IJavaComponent.TYPE_NAME)));
148
		TreeSet<String> scs = new TreeSet<String>(cs);
149
		sreq.setAttribute("components", scs);
150
		sreq.getRequestDispatcher("/WEB-INF/all.jsp").forward(sreq, resp);		
151
	}
152

    
153
	private void redirect2Index(HttpServletRequest sreq,HttpServletResponse resp) throws IOException, ServletException {
154
		String s = sreq.getRequestURI();
155
		if (!s.endsWith("/")) {
156
			s += "/";
157
		}
158
		if (s.endsWith("/api/") || s.endsWith("/impl/")) {
159
			resp.sendRedirect(s+"index.html");
160
		} else {
161
			resp.sendRedirect(s+"api/index.html");
162
		}
163
	}
164

    
165
	/*
166
	 * Check for javadocs of the given type from the given component.
167
	 * If not found, trigger creation
168
	 */
169
	private File checkDocs(String component, String type) {
170
		short t = 0;
171
		if ("both".equals(type)) {
172
			t = ComponentJavaDoc.TYPE_BOTH;
173
		} else 
174
		if ("impl".equals(type)) {
175
			t = ComponentJavaDoc.TYPE_IMPL;
176
		} else 
177
		if ("api".equals(type)) {
178
			t = ComponentJavaDoc.TYPE_API;
179
		} else 
180
			return null;
181
			
182
		return new ComponentJavaDoc(component,t).getRootFolder();
183
	}
184
}
(1-1/2)