Return-Path: X-Original-To: apmail-tamaya-commits-archive@minotaur.apache.org Delivered-To: apmail-tamaya-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 6F71718DF7 for ; Sat, 30 Apr 2016 19:37:48 +0000 (UTC) Received: (qmail 92291 invoked by uid 500); 30 Apr 2016 19:37:48 -0000 Delivered-To: apmail-tamaya-commits-archive@tamaya.apache.org Received: (qmail 92259 invoked by uid 500); 30 Apr 2016 19:37:48 -0000 Mailing-List: contact commits-help@tamaya.incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@tamaya.incubator.apache.org Delivered-To: mailing list commits@tamaya.incubator.apache.org Received: (qmail 92249 invoked by uid 99); 30 Apr 2016 19:37:48 -0000 Received: from pnap-us-west-generic-nat.apache.org (HELO spamd3-us-west.apache.org) (209.188.14.142) by apache.org (qpsmtpd/0.29) with ESMTP; Sat, 30 Apr 2016 19:37:48 +0000 Received: from localhost (localhost [127.0.0.1]) by spamd3-us-west.apache.org (ASF Mail Server at spamd3-us-west.apache.org) with ESMTP id C882A180290 for ; Sat, 30 Apr 2016 19:37:47 +0000 (UTC) X-Virus-Scanned: Debian amavisd-new at spamd3-us-west.apache.org X-Spam-Flag: NO X-Spam-Score: -3.221 X-Spam-Level: X-Spam-Status: No, score=-3.221 tagged_above=-999 required=6.31 tests=[KAM_ASCII_DIVIDERS=0.8, KAM_LAZY_DOMAIN_SECURITY=1, RCVD_IN_DNSWL_HI=-5, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, RP_MATCHES_RCVD=-0.001] autolearn=disabled Received: from mx2-lw-eu.apache.org ([10.40.0.8]) by localhost (spamd3-us-west.apache.org [10.40.0.10]) (amavisd-new, port 10024) with ESMTP id pSaCRefbZLTC for ; Sat, 30 Apr 2016 19:37:39 +0000 (UTC) Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by mx2-lw-eu.apache.org (ASF Mail Server at mx2-lw-eu.apache.org) with SMTP id 363E35F296 for ; Sat, 30 Apr 2016 19:37:37 +0000 (UTC) Received: (qmail 92003 invoked by uid 99); 30 Apr 2016 19:37:36 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Sat, 30 Apr 2016 19:37:36 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 1DACBE00C7; Sat, 30 Apr 2016 19:37:36 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: anatole@apache.org To: commits@tamaya.incubator.apache.org Date: Sat, 30 Apr 2016 19:37:37 -0000 Message-Id: In-Reply-To: References: X-Mailer: ASF-Git Admin Mailer Subject: [2/5] incubator-tamaya git commit: TAMAYA-156: Added stats function, TAMAYA-150: Refactored UI Widgets., TAMAYA-157: Added CLI main arg support. TAMAYA-156: Added stats function, TAMAYA-150: Refactored UI Widgets., TAMAYA-157: Added CLI main arg support. Project: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/commit/4749d395 Tree: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/tree/4749d395 Diff: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/diff/4749d395 Branch: refs/heads/master Commit: 4749d3950983a78b0fd33459cf15cf339dc44f51 Parents: a7ee4e4 Author: anatole Authored: Sat Apr 30 19:57:52 2016 +0200 Committer: anatole Committed: Sat Apr 30 19:57:52 2016 +0200 ---------------------------------------------------------------------- .../core/propertysource/CLIPropertySource.java | 102 +++++++ .../propertysource/CLIPropertySourceTest.java | 58 ++++ .../java/org/apache/tamaya/model/Usage.java | 275 +++++++++++++++++++ .../org/apache/tamaya/model/UsageReference.java | 45 +++ .../model/internal/DefaultUsageTracker.java | 127 +++++++++ .../model/internal/UsageTrackerFilter.java | 45 +++ .../tamaya/model/spi/UsageTrackerSpi.java | 67 +++++ .../org.apache.tamaya.model.spi.UsageTrackerSpi | 19 ++ .../org.apache.tamaya.spi.PropertyFilter | 19 ++ .../java/test/model/TestConfigAccessor.java | 27 ++ .../mutableconfig/ui/ConfigEditorWidget.java | 110 ++++++++ .../mutableconfig/ui/ConfigUpdaterView.java | 33 +-- .../tamaya/mutableconfig/ui/ProtocolWidget.java | 87 ++++++ .../ui/TransactionControlWidget.java | 168 +++++++++++ .../main/resources/ui/lang/tamaya.properties | 13 +- 15 files changed, 1175 insertions(+), 20 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/4749d395/code/core/src/main/java/org/apache/tamaya/core/propertysource/CLIPropertySource.java ---------------------------------------------------------------------- diff --git a/code/core/src/main/java/org/apache/tamaya/core/propertysource/CLIPropertySource.java b/code/core/src/main/java/org/apache/tamaya/core/propertysource/CLIPropertySource.java new file mode 100644 index 0000000..ddc540e --- /dev/null +++ b/code/core/src/main/java/org/apache/tamaya/core/propertysource/CLIPropertySource.java @@ -0,0 +1,102 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.tamaya.core.propertysource; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +/** + * PropertySource that allows to add the programs main arguments as configuration entries. Unix syntax using '--' and + * '-' params is supported. + */ +public class CLIPropertySource extends BasePropertySource{ + + /** The original main arguments. */ + private static String[] args = new String[0]; + + /** The map of parsed main arguments. */ + private static Map mainArgs; + + /** Initializes the initial state. */ + static{ + initMainArgs(args); + } + + + /** + * Creates a new instance. + */ + public CLIPropertySource(){} + + /** + * Configure the main arguments, herby parsing and mapping the main arguments into + * configuration properties. + * @param args the main arguments, not null. + * @returns the parsed main arguments as key/value pairs. + */ + public static void initMainArgs(String... args){ + CLIPropertySource.args = Objects.requireNonNull(args); + // TODO is there a way to figure out the args? + String argsProp = System.getProperty("main.args"); + if(argsProp!=null){ + CLIPropertySource.args = argsProp.split("\\s"); + } + Map result = null; + if(CLIPropertySource.args==null){ + result = Collections.emptyMap(); + }else{ + result = new HashMap<>(); + String prefix = System.getProperty("main.args.prefix"); + if(prefix==null){ + prefix=""; + } + String key = null; + for(String arg:CLIPropertySource.args){ + if(arg.startsWith("--")){ + arg = arg.substring(2); + int index = arg.indexOf("="); + if(index>0){ + key = arg.substring(0,index).trim(); + result.put(prefix+key, arg.substring(index+1).trim()); + key = null; + }else{ + result.put(prefix+arg, arg); + } + }else if(arg.startsWith("-")){ + key = arg.substring(1); + }else{ + if(key!=null){ + result.put(prefix+key, arg); + key = null; + }else{ + result.put(prefix+arg, arg); + } + } + } + } + CLIPropertySource.mainArgs = Collections.unmodifiableMap(result); + } + + @Override + public Map getProperties() { + return Collections.unmodifiableMap(mainArgs); + } +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/4749d395/code/core/src/test/java/org/apache/tamaya/core/propertysource/CLIPropertySourceTest.java ---------------------------------------------------------------------- diff --git a/code/core/src/test/java/org/apache/tamaya/core/propertysource/CLIPropertySourceTest.java b/code/core/src/test/java/org/apache/tamaya/core/propertysource/CLIPropertySourceTest.java new file mode 100644 index 0000000..dde63e5 --- /dev/null +++ b/code/core/src/test/java/org/apache/tamaya/core/propertysource/CLIPropertySourceTest.java @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.tamaya.core.propertysource; + +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * Tests for PropertySource for reading main arguments as configuration. + */ +public class CLIPropertySourceTest { + + @Test + public void setCLIProps() throws Exception { + System.clearProperty("main.args"); + CLIPropertySource ps = new CLIPropertySource(); + assertTrue(ps.getProperties().isEmpty()); + CLIPropertySource.initMainArgs("-a", "b"); + assertFalse(ps.getProperties().isEmpty()); + assertEquals(ps.getProperties().get("a"), "b"); + CLIPropertySource.initMainArgs("--c"); + assertFalse(ps.getProperties().isEmpty()); + assertEquals(ps.getProperties().get("c"), "c"); + CLIPropertySource.initMainArgs("sss"); + assertFalse(ps.getProperties().isEmpty()); + assertEquals(ps.getProperties().get("sss"), "sss"); + CLIPropertySource.initMainArgs("-a", "b", "--c", "sss", "--val=vvv"); + assertFalse(ps.getProperties().isEmpty()); + assertEquals(ps.getProperties().get("a"), "b"); + assertEquals(ps.getProperties().get("c"), "c"); + assertEquals(ps.getProperties().get("sss"), "sss"); + // getProperties() throws Exception { + System.setProperty("main.args", "-a b\t--c sss "); + ps = new CLIPropertySource(); + assertFalse(ps.getProperties().isEmpty()); + System.clearProperty("main.args"); + assertEquals(ps.getProperties().get("a"), "b"); + assertEquals(ps.getProperties().get("c"), "c"); + assertEquals(ps.getProperties().get("sss"), "sss"); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/4749d395/modules/model/src/main/java/org/apache/tamaya/model/Usage.java ---------------------------------------------------------------------- diff --git a/modules/model/src/main/java/org/apache/tamaya/model/Usage.java b/modules/model/src/main/java/org/apache/tamaya/model/Usage.java new file mode 100644 index 0000000..d5625f3 --- /dev/null +++ b/modules/model/src/main/java/org/apache/tamaya/model/Usage.java @@ -0,0 +1,275 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.tamaya.model; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicLong; +import java.util.logging.Logger; + +/** + * Metrics container containing access statistics for a given vonfiguration key. + */ +public final class Usage { + private static final Logger LOG = Logger.getLogger(Usage.class.getName()); + /** + * the config section. + */ + private final String key; + + /** + * Maps with usage references, key is the fully qualified package name. + */ + private final Map accessDetails = new ConcurrentHashMap<>(); + + /** + * Creates a usage metric container for a given key. + * @param key the parameter (fully qualified). + */ + public Usage(String key) { + this.key = Objects.requireNonNull(key); + } + + /** + * Get the configModel section. + * + * @return the section, never null. + */ + public String getKey() { + return key; + } + + /** + * Clears all collected usage metrics for this key. + */ + public void clearMetrics(){ + this.accessDetails.clear(); + } + + /** + * Get the detail message. + * + * @return the detail message, or null. + */ + public int getReferenceCount() { + return accessDetails.size(); + } + + /** + * Get the detail message. + * + * @return the detail message, or null. + */ + public int getUsageCount() { + int count = 0; + for(AccessDetail ref: accessDetails.values()){ + count += ref.getAccessCount(); + } + return count; + } + + /** + * Access a usage reference for a given class. + * @return the usage ref, if present, or null. + */ + public Collection getAccessDetails(Class type){ + return getAccessDetails(type.getName() +"\\..*"); + } + + /** + * Access a usage reference for a given package. + * @return the usage ref, if present, or null. + */ + public Collection getAccessDetails(Package pack){ + return getAccessDetails(pack.getName() +"\\..*"); + } + + /** + * Find usages of this key for the given expression (regex). Hereby the expression is + * matched with the tracked reference identifier, which has the form + * {@code f.q.n.ClassName#methodName(line: 123)}. + * @param lookupExpression the target lookup expression, not null. + * @return the matching references, not null. + */ + public Collection getAccessDetails(String lookupExpression){ + List result = new ArrayList<>(); + for(AccessDetail ref:this.accessDetails.values()){ + if(ref.getAccessPoint().matches(lookupExpression)){ + result.add(ref); + } + } + return result; + } + + @Override + public String toString() { + return "Usage Count: " + key + " -> " + getUsageCount() + '\n'; + } + + /** + * Get the access details (stacktrace etrc) for this reference. + * @return return the access details, not null. + */ + public Collection getAccessDetails(){ + return Collections.unmodifiableCollection(accessDetails.values()); + } + + /** + * Evaluates the current access point from the current stacktrace and adds an according + * usage reference object (or updates any existing one) for the given key. The + * stacktrace is shortened to a maximal size of 20 items. + * @param value the value returned, not null. + */ + public void trackUsage(String value){ + trackUsage(value, 10); + } + + /** + * Evaluates the current access point from the current stacktrace and adds an according + * usage reference object (or updates any existing one) for the given key. + * @param value the value returned, not null. + * @param maxTraceLength the maximal length of the stored stacktrace. + */ + public void trackUsage(String value, int maxTraceLength){ + + Exception e = new Exception(); + List trace = new ArrayList<>(); + String accessPoint = null; + stack:for(StackTraceElement ste:e.getStackTrace()){ + for(String ignored: ConfigModelManager.getIgnoredPackages()) { + if (ste.getClassName().startsWith(ignored)) { + continue stack; + } + } + String ref = ste.getClassName() + '#' + ste.getMethodName() + "(line:" + ste.getLineNumber() + ')'; + trace.add(ref); + if (accessPoint == null) { + accessPoint = ref; + } + if(trace.size()>=maxTraceLength){ + break; + } + } + if (accessPoint == null) { + // all ignored, take first one, with different package + accessPoint = ""; + } + AccessDetail details = getAccessDetails(accessPoint, trace.toArray(new String[trace.size()])); + details.trackAccess(value); + } + + private AccessDetail getAccessDetails(String accessPoint, String[] trace) { + AccessDetail details = accessDetails.get(accessPoint); + if(details==null){ + details = new AccessDetail(accessPoint, trace); + accessDetails.put(accessPoint, details); + } + return details; + } + + /** + * Class modelling the access details tracked per detailed item, e.g. per class in the owning package. + */ + public static final class AccessDetail { + private AtomicLong accessCount = new AtomicLong(); + private long lastAccessTS; + private long firstAccessTS; + private String[] stackTrace; + private String accessPoint; + private Map trackedValues; + + public AccessDetail(String accessPoint, String[] stackTrace){ + this.accessPoint = Objects.requireNonNull(accessPoint); + this.stackTrace = stackTrace.clone(); + } + + public void clearStats(){ + lastAccessTS = 0; + firstAccessTS = 0; + accessCount.set(0); + } + + public long trackAccess(String value){ + long count = accessCount.incrementAndGet(); + lastAccessTS = System.currentTimeMillis(); + if(firstAccessTS==0){ + firstAccessTS = lastAccessTS; + } + if(value!=null){ + synchronized (this) { + if(trackedValues==null){ + trackedValues = new HashMap<>(); + } + trackedValues.put(lastAccessTS, value); + } + } + return count; + } + + public long getAccessCount() { + return accessCount.get(); + } + + public String getAccessPoint() { + return accessPoint; + } + + public long getFirstAccessTS() { + return firstAccessTS; + } + + public long getLastAccessTS() { + return lastAccessTS; + } + + public String[] getStackTrace() { + return stackTrace.clone(); + } + + public Map getTrackedValues(){ + if(trackedValues==null){ + return Collections.emptyMap(); + }else{ + synchronized (this) { + return new HashMap<>(trackedValues); + } + } + } + + @Override + public String toString() { + return "AccessDetails{" + + "accessCount=" + accessCount + + ", lastAccessTS=" + lastAccessTS + + ", firstAccessTS=" + firstAccessTS + + ", stackTrace=" + Arrays.toString(stackTrace) + + ", accessPoint='" + accessPoint + '\'' + + ", trackedValues=" + trackedValues + + '}'; + } + } + +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/4749d395/modules/model/src/main/java/org/apache/tamaya/model/UsageReference.java ---------------------------------------------------------------------- diff --git a/modules/model/src/main/java/org/apache/tamaya/model/UsageReference.java b/modules/model/src/main/java/org/apache/tamaya/model/UsageReference.java new file mode 100644 index 0000000..3504def --- /dev/null +++ b/modules/model/src/main/java/org/apache/tamaya/model/UsageReference.java @@ -0,0 +1,45 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.tamaya.model; + +import java.util.*; +import java.util.concurrent.atomic.AtomicLong; + +/** + * Reference object store for a parameter or configuration accessed. + */ +public class UsageReference { + + private String reference; + + + public UsageReference(String reference){ + this.reference = Objects.requireNonNull(reference); + } + + /** + * Access the package name which accessed the configuration. + * @return the package name, never null. + */ + public String getReference(){ + return reference; + } + + +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/4749d395/modules/model/src/main/java/org/apache/tamaya/model/internal/DefaultUsageTracker.java ---------------------------------------------------------------------- diff --git a/modules/model/src/main/java/org/apache/tamaya/model/internal/DefaultUsageTracker.java b/modules/model/src/main/java/org/apache/tamaya/model/internal/DefaultUsageTracker.java new file mode 100644 index 0000000..73729f1 --- /dev/null +++ b/modules/model/src/main/java/org/apache/tamaya/model/internal/DefaultUsageTracker.java @@ -0,0 +1,127 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.tamaya.model.internal; + +import org.apache.tamaya.model.Usage; +import org.apache.tamaya.model.spi.UsageTrackerSpi; + +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; + +/** + * Created by atsticks on 29.04.16. + */ +public class DefaultUsageTracker implements UsageTrackerSpi{ + + private Set ignoredPackages = new HashSet<>(); + + private Map usages = new ConcurrentHashMap<>(); + + public DefaultUsageTracker(){ + ignoredPackages.add("com.intellij"); + ignoredPackages.add("java"); + ignoredPackages.add("org.junit"); + ignoredPackages.add("junit"); + ignoredPackages.add("javax"); + ignoredPackages.add("sun"); + ignoredPackages.add("oracle"); + ignoredPackages.add("com.sun"); + ignoredPackages.add("com.oracle"); + ignoredPackages.add("org.apache.tamaya"); + } + + @Override + public Set getIgnoredPackages() { + return Collections.unmodifiableSet(ignoredPackages); + } + + /** + * Get the recorded usage references of configuration. + * @return the recorded usge references, never null. + */ + @Override + public Collection getUsages() { + return usages.values(); + } + + @Override + public void trackConfigurationAccess(){ + trackSingleKeyAccess("[[Configuration]]", ""); + } + + @Override + public void trackAllPropertiesAccess(){ + trackSingleKeyAccess("<>", ""); + } + + @Override + public void trackSingleKeyAccess(String key, String value){ + // Ignore meta-entries + if(key.startsWith("_")){ + return; + } + Usage usage = this.usages.get(key); + if(usage==null){ + usage = new Usage(key); + this.usages.put(key, usage); + } + usage.trackUsage(value); + } + + + /** + * Access the usage statistics for the recorded uses of configuration. + */ + @Override + public String getUsageInfo(){ + StringBuilder b = new StringBuilder(); + b.append("Apache Tamaya Configuration Usage Metrics\n"); + b.append("=========================================\n"); + b.append("DATE: " + new Date()).append("\n\n"); + List usages = new ArrayList<>(getUsages()); + Collections.sort(usages, new Comparator() { + @Override + public int compare(Usage k1, Usage k2) { + return k2.getUsageCount() - k1.getUsageCount(); + } + }); + for(Usage usage:usages){ + String usageCount = String.valueOf(usage.getUsageCount()); + b.append(usageCount); + b.append(" ".substring(0, 7-usageCount.length())); + b.append(usage.getKey()).append(":\n"); + for(Usage.AccessDetail details: usage.getAccessDetails()) { + String accessCount = String.valueOf(details.getAccessCount()); + b.append(" - ").append(accessCount); + b.append(" ".substring(0, 6-usageCount.length())); + b.append(details.getAccessPoint()); + int endIndex = 50-details.getAccessPoint().length(); + if(endIndex<0){ + endIndex = 0; + } + b.append(" ".substring(0, endIndex)); + b.append(",");b.append(" first=").append(new Date(details.getFirstAccessTS())) + .append(",");b.append(" last=").append(new Date(details.getLastAccessTS())) + .append('\n'); + } + } + return b.toString(); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/4749d395/modules/model/src/main/java/org/apache/tamaya/model/internal/UsageTrackerFilter.java ---------------------------------------------------------------------- diff --git a/modules/model/src/main/java/org/apache/tamaya/model/internal/UsageTrackerFilter.java b/modules/model/src/main/java/org/apache/tamaya/model/internal/UsageTrackerFilter.java new file mode 100644 index 0000000..8cf7b60 --- /dev/null +++ b/modules/model/src/main/java/org/apache/tamaya/model/internal/UsageTrackerFilter.java @@ -0,0 +1,45 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.tamaya.model.internal; + +import org.apache.tamaya.model.spi.UsageTrackerSpi; +import org.apache.tamaya.spi.FilterContext; +import org.apache.tamaya.spi.PropertyFilter; +import org.apache.tamaya.spi.ServiceContextManager; + +import javax.annotation.Priority; + +/** + * Configuration filter to be applied at the end of the filter chain. This filter + * actually does not change the current filter value, but use the filter process + * to track configuration usage. + */ +@Priority(Integer.MAX_VALUE) +public class UsageTrackerFilter implements PropertyFilter{ + @Override + public String filterProperty(String value, FilterContext context) { + UsageTrackerSpi tracker = ServiceContextManager.getServiceContext().getService(UsageTrackerSpi.class); + if(context.isSinglePropertyScoped()) { + tracker.trackSingleKeyAccess(context.getKey(), value); + }else{ + tracker.trackAllPropertiesAccess(); + } + return value; + } +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/4749d395/modules/model/src/main/java/org/apache/tamaya/model/spi/UsageTrackerSpi.java ---------------------------------------------------------------------- diff --git a/modules/model/src/main/java/org/apache/tamaya/model/spi/UsageTrackerSpi.java b/modules/model/src/main/java/org/apache/tamaya/model/spi/UsageTrackerSpi.java new file mode 100644 index 0000000..fd85597 --- /dev/null +++ b/modules/model/src/main/java/org/apache/tamaya/model/spi/UsageTrackerSpi.java @@ -0,0 +1,67 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.tamaya.model.spi; + +import org.apache.tamaya.model.Usage; + +import java.util.Collection; +import java.util.Set; + +/** + * SPI to implemented by the component responsible for usage tracking of + * configuration. + */ +public interface UsageTrackerSpi { + + /** + * Get the list of package, which are not evaluated for tracking configuration access and usage statistics. + * @return the set of ignored package names. + */ + Set getIgnoredPackages(); + + /** + * Get the recorded usage references of configuration. + * @return the recorded usge references, never null. + */ + Collection getUsages(); + + /** + * Track the access of {@code ConfigurationProvider#getConfiguration()} for + * usage statistics. + */ + void trackConfigurationAccess(); + + /** + * Track the access of {@code Configuration#getProperties()} for + * usage statistics. + */ + void trackAllPropertiesAccess(); + + /** + * Track the access of {@code Configuration#get(String)} for + * usage statistics. + */ + void trackSingleKeyAccess(String key, String value); + + /** + * Access the usage statistics for the recorded uses of configuration. + */ + String getUsageInfo(); + +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/4749d395/modules/model/src/main/resources/META-INF/services/org.apache.tamaya.model.spi.UsageTrackerSpi ---------------------------------------------------------------------- diff --git a/modules/model/src/main/resources/META-INF/services/org.apache.tamaya.model.spi.UsageTrackerSpi b/modules/model/src/main/resources/META-INF/services/org.apache.tamaya.model.spi.UsageTrackerSpi new file mode 100644 index 0000000..1a87f60 --- /dev/null +++ b/modules/model/src/main/resources/META-INF/services/org.apache.tamaya.model.spi.UsageTrackerSpi @@ -0,0 +1,19 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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 current 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. +# +org.apache.tamaya.model.internal.DefaultUsageTracker \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/4749d395/modules/model/src/main/resources/META-INF/services/org.apache.tamaya.spi.PropertyFilter ---------------------------------------------------------------------- diff --git a/modules/model/src/main/resources/META-INF/services/org.apache.tamaya.spi.PropertyFilter b/modules/model/src/main/resources/META-INF/services/org.apache.tamaya.spi.PropertyFilter new file mode 100644 index 0000000..04cec4a --- /dev/null +++ b/modules/model/src/main/resources/META-INF/services/org.apache.tamaya.spi.PropertyFilter @@ -0,0 +1,19 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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 current 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. +# +org.apache.tamaya.model.internal.UsageTrackerFilter \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/4749d395/modules/model/src/test/java/test/model/TestConfigAccessor.java ---------------------------------------------------------------------- diff --git a/modules/model/src/test/java/test/model/TestConfigAccessor.java b/modules/model/src/test/java/test/model/TestConfigAccessor.java new file mode 100644 index 0000000..191a074 --- /dev/null +++ b/modules/model/src/test/java/test/model/TestConfigAccessor.java @@ -0,0 +1,27 @@ +package test.model; + +import org.apache.tamaya.Configuration; +import org.apache.tamaya.ConfigurationProvider; + +import java.util.Map; + +/** + * Created by atsticks on 30.04.16. + */ +public final class TestConfigAccessor { + + private TestConfigAccessor(){} + + public static Map readAllProperties(){ + return ConfigurationProvider.getConfiguration() + .getProperties(); + } + + public static Configuration readConfiguration(){ + return ConfigurationProvider.getConfiguration(); + } + + public static String readProperty(Configuration config, String key){ + return config.get(key); + } +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/4749d395/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/ui/ConfigEditorWidget.java ---------------------------------------------------------------------- diff --git a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/ui/ConfigEditorWidget.java b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/ui/ConfigEditorWidget.java new file mode 100644 index 0000000..02e486b --- /dev/null +++ b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/ui/ConfigEditorWidget.java @@ -0,0 +1,110 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.tamaya.mutableconfig.ui; + +import com.vaadin.ui.*; +import org.apache.tamaya.mutableconfig.MutableConfiguration; +import org.apache.tamaya.spi.ServiceContextManager; +import org.apache.tamaya.ui.services.MessageProvider; + +import java.util.Objects; + +/** + * Tamaya UI view to change configuration. + */ +public class ConfigEditorWidget extends FormLayout { + + private MutableConfiguration mutableConfig; + private ProtocolWidget logWriter; + + private TextField configKey = new TextField( + ServiceContextManager.getServiceContext().getService(MessageProvider.class) + .getMessage("view.edit.text.configKey")); + private TextField configValue = new TextField( + ServiceContextManager.getServiceContext().getService(MessageProvider.class) + .getMessage("view.edit.text.configValue")); + private Button updateButton = new Button(ServiceContextManager.getServiceContext().getService(MessageProvider.class) + .getMessage("view.edit.button.updateKey")); + private Button removeButton = new Button(ServiceContextManager.getServiceContext().getService(MessageProvider.class) + .getMessage("view.edit.button.removeKey")); + private Button readButton = new Button(ServiceContextManager.getServiceContext().getService(MessageProvider.class) + .getMessage("view.edit.button.readKey")); + + public ConfigEditorWidget(MutableConfiguration mutableConfig, ProtocolWidget logWriter) { + this.mutableConfig = Objects.requireNonNull(mutableConfig); + this.logWriter = Objects.requireNonNull(logWriter); + configKey.setWidth(50, Unit.PERCENTAGE); + configValue.setWidth(50, Unit.PERCENTAGE); + addComponents(configKey, configValue); + HorizontalLayout buttonLayout = new HorizontalLayout(); + buttonLayout.addComponents(readButton, new Label(" "), updateButton, removeButton); + buttonLayout.setSpacing(true); + addComponents(buttonLayout); + initActions(); + } + + private void initActions() { + updateButton.addClickListener(new Button.ClickListener() { + @Override + public void buttonClick(Button.ClickEvent clickEvent) { + if(mutableConfig.isWritable(configKey.getValue())){ + mutableConfig.put(configKey.getValue(), configValue.getValue()); + logWriter.println(" - PUT " + configKey.getValue() + " = " + configValue.getValue()); + }else{ + logWriter.println(" - PUT " + configKey.getValue() + " rejected - not writable."); + } + } + }); + removeButton.addClickListener(new Button.ClickListener() { + @Override + public void buttonClick(Button.ClickEvent clickEvent) { + if(mutableConfig.isRemovable(configKey.getValue())){ + mutableConfig.remove(configKey.getValue()); + logWriter.println(" - DEL " + configKey.getValue()); + }else{ + logWriter.println(" - DEL " + configKey.getValue() + " rejected - not removable."); + } + } + }); + readButton.addClickListener(new Button.ClickListener() { + @Override + public void buttonClick(Button.ClickEvent clickEvent) { + if(mutableConfig.isExisting(configKey.getValue())){ + String key = configKey.getValue(); + configValue.setValue(mutableConfig.get(key)); + logWriter.println(" - GET " + key + " = " + configValue.getValue()); + logWriter.println(" - removable: " + mutableConfig.isRemovable(key)); + logWriter.println(" - writable : " + mutableConfig.isWritable(key)); + }else{ + logWriter.println(" - GET " + configKey.getValue() + " rejected - not existing."); + } + } + }); + } + + private String getCaption(String key, String value) { + int index = key.lastIndexOf('.'); + if(index<0){ + return key + " = " + value; + }else{ + return key.substring(index+1) + " = " + value; + } + } + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/4749d395/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/ui/ConfigUpdaterView.java ---------------------------------------------------------------------- diff --git a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/ui/ConfigUpdaterView.java b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/ui/ConfigUpdaterView.java index 81dfc3f..ea33d22 100644 --- a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/ui/ConfigUpdaterView.java +++ b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/ui/ConfigUpdaterView.java @@ -21,11 +21,10 @@ package org.apache.tamaya.mutableconfig.ui; import com.vaadin.navigator.View; import com.vaadin.navigator.ViewChangeListener; import com.vaadin.shared.ui.label.ContentMode; -import com.vaadin.ui.ComboBox; -import com.vaadin.ui.Label; -import com.vaadin.ui.TextArea; -import com.vaadin.ui.TextField; +import com.vaadin.ui.*; +import org.apache.tamaya.mutableconfig.MutableConfiguration; import org.apache.tamaya.mutableconfig.MutableConfigurationProvider; +import org.apache.tamaya.mutableconfig.spi.MutablePropertySource; import org.apache.tamaya.spi.ServiceContextManager; import org.apache.tamaya.ui.UIConstants; import org.apache.tamaya.ui.ViewProvider; @@ -33,7 +32,6 @@ import org.apache.tamaya.ui.components.VerticalSpacedLayout; import org.apache.tamaya.ui.services.MessageProvider; import javax.annotation.Priority; -import java.util.Arrays; /** * Tamaya UI view to change configuration. @@ -68,18 +66,14 @@ public class ConfigUpdaterView extends VerticalSpacedLayout implements View { } } - private ComboBox changePropagationPolicy = new ComboBox(ServiceContextManager.getServiceContext() - .getService(MessageProvider.class).getMessage("view.edit.select.propagationPolicy"), - Arrays.asList(new String[]{"ALL", "MOST_SIGNIFICANT_ONLY", "SELECTIVE", "NONE"})); + private ProtocolWidget protocolArea = new ProtocolWidget(); - private TextField changePropagationPolicyOther = new TextField( - ServiceContextManager.getServiceContext().getService(MessageProvider.class) - .getMessage("view.edit.text.propagationPolicyOther"), - MutableConfigurationProvider.getApplyAllChangePolicy().getClass().getName()); + private MutableConfiguration mutableConfig = MutableConfigurationProvider.getMutableConfiguration(); - private TextArea generalInfo = new TextArea(ServiceContextManager.getServiceContext() - .getService(MessageProvider.class).getMessage("view.edit.textArea.general")); + private TransactionControlWidget taControlWidget = new TransactionControlWidget(mutableConfig, + protocolArea); + private ConfigEditorWidget editorWidget = new ConfigEditorWidget(mutableConfig, protocolArea); public ConfigUpdaterView() { @@ -91,13 +85,14 @@ public class ConfigUpdaterView extends VerticalSpacedLayout implements View { caption.addStyleName(UIConstants.LABEL_HUGE); description.addStyleName(UIConstants.LABEL_LARGE); - changePropagationPolicy.setWidth(300, Unit.PIXELS); - changePropagationPolicyOther.setWidth(600, Unit.PIXELS); - generalInfo.setWidth(100, Unit.PERCENTAGE); - addComponents(caption, description,changePropagationPolicy,changePropagationPolicyOther,generalInfo); + protocolArea.print("INFO: Writable Property Sources: "); + for(MutablePropertySource ps:mutableConfig.getMutablePropertySources()){ + protocolArea.print(ps.getName(), ", "); + } + protocolArea.println(); + addComponents(caption, description, editorWidget, protocolArea, taControlWidget); } - private String getCaption(String key, String value) { int index = key.lastIndexOf('.'); if(index<0){ http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/4749d395/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/ui/ProtocolWidget.java ---------------------------------------------------------------------- diff --git a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/ui/ProtocolWidget.java b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/ui/ProtocolWidget.java new file mode 100644 index 0000000..5ceaaa6 --- /dev/null +++ b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/ui/ProtocolWidget.java @@ -0,0 +1,87 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.tamaya.mutableconfig.ui; + +import com.vaadin.ui.Button; +import com.vaadin.ui.TextArea; +import com.vaadin.ui.VerticalLayout; +import org.apache.tamaya.spi.ServiceContextManager; +import org.apache.tamaya.ui.services.MessageProvider; + +import java.io.PrintWriter; +import java.io.StringWriter; + +/** + * Widget showing a text protocol wioth a clear button to clear the widget space. + */ +public class ProtocolWidget extends VerticalLayout{ + + private TextArea textArea = new TextArea(ServiceContextManager.getServiceContext() + .getService(MessageProvider.class).getMessage("view.edit.textArea.protocol")); + private Button clearButton = new Button(ServiceContextManager.getServiceContext().getService(MessageProvider.class) + .getMessage("view.edit.button.clearProtocol")); + + private StringWriter protocol = new StringWriter(); + private PrintWriter writer = new PrintWriter(protocol); + + public ProtocolWidget(){ + textArea.setWidth(100, Unit.PERCENTAGE); + textArea.setReadOnly(true); + clearButton.addClickListener(new Button.ClickListener() { + @Override + public void buttonClick(Button.ClickEvent clickEvent) { + protocol.getBuffer().setLength(0); + flush(); + } + }); + textArea.setSizeFull(); + addComponents(textArea, clearButton); + } + + public PrintWriter getWriter(){ + return writer; + } + + public void println(){ + writer.println(); + } + + public void println(Object... items){ + for(int i=0;i