From f6b200be4c8b90c26886c6cdd5809abac8c4ac15 Mon Sep 17 00:00:00 2001 From: James Moger Date: Wed, 27 Mar 2013 12:46:05 -0400 Subject: Reorganized to Apache Standard Directory Layout & integrated Moxie This is a massive commit which reorganizes the entire project structure (although it is still monolithic), removes the Build classes, and switches to Moxie, a smarter Ant build tookit based on the original Gitblit Build classes. The Ant build script will likely require additional fine-tuning, but this is big step forward. --- src/main/java/com/gitblit/utils/JsonUtils.java | 346 +++++++++++++++++++++++++ 1 file changed, 346 insertions(+) create mode 100644 src/main/java/com/gitblit/utils/JsonUtils.java (limited to 'src/main/java/com/gitblit/utils/JsonUtils.java') diff --git a/src/main/java/com/gitblit/utils/JsonUtils.java b/src/main/java/com/gitblit/utils/JsonUtils.java new file mode 100644 index 00000000..24f4ecb8 --- /dev/null +++ b/src/main/java/com/gitblit/utils/JsonUtils.java @@ -0,0 +1,346 @@ +/* + * Copyright 2011 gitblit.com. + * + * 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 com.gitblit.utils; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.lang.reflect.Type; +import java.net.HttpURLConnection; +import java.net.URLConnection; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Collection; +import java.util.Date; +import java.util.Locale; +import java.util.Map; +import java.util.TimeZone; + +import com.gitblit.Constants.AccessPermission; +import com.gitblit.GitBlitException.ForbiddenException; +import com.gitblit.GitBlitException.NotAllowedException; +import com.gitblit.GitBlitException.UnauthorizedException; +import com.gitblit.GitBlitException.UnknownRequestException; +import com.gitblit.models.RepositoryModel; +import com.gitblit.models.UserModel; +import com.google.gson.ExclusionStrategy; +import com.google.gson.FieldAttributes; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonPrimitive; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; +import com.google.gson.JsonSyntaxException; +import com.google.gson.reflect.TypeToken; + +/** + * Utility methods for json calls to a Gitblit server. + * + * @author James Moger + * + */ +public class JsonUtils { + + public static final Type REPOSITORIES_TYPE = new TypeToken>() { + }.getType(); + + public static final Type USERS_TYPE = new TypeToken>() { + }.getType(); + + /** + * Creates JSON from the specified object. + * + * @param o + * @return json + */ + public static String toJsonString(Object o) { + String json = gson().toJson(o); + return json; + } + + /** + * Convert a json string to an object of the specified type. + * + * @param json + * @param clazz + * @return an object + */ + public static X fromJsonString(String json, Class clazz) { + return gson().fromJson(json, clazz); + } + + /** + * Convert a json string to an object of the specified type. + * + * @param json + * @param clazz + * @return an object + */ + public static X fromJsonString(String json, Type type) { + return gson().fromJson(json, type); + } + + /** + * Reads a gson object from the specified url. + * + * @param url + * @param type + * @return the deserialized object + * @throws {@link IOException} + */ + public static X retrieveJson(String url, Type type) throws IOException, + UnauthorizedException { + return retrieveJson(url, type, null, null); + } + + /** + * Reads a gson object from the specified url. + * + * @param url + * @param type + * @return the deserialized object + * @throws {@link IOException} + */ + public static X retrieveJson(String url, Class clazz) throws IOException, + UnauthorizedException { + return retrieveJson(url, clazz, null, null); + } + + /** + * Reads a gson object from the specified url. + * + * @param url + * @param type + * @param username + * @param password + * @return the deserialized object + * @throws {@link IOException} + */ + public static X retrieveJson(String url, Type type, String username, char[] password) + throws IOException { + String json = retrieveJsonString(url, username, password); + if (StringUtils.isEmpty(json)) { + return null; + } + return gson().fromJson(json, type); + } + + /** + * Reads a gson object from the specified url. + * + * @param url + * @param clazz + * @param username + * @param password + * @return the deserialized object + * @throws {@link IOException} + */ + public static X retrieveJson(String url, Class clazz, String username, char[] password) + throws IOException { + String json = retrieveJsonString(url, username, password); + if (StringUtils.isEmpty(json)) { + return null; + } + return gson().fromJson(json, clazz); + } + + /** + * Retrieves a JSON message. + * + * @param url + * @return the JSON message as a string + * @throws {@link IOException} + */ + public static String retrieveJsonString(String url, String username, char[] password) + throws IOException { + try { + URLConnection conn = ConnectionUtils.openReadConnection(url, username, password); + InputStream is = conn.getInputStream(); + BufferedReader reader = new BufferedReader(new InputStreamReader(is, + ConnectionUtils.CHARSET)); + StringBuilder json = new StringBuilder(); + char[] buffer = new char[4096]; + int len = 0; + while ((len = reader.read(buffer)) > -1) { + json.append(buffer, 0, len); + } + is.close(); + return json.toString(); + } catch (IOException e) { + if (e.getMessage().indexOf("401") > -1) { + // unauthorized + throw new UnauthorizedException(url); + } else if (e.getMessage().indexOf("403") > -1) { + // requested url is forbidden by the requesting user + throw new ForbiddenException(url); + } else if (e.getMessage().indexOf("405") > -1) { + // requested url is not allowed by the server + throw new NotAllowedException(url); + } else if (e.getMessage().indexOf("501") > -1) { + // requested url is not recognized by the server + throw new UnknownRequestException(url); + } + throw e; + } + } + + /** + * Sends a JSON message. + * + * @param url + * the url to write to + * @param json + * the json message to send + * @return the http request result code + * @throws {@link IOException} + */ + public static int sendJsonString(String url, String json) throws IOException { + return sendJsonString(url, json, null, null); + } + + /** + * Sends a JSON message. + * + * @param url + * the url to write to + * @param json + * the json message to send + * @param username + * @param password + * @return the http request result code + * @throws {@link IOException} + */ + public static int sendJsonString(String url, String json, String username, char[] password) + throws IOException { + try { + byte[] jsonBytes = json.getBytes(ConnectionUtils.CHARSET); + URLConnection conn = ConnectionUtils.openConnection(url, username, password); + conn.setRequestProperty("Content-Type", "text/plain;charset=" + ConnectionUtils.CHARSET); + conn.setRequestProperty("Content-Length", "" + jsonBytes.length); + + // write json body + OutputStream os = conn.getOutputStream(); + os.write(jsonBytes); + os.close(); + + int status = ((HttpURLConnection) conn).getResponseCode(); + return status; + } catch (IOException e) { + if (e.getMessage().indexOf("401") > -1) { + // unauthorized + throw new UnauthorizedException(url); + } else if (e.getMessage().indexOf("403") > -1) { + // requested url is forbidden by the requesting user + throw new ForbiddenException(url); + } else if (e.getMessage().indexOf("405") > -1) { + // requested url is not allowed by the server + throw new NotAllowedException(url); + } else if (e.getMessage().indexOf("501") > -1) { + // requested url is not recognized by the server + throw new UnknownRequestException(url); + } + throw e; + } + } + + // build custom gson instance with GMT date serializer/deserializer + // http://code.google.com/p/google-gson/issues/detail?id=281 + public static Gson gson(ExclusionStrategy... strategies) { + GsonBuilder builder = new GsonBuilder(); + builder.registerTypeAdapter(Date.class, new GmtDateTypeAdapter()); + builder.registerTypeAdapter(AccessPermission.class, new AccessPermissionTypeAdapter()); + builder.setPrettyPrinting(); + if (!ArrayUtils.isEmpty(strategies)) { + builder.setExclusionStrategies(strategies); + } + return builder.create(); + } + + private static class GmtDateTypeAdapter implements JsonSerializer, JsonDeserializer { + private final DateFormat dateFormat; + + private GmtDateTypeAdapter() { + dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US); + dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); + } + + @Override + public synchronized JsonElement serialize(Date date, Type type, + JsonSerializationContext jsonSerializationContext) { + synchronized (dateFormat) { + String dateFormatAsString = dateFormat.format(date); + return new JsonPrimitive(dateFormatAsString); + } + } + + @Override + public synchronized Date deserialize(JsonElement jsonElement, Type type, + JsonDeserializationContext jsonDeserializationContext) { + try { + synchronized (dateFormat) { + Date date = dateFormat.parse(jsonElement.getAsString()); + return new Date((date.getTime() / 1000) * 1000); + } + } catch (ParseException e) { + throw new JsonSyntaxException(jsonElement.getAsString(), e); + } + } + } + + private static class AccessPermissionTypeAdapter implements JsonSerializer, JsonDeserializer { + + private AccessPermissionTypeAdapter() { + } + + @Override + public synchronized JsonElement serialize(AccessPermission permission, Type type, + JsonSerializationContext jsonSerializationContext) { + return new JsonPrimitive(permission.code); + } + + @Override + public synchronized AccessPermission deserialize(JsonElement jsonElement, Type type, + JsonDeserializationContext jsonDeserializationContext) { + return AccessPermission.fromCode(jsonElement.getAsString()); + } + } + + public static class ExcludeField implements ExclusionStrategy { + + private Class c; + private String fieldName; + + public ExcludeField(String fqfn) throws SecurityException, NoSuchFieldException, + ClassNotFoundException { + this.c = Class.forName(fqfn.substring(0, fqfn.lastIndexOf("."))); + this.fieldName = fqfn.substring(fqfn.lastIndexOf(".") + 1); + } + + public boolean shouldSkipClass(Class arg0) { + return false; + } + + public boolean shouldSkipField(FieldAttributes f) { + return (f.getDeclaringClass() == c && f.getName().equals(fieldName)); + } + } +} -- cgit v1.2.3