Java tutorial
/******************************************************************************* * Copyright 2012 Apigee Corporation * * 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 org.usergrid.rest; import static org.usergrid.persistence.cassandra.CassandraService.MANAGEMENT_APPLICATION_ID; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.util.Map; import java.util.SortedMap; import java.util.UUID; import javax.ws.rs.DefaultValue; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.ResponseBuilder; import javax.ws.rs.core.UriInfo; import org.apache.commons.lang.StringUtils; import org.apache.shiro.authz.UnauthorizedException; import org.codehaus.jackson.node.JsonNodeFactory; import org.codehaus.jackson.node.ObjectNode; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; import org.usergrid.rest.applications.ApplicationResource; import org.usergrid.rest.exceptions.NoOpException; import org.usergrid.rest.organizations.OrganizationResource; import org.usergrid.rest.security.annotations.RequireSystemAccess; import org.usergrid.system.UsergridSystemMonitor; import com.google.common.collect.BiMap; import com.sun.jersey.api.json.JSONWithPadding; import com.yammer.metrics.Metrics; import com.yammer.metrics.annotation.ExceptionMetered; import com.yammer.metrics.annotation.Timed; import com.yammer.metrics.core.Counter; import com.yammer.metrics.core.Gauge; import com.yammer.metrics.core.Histogram; import com.yammer.metrics.core.Metered; import com.yammer.metrics.core.Metric; import com.yammer.metrics.core.MetricName; import com.yammer.metrics.core.MetricProcessor; import com.yammer.metrics.core.MetricsRegistry; import com.yammer.metrics.core.Sampling; import com.yammer.metrics.core.Summarizable; import com.yammer.metrics.core.Timer; import com.yammer.metrics.stats.Snapshot; /** * * @author ed@anuff.com */ @Path("/") @Component @Scope("singleton") @Produces({ MediaType.APPLICATION_JSON, "application/javascript", "application/x-javascript", "text/ecmascript", "application/ecmascript", "text/jscript" }) public class RootResource extends AbstractContextResource implements MetricProcessor<RootResource.MetricContext> { static final class MetricContext { final boolean showFullSamples; final ObjectNode objectNode; MetricContext(ObjectNode objectNode, boolean showFullSamples) { this.objectNode = objectNode; this.showFullSamples = showFullSamples; } } private static final Logger logger = LoggerFactory.getLogger(RootResource.class); long started = System.currentTimeMillis(); @Autowired private UsergridSystemMonitor usergridSystemMonitor; public RootResource() { } @RequireSystemAccess @GET @Path("applications") public JSONWithPadding getAllApplications(@Context UriInfo ui, @QueryParam("callback") @DefaultValue("callback") String callback) throws URISyntaxException { logger.info("RootResource.getAllApplications"); ApiResponse response = createApiResponse(); response.setAction("get applications"); Map<String, UUID> applications = null; try { applications = emf.getApplications(); response.setSuccess(); response.setApplications(applications); } catch (Exception e) { logger.info("Unable to retrieve applications", e); response.setError("Unable to retrieve applications"); } return new JSONWithPadding(response, callback); } @RequireSystemAccess @GET @Path("apps") public JSONWithPadding getAllApplications2(@Context UriInfo ui, @QueryParam("callback") @DefaultValue("callback") String callback) throws URISyntaxException { return getAllApplications(ui, callback); } @GET public Response getRoot(@Context UriInfo ui) throws URISyntaxException { String redirect_root = properties.getRedirectRoot(); if (StringUtils.isNotBlank(redirect_root)) { ResponseBuilder response = Response.temporaryRedirect(new URI(redirect_root)); return response.build(); } else { ResponseBuilder response = Response.temporaryRedirect(new URI("/status")); return response.build(); } } @GET @Path("status") public JSONWithPadding getStatus(@QueryParam("callback") @DefaultValue("callback") String callback) { ApiResponse response = createApiResponse(); ObjectNode node = JsonNodeFactory.instance.objectNode(); node.put("started", started); node.put("uptime", System.currentTimeMillis() - started); node.put("version", usergridSystemMonitor.getBuildNumber()); node.put("cassandraAvailable", usergridSystemMonitor.getIsCassandraAlive()); dumpMetrics(node); response.setProperty("status", node); return new JSONWithPadding(response, callback); } @GET @Path("lb-status") public Response getLbStatus() { ResponseBuilder response; if (usergridSystemMonitor.getIsCassandraAlive()) { response = Response.noContent().status(Response.Status.OK); } else { response = Response.noContent().status(Response.Status.SERVICE_UNAVAILABLE); } return response.build(); } private void dumpMetrics(ObjectNode node) { MetricsRegistry registry = Metrics.defaultRegistry(); for (Map.Entry<String, SortedMap<MetricName, Metric>> entry : registry.groupedMetrics().entrySet()) { ObjectNode meterNode = JsonNodeFactory.instance.objectNode(); for (Map.Entry<MetricName, Metric> subEntry : entry.getValue().entrySet()) { ObjectNode metricNode = JsonNodeFactory.instance.objectNode(); try { subEntry.getValue().processWith(this, subEntry.getKey(), new MetricContext(metricNode, true)); } catch (Exception e) { logger.warn("Error writing out {}", subEntry.getKey(), e); } meterNode.put(subEntry.getKey().getName(), metricNode); } node.put(entry.getKey(), meterNode); } } @Path("{applicationId: [A-Fa-f0-9]{8}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{12}}") public ApplicationResource getApplicationById(@PathParam("applicationId") String applicationIdStr) throws Exception { if ("options".equalsIgnoreCase(request.getMethod())) { throw new NoOpException(); } UUID applicationId = UUID.fromString(applicationIdStr); if (applicationId == null) { return null; } return appResourceFor(applicationId); } private ApplicationResource appResourceFor(UUID applicationId) throws Exception { if (applicationId.equals(MANAGEMENT_APPLICATION_ID)) { throw new UnauthorizedException(); } return getSubResource(ApplicationResource.class).init(applicationId); } @Path("applications/{applicationId: [A-Fa-f0-9]{8}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{12}}") public ApplicationResource getApplicationById2(@PathParam("applicationId") String applicationId) throws Exception { return getApplicationById(applicationId); } @Path("apps/{applicationId: [A-Fa-f0-9]{8}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{12}}") public ApplicationResource getApplicationById3(@PathParam("applicationId") String applicationId) throws Exception { return getApplicationById(applicationId); } @Timed(name = "getApplicationByUuids_timer", group = "rest_timers") @ExceptionMetered(group = "rest_exceptions", name = "getApplicationByUuids_exceptions") @Path("{organizationId: [A-Fa-f0-9]{8}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{12}}/{applicationId: [A-Fa-f0-9]{8}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{12}}") public ApplicationResource getApplicationByUuids(@PathParam("organizationId") String organizationIdStr, @PathParam("applicationId") String applicationIdStr) throws Exception { UUID applicationId = UUID.fromString(applicationIdStr); UUID organizationId = UUID.fromString(organizationIdStr); if (applicationId == null || organizationId == null) { return null; } BiMap<UUID, String> apps = management.getApplicationsForOrganization(organizationId); if (apps.get(applicationId) == null) { return null; } return appResourceFor(applicationId); } private OrganizationResource orgResourceFor(String organizationName) throws Exception { return getSubResource(OrganizationResource.class).init(organizationName); } @Timed(name = "getOrganizationByName_timer", group = "rest_timers") @ExceptionMetered(group = "rest_exceptions", name = "getOrganizationByName_exceptions") @Path("{organizationName}") public OrganizationResource getOrganizationByName(@PathParam("organizationName") String organizationName) throws Exception { if ("options".equalsIgnoreCase(request.getMethod())) { throw new NoOpException(); } return orgResourceFor(organizationName); } @Path("organizations/{organizationName}") public OrganizationResource getOrganizationByName2(@PathParam("organizationName") String organizationName) throws Exception { return getOrganizationByName(organizationName); } @Path("orgs/{organizationName}") public OrganizationResource getOrganizationByName3(@PathParam("organizationName") String organizationName) throws Exception { return getOrganizationByName(organizationName); } @Path("o/{organizationName}") public OrganizationResource getOrganizationByName4(@PathParam("organizationName") String organizationName) throws Exception { return getOrganizationByName(organizationName); } @Override public void processHistogram(MetricName name, Histogram histogram, MetricContext context) throws Exception { final ObjectNode node = context.objectNode; node.put("type", "histogram"); node.put("count", histogram.count()); writeSummarizable(histogram, node); writeSampling(histogram, node); } @Override public void processCounter(MetricName name, Counter counter, MetricContext context) throws Exception { final ObjectNode node = context.objectNode; node.put("type", "counter"); node.put("count", counter.count()); } @Override public void processGauge(MetricName name, Gauge<?> gauge, MetricContext context) throws Exception { final ObjectNode node = context.objectNode; node.put("type", "gauge"); node.put("vale", "[disabled]"); } @Override public void processMeter(MetricName name, Metered meter, MetricContext context) throws Exception { final ObjectNode node = context.objectNode; node.put("type", "meter"); node.put("event_type", meter.eventType()); writeMeteredFields(meter, node); } @Override public void processTimer(MetricName name, Timer timer, MetricContext context) throws Exception { final ObjectNode node = context.objectNode; node.put("type", "timer"); // json.writeFieldName("duration"); node.put("unit", timer.durationUnit().toString().toLowerCase()); ObjectNode durationNode = JsonNodeFactory.instance.objectNode(); writeSummarizable(timer, durationNode); writeSampling(timer, durationNode); node.put("duration", durationNode); writeMeteredFields(timer, node); } private static void writeSummarizable(Summarizable metric, ObjectNode mNode) throws IOException { mNode.put("min", metric.min()); mNode.put("max", metric.max()); mNode.put("mean", metric.mean()); mNode.put("std_dev", metric.stdDev()); } private static void writeSampling(Sampling metric, ObjectNode mNode) throws IOException { final Snapshot snapshot = metric.getSnapshot(); mNode.put("median", snapshot.getMedian()); mNode.put("p75", snapshot.get75thPercentile()); mNode.put("p95", snapshot.get95thPercentile()); mNode.put("p98", snapshot.get98thPercentile()); mNode.put("p99", snapshot.get99thPercentile()); mNode.put("p999", snapshot.get999thPercentile()); } private static void writeMeteredFields(Metered metered, ObjectNode node) throws IOException { ObjectNode mNode = JsonNodeFactory.instance.objectNode(); mNode.put("unit", metered.rateUnit().toString().toLowerCase()); mNode.put("count", metered.count()); mNode.put("mean", metered.meanRate()); mNode.put("m1", metered.oneMinuteRate()); mNode.put("m5", metered.fiveMinuteRate()); mNode.put("m15", metered.fifteenMinuteRate()); node.put("rate", mNode); } }