Skip to content
This repository has been archived by the owner on Feb 3, 2022. It is now read-only.

Safetymaps api in jar dependency #66

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
139 changes: 139 additions & 0 deletions safetymaps-api/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>nl.opengeogroep</groupId>
<artifactId>safetymaps-api</artifactId>
<version>1.0</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>7</source>
<target>7</target>
<compilerArguments>

</compilerArguments>
</configuration>
</plugin>
</plugins>
</build>
<packaging>jar</packaging>

<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.1</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>javax.mail</groupId>
<artifactId>javax.mail-api</artifactId>
<version>1.5.6</version>
<type>jar</type>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<type>jar</type>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.3.2</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-web-api</artifactId>
<version>7.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20140107</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>net.sourceforge.stripes</groupId>
<artifactId>stripes</artifactId>
<version>1.5.6</version>
</dependency>
<dependency>
<groupId>commons-dbutils</groupId>
<artifactId>commons-dbutils</artifactId>
<version>1.6</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.8</version>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.2.5.jre7</version>
<!-- scope provided voor commandline gebruik API, jre7 op server -->
<scope>provided</scope>
</dependency>
<dependency>
<groupId>commons-cli</groupId>
<artifactId>commons-cli</artifactId>
<version>1.3.1</version>
<type>jar</type>
</dependency>
</dependencies>
<distributionManagement>
<repository>
<id>repo.b3p.nl</id>
<name>B3Partners releases repository</name>
<url>https://repo.b3p.nl/nexus/repository/releases/</url>
</repository>
<snapshotRepository>
<id>repo.b3p.nl</id>
<name>B3Partners snapshots repository</name>
<url>https://repo.b3p.nl/nexus/repository/snapshots/</url>
</snapshotRepository>
</distributionManagement>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package nl.opengeogroep;

import net.sourceforge.stripes.action.ActionBeanContext;
import net.sourceforge.stripes.action.ErrorResolution;
import net.sourceforge.stripes.action.Resolution;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.mutable.MutableObject;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpResponse;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.methods.RequestBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.io.StringReader;
import java.util.zip.GZIPOutputStream;

