/sigmah/src/main/java/org/sigmah/server/endpoint/kml/KmlDataServlet.java

http://sigma-h.googlecode.com/ · Java · 262 lines · 177 code · 63 blank · 22 comment · 27 complexity · f9710344e7aaed950a2e7810995a98fb MD5 · raw file

  1. /*
  2. * All Sigmah code is released under the GNU General Public License v3
  3. * See COPYRIGHT.txt and LICENSE.txt.
  4. */
  5. package org.sigmah.server.endpoint.kml;
  6. import com.google.inject.Inject;
  7. import com.google.inject.Injector;
  8. import com.google.inject.Singleton;
  9. import org.apache.commons.codec.binary.Base64;
  10. import org.sigmah.server.auth.Authenticator;
  11. import org.sigmah.server.domain.DomainFilters;
  12. import org.sigmah.server.domain.SiteData;
  13. import org.sigmah.server.report.generator.SiteDataBinder;
  14. import org.sigmah.server.report.util.HtmlWriter;
  15. import org.sigmah.server.util.KMLNamespace;
  16. import org.sigmah.server.util.XmlBuilder;
  17. import org.sigmah.shared.command.GetSchema;
  18. import org.sigmah.shared.command.handler.GetSchemaHandler;
  19. import org.sigmah.shared.dao.*;
  20. import org.sigmah.shared.domain.User;
  21. import org.sigmah.shared.dto.ActivityDTO;
  22. import org.sigmah.shared.dto.IndicatorDTO;
  23. import org.sigmah.shared.dto.SchemaDTO;
  24. import org.sigmah.shared.exception.CommandException;
  25. import org.xml.sax.SAXException;
  26. import javax.persistence.EntityManager;
  27. import javax.persistence.NoResultException;
  28. import javax.servlet.ServletException;
  29. import javax.servlet.http.HttpServletRequest;
  30. import javax.servlet.http.HttpServletResponse;
  31. import javax.xml.transform.TransformerConfigurationException;
  32. import javax.xml.transform.stream.StreamResult;
  33. import java.io.IOException;
  34. import java.io.PrintWriter;
  35. import java.nio.charset.Charset;
  36. import java.util.ArrayList;
  37. import java.util.List;
  38. /**
  39. * Serves a KML (Google Earth) file containing the locations of all activities
  40. * that are visible to the user.
  41. * <p/>
  42. * Users are authenticated using Basic HTTP authentication, and will see a prompt
  43. * for their username (email) and password when they access from Google Earth.
  44. *
  45. * @author Alex Bertram
  46. */
  47. @Singleton
  48. public class KmlDataServlet extends javax.servlet.http.HttpServlet {
  49. @Inject
  50. private Injector injector;
  51. public void doGet(HttpServletRequest req, HttpServletResponse res)
  52. throws ServletException, IOException {
  53. PrintWriter out = res.getWriter();
  54. // Get Authorization header
  55. String auth = req.getHeader("Authorization");
  56. // Do we allow that user?
  57. User user = authenticate(auth);
  58. if (user == null) {
  59. // Not allowed, or no password provided so report unauthorized
  60. res.setHeader("WWW-Authenticate", "BASIC realm=\"Utilisateurs authorises\"");
  61. res.sendError(HttpServletResponse.SC_UNAUTHORIZED);
  62. return;
  63. }
  64. res.setContentType("application/vnd.google-earth.kml+xml");
  65. try {
  66. writeDocument(user, res.getWriter());
  67. } catch (TransformerConfigurationException e) {
  68. e.printStackTrace();
  69. } catch (SAXException e) {
  70. e.printStackTrace();
  71. } catch (CommandException e) {
  72. e.printStackTrace();
  73. }
  74. }
  75. // This method checks the user information sent in the Authorization
  76. // header against the database of users maintained in the users Hashtable.
  77. protected User authenticate(String auth) throws IOException {
  78. if (auth == null) {
  79. return null;
  80. }// no auth
  81. if (!auth.toUpperCase().startsWith("BASIC ")) {
  82. return null;
  83. }// we only do BASIC
  84. // Get encoded user and password, comes after "BASIC "
  85. String emailpassEncoded = auth.substring(6);
  86. // Decode it, using any base 64 decoder
  87. byte[] emailpassDecodedBytes = Base64.decodeBase64(emailpassEncoded.getBytes());
  88. String emailpassDecoded = new String(emailpassDecodedBytes, Charset.defaultCharset());
  89. String[] emailPass = emailpassDecoded.split(":");
  90. if (emailPass.length != 2) {
  91. return null;
  92. }
  93. // look up the user in the database
  94. UserDAO userDAO = injector.getInstance(UserDAO.class);
  95. User user = null;
  96. try {
  97. userDAO.findUserByEmail(emailPass[0]);
  98. } catch (NoResultException e) {
  99. return null;
  100. }
  101. Authenticator checker = injector.getInstance(Authenticator.class);
  102. if (!checker.check(user, emailPass[1])) {
  103. return null;
  104. }
  105. return user;
  106. }
  107. protected void writeDocument(User user, PrintWriter out) throws TransformerConfigurationException, SAXException, CommandException {
  108. // TODO: rewrite using FreeMarker
  109. EntityManager em = injector.getInstance(EntityManager.class);
  110. DomainFilters.applyUserFilter(user, em);
  111. XmlBuilder xml = new XmlBuilder(new StreamResult(out));
  112. GetSchemaHandler schemaHandler = injector.getInstance(GetSchemaHandler.class);
  113. SchemaDTO schema = (SchemaDTO) schemaHandler.execute(new GetSchema(), user);
  114. List<SiteData> sites = querySites(user, schema);
  115. xml.startDocument();
  116. KMLNamespace kml = new KMLNamespace(xml);
  117. kml.startKml();
  118. kml.startDocument();
  119. kml.name("ActivityInfo");
  120. kml.open(true);
  121. int lastDatabaseId = -1;
  122. int lastActivityId = -1;
  123. ActivityDTO activity = null;
  124. for (SiteData pm : sites) {
  125. if (pm.hasLatLong()) {
  126. if (pm.getActivityId() != lastActivityId && lastActivityId != -1) {
  127. xml.close();
  128. }
  129. if (pm.getDatabaseId() != lastDatabaseId) {
  130. if (lastDatabaseId != -1) {
  131. xml.close();
  132. }
  133. kml.startFolder();
  134. kml.name(schema.getDatabaseById(pm.getDatabaseId()).getName());
  135. kml.open(true);
  136. lastDatabaseId = pm.getDatabaseId();
  137. }
  138. if (pm.getActivityId() != lastActivityId) {
  139. kml.startFolder();
  140. kml.name(schema.getActivityById(pm.getActivityId()).getName());
  141. kml.open(false);
  142. activity = schema.getActivityById(pm.getActivityId());
  143. lastActivityId = activity.getId();
  144. }
  145. kml.startPlaceMark();
  146. kml.name(pm.getLocationName());
  147. kml.startSnippet();
  148. xml.cdata(renderSnippet(activity, pm));
  149. xml.close(); // Snippet
  150. kml.startDescription();
  151. xml.cdata(renderDescription(activity, pm));
  152. xml.close(); // Description
  153. kml.startTimeSpan();
  154. kml.begin(pm.getDate1());
  155. kml.end(pm.getDate2());
  156. xml.close(); // Timespan
  157. kml.startPoint();
  158. kml.coordinates(pm.getLongitude(), pm.getLatitude());
  159. xml.close(); // Point
  160. xml.close(); // Placemark
  161. }
  162. }
  163. if (lastActivityId != -1) {
  164. xml.close();
  165. }
  166. if (lastDatabaseId != -1) {
  167. xml.close();
  168. }
  169. xml.close(); // Document
  170. xml.close(); // kml
  171. xml.endDocument();
  172. }
  173. private String renderSnippet(ActivityDTO activity, SiteData pm) {
  174. return activity.getName() + " ?  " + pm.getLocationName() + " (" + pm.getPartnerName() + ")";
  175. }
  176. private List<SiteData> querySites(User user, SchemaDTO schema) {
  177. List<SiteOrder> order = new ArrayList<SiteOrder>();
  178. order.add(SiteOrder.ascendingOn(SiteTableColumn.database_name.property()));
  179. order.add(SiteOrder.ascendingOn(SiteTableColumn.activity_name.property()));
  180. order.add(SiteOrder.ascendingOn(SiteTableColumn.date2.property()));
  181. SiteTableDAO siteDAO = injector.getInstance(SiteTableDAO.class);
  182. return siteDAO.query(user, new Filter(), order, new SiteDataBinder(), SiteTableDAO.RETRIEVE_ALL, 0, -1);
  183. }
  184. private String renderDescription(ActivityDTO activity, SiteData data) {
  185. HtmlWriter html = new HtmlWriter();
  186. html.startTable();
  187. for (IndicatorDTO indicator : activity.getIndicators()) {
  188. if (data.getIndicatorValue(indicator.getId()) != null) {
  189. html.startTableRow();
  190. html.tableCell(indicator.getName());
  191. html.tableCell(Double.toString(data.getIndicatorValue(indicator.getId())));
  192. html.tableCell(indicator.getUnits());
  193. html.endTableRow();
  194. }
  195. }
  196. html.endTable();
  197. return html.toString();
  198. }
  199. }