001/*
002 * Copyright 2011-2016 UnboundID Corp.
003 *
004 * This program is free software; you can redistribute it and/or modify
005 * it under the terms of the GNU General Public License (GPLv2 only)
006 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
007 * as published by the Free Software Foundation.
008 *
009 * This program is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
012 * GNU General Public License for more details.
013 *
014 * You should have received a copy of the GNU General Public License
015 * along with this program; if not, see <http://www.gnu.org/licenses>.
016 */
017
018package com.unboundid.scim.wink;
019
020import java.util.HashMap;
021import java.util.Map;
022import java.util.concurrent.ConcurrentHashMap;
023import java.util.concurrent.atomic.AtomicLong;
024
025/**
026 * This class holds various statistics of each SCIM resource being served.
027 */
028public class ResourceStats
029{
030  /**
031   * Number of query requests that were successful.
032   */
033  public static final String QUERY_OK = "query-successful";
034
035  /**
036   * Number of query requests that failed with code 400 Bad Request.
037   */
038  public static final String QUERY_BAD_REQUEST = "query-400";
039
040  /**
041   * Number of query requests that failed with code 401 Unauthorized.
042   */
043  public static final String QUERY_UNAUTHORIZED = "query-401";
044
045  /**
046   * Number of query requests that failed with code 403 Forbidden.
047   */
048  public static final String QUERY_FORBIDDEN = "query-403";
049
050  /**
051   * Number of query requests that failed with code 404 Not Found.
052   */
053  public static final String QUERY_NOT_FOUND = "query-404";
054
055  /**
056   * Number of query requests that failed with code 500 Internal Server Error.
057   */
058  public static final String QUERY_INTERNAL_SERVER_ERROR = "query-500";
059
060  /**
061   * Number of query requests that failed with code 505 Not Implemented.
062   */
063  public static final String QUERY_NOT_IMPLEMENTED = "query-505";
064
065  /**
066   * Number of query requests that responded in XML format.
067   */
068  public static final String QUERY_RESPONSE_XML = "query-response-xml";
069
070  /**
071   * Number of query requests that responded in JSON format.
072   */
073  public static final String QUERY_RESPONSE_JSON = "query-response-json";
074
075
076  /**
077   * Number of get requests that were successful.
078   */
079  public static final String GET_OK = "get-successful";
080
081  /**
082   * Number of versioned get requests that were not modified.
083   */
084  public static final String GET_NOT_MODIFIED = "get-304";
085
086  /**
087   * Number of get requests that failed with code 400 Bad Request.
088   */
089  public static final String GET_BAD_REQUEST = "get-400"
090
091  /**
092   * Number of get requests that failed with code 401 Unauthorized.
093   */;
094  public static final String GET_UNAUTHORIZED = "get-401";
095
096  /**
097   * Number of get requests that failed with code 403 Forbidden.
098   */
099  public static final String GET_FORBIDDEN = "get-403";
100
101  /**
102   * Number of get requests that failed with code 404 Not Found.
103   */
104  public static final String GET_NOT_FOUND = "get-404";
105
106  /**
107   * Number of get requests that failed with code 500 Internal Server Error.
108   */
109  public static final String GET_INTERNAL_SERVER_ERROR = "get-500";
110
111  /**
112   * Number of get requests that failed with code 505 Not Implemented.
113   */
114  public static final String GET_NOT_IMPLEMENTED = "get-505";
115
116  /**
117   * Number of get requests that responded in XML format.
118   */
119  public static final String GET_RESPONSE_XML = "get-response-xml";
120
121  /**
122   * Number of get requests that responded in JSON format.
123   */
124  public static final String GET_RESPONSE_JSON = "get-response-json";
125
126  /**
127   * Number of put requests that were successful.
128   */
129  public static final String PUT_OK = "put-successful";
130
131  /**
132   * Number of put requests that failed with code 400 Bad Request.
133   */
134  public static final String PUT_BAD_REQUEST = "put-400";
135
136  /**
137   * Number of put requests that failed with code 401 Unauthorized.
138   */
139  public static final String PUT_UNAUTHORIZED = "put-401";
140
141  /**
142   * Number of put requests that failed with code 403 Forbidden.
143   */
144  public static final String PUT_FORBIDDEN = "put-403";
145
146  /**
147   * Number of put requests that failed with code 404 Not Found.
148   */
149  public static final String PUT_NOT_FOUND = "put-404";
150
151  /**
152   * Number of put requests that failed with code 409 Conflict.
153   */
154  public static final String PUT_CONFLICT = "put-409";
155
156  /**
157   * Number of put requests that failed with code 412 Precondition Failed.
158   */
159  public static final String PUT_PRECONDITION_FAILED = "put-412";
160
161  /**
162   * Number of put requests that failed with code 500 Internal Server Error.
163   */
164  public static final String PUT_INTERNAL_SERVER_ERROR = "put-500";
165
166  /**
167   * Number of put requests that failed with code 505 Not Implemented.
168   */
169  public static final String PUT_NOT_IMPLEMENTED = "put-505";
170
171  /**
172   * Number of put requests that responded in XML format.
173   */
174  public static final String PUT_RESPONSE_XML = "put-response-xml";
175
176  /**
177   * Number of put requests that responded in JSON format.
178   */
179  public static final String PUT_RESPONSE_JSON = "put-response-json";
180
181  /**
182   * Number of put requests with content in XML format.
183   */
184  public static final String PUT_CONTENT_XML = "put-content-xml";
185
186  /**
187   * Number of put requests with content in JSON format.
188   */
189  public static final String PUT_CONTENT_JSON = "put-content-json";
190
191
192  /**
193   * Number of post requests that were successful.
194   */
195  public static final String POST_OK = "post-successful";
196
197  /**
198   * Number of post requests that failed with code 400 Bad Request.
199   */
200  public static final String POST_BAD_REQUEST = "post-400";
201
202  /**
203   * Number of post requests that failed with code 401 Unauthorized.
204   */
205  public static final String POST_UNAUTHORIZED = "post-401";
206
207  /**
208   * Number of post requests that failed with code 403 Forbidden.
209   */
210  public static final String POST_FORBIDDEN = "post-403";
211
212  /**
213   * Number of post requests that failed with code 409 Conflict.
214   */
215  public static final String POST_CONFLICT = "post-409";
216
217  /**
218   * Number of post requests that failed with code 413 Entity Too Large.
219   */
220  public static final String POST_REQUEST_ENTITY_TOO_LARGE = "post-413";
221
222  /**
223   * Number of post requests that failed with code 500 Internal Server Error.
224   */
225  public static final String POST_INTERNAL_SERVER_ERROR = "post-500";
226
227  /**
228   * Number of post requests that failed with code 505 Not Implemented.
229   */
230  public static final String POST_NOT_IMPLEMENTED = "post-505";
231
232  /**
233   * Number of post requests that responded in XML format.
234   */
235  public static final String POST_RESPONSE_XML = "post-response-xml";
236
237  /**
238   * Number of post requests that responded in JSON format.
239   */
240  public static final String POST_RESPONSE_JSON = "post-response-json";
241
242  /**
243   * Number of post requests with content in XML format.
244   */
245  public static final String POST_CONTENT_XML = "post-content-xml";
246
247  /**
248   * Number of post requests with content in JSON format.
249   */
250  public static final String POST_CONTENT_JSON = "post-content-json";
251
252
253  /**
254   * Number of patch requests that were successful.
255   */
256  public static final String PATCH_OK = "patch-successful";
257
258  /**
259   * Number of patch requests that failed with code 400 Bad Request.
260   */
261  public static final String PATCH_BAD_REQUEST = "patch-400";
262
263  /**
264   * Number of patch requests that failed with code 401 Unauthorized.
265   */
266  public static final String PATCH_UNAUTHORIZED = "patch-401";
267
268  /**
269   * Number of patch requests that failed with code 403 Forbidden.
270   */
271  public static final String PATCH_FORBIDDEN = "patch-403";
272
273  /**
274   * Number of patch requests that failed with code 404 Not Found.
275   */
276  public static final String PATCH_NOT_FOUND = "patch-404";
277
278  /**
279   * Number of patch requests that failed with code 409 Conflict.
280   */
281  public static final String PATCH_CONFLICT = "patch-409";
282
283  /**
284   * Number of patch requests that failed with code 412 Precondition Failed.
285   */
286  public static final String PATCH_PRECONDITION_FAILED = "patch-412";
287
288  /**
289   * Number of patch requests that failed with code 500 Internal Server Error.
290   */
291  public static final String PATCH_INTERNAL_SERVER_ERROR = "patch-500";
292
293  /**
294   * Number of patch requests that failed with code 505 Not Implemented.
295   */
296  public static final String PATCH_NOT_IMPLEMENTED = "patch-505";
297
298  /**
299   * Number of patch requests that responded in XML format.
300   */
301  public static final String PATCH_RESPONSE_XML = "patch-response-xml";
302
303  /**
304   * Number of patch requests that responded in JSON format.
305   */
306  public static final String PATCH_RESPONSE_JSON = "patch-response-json";
307
308  /**
309   * Number of patch requests with content in XML format.
310   */
311  public static final String PATCH_CONTENT_XML = "patch-content-xml";
312
313  /**
314   * Number of patch requests with content in JSON format.
315   */
316  public static final String PATCH_CONTENT_JSON = "patch-content-json";
317
318
319  /**
320   * Number of delete requests that were successful.
321   */
322  public static final String DELETE_OK = "delete-successful";
323
324  /**
325   * Number of delete requests that failed with code 400 Bad Request.
326   */
327  public static final String DELETE_BAD_REQUEST = "delete-400";
328
329  /**
330   * Number of delete requests that failed with code 401 Unauthorized.
331   */
332  public static final String DELETE_UNAUTHORIZED = "delete-401";
333
334  /**
335   * Number of delete requests that failed with code 403 Forbidden.
336   */
337  public static final String DELETE_FORBIDDEN = "delete-403";
338
339  /**
340   * Number of delete requests that failed with code 404 Not Found.
341   */
342  public static final String DELETE_NOT_FOUND = "delete-404";
343
344  /**
345   * Number of delete requests that failed with code 409 Conflict.
346   */
347  public static final String DELETE_CONFLICT = "delete-409";
348
349  /**
350   * Number of delete requests that failed with code 412 Precondition Failed.
351   */
352  public static final String DELETE_PRECONDITION_FAILED = "delete-412";
353
354  /**
355   * Number of delete requests that failed with code 500 Internal Server Error.
356   */
357  public static final String DELETE_INTERNAL_SERVER_ERROR = "delete-500";
358
359  /**
360   * Number of delete requests that failed with code 505 Not Implemented.
361   */
362  public static final String DELETE_NOT_IMPLEMENTED = "delete-505";
363
364  private final String name;
365  private final ConcurrentHashMap<String, AtomicLong> stats =
366      new ConcurrentHashMap<String, AtomicLong>();
367
368  /**
369   * Create a new ResourceStats instance with the provided name.
370   *
371   * @param name The name of this ResourceStats instance, usually it should
372   *             be the name of the SCIM resource being served.
373   */
374  public ResourceStats(final String name) {
375    this.name = name;
376  }
377
378  /**
379   * Increments a single statistical value.
380   *
381   * @param stat The name of the statistical value to increment.
382   */
383  void incrementStat(final String stat)
384  {
385    AtomicLong num = stats.get(stat);
386    if(num == null)
387    {
388      num = new AtomicLong();
389      AtomicLong prev = stats.putIfAbsent(stat, num);
390      if(prev != null)
391      {
392        num = prev;
393      }
394    }
395    num.getAndIncrement();
396  }
397
398  /**
399   * Retrieves a single statistical value.
400   *
401   * @param stat The name of the statistical value to retrieve.
402   * @return The statistical value or 0 if it is not present.
403   */
404  public long getStat(final String stat)
405  {
406    AtomicLong i = stats.get(stat);
407    if(i != null)
408    {
409      return i.get();
410    }
411    return 0;
412  }
413
414  /**
415   * Retrieves all statistical values that are present.
416   *
417   * @return All statistical values that are present.
418   */
419  public Map<String, Long> getStats()
420  {
421    Map<String, Long> map = new HashMap<String, Long>(stats.size());
422    for(Map.Entry<String, AtomicLong> entry : stats.entrySet())
423    {
424      map.put(entry.getKey(), entry.getValue().get());
425    }
426    return map;
427  }
428
429  /**
430   * Retrieves the name of this ResourceStats instance, usually the name of
431   * the SCIM resource being served.
432   *
433   * @return The name of this ResourceStats instance, usually the name of
434   * the SCIM resource being served.
435   */
436  public String getName() {
437    return name;
438  }
439}