diff --git a/org.eclipse.jgit.lfs.server/src/org/eclipse/jgit/lfs/server/LfsProtocolServlet.java b/org.eclipse.jgit.lfs.server/src/org/eclipse/jgit/lfs/server/LfsProtocolServlet.java index 2473dcdc8..79f54f1ba 100644 --- a/org.eclipse.jgit.lfs.server/src/org/eclipse/jgit/lfs/server/LfsProtocolServlet.java +++ b/org.eclipse.jgit.lfs.server/src/org/eclipse/jgit/lfs/server/LfsProtocolServlet.java @@ -81,13 +81,10 @@ import org.eclipse.jgit.lfs.errors.LfsUnavailable; import org.eclipse.jgit.lfs.errors.LfsValidationError; import org.eclipse.jgit.lfs.internal.LfsText; +import org.eclipse.jgit.lfs.server.internal.LfsGson; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.google.gson.FieldNamingPolicy; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; - /** * LFS protocol handler implementing the LFS batch API [1] * @@ -108,8 +105,6 @@ public abstract class LfsProtocolServlet extends HttpServlet { private static final int SC_BANDWIDTH_LIMIT_EXCEEDED = 509; - private Gson gson = createGson(); - /** * Get the large file repository for the given request and path. * @@ -254,7 +249,7 @@ protected void doPost(HttpServletRequest req, HttpServletResponse res) Reader r = new BufferedReader( new InputStreamReader(req.getInputStream(), UTF_8)); - LfsRequest request = gson.fromJson(r, LfsRequest.class); + LfsRequest request = LfsGson.fromJson(r, LfsRequest.class); String path = req.getPathInfo(); res.setContentType(CONTENTTYPE_VND_GIT_LFS_JSON); @@ -271,7 +266,7 @@ protected void doPost(HttpServletRequest req, HttpServletResponse res) res.setStatus(SC_OK); TransferHandler handler = TransferHandler .forOperation(request.operation, repo, request.objects); - gson.toJson(handler.process(), w); + LfsGson.toJson(handler.process(), w); } catch (LfsValidationError e) { sendError(res, w, SC_UNPROCESSABLE_ENTITY, e.getMessage()); } catch (LfsRepositoryNotFound e) { @@ -295,24 +290,9 @@ protected void doPost(HttpServletRequest req, HttpServletResponse res) } } - static class Error { - String message; - - Error(String m) { - this.message = m; - } - } - private void sendError(HttpServletResponse rsp, Writer writer, int status, String message) { rsp.setStatus(status); - gson.toJson(new Error(message), writer); - } - - private Gson createGson() { - return new GsonBuilder() - .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES) - .disableHtmlEscaping() - .create(); + LfsGson.toJson(message, writer); } } diff --git a/org.eclipse.jgit.lfs.server/src/org/eclipse/jgit/lfs/server/fs/FileLfsServlet.java b/org.eclipse.jgit.lfs.server/src/org/eclipse/jgit/lfs/server/fs/FileLfsServlet.java index b13beb595..145fcd130 100644 --- a/org.eclipse.jgit.lfs.server/src/org/eclipse/jgit/lfs/server/fs/FileLfsServlet.java +++ b/org.eclipse.jgit.lfs.server/src/org/eclipse/jgit/lfs/server/fs/FileLfsServlet.java @@ -58,12 +58,9 @@ import org.eclipse.jgit.lfs.lib.AnyLongObjectId; import org.eclipse.jgit.lfs.lib.Constants; import org.eclipse.jgit.lfs.lib.LongObjectId; +import org.eclipse.jgit.lfs.server.internal.LfsGson; import org.eclipse.jgit.lfs.server.internal.LfsServerText; -import com.google.gson.FieldNamingPolicy; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; - /** * Servlet supporting upload and download of large objects as defined by the * GitHub Large File Storage extension API extending git to allow separate @@ -81,8 +78,6 @@ public class FileLfsServlet extends HttpServlet { private final long timeout; - private static Gson gson = createGson(); - /** * @param repository * the repository storing the large objects @@ -179,14 +174,6 @@ protected void doPut(HttpServletRequest req, } } - static class Error { - String message; - - Error(String m) { - this.message = m; - } - } - /** * Send an error response. * @@ -204,16 +191,9 @@ protected static void sendError(HttpServletResponse rsp, int status, String mess throws IOException { rsp.setStatus(status); PrintWriter writer = rsp.getWriter(); - gson.toJson(new Error(message), writer); + LfsGson.toJson(message, writer); writer.flush(); writer.close(); rsp.flushBuffer(); } - - private static Gson createGson() { - return new GsonBuilder() - .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES) - .disableHtmlEscaping() - .create(); - } } diff --git a/org.eclipse.jgit.lfs.server/src/org/eclipse/jgit/lfs/server/internal/LfsGson.java b/org.eclipse.jgit.lfs.server/src/org/eclipse/jgit/lfs/server/internal/LfsGson.java new file mode 100644 index 000000000..c1659208a --- /dev/null +++ b/org.eclipse.jgit.lfs.server/src/org/eclipse/jgit/lfs/server/internal/LfsGson.java @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2017, David Pursehouse + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.lfs.server.internal; + +import java.io.Reader; + +import com.google.gson.FieldNamingPolicy; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonIOException; +import com.google.gson.JsonSyntaxException; + +/** + * Wrapper for {@link Gson} used by LFS servlets. + * + */ +public class LfsGson { + private static final Gson gson = new GsonBuilder() + .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES) + .disableHtmlEscaping() + .create(); + + /** + * Wrapper class only used for serialization of error messages. + */ + static class Error { + String message; + + Error(String m) { + this.message = m; + } + } + + /** + * Serializes the specified object into its equivalent Json representation. + * + * @param src + * the object for which Json representation is to be created. If + * this is a String, it is wrapped in an instance of + * {@link Error}. + * @param writer + * Writer to which the Json representation needs to be written + * @throws JsonIOException + * if there was a problem writing to the writer + * @see Gson#toJson(Object, Appendable) + */ + public static void toJson(Object src, Appendable writer) + throws JsonIOException { + if (src instanceof String) { + gson.toJson(new Error((String) src), writer); + } else { + gson.toJson(src, writer); + } + } + + /** + * Deserializes the Json read from the specified reader into an object of + * the specified type. + * + * @param json + * reader producing json from which the object is to be + * deserialized + * @param classOfT + * specified type to deserialize + * @return an Object of type T + * @throws JsonIOException + * if there was a problem reading from the Reader + * @throws JsonSyntaxException + * if json is not a valid representation for an object of type + * @see Gson#fromJson(Reader, java.lang.reflect.Type) + */ + public static T fromJson(Reader json, Class classOfT) + throws JsonSyntaxException, JsonIOException { + return gson.fromJson(json, classOfT); + } +}