This repository has been archived by the owner on Nov 9, 2017. It is now read-only.
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
rhbz988202 - add introspectable REST service and make rate limiting b…
…ucket monitorable
- Loading branch information
Patrick Huang
committed
Mar 10, 2014
1 parent
520aab9
commit bc91d20
Showing
4 changed files
with
250 additions
and
21 deletions.
There are no files selected for viewing
147 changes: 147 additions & 0 deletions
147
zanata-war/src/main/java/org/zanata/rest/service/IntrospectableObjectMonitorService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
package org.zanata.rest.service; | ||
|
||
import java.lang.reflect.Type; | ||
import java.net.URI; | ||
import java.util.List; | ||
import javax.ws.rs.Consumes; | ||
import javax.ws.rs.DefaultValue; | ||
import javax.ws.rs.GET; | ||
import javax.ws.rs.HeaderParam; | ||
import javax.ws.rs.Path; | ||
import javax.ws.rs.PathParam; | ||
import javax.ws.rs.Produces; | ||
import javax.ws.rs.core.Context; | ||
import javax.ws.rs.core.GenericEntity; | ||
import javax.ws.rs.core.MediaType; | ||
import javax.ws.rs.core.Response; | ||
import javax.xml.bind.annotation.XmlRootElement; | ||
|
||
import org.jboss.resteasy.annotations.providers.jaxb.Wrapped; | ||
import org.jboss.resteasy.util.GenericType; | ||
import org.jboss.seam.annotations.Name; | ||
import org.jboss.seam.annotations.Transactional; | ||
import org.jboss.seam.annotations.security.Restrict; | ||
import org.zanata.common.Namespaces; | ||
import org.zanata.rest.MediaTypes; | ||
import org.zanata.rest.dto.Link; | ||
import org.zanata.seam.interceptor.RateLimitingInterceptor; | ||
import org.zanata.util.Introspectable; | ||
import com.google.common.base.Function; | ||
import com.google.common.base.Optional; | ||
import com.google.common.base.Predicate; | ||
import com.google.common.collect.ImmutableList; | ||
import com.google.common.collect.Iterables; | ||
import com.google.common.collect.Lists; | ||
import lombok.extern.slf4j.Slf4j; | ||
|
||
/** | ||
* @author Patrick Huang <a | ||
* href="mailto:pahuang@redhat.com">pahuang@redhat.com</a> | ||
*/ | ||
@Name("introspectableObjectMonitorService") | ||
@Path("/monitor") | ||
@Produces({ "application/xml" }) | ||
@Consumes({ "application/xml" }) | ||
@Transactional | ||
@Restrict("#{s:hasRole('admin')}") | ||
@Slf4j | ||
public class IntrospectableObjectMonitorService { | ||
// TODO check http://code.google.com/p/reflections/ and re-implement this | ||
private static List<Introspectable> introspectables = ImmutableList | ||
.<Introspectable> builder().add(new RateLimitingInterceptor()) | ||
.build(); | ||
|
||
/** Type of media requested. */ | ||
@HeaderParam("Accept") | ||
@DefaultValue(MediaType.APPLICATION_XML) | ||
@Context | ||
private MediaType accept; | ||
|
||
/** | ||
* Return all Introspectable objects link. | ||
* | ||
* @return The following response status codes will be returned from this | ||
* operation:<br> | ||
* OK(200) - all available introspectable objects with hypermedia link.<br> | ||
* UNAUTHORIZED(401) - if not admin role.<br> | ||
* INTERNAL SERVER ERROR(500) - If there is an unexpected error in | ||
* the server while performing this operation. | ||
*/ | ||
@GET | ||
@Wrapped(element = "introspectable", namespace = Namespaces.ZANATA_API) | ||
public Response get() { | ||
List<LinkRoot> all = | ||
Lists.transform(introspectables, | ||
new Function<Introspectable, LinkRoot>() { | ||
@Override | ||
public LinkRoot apply(Introspectable input) { | ||
return new LinkRoot( | ||
URI.create("/" | ||
+ new RateLimitingInterceptor() | ||
.getId()), "self", | ||
MediaTypes.createFormatSpecificType( | ||
MediaType.APPLICATION_XML, | ||
accept)); | ||
} | ||
}); | ||
|
||
Type genericType = new GenericType<List<LinkRoot>>() { | ||
}.getGenericType(); | ||
Object entity = new GenericEntity<List<LinkRoot>>(all, genericType); | ||
return Response.ok().entity(entity).build(); | ||
} | ||
|
||
/** | ||
* Return a single introspectable fields as String. | ||
* @param id introspectable id | ||
* @return The following response status codes will be returned from this | ||
* operation:<br> | ||
* OK(200) - Response containing a string of all fields and values.<br> | ||
* NOT_FOUND(404) - given id does not represent an introspectable.<br> | ||
* INTERNAL SERVER ERROR(500) - If there is an unexpected error in | ||
* the server while performing this operation. | ||
*/ | ||
@GET | ||
@Path("/{id}") | ||
public Response get(@PathParam("id") final String id) { | ||
|
||
Optional<Introspectable> optional = | ||
Iterables.tryFind(introspectables, | ||
new Predicate<Introspectable>() { | ||
@Override | ||
public boolean apply(Introspectable input) { | ||
return input.getId().equals(id); | ||
} | ||
}); | ||
if (!optional.isPresent()) { | ||
return Response.status(Response.Status.NOT_FOUND).build(); | ||
} | ||
final Introspectable introspectable = optional.get(); | ||
final String format = "%s:%s\n"; | ||
Iterable<String> report = | ||
Iterables.transform(introspectable.getFieldNames(), | ||
new Function<String, String>() { | ||
@Override | ||
public String apply(String fieldName) { | ||
return String.format(format, fieldName, | ||
introspectable.get(fieldName)); | ||
} | ||
}); | ||
return Response | ||
.ok() | ||
.entity(introspectable.getId() + "{" | ||
+ Iterables.toString(report) + "}").build(); | ||
} | ||
|
||
@XmlRootElement(name = "link") | ||
public static class LinkRoot extends Link { | ||
@SuppressWarnings("unused") | ||
public LinkRoot() { | ||
super(); | ||
} | ||
|
||
public LinkRoot(URI href, String rel, String type) { | ||
super(href, rel, type); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
12 changes: 12 additions & 0 deletions
12
zanata-war/src/main/java/org/zanata/util/Introspectable.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package org.zanata.util; | ||
|
||
import java.util.Collection; | ||
|
||
public interface Introspectable { | ||
|
||
String getId(); | ||
|
||
Collection<String> getFieldNames(); | ||
|
||
String get(String fieldName); | ||
} |