Gather statistics about access to the web API.
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/remoting/server/web/base.web.api/src/org/netbeans/modules/jackpot30/backend/base/AccessStatistics.java Sat Oct 27 14:43:13 2012 +0200
1.3 @@ -0,0 +1,187 @@
1.4 +/*
1.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
1.6 + *
1.7 + * Copyright 2012 Oracle and/or its affiliates. All rights reserved.
1.8 + *
1.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
1.10 + * Other names may be trademarks of their respective owners.
1.11 + *
1.12 + * The contents of this file are subject to the terms of either the GNU
1.13 + * General Public License Version 2 only ("GPL") or the Common
1.14 + * Development and Distribution License("CDDL") (collectively, the
1.15 + * "License"). You may not use this file except in compliance with the
1.16 + * License. You can obtain a copy of the License at
1.17 + * http://www.netbeans.org/cddl-gplv2.html
1.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
1.19 + * specific language governing permissions and limitations under the
1.20 + * License. When distributing the software, include this License Header
1.21 + * Notice in each file and include the License file at
1.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
1.23 + * particular file as subject to the "Classpath" exception as provided
1.24 + * by Oracle in the GPL Version 2 section of the License file that
1.25 + * accompanied this code. If applicable, add the following below the
1.26 + * License Header, with the fields enclosed by brackets [] replaced by
1.27 + * your own identifying information:
1.28 + * "Portions Copyrighted [year] [name of copyright owner]"
1.29 + *
1.30 + * If you wish your version of this file to be governed by only the CDDL
1.31 + * or only the GPL Version 2, indicate your decision by adding
1.32 + * "[Contributor] elects to include this software in this distribution
1.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
1.34 + * single choice of license, a recipient has the option to distribute
1.35 + * your version of this file under either the CDDL, the GPL Version 2 or
1.36 + * to extend the choice of license to its licensees as provided above.
1.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
1.38 + * Version 2 license, then the option applies only if the new code is
1.39 + * made subject to such option by the copyright holder.
1.40 + *
1.41 + * Contributor(s):
1.42 + *
1.43 + * Portions Copyrighted 2012 Sun Microsystems, Inc.
1.44 + */
1.45 +package org.netbeans.modules.jackpot30.backend.base;
1.46 +
1.47 +import com.sun.jersey.spi.container.ContainerRequest;
1.48 +import com.sun.jersey.spi.container.ContainerRequestFilter;
1.49 +import java.io.BufferedInputStream;
1.50 +import java.io.BufferedOutputStream;
1.51 +import java.io.File;
1.52 +import java.io.FileInputStream;
1.53 +import java.io.FileOutputStream;
1.54 +import java.io.IOException;
1.55 +import java.io.InputStream;
1.56 +import java.io.OutputStream;
1.57 +import java.util.Collections;
1.58 +import java.util.HashMap;
1.59 +import java.util.List;
1.60 +import java.util.Map;
1.61 +import java.util.Map.Entry;
1.62 +import java.util.Properties;
1.63 +import java.util.concurrent.Executors;
1.64 +import java.util.concurrent.ScheduledExecutorService;
1.65 +import java.util.concurrent.TimeUnit;
1.66 +import java.util.logging.Level;
1.67 +import java.util.logging.Logger;
1.68 +
1.69 +/**
1.70 + *
1.71 + * @author lahvac
1.72 + */
1.73 +public class AccessStatistics implements ContainerRequestFilter {
1.74 +
1.75 + private static Map<String, Long> statistics = null;
1.76 + private static long lastModifyStamp = 0;
1.77 + private static long lastSaveStamp = -1;
1.78 + private static ScheduledExecutorService store = Executors.newSingleThreadScheduledExecutor();
1.79 +
1.80 + private static synchronized void incrementUsage(String key) {
1.81 + if (statistics == null) {
1.82 + statistics = new HashMap<String, Long>();
1.83 +
1.84 + File accessStatistics = CategoryStorage.getAccessStatisticsFile();
1.85 +
1.86 + if (accessStatistics.canRead()) {
1.87 + InputStream in = null;
1.88 +
1.89 + try {
1.90 + in = new BufferedInputStream(new FileInputStream(accessStatistics));
1.91 + Properties p = new Properties();
1.92 +
1.93 + p.load(in);
1.94 +
1.95 + for (String propertyKey : p.stringPropertyNames()) {
1.96 + try {
1.97 + long count = Long.parseLong(p.getProperty(propertyKey));
1.98 +
1.99 + statistics.put(propertyKey, count);
1.100 + } catch (NumberFormatException ex) {
1.101 + //ignore...
1.102 + Logger.getLogger(AccessStatistics.class.getName()).log(Level.SEVERE, null, ex);
1.103 + }
1.104 + }
1.105 + } catch (IOException ex) {
1.106 + Logger.getLogger(AccessStatistics.class.getName()).log(Level.SEVERE, null, ex);
1.107 + } finally {
1.108 + if (in != null) {
1.109 + try {
1.110 + in.close();
1.111 + } catch (IOException ex) {
1.112 + Logger.getLogger(AccessStatistics.class.getName()).log(Level.SEVERE, null, ex);
1.113 + }
1.114 + }
1.115 + }
1.116 + }
1.117 + }
1.118 +
1.119 + Long l = statistics.get(key);
1.120 +
1.121 + if (l == null) l = 0L;
1.122 +
1.123 + statistics.put(key, l + 1);
1.124 +
1.125 + lastModifyStamp++;
1.126 +
1.127 + store.schedule(new Runnable() {
1.128 + @Override public void run() {
1.129 + storeStatistics();
1.130 + }
1.131 + }, 1, TimeUnit.SECONDS);
1.132 + }
1.133 +
1.134 + private static void storeStatistics() {
1.135 + Properties p = new Properties();
1.136 +
1.137 + synchronized (AccessStatistics.class) {
1.138 + if (lastSaveStamp == lastModifyStamp) return;
1.139 + lastSaveStamp = lastModifyStamp;
1.140 + for (Entry<String, Long> e : statistics.entrySet()) {
1.141 + p.setProperty(e.getKey(), Long.toString(e.getValue()));
1.142 + }
1.143 + }
1.144 +
1.145 + File accessStatistics = CategoryStorage.getAccessStatisticsFile();
1.146 + File tempFile = new File(accessStatistics.getParentFile(), accessStatistics.getName() + ".new");
1.147 + OutputStream out = null;
1.148 +
1.149 + try {
1.150 + out = new BufferedOutputStream(new FileOutputStream(tempFile));
1.151 +
1.152 + p.store(out, "");
1.153 + } catch (IOException ex) {
1.154 + Logger.getLogger(AccessStatistics.class.getName()).log(Level.SEVERE, null, ex);
1.155 + } finally {
1.156 + if (out != null) {
1.157 + try {
1.158 + out.close();
1.159 + } catch (IOException ex) {
1.160 + Logger.getLogger(AccessStatistics.class.getName()).log(Level.SEVERE, null, ex);
1.161 + }
1.162 +
1.163 + tempFile.renameTo(accessStatistics);
1.164 + }
1.165 + }
1.166 + }
1.167 +
1.168 + public static synchronized Map<String, Long> getStatistics() {
1.169 + return Collections.unmodifiableMap(new HashMap<String, Long>(statistics));
1.170 + }
1.171 +
1.172 + @Override
1.173 + public ContainerRequest filter(ContainerRequest request) {
1.174 + StringBuilder statisticsKey = new StringBuilder();
1.175 + List<String> paths = request.getQueryParameters().get("path");
1.176 +
1.177 + statisticsKey.append(request.getPath());
1.178 +
1.179 + if (paths != null) {
1.180 + for (String path : paths) {
1.181 + statisticsKey.append(":").append(path);
1.182 + }
1.183 + }
1.184 +
1.185 + incrementUsage(statisticsKey.toString());
1.186 +
1.187 + return request;
1.188 + }
1.189 +
1.190 +}
2.1 --- a/remoting/server/web/base.web.api/src/org/netbeans/modules/jackpot30/backend/base/CategoryStorage.java Wed Oct 24 19:28:02 2012 +0200
2.2 +++ b/remoting/server/web/base.web.api/src/org/netbeans/modules/jackpot30/backend/base/CategoryStorage.java Sat Oct 27 14:43:13 2012 +0200
2.3 @@ -80,6 +80,10 @@
2.4 categoryCache = null;
2.5 }
2.6
2.7 + public static synchronized File getAccessStatisticsFile() {
2.8 + return new File(cacheRoot, "accessStatistics");
2.9 + }
2.10 +
2.11 public static void internalReset() {
2.12 setCacheRoot(cacheRoot);
2.13 }
2.14 @@ -95,6 +99,7 @@
2.15 List<CategoryStorage> result = new ArrayList<CategoryStorage>();
2.16
2.17 for (File cat : cacheRoot.listFiles()) {
2.18 + if (!cat.isDirectory()) continue;
2.19 File info = new File(cat, "info");
2.20 String displayName = cat.getName();
2.21 if (info.canRead()) {
3.1 --- a/remoting/server/web/base.web.api/src/org/netbeans/modules/jackpot30/backend/base/api/API.java Wed Oct 24 19:28:02 2012 +0200
3.2 +++ b/remoting/server/web/base.web.api/src/org/netbeans/modules/jackpot30/backend/base/api/API.java Sat Oct 27 14:43:13 2012 +0200
3.3 @@ -44,10 +44,9 @@
3.4 import javax.ws.rs.Path;
3.5 import javax.ws.rs.Produces;
3.6 import javax.ws.rs.QueryParam;
3.7 -import javax.ws.rs.core.Response;
3.8 -import javax.ws.rs.core.Response.Status;
3.9 +import org.codeviation.pojson.Pojson;
3.10 +import org.netbeans.modules.jackpot30.backend.base.AccessStatistics;
3.11 import org.netbeans.modules.jackpot30.backend.base.CategoryStorage;
3.12 -import org.openide.filesystems.FileObject;
3.13
3.14 /**
3.15 *
3.16 @@ -92,4 +91,11 @@
3.17 return cat.getInfo();
3.18 }
3.19
3.20 + @GET
3.21 + @Path("/accessStatistics")
3.22 + @Produces("text/plain")
3.23 + public String accessStatistics() throws IOException {
3.24 + return Pojson.save(AccessStatistics.getStatistics());
3.25 + }
3.26 +
3.27 }
4.1 --- a/remoting/server/web/web.main/src/web/main/WebMain.java Wed Oct 24 19:28:02 2012 +0200
4.2 +++ b/remoting/server/web/web.main/src/web/main/WebMain.java Sat Oct 27 14:43:13 2012 +0200
4.3 @@ -56,6 +56,7 @@
4.4 import java.util.ArrayList;
4.5 import java.util.Arrays;
4.6 import java.util.List;
4.7 +import org.netbeans.modules.jackpot30.backend.base.AccessStatistics;
4.8 import org.netbeans.modules.jackpot30.backend.base.CategoryStorage;
4.9 import org.netbeans.modules.jackpot30.backend.base.RelStreamHandlerFactory;
4.10 import org.openide.util.Exceptions;
4.11 @@ -104,6 +105,7 @@
4.12 // Jersey web resources
4.13 ServletAdapter jerseyAdapter = new ServletAdapter();
4.14 jerseyAdapter.addInitParameter("com.sun.jersey.config.property.packages", "org.netbeans.modules.jackpot30");
4.15 + jerseyAdapter.addInitParameter("com.sun.jersey.spi.container.ContainerRequestFilters", AccessStatistics.class.getName());
4.16 // jerseyAdapter.setContextPath("/");
4.17 jerseyAdapter.setServletInstance(new ServletContainer());
4.18