public class SafetyConnectProxy {
private static final Log log = LogFactory.getLog(SafetyConnectProxy.class);

public static Resolution proxy(final ActionBeanContext context, String authorization, String url, String path) throws Exception {
if(authorization == null || url == null) {
return new ErrorResolution(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Geen toegangsgegevens voor webservice geconfigureerd door beheerder");
}

// TODO: serverside checks incidentmonitor, incidentmonitor_kladblok,
// eigen_voertuignummer roles and use voertuignummer from user details

String qs = context.getRequest().getQueryString();
final HttpUriRequest req = RequestBuilder.get()
.setUri(url + "/" + path + (qs == null ? "" : "?" + qs))
.addHeader("Authorization", authorization)
.build();

try(CloseableHttpClient client = HttpClients.createDefault()) {
final MutableObject<String> contentType = new MutableObject<>("text/plain");
final String content = client.execute(req, new ResponseHandler<String>() {
@Override
public String handleResponse(HttpResponse hr) {
log.debug("proxy for user " + context.getRequest().getRemoteUser() + " URL " + req.getURI() + ", response: " + hr.getStatusLine().getStatusCode() + " " + hr.getStatusLine().getReasonPhrase());
contentType.setValue(hr.getEntity().getContentType().getValue());
try {
return IOUtils.toString(hr.getEntity().getContent(), "UTF-8");
} catch(IOException e) {
log.error("Exception reading HTTP content", e);
return "Exception " + e.getClass() + ": " + e.getMessage();
}
}
});

return new Resolution() {
@Override
public void execute(HttpServletRequest request, HttpServletResponse response) throws Exception {
String encoding = "UTF-8";
response.setCharacterEncoding(encoding);
response.setContentType(contentType.getValue());

OutputStream out;
String acceptEncoding = request.getHeader("Accept-Encoding");
if(acceptEncoding != null && acceptEncoding.contains("gzip")) {
response.setHeader("Content-Encoding", "gzip");
out = new GZIPOutputStream(response.getOutputStream(), true);
} else {
out = response.getOutputStream();
}
IOUtils.copy(new StringReader(content), out, encoding);
out.flush();
out.close();
}
};

//return new StreamingResolution(contentType.getValue(), new StringReader(content));
} catch(IOException e) {
log.error("Failed to write output:", e);
return null;
}
}
}

157 changes: 157 additions & 0 deletions safetymaps-api/src/main/java/nl/opengeogroep/SafetymapsApi.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
package nl.opengeogroep;

import net.sourceforge.stripes.action.ActionBeanContext;
import net.sourceforge.stripes.action.ErrorResolution;
import net.sourceforge.stripes.action.Resolution;
import net.sourceforge.stripes.action.StreamingResolution;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.ColumnListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;
import org.apache.commons.io.IOUtils;
import org.json.JSONArray;
import org.json.JSONObject;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.OutputStream;
import java.io.StringReader;
import java.nio.file.Files;
import java.sql.Connection;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.GZIPOutputStream;

public class SafetymapsApi {

public static Resolution features(Connection c, ActionBeanContext context, int version, final int indent, int srid) {

ViewerDataExporter vde = new ViewerDataExporter(c);
try {
final String etag = '"' + vde.getObjectsETag() + '"';

String ifNoneMatch = context.getRequest().getHeader("If-None-Match");
if(ifNoneMatch != null && ifNoneMatch.contains(etag)) {
return new ErrorResolution(HttpServletResponse.SC_NOT_MODIFIED);
}

final JSONObject o = version < 3 ? getFeaturesLegacy(c, version, srid) : getFeaturesJson(vde);

return new Resolution() {
@Override
public void execute(HttpServletRequest request, HttpServletResponse response) throws Exception {
String encoding = "UTF-8";
response.setCharacterEncoding(encoding);
response.setContentType("application/json");
response.addHeader("ETag", etag);

OutputStream out;
String acceptEncoding = request.getHeader("Accept-Encoding");
if(acceptEncoding != null && acceptEncoding.contains("gzip")) {
response.setHeader("Content-Encoding", "gzip");
out = new GZIPOutputStream(response.getOutputStream(), true);
} else {
out = response.getOutputStream();
}
IOUtils.copy(new StringReader(o.toString(indent)), out, encoding);
out.flush();
out.close();
}
};

} catch(Exception e) {
return new StreamingResolution("application/json", "error");
}
}

private static JSONObject getFeaturesJson(ViewerDataExporter vde) throws Exception {
JSONObject o = new JSONObject("{success:true}");
o.put("results", vde.getViewerObjectMapOverview());
return o;
}

private static JSONObject getFeaturesLegacy(Connection c, int version, int srid) throws Exception {
JSONObject o = new JSONObject();
o.put("type", "FeatureCollection");
JSONArray ja = new JSONArray();
o.put("features", ja);
boolean version2 = version == 2;
String from = version2 ? "dbk2.dbkfeatures_json" : " dbk.dbkfeatures_adres_json";
List rows = (List)new QueryRunner().query(c, "select \"feature\" from " + from + "(" + srid + ")", new ColumnListHandler());
for (Object row: rows) {
JSONObject d = new JSONObject(row.toString());
JSONObject j = new JSONObject();
ja.put(j);
j.put("type", "Feature");
j.put("id", "DBKFeature.gid--" + d.get("gid"));
j.put("geometry", d.get("geometry"));
JSONObject properties = new JSONObject();
j.put("properties", properties);
for(Object key: d.keySet()) {
if(!"geometry".equals(key)) {
properties.put((String)key, d.get((String)key));
}
}
}
return o;
}

public static Resolution styles(Connection c, int indent) throws Exception {
JSONObject o = new ViewerDataExporter(c).getStyles();
return new StreamingResolution("application/json", o.toString(indent));
}

public static Resolution object(Connection c, int version, int indent, String path) throws Exception {
Pattern p = Pattern.compile("object\\/([0-9]+)\\.json");
Matcher m = p.matcher(path);

if(!m.find()) {
return new ErrorResolution(HttpServletResponse.SC_NOT_FOUND, "No object id found: /api/" + path);
}

int id = Integer.parseInt(m.group(1));

JSONObject o = null;
if(version == 3) {
o = new ViewerDataExporter(c).getViewerObjectDetails(id);
} else {
Object json = new QueryRunner().query(c, "select \"DBKObject\" from " + (version == 2 ? "dbk2" : "dbk") + ".dbkobject_json(?)", new ScalarHandler(), id);
if(json != null) {
o = new JSONObject();
o.put("DBKObject", new JSONObject(json.toString()));
}
}

if(o == null) {
return new ErrorResolution(HttpServletResponse.SC_NOT_FOUND, "Object id not found: " + id);
} else {
return new StreamingResolution("application/json", o.toString(indent));
}
}

public static Resolution media(String filename, String mediaPath) throws Exception {

// First security check: No path breaker like /../ in filename
if (filename.contains("..")) {
return new ErrorResolution(HttpServletResponse.SC_NOT_FOUND, "Document '" + filename + "' niet gevonden");
}

File mediaPathDir = new File(mediaPath);
File f = new File(mediaPath, filename);

// second security check: resulting path parent file must be the foto directory,
// not another directory using path breakers like /../ etc.
if (!f.getParentFile().equals(mediaPathDir)) {
return new ErrorResolution(HttpServletResponse.SC_BAD_REQUEST, "Filename contains path breaker: " + filename);
}

if (!f.exists() || !f.canRead()) {
return new ErrorResolution(HttpServletResponse.SC_NOT_FOUND, "Document '" + filename + "' niet gevonden");
}

String mimeType = Files.probeContentType(f.toPath());
return new StreamingResolution(mimeType, new FileInputStream(f));
}
}
Loading