View Javadoc
1   package org.argeo.support.freemarker;
2   
3   import java.io.File;
4   import java.io.IOException;
5   import java.net.URLDecoder;
6   import java.nio.charset.StandardCharsets;
7   import java.security.PrivilegedExceptionAction;
8   import java.util.HashMap;
9   import java.util.Map;
10  
11  import javax.jcr.Node;
12  import javax.jcr.Repository;
13  import javax.jcr.Session;
14  import javax.security.auth.Subject;
15  import javax.security.auth.login.LoginContext;
16  import javax.servlet.ServletException;
17  import javax.servlet.http.HttpServlet;
18  import javax.servlet.http.HttpServletRequest;
19  import javax.servlet.http.HttpServletResponse;
20  
21  import org.argeo.cms.CmsException;
22  import org.argeo.cms.auth.HttpRequestCallbackHandler;
23  import org.argeo.jcr.JcrUtils;
24  import org.argeo.node.NodeConstants;
25  import org.osgi.framework.BundleContext;
26  import org.osgi.framework.FrameworkUtil;
27  import org.osgi.framework.ServiceReference;
28  import org.osgi.util.tracker.ServiceTracker;
29  
30  import freemarker.template.Configuration;
31  import freemarker.template.SimpleScalar;
32  import freemarker.template.Template;
33  import freemarker.template.TemplateExceptionHandler;
34  
35  public class HtmlServlet extends HttpServlet {
36  	private static final long serialVersionUID = 2083925371199357045L;
37  	static String base = System.getProperty("user.home") + File.separator + "dev" + File.separator + "work"
38  			+ File.separator + "ftl";
39  	static Configuration cfg;
40  	static {
41  		try {
42  			cfg = new Configuration(Configuration.VERSION_2_3_28);
43  			cfg.setDirectoryForTemplateLoading(new File(base));
44  			cfg.setDefaultEncoding("UTF-8");
45  			cfg.setTemplateExceptionHandler(TemplateExceptionHandler.HTML_DEBUG_HANDLER);
46  			cfg.setLogTemplateExceptions(false);
47  			cfg.setWrapUncheckedExceptions(true);
48  		} catch (IOException e) {
49  			// TODO Auto-generated catch block
50  			e.printStackTrace();
51  		}
52  	}
53  
54  	private final BundleContext bc = FrameworkUtil.getBundle(getClass()).getBundleContext();
55  	private ServiceTracker<Repository, Repository> repositorySt;
56  
57  	private Repository repository;
58  
59  	@Override
60  	public void init() throws ServletException {
61  		repositorySt = new ServiceTracker<Repository, Repository>(bc, Repository.class, null) {
62  
63  			@Override
64  			public Repository addingService(ServiceReference<Repository> reference) {
65  				String cn = reference.getProperty(NodeConstants.CN).toString();
66  				Repository repo = super.addingService(reference);
67  				if (NodeConstants.NODE.equals(cn))
68  					repository = repo;
69  				return repo;
70  			}
71  
72  		};
73  		repositorySt.open();
74  	}
75  
76  	@Override
77  	public void destroy() {
78  		if (repositorySt != null)
79  			repositorySt.close();
80  	}
81  
82  	@Override
83  	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
84  //		String path = req.getPathInfo();
85  		String path = URLDecoder.decode(req.getPathInfo(), StandardCharsets.UTF_8.name());
86  		String servletPath = req.getServletPath();
87  		String[] p = path.split("/");
88  
89  		String basePath = servletPath + '/' + p[1];
90  		String template = p[1] + ".ftl";
91  		StringBuilder sb = new StringBuilder();
92  		for (int i = 2; i < p.length; i++)
93  			sb.append('/').append(p[i]);
94  		String nodePath = sb.toString();
95  		if ("".equals(nodePath.trim()))
96  			nodePath = "/"; // root node
97  		Session session = null;
98  		try {
99  			LoginContext lc = new LoginContext(NodeConstants.LOGIN_CONTEXT_USER,
100 					new HttpRequestCallbackHandler(req, resp));
101 			lc.login();
102 			session = Subject.doAs(lc.getSubject(), new PrivilegedExceptionAction<Session>() {
103 
104 				@Override
105 				public Session run() throws Exception {
106 					Session session = repository.login();
107 					return session;
108 				}
109 			});
110 
111 			Node node = session.getNode(nodePath);
112 
113 			Template t = cfg.getTemplate(template);
114 			Map<String, Object> root = new HashMap<>();
115 			root.put("node", new JcrModel(node));
116 			root.put("basePath", new SimpleScalar(basePath));
117 
118 			t.process(root, resp.getWriter());
119 
120 			resp.setContentType("text/html");
121 		} catch (Exception e) {
122 			throw new CmsException("Cannot process template", e);
123 		} finally {
124 			JcrUtils.logoutQuietly(session);
125 		}
126 	}
127 
128 }