Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add protobuf support #518

Open
wants to merge 1 commit 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
Add protobuf support
  • Loading branch information
denysvitali committed Jun 5, 2019
commit 5209e63f6bd42e63b569402c4237bf24b519d05a
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,11 @@ public <T> T fromString(String content, Class<T> classOfT) {
}
}

@Override
public byte[] toByteArray(Object object) {
return toString(object).getBytes();
}

public String objectToString(Object object) {
if (object == null) {
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,19 @@ public String getContentType() {

@Override
public String toString(Object object) {
return JSON.toJSONString(object, SerializerFeature.UseISO8601DateFormat);
return JSON.toJSONString(object,
SerializerFeature.UseISO8601DateFormat);
}

@Override
public <T> T fromString(String content, Class<T> classOfT) {
return JSON.parseObject(content, classOfT);
}

@Override
public byte[] toByteArray(Object object) {
return JSON.toJSONBytes(object,
SerializerFeature.UseISO8601DateFormat);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,11 @@ public <T> T fromString(String content, Class<T> classOfT) {
return gson().fromJson(content, classOfT);
}

@Override
public byte[] toByteArray(Object object) {
return gson().toJson(object).getBytes();
}

private Gson gson() {
return new GsonBuilder()
.registerTypeAdapter(Date.class, new ISO8601DateTimeTypeAdapter())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,4 +68,13 @@ public <T> T fromString(String content, Class<T> classOfT) {
}
}

@Override
public byte[] toByteArray(Object object) {
try {
return objectMapper.writeValueAsBytes(object);
} catch (JsonProcessingException e) {
throw new PippoRuntimeException(e, "Error serializing object to {}", getContentType());
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import java.io.ByteArrayOutputStream;
import java.io.StringReader;
import java.io.StringWriter;

Expand Down Expand Up @@ -86,4 +87,21 @@ public <T> T fromString(String content, Class<T> classOfT) {
}
}

@Override
public byte[] toByteArray(Object object) {
try {
JAXBContext jaxbContext = JAXBContext.newInstance(object.getClass());
Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, prettyPrint);

ByteArrayOutputStream writer = new ByteArrayOutputStream();
jaxbMarshaller.marshal(object, writer);

return writer.toByteArray();
} catch (JAXBException e) {
throw new PippoRuntimeException(e,
"Failed to serialize '{}' to XML'", object.getClass().getName());
}
}

}
42 changes: 42 additions & 0 deletions pippo-content-type-parent/pippo-protobuf/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?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/maven-v4_0_0.xsd">

<parent>
<groupId>ro.pippo</groupId>
<artifactId>pippo-content-type-parent</artifactId>
<version>1.13.0-SNAPSHOT</version>
</parent>

<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>
<artifactId>pippo-protobuf</artifactId>
<version>1.13.0-SNAPSHOT</version>
<name>Pippo Protobuf</name>
<description>Protobuf integration</description>

<properties>
<protobuf.version>3.8.0</protobuf.version>
</properties>

<dependencies>
<dependency>
<groupId>ro.pippo</groupId>
<artifactId>pippo-core</artifactId>
<version>${project.version}</version>
</dependency>

<!-- Protobuf -->
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>${protobuf.version}</version>
</dependency>

<dependency>
<groupId>org.kohsuke.metainf-services</groupId>
<artifactId>metainf-services</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package ro.pippo.protobuf;

import com.google.protobuf.AbstractMessage;
import com.google.protobuf.ByteString;
import org.kohsuke.MetaInfServices;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ro.pippo.core.Application;
import ro.pippo.core.ContentTypeEngine;
import java.lang.reflect.InvocationTargetException;
import java.nio.charset.StandardCharsets;

/**
* A Protobuf Engine
*
* @author Denys Vitali
*/

@MetaInfServices
public class ProtobufEngine implements ContentTypeEngine {
private static final Logger log =
LoggerFactory.getLogger(ProtobufInitializer.class);

@Override
public void init(Application application) {

}

@Override
public String getContentType() {
return "application/protobuf";
}

@Override
public String toString(Object msg) {
if(msg instanceof AbstractMessage){
try {
return (String)
msg.getClass()
.getMethod("getMessage")
.invoke(msg);
} catch (IllegalAccessException |
InvocationTargetException |
NoSuchMethodException e) {
e.printStackTrace();
}
}
return null;
}

@Override
public <T> T fromString(String content, Class<T> classOfT) {
ByteString bs = ByteString.copyFrom(content, StandardCharsets.UTF_8);

try {
return (T) classOfT.getMethod("fromString", ByteString.class)
.invoke(bs);
} catch (NoSuchMethodException |
IllegalAccessException |
InvocationTargetException e) {
log.error("Unable to deserialize protobuf object", e);
}
return null;
}

@Override
public byte[] toByteArray(Object o) {
if(o instanceof AbstractMessage){
try {
return(byte[])
o.getClass()
.getMethod("toByteArray")
.invoke(o);
} catch (IllegalAccessException |
InvocationTargetException |
NoSuchMethodException e) {
e.printStackTrace();
}
}
return new byte[]{};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright (C) 2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ro.pippo.protobuf;

import org.kohsuke.MetaInfServices;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import ro.pippo.core.Application;
import ro.pippo.core.Initializer;

/**
* @author Denys Vitali
*/

@MetaInfServices
public class ProtobufInitializer implements Initializer {

private static final Logger log = LoggerFactory.getLogger(ProtobufInitializer.class);

@Override
public void init(Application application) {
application.registerContentTypeEngine(ProtobufEngine.class);
}

@Override
public void destroy(Application application) {
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,9 @@ public <T> T fromString(String content, Class<T> classOfT) {
return (T) new Yaml().load(content);
}

@Override
public byte[] toByteArray(Object object) {
return new Yaml().dump(object).getBytes();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,9 @@ public <T> T fromString(String content, Class<T> classOfT) {
return (T) xstream().fromXML(content);
}

@Override
public byte[] toByteArray(Object object) {
return xstream().toXML(object).getBytes();
}

}
1 change: 1 addition & 0 deletions pippo-content-type-parent/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
<module>pippo-gson</module>
<module>pippo-jackson</module>
<module>pippo-jaxb</module>
<module>pippo-protobuf</module>
<module>pippo-snakeyaml</module>
<module>pippo-xstream</module>
</modules>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,5 @@ public interface ContentTypeEngine {

<T> T fromString(String content, Class<T> classOfT);

byte[] toByteArray(Object object);
}
2 changes: 2 additions & 0 deletions pippo-core/src/main/java/ro/pippo/core/HttpConstants.java
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,8 @@ public static final class ContentType {
public static final String APPLICATION_JSON = "application/json";
public static final String APPLICATION_XML = "application/xml";
public static final String APPLICATION_X_YAML = "application/x-yaml";
public static final String APPLICATION_PROTOBUF = "application/protobuf";

public static final String TEXT_HTML = "text/html";
public static final String TEXT_XHTML = "text/xhtml";
public static final String TEXT_PLAIN = "text/plain";
Expand Down
27 changes: 18 additions & 9 deletions pippo-core/src/main/java/ro/pippo/core/Response.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,7 @@
import javax.servlet.ServletOutputStream;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.Date;
Expand Down Expand Up @@ -825,6 +818,13 @@ public Response yaml() {
return contentType(HttpConstants.ContentType.APPLICATION_X_YAML);
}

/**
* Sets the Response content-type to application/protobuf.
*/
public Response protobuf() {
return contentType(HttpConstants.ContentType.APPLICATION_PROTOBUF);
}

/**
* Writes the string content directly to the response.
* <p>This method commits the response.</p>
Expand Down Expand Up @@ -921,7 +921,16 @@ private void send(Object object, String contentType) {
}

header(HttpConstants.Header.CONTENT_TYPE, contentTypeEngine.getContentType());
send(contentTypeEngine.toString(object));

try {
byte[] byteArr = contentTypeEngine.toByteArray(object);
contentLength(byteArr.length);
send(new BufferedInputStream(new ByteArrayInputStream(byteArr)));
} catch (IOException e) {
log.error(e.getMessage());
log.warn("Sending ContentType toString instead...");
send(contentTypeEngine.toString(object));
}
}

/**
Expand Down
5 changes: 5 additions & 0 deletions pippo-core/src/main/java/ro/pippo/core/TextPlainEngine.java
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,9 @@ public <T> T fromString(String content, Class<T> classOfT) {
classOfT.getName());
}

@Override
public byte[] toByteArray(Object object) {
return object.toString().getBytes();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -345,13 +345,27 @@ public RouteContext html() {
return this;
}

@Override
public RouteContext protobuf(){
response.protobuf();

return this;
}

@Override
public RouteContext negotiateContentType() {
response.contentType(request);

return this;
}

@Override
public RouteContext contentType(String contentType) {
response.contentType(contentType);

return this;
}

@Override
public RouteContext status(int code) {
response.status(code);
Expand Down
Loading