You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sirona.apache.org by rm...@apache.org on 2013/11/05 18:25:24 UTC
svn commit: r1539076 [2/17] - in /incubator/sirona/trunk: ./ agent/
agent/performance/ agent/performance/aop/ agent/performance/aop/src/
agent/performance/aop/src/main/ agent/performance/aop/src/main/java/
agent/performance/aop/src/main/java/org/ agent...
Added: incubator/sirona/trunk/agent/performance/cdi/src/main/java/org/apache/sirona/cdi/SironaInterceptor.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/performance/cdi/src/main/java/org/apache/sirona/cdi/SironaInterceptor.java?rev=1539076&view=auto
==============================================================================
--- incubator/sirona/trunk/agent/performance/cdi/src/main/java/org/apache/sirona/cdi/SironaInterceptor.java (added)
+++ incubator/sirona/trunk/agent/performance/cdi/src/main/java/org/apache/sirona/cdi/SironaInterceptor.java Tue Nov 5 17:25:15 2013
@@ -0,0 +1,49 @@
+/*
+ * 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.sirona.cdi;
+
+import org.apache.sirona.aop.AbstractPerformanceInterceptor;
+
+import javax.interceptor.AroundInvoke;
+import javax.interceptor.AroundTimeout;
+import javax.interceptor.Interceptor;
+import javax.interceptor.InvocationContext;
+
+@Interceptor
+@Monitored
+public class SironaInterceptor extends AbstractPerformanceInterceptor<InvocationContext> {
+ @AroundInvoke
+ @AroundTimeout
+ public Object monitor(final InvocationContext invocationContext) throws Throwable {
+ return doInvoke(invocationContext);
+ }
+
+ @Override
+ protected Object proceed(final InvocationContext invocation) throws Throwable {
+ return invocation.proceed();
+ }
+
+ @Override
+ protected String getCounterName(final InvocationContext invocation) {
+ return getCounterName(invocation.getTarget(), invocation.getMethod());
+ }
+
+ @Override
+ protected Object extractContextKey(final InvocationContext invocation) {
+ return new SerializableMethod(invocation.getMethod());
+ }
+}
Added: incubator/sirona/trunk/agent/performance/cdi/src/main/java/org/apache/sirona/cdi/internal/SironaPerformanceExtension.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/performance/cdi/src/main/java/org/apache/sirona/cdi/internal/SironaPerformanceExtension.java?rev=1539076&view=auto
==============================================================================
--- incubator/sirona/trunk/agent/performance/cdi/src/main/java/org/apache/sirona/cdi/internal/SironaPerformanceExtension.java (added)
+++ incubator/sirona/trunk/agent/performance/cdi/src/main/java/org/apache/sirona/cdi/internal/SironaPerformanceExtension.java Tue Nov 5 17:25:15 2013
@@ -0,0 +1,154 @@
+/*
+ * 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.sirona.cdi.internal;
+
+import org.apache.sirona.cdi.Monitored;
+import org.apache.sirona.configuration.Configuration;
+import org.apache.sirona.configuration.predicate.PredicateEvaluator;
+
+import javax.enterprise.event.Observes;
+import javax.enterprise.inject.spi.BeforeBeanDiscovery;
+import javax.enterprise.inject.spi.Extension;
+import javax.enterprise.inject.spi.ProcessAnnotatedType;
+import java.io.Serializable;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+
+public class SironaPerformanceExtension implements Extension {
+ private final boolean enabled = Configuration.is(Configuration.CONFIG_PROPERTY_PREFIX + "cdi.enabled", true);
+ private final Monitored performanceBinding = newAnnotation(Monitored.class);
+ private final Annotation jtaBinding = tryNewAnnotation("org.apache.sirona.jta.JTAMonitored");
+
+ private PredicateEvaluator performaceEvaluator;
+ private PredicateEvaluator jtaEvaluator;
+
+ void init(final @Observes BeforeBeanDiscovery beforeBeanDiscovery) {
+ if (!enabled) {
+ return;
+ }
+
+ performaceEvaluator = new PredicateEvaluator(Configuration.getProperty(Configuration.CONFIG_PROPERTY_PREFIX + "cdi.performance", null), ",");
+ jtaEvaluator = new PredicateEvaluator(Configuration.getProperty(Configuration.CONFIG_PROPERTY_PREFIX + "cdi.jta", null), ",");
+ }
+
+ <A> void processAnnotatedType(final @Observes ProcessAnnotatedType<A> pat) {
+ if (!enabled) {
+ return;
+ }
+
+ final String beanClassName = pat.getAnnotatedType().getJavaClass().getName();
+ final boolean addPerf = performaceEvaluator.matches(beanClassName);
+ final boolean addJta = jtaEvaluator.matches(beanClassName);
+
+ final WrappedAnnotatedType<A> wrapper;
+ if (addPerf || addJta) {
+ wrapper = new WrappedAnnotatedType<A>(pat.getAnnotatedType());
+ if (addPerf) {
+ wrapper.getAnnotations().add(performanceBinding);
+ }
+ if (addJta) {
+ wrapper.getAnnotations().add(jtaBinding);
+ }
+ } else {
+ wrapper = null;
+ }
+ if (wrapper != null) {
+ pat.setAnnotatedType(wrapper);
+ }
+ }
+
+ private static String findConfiguration(final String name) {
+ String current = name;
+ String property;
+ do {
+ property = Configuration.getProperty(current + ".cdi", null);
+
+ final int endIndex = current.lastIndexOf('.');
+ if (endIndex > 0) {
+ current = current.substring(0, endIndex);
+ } else {
+ current = null;
+ }
+ } while (property == null && current != null);
+ return property;
+ }
+
+ private static Annotation tryNewAnnotation(final String clazz) {
+ try {
+ return newAnnotation(Class.class.cast(Thread.currentThread().getContextClassLoader().loadClass(clazz)));
+ } catch (final ClassNotFoundException e) {
+ return null;
+ } catch (final NoClassDefFoundError e) {
+ return null;
+ }
+ }
+ private static <T extends Annotation> T newAnnotation(final Class<T> clazz) {
+ return clazz.cast(
+ Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
+ new Class<?>[]{ Annotation.class, clazz },
+ new AnnotationHandler(clazz)));
+ }
+
+ // Note: for annotations without any members
+ private static class AnnotationHandler implements InvocationHandler, Annotation, Serializable {
+ private final Class<? extends Annotation> annotationClass;
+
+ private AnnotationHandler(final Class<? extends Annotation> annotationClass) {
+ this.annotationClass = annotationClass;
+ }
+
+ @Override
+ public Object invoke(final Object proxy, final Method method, final Object[] args) throws Exception {
+ if ("hashCode".equals(method.getName())) {
+ return hashCode();
+ } else if ("equals".equals(method.getName())) {
+ if (Proxy.isProxyClass(args[0].getClass()) && AnnotationHandler.class.isInstance(Proxy.getInvocationHandler(args[0]))) {
+ return equals(Proxy.getInvocationHandler(args[0]));
+ }
+ return equals(args[0]);
+ } else if ("annotationType".equals(method.getName())) {
+ return annotationType();
+ } else if ("toString".equals(method.getName())) {
+ return toString();
+ }
+ return method.getDefaultValue();
+ }
+
+ @Override
+ public Class<? extends Annotation> annotationType() {
+ return annotationClass;
+ }
+
+ @Override
+ public String toString() {
+ return "@" + annotationClass.getName();
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ return this == o
+ || Annotation.class.isInstance(o) && Annotation.class.cast(o).annotationType().equals(annotationClass);
+ }
+
+ @Override
+ public int hashCode() {
+ return 0;
+ }
+ }
+}
Added: incubator/sirona/trunk/agent/performance/cdi/src/main/java/org/apache/sirona/cdi/internal/WrappedAnnotatedType.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/performance/cdi/src/main/java/org/apache/sirona/cdi/internal/WrappedAnnotatedType.java?rev=1539076&view=auto
==============================================================================
--- incubator/sirona/trunk/agent/performance/cdi/src/main/java/org/apache/sirona/cdi/internal/WrappedAnnotatedType.java (added)
+++ incubator/sirona/trunk/agent/performance/cdi/src/main/java/org/apache/sirona/cdi/internal/WrappedAnnotatedType.java Tue Nov 5 17:25:15 2013
@@ -0,0 +1,88 @@
+/*
+ * 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.sirona.cdi.internal;
+
+import javax.enterprise.inject.spi.AnnotatedConstructor;
+import javax.enterprise.inject.spi.AnnotatedField;
+import javax.enterprise.inject.spi.AnnotatedMethod;
+import javax.enterprise.inject.spi.AnnotatedType;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.HashSet;
+import java.util.Set;
+
+public class WrappedAnnotatedType<A> implements AnnotatedType<A> {
+ private final AnnotatedType<A> delegate;
+ private final Set<Annotation> annotations;
+
+ public WrappedAnnotatedType(final AnnotatedType<A> at) {
+ this.delegate = at;
+
+ this.annotations = new HashSet<Annotation>(at.getAnnotations().size());
+ this.annotations.addAll(at.getAnnotations());
+ }
+
+ @Override
+ public Set<Annotation> getAnnotations() {
+ return annotations;
+ }
+
+ @Override
+ public <T extends Annotation> T getAnnotation(final Class<T> annotationType) {
+ for (final Annotation ann : annotations) {
+ if (ann.annotationType().equals(annotationType)) {
+ return annotationType.cast(ann);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isAnnotationPresent(final Class<? extends Annotation> annotationType) {
+ return getAnnotation(annotationType) != null;
+ }
+
+ @Override
+ public Class<A> getJavaClass() {
+ return delegate.getJavaClass();
+ }
+
+ @Override
+ public Set<AnnotatedConstructor<A>> getConstructors() {
+ return delegate.getConstructors();
+ }
+
+ @Override
+ public Set<AnnotatedMethod<? super A>> getMethods() {
+ return delegate.getMethods();
+ }
+
+ @Override
+ public Set<AnnotatedField<? super A>> getFields() {
+ return delegate.getFields();
+ }
+
+ @Override
+ public Type getBaseType() {
+ return delegate.getBaseType();
+ }
+
+ @Override
+ public Set<Type> getTypeClosure() {
+ return delegate.getTypeClosure();
+ }
+}
Added: incubator/sirona/trunk/agent/performance/cdi/src/main/resources/META-INF/beans.xml
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/performance/cdi/src/main/resources/META-INF/beans.xml?rev=1539076&view=auto
==============================================================================
--- incubator/sirona/trunk/agent/performance/cdi/src/main/resources/META-INF/beans.xml (added)
+++ incubator/sirona/trunk/agent/performance/cdi/src/main/resources/META-INF/beans.xml Tue Nov 5 17:25:15 2013
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+<beans xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
+ http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
+ <interceptors>
+ <class>org.apache.sirona.cdi.SironaInterceptor</class>
+ </interceptors>
+</beans>
Added: incubator/sirona/trunk/agent/performance/cdi/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/performance/cdi/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension?rev=1539076&view=auto
==============================================================================
--- incubator/sirona/trunk/agent/performance/cdi/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension (added)
+++ incubator/sirona/trunk/agent/performance/cdi/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension Tue Nov 5 17:25:15 2013
@@ -0,0 +1 @@
+org.apache.sirona.cdi.internal.SironaPerformanceExtension
Added: incubator/sirona/trunk/agent/performance/cdi/src/test/java/org/apache/sirona/cdi/SironaExtensionTest.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/performance/cdi/src/test/java/org/apache/sirona/cdi/SironaExtensionTest.java?rev=1539076&view=auto
==============================================================================
--- incubator/sirona/trunk/agent/performance/cdi/src/test/java/org/apache/sirona/cdi/SironaExtensionTest.java (added)
+++ incubator/sirona/trunk/agent/performance/cdi/src/test/java/org/apache/sirona/cdi/SironaExtensionTest.java Tue Nov 5 17:25:15 2013
@@ -0,0 +1,37 @@
+/*
+ * 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.sirona.cdi;
+
+import javax.enterprise.context.ApplicationScoped;
+
+public class SironaExtensionTest extends SironaExtensionTestBase {
+ @Override
+ protected Class<? extends TwoSeconds> type() {
+ return AutoMonitoredBean.class;
+ }
+
+ @ApplicationScoped
+ public static class AutoMonitoredBean implements TwoSeconds {
+ public void twoSeconds() {
+ try {
+ Thread.sleep(2000);
+ } catch (final InterruptedException e) {
+ // no-op
+ }
+ }
+ }
+}
Added: incubator/sirona/trunk/agent/performance/cdi/src/test/java/org/apache/sirona/cdi/SironaExtensionTestBase.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/performance/cdi/src/test/java/org/apache/sirona/cdi/SironaExtensionTestBase.java?rev=1539076&view=auto
==============================================================================
--- incubator/sirona/trunk/agent/performance/cdi/src/test/java/org/apache/sirona/cdi/SironaExtensionTestBase.java (added)
+++ incubator/sirona/trunk/agent/performance/cdi/src/test/java/org/apache/sirona/cdi/SironaExtensionTestBase.java Tue Nov 5 17:25:15 2013
@@ -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.sirona.cdi;
+
+import org.apache.sirona.Role;
+import org.apache.sirona.counters.Counter;
+import org.apache.sirona.repositories.Repository;
+import org.apache.webbeans.cditest.CdiTestContainer;
+import org.apache.webbeans.cditest.CdiTestContainerLoader;
+import org.junit.Test;
+
+import javax.enterprise.inject.spi.BeanManager;
+import java.util.concurrent.TimeUnit;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+public abstract class SironaExtensionTestBase {
+ @Test
+ public void checkMeasures() throws Exception {
+ final CdiTestContainer container = CdiTestContainerLoader.getCdiContainer();
+ container.bootContainer();
+ container.startApplicationScope();
+
+ final BeanManager beanManager = container.getBeanManager();
+ final Class<?> type = type();
+ final TwoSeconds bean = TwoSeconds.class.cast(beanManager.getReference(beanManager.resolve(beanManager.getBeans(type)), type, null));
+
+ bean.twoSeconds();
+
+ container.stopApplicationScope();
+ container.shutdownContainer();
+
+ final Counter perf = Repository.INSTANCE.getCounter(new Counter.Key(Role.PERFORMANCES, type.getName() + ".twoSeconds"));
+ assertNotNull(perf);
+ assertEquals(2000, TimeUnit.NANOSECONDS.toMillis((int) perf.getMax()), 200);
+ }
+
+ protected abstract Class<? extends TwoSeconds> type();
+
+ protected static interface TwoSeconds {
+ void twoSeconds();
+ }
+}
Added: incubator/sirona/trunk/agent/performance/cdi/src/test/java/org/apache/sirona/cdi/SironaInterceptorTest.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/performance/cdi/src/test/java/org/apache/sirona/cdi/SironaInterceptorTest.java?rev=1539076&view=auto
==============================================================================
--- incubator/sirona/trunk/agent/performance/cdi/src/test/java/org/apache/sirona/cdi/SironaInterceptorTest.java (added)
+++ incubator/sirona/trunk/agent/performance/cdi/src/test/java/org/apache/sirona/cdi/SironaInterceptorTest.java Tue Nov 5 17:25:15 2013
@@ -0,0 +1,38 @@
+/*
+ * 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.sirona.cdi;
+
+import javax.enterprise.context.ApplicationScoped;
+
+public class SironaInterceptorTest extends SironaExtensionTestBase {
+ @Override
+ protected Class<? extends TwoSeconds> type() {
+ return MonitoredBean.class;
+ }
+
+ @Monitored
+ @ApplicationScoped
+ public static class MonitoredBean implements TwoSeconds {
+ public void twoSeconds() {
+ try {
+ Thread.sleep(2000);
+ } catch (final InterruptedException e) {
+ // no-op
+ }
+ }
+ }
+}
Added: incubator/sirona/trunk/agent/performance/cdi/src/test/resources/META-INF/beans.xml
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/performance/cdi/src/test/resources/META-INF/beans.xml?rev=1539076&view=auto
==============================================================================
--- incubator/sirona/trunk/agent/performance/cdi/src/test/resources/META-INF/beans.xml (added)
+++ incubator/sirona/trunk/agent/performance/cdi/src/test/resources/META-INF/beans.xml Tue Nov 5 17:25:15 2013
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+<beans xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
+ http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
+
+</beans>
Added: incubator/sirona/trunk/agent/performance/cdi/src/test/resources/sirona.properties
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/performance/cdi/src/test/resources/sirona.properties?rev=1539076&view=auto
==============================================================================
--- incubator/sirona/trunk/agent/performance/cdi/src/test/resources/sirona.properties (added)
+++ incubator/sirona/trunk/agent/performance/cdi/src/test/resources/sirona.properties Tue Nov 5 17:25:15 2013
@@ -0,0 +1,17 @@
+# 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.
+org.apache.sirona.cdi.performance = prefix:org.apache.sirona.cdi.SironaExtensionTest$AutoMonitoredBean
Added: incubator/sirona/trunk/agent/performance/jdbc/pom.xml
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/performance/jdbc/pom.xml?rev=1539076&view=auto
==============================================================================
--- incubator/sirona/trunk/agent/performance/jdbc/pom.xml (added)
+++ incubator/sirona/trunk/agent/performance/jdbc/pom.xml Tue Nov 5 17:25:15 2013
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <parent>
+ <artifactId>sirona-performance</artifactId>
+ <groupId>org.apache.sirona</groupId>
+ <version>0.1-incubating-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>sirona-jdbc</artifactId>
+ <version>0.1-incubating-SNAPSHOT</version>
+ <name>Apache Sirona Incubator :: Agent :: Performance :: JDBC</name>
+
+ <properties>
+ <!-- Java6 required for JDBC 4 -->
+ <maven.compile.source>1.6</maven.compile.source>
+ <maven.compile.target>1.6</maven.compile.target>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.sirona</groupId>
+ <artifactId>sirona-core</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.hsqldb</groupId>
+ <artifactId>hsqldb</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ </dependency>
+ </dependencies>
+</project>
\ No newline at end of file
Added: incubator/sirona/trunk/agent/performance/jdbc/src/main/java/org/apache/sirona/jdbc/ConnectionClosedCallBack.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/performance/jdbc/src/main/java/org/apache/sirona/jdbc/ConnectionClosedCallBack.java?rev=1539076&view=auto
==============================================================================
--- incubator/sirona/trunk/agent/performance/jdbc/src/main/java/org/apache/sirona/jdbc/ConnectionClosedCallBack.java (added)
+++ incubator/sirona/trunk/agent/performance/jdbc/src/main/java/org/apache/sirona/jdbc/ConnectionClosedCallBack.java Tue Nov 5 17:25:15 2013
@@ -0,0 +1,25 @@
+/*
+ * 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.sirona.jdbc;
+
+/**
+ * CallBack on connection beeing closed
+ */
+public interface ConnectionClosedCallBack {
+ void onConnectionClosed();
+}
\ No newline at end of file
Added: incubator/sirona/trunk/agent/performance/jdbc/src/main/java/org/apache/sirona/jdbc/MonitoredConnection.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/performance/jdbc/src/main/java/org/apache/sirona/jdbc/MonitoredConnection.java?rev=1539076&view=auto
==============================================================================
--- incubator/sirona/trunk/agent/performance/jdbc/src/main/java/org/apache/sirona/jdbc/MonitoredConnection.java (added)
+++ incubator/sirona/trunk/agent/performance/jdbc/src/main/java/org/apache/sirona/jdbc/MonitoredConnection.java Tue Nov 5 17:25:15 2013
@@ -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.sirona.jdbc;
+
+import org.apache.sirona.counters.Counter;
+import org.apache.sirona.stopwatches.CounterStopWatch;
+import org.apache.sirona.stopwatches.StopWatch;
+import org.apache.sirona.util.ClassLoaders;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.sql.CallableStatement;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.Statement;
+
+/**
+ * @author <a href="mailto:nicolas@apache.org">Nicolas De Loof</a>
+ */
+public class MonitoredConnection implements InvocationHandler {
+ private Connection connection;
+ private StopWatch stopWatch;
+
+ /**
+ * @param connection target connection
+ */
+ public MonitoredConnection(final Connection connection, final StopWatch stopWatch) {
+ this.connection = connection;
+ this.stopWatch = stopWatch;
+ }
+
+ @Override
+ public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
+ final String name = method.getName();
+ if ("close".equals(name)) {
+ connection.close();
+ stopWatch.stop();
+ return null;
+ }
+
+ if (name.startsWith("prepare") || name.startsWith("create")) {
+ final Class<?> returnType = method.getReturnType();
+ if (CallableStatement.class.equals(returnType)) {
+ return monitor(CallableStatement.class.cast(doInvoke(method, args)), (String) args[0]);
+ } else if (PreparedStatement.class.equals(returnType)) {
+ return monitor(PreparedStatement.class.cast(doInvoke(method, args)), (String) args[0]);
+ } else if (Statement.class.equals(returnType)) {
+ return monitor(Statement.class.cast(doInvoke(method, args)));
+ }
+ }
+
+ return doInvoke(method, args);
+ }
+
+ private Object doInvoke(final Method method, final Object[] args) throws IllegalAccessException, InvocationTargetException {
+ return method.invoke(connection, args);
+ }
+
+ private Statement monitor(final Statement statement) {
+ return Statement.class.cast(Proxy.newProxyInstance(ClassLoaders.current(), new Class<?>[]{Statement.class}, new MonitoredStatement(statement)));
+ }
+
+ /**
+ * @param statement traget PreparedStatement
+ * @param sql SQL Query
+ * @return monitored PreparedStatement
+ */
+ private PreparedStatement monitor(final PreparedStatement statement, final String sql) {
+ return PreparedStatement.class.cast(Proxy.newProxyInstance(ClassLoaders.current(), new Class<?>[]{PreparedStatement.class}, new MonitoredPreparedStatement(statement, sql)));
+ }
+
+ /**
+ * @param statement target PreparedStatement
+ * @param sql SQL Query
+ * @return Monitored CallableStatement
+ */
+ private CallableStatement monitor(final CallableStatement statement, final String sql) {
+ return CallableStatement.class.cast(Proxy.newProxyInstance(ClassLoaders.current(), new Class<?>[]{CallableStatement.class}, new MonitoredPreparedStatement(statement, sql)));
+ }
+
+ public static Connection monitor(final Connection connection, final Counter counter) {
+ final StopWatch stopWatch = new CounterStopWatch(counter);
+ return Connection.class.cast(Proxy.newProxyInstance(ClassLoaders.current(), new Class<?>[]{Connection.class}, new MonitoredConnection(connection, stopWatch)));
+ }
+}
Added: incubator/sirona/trunk/agent/performance/jdbc/src/main/java/org/apache/sirona/jdbc/MonitoredDataSource.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/performance/jdbc/src/main/java/org/apache/sirona/jdbc/MonitoredDataSource.java?rev=1539076&view=auto
==============================================================================
--- incubator/sirona/trunk/agent/performance/jdbc/src/main/java/org/apache/sirona/jdbc/MonitoredDataSource.java (added)
+++ incubator/sirona/trunk/agent/performance/jdbc/src/main/java/org/apache/sirona/jdbc/MonitoredDataSource.java Tue Nov 5 17:25:15 2013
@@ -0,0 +1,147 @@
+/*
+ * 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.sirona.jdbc;
+
+
+import org.apache.sirona.Role;
+import org.apache.sirona.counters.Counter;
+import org.apache.sirona.repositories.Repository;
+
+import javax.sql.DataSource;
+import java.io.PrintWriter;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.sql.SQLFeatureNotSupportedException;
+import java.util.logging.Logger;
+
+
+/**
+ * @author <a href="mailto:nicolas@apache.org">Nicolas De Loof</a>
+ */
+public class MonitoredDataSource implements DataSource {
+ /**
+ * delegate DataSource
+ */
+ private DataSource dataSource;
+
+ /**
+ * dataSource name
+ */
+ private String dataSourceName = DataSource.class.getName();
+ private Counter counter;
+
+ /**
+ * Constructor
+ *
+ * @param dataSource the datasource to counter
+ */
+ public MonitoredDataSource(final DataSource dataSource) {
+ this.dataSource = dataSource;
+ this.counter = Repository.INSTANCE.getCounter(new Counter.Key(Role.JDBC, dataSourceName));
+ }
+
+ public MonitoredDataSource() {
+ super();
+ }
+
+ public void setDataSource(final DataSource dataSource) {
+ this.dataSource = dataSource;
+ }
+
+ /**
+ * @param dataSourceName the dataSourceName to set
+ */
+ public void setDataSourceName(final String dataSourceName) {
+ this.dataSourceName = dataSourceName;
+ }
+
+ /**
+ * @param counter the counter to set
+ */
+ public void setCounter(final Counter counter) {
+ this.counter = counter;
+ }
+
+ protected Connection monitor(final Connection connection) {
+ return MonitoredConnection.monitor(connection, counter);
+ }
+
+ /**
+ * @return the dataSource
+ */
+ protected DataSource getDataSource() {
+ return dataSource;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see javax.sql.DataSource#getConnection()
+ */
+ public Connection getConnection()
+ throws SQLException {
+ return monitor(getDataSource().getConnection());
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see javax.sql.DataSource#getConnection(java.lang.String, java.lang.String)
+ */
+ public Connection getConnection(String username, String password)
+ throws SQLException {
+ return monitor(getDataSource().getConnection(username, password));
+ }
+
+ public int getLoginTimeout()
+ throws SQLException {
+ return getDataSource().getLoginTimeout();
+ }
+
+ public PrintWriter getLogWriter()
+ throws SQLException {
+ return getDataSource().getLogWriter();
+ }
+
+ public void setLoginTimeout(int seconds)
+ throws SQLException {
+ getDataSource().setLoginTimeout(seconds);
+ }
+
+ public void setLogWriter(PrintWriter out)
+ throws SQLException {
+ getDataSource().setLogWriter(out);
+ }
+
+ // --- jdbc4 ----
+
+ public boolean isWrapperFor(Class<?> iface)
+ throws SQLException {
+ return getDataSource().isWrapperFor(iface);
+ }
+
+ public <T> T unwrap(Class<T> iface)
+ throws SQLException {
+ return getDataSource().unwrap(iface);
+ }
+
+ public Logger getParentLogger()
+ throws SQLFeatureNotSupportedException {
+ return Logger.getLogger("commons-monitoring.datasource");
+ }
+}
Added: incubator/sirona/trunk/agent/performance/jdbc/src/main/java/org/apache/sirona/jdbc/MonitoredPreparedStatement.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/performance/jdbc/src/main/java/org/apache/sirona/jdbc/MonitoredPreparedStatement.java?rev=1539076&view=auto
==============================================================================
--- incubator/sirona/trunk/agent/performance/jdbc/src/main/java/org/apache/sirona/jdbc/MonitoredPreparedStatement.java (added)
+++ incubator/sirona/trunk/agent/performance/jdbc/src/main/java/org/apache/sirona/jdbc/MonitoredPreparedStatement.java Tue Nov 5 17:25:15 2013
@@ -0,0 +1,57 @@
+/*
+ * 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.sirona.jdbc;
+
+import org.apache.sirona.Role;
+import org.apache.sirona.counters.Counter;
+import org.apache.sirona.repositories.Repository;
+import org.apache.sirona.stopwatches.StopWatch;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.sql.PreparedStatement;
+
+/**
+ * @author ndeloof
+ */
+public class MonitoredPreparedStatement extends MonitoredStatement {
+ private final PreparedStatement statement;
+ private final String sql;
+
+ public MonitoredPreparedStatement(final PreparedStatement statement, final String sql) {
+ super(statement);
+ this.statement = statement;
+ this.sql = sql;
+ }
+
+ @Override
+ public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
+ final String name = method.getName();
+ if ((args == null || args.length == 0) && name.startsWith("execute")) {
+ final StopWatch stopWatch = Repository.INSTANCE.start(Repository.INSTANCE.getCounter(new Counter.Key(Role.JDBC, sql)));
+ try {
+ return method.invoke(statement, args);
+ } catch (final InvocationTargetException e) {
+ throw extractSQLException(e);
+ } finally {
+ stopWatch.stop();
+ }
+ }
+ return super.invoke(proxy, method, args);
+ }
+
+}
Added: incubator/sirona/trunk/agent/performance/jdbc/src/main/java/org/apache/sirona/jdbc/MonitoredStatement.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/performance/jdbc/src/main/java/org/apache/sirona/jdbc/MonitoredStatement.java?rev=1539076&view=auto
==============================================================================
--- incubator/sirona/trunk/agent/performance/jdbc/src/main/java/org/apache/sirona/jdbc/MonitoredStatement.java (added)
+++ incubator/sirona/trunk/agent/performance/jdbc/src/main/java/org/apache/sirona/jdbc/MonitoredStatement.java Tue Nov 5 17:25:15 2013
@@ -0,0 +1,77 @@
+/*
+ * 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.sirona.jdbc;
+
+import org.apache.sirona.Role;
+import org.apache.sirona.counters.Counter;
+import org.apache.sirona.repositories.Repository;
+import org.apache.sirona.stopwatches.StopWatch;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+public class MonitoredStatement implements InvocationHandler {
+ private final Statement statement;
+
+ public MonitoredStatement(final Statement statement) {
+ this.statement = statement;
+ }
+
+ protected SQLException monitor(final SQLException sqle) {
+ final String name = "SQLException:" + sqle.getSQLState() + ":" + sqle.getErrorCode();
+ Repository.INSTANCE.getCounter(new Counter.Key(Role.FAILURES, name)).add(1);
+ return sqle;
+ }
+
+ @Override
+ public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
+ final String name = method.getName();
+ if (name.startsWith("execute")) {
+ final StopWatch stopWatch;
+ if (name.endsWith("Batch") && (args == null || args.length == 0)) {
+ stopWatch = Repository.INSTANCE.start(Repository.INSTANCE.getCounter(new Counter.Key(Role.JDBC, "batch")));
+ } else {
+ stopWatch = Repository.INSTANCE.start(Repository.INSTANCE.getCounter(new Counter.Key(Role.JDBC, (String) args[0])));
+ }
+
+ try {
+ return doInvoke(method, args);
+ } catch (final InvocationTargetException e) {
+ throw extractSQLException(e);
+ } finally {
+ stopWatch.stop();
+ }
+ }
+ return doInvoke(method, args);
+ }
+
+ private Object doInvoke(final Method method, final Object[] args) throws IllegalAccessException, InvocationTargetException {
+ return method.invoke(statement, args);
+ }
+
+ protected Throwable extractSQLException(final InvocationTargetException e) throws Throwable {
+ final Throwable th = e.getCause();
+ if (SQLException.class.isInstance(th)) {
+ return monitor(SQLException.class.cast(th));
+ }
+ return th;
+ }
+}
Added: incubator/sirona/trunk/agent/performance/jdbc/src/main/java/org/apache/sirona/jdbc/MonitoringDriver.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/performance/jdbc/src/main/java/org/apache/sirona/jdbc/MonitoringDriver.java?rev=1539076&view=auto
==============================================================================
--- incubator/sirona/trunk/agent/performance/jdbc/src/main/java/org/apache/sirona/jdbc/MonitoringDriver.java (added)
+++ incubator/sirona/trunk/agent/performance/jdbc/src/main/java/org/apache/sirona/jdbc/MonitoringDriver.java Tue Nov 5 17:25:15 2013
@@ -0,0 +1,98 @@
+/*
+ * 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.sirona.jdbc;
+
+import org.apache.sirona.Role;
+import org.apache.sirona.counters.Counter;
+import org.apache.sirona.repositories.Repository;
+
+import java.sql.Connection;
+import java.sql.Driver;
+import java.sql.DriverManager;
+import java.sql.DriverPropertyInfo;
+import java.sql.SQLException;
+import java.sql.SQLFeatureNotSupportedException;
+import java.util.Properties;
+import java.util.logging.Logger;
+
+public class MonitoringDriver implements Driver {
+ static {
+ try {
+ DriverManager.registerDriver(new MonitoringDriver());
+ } catch (final SQLException e) {
+ // no-op
+ }
+ }
+
+ private static final String PREFIX = "jdbc:monitoring:";
+ private static final String DRIVER_SUFFIX = "delegateDriver=";
+
+ public static void load() {
+ } // sexier than Class.forName("org.apache.sirona.jdbc.MonitoringDriver"); in full java
+
+ @Override
+ public Connection connect(final String url, final Properties info) throws SQLException {
+ if (!acceptsURL(url)) {
+ throw new SQLException("Driver " + MonitoringDriver.class.getName() + " doesn't accept " + url + ". Pattern is jdbc:monitoring:<xxx>:<yyy>?delegateDriver=<zzz>");
+ }
+
+ final int driverIndex = url.indexOf(DRIVER_SUFFIX);
+
+ String realUrl = "jdbc:" + url.substring(PREFIX.length(), driverIndex);
+ if (realUrl.endsWith("?") || realUrl.endsWith("&")) {
+ realUrl = realUrl.substring(0, realUrl.length() - 1);
+ }
+
+ final String realDriver = url.substring(driverIndex + DRIVER_SUFFIX.length());
+ try {
+ final Driver delegate = Driver.class.cast(Class.forName(realDriver).newInstance());
+ return MonitoredConnection.monitor(delegate.connect(realUrl, info), Repository.INSTANCE.getCounter(new Counter.Key(Role.JDBC, url)));
+ } catch (final Exception e) {
+ throw new SQLException(e);
+ }
+ }
+
+ @Override
+ public boolean acceptsURL(final String url) throws SQLException {
+ return url != null && url.startsWith(PREFIX) && url.contains(DRIVER_SUFFIX);
+ }
+
+ @Override
+ public DriverPropertyInfo[] getPropertyInfo(final String url, final Properties info) throws SQLException {
+ return new DriverPropertyInfo[0];
+ }
+
+ @Override
+ public int getMajorVersion() {
+ return 1;
+ }
+
+ @Override
+ public int getMinorVersion() {
+ return 0;
+ }
+
+ @Override
+ public boolean jdbcCompliant() {
+ return true;
+ }
+
+ // @Override // java 7
+ public Logger getParentLogger() throws SQLFeatureNotSupportedException {
+ return Logger.getLogger("commons-monitoring.jdbc-driver");
+ }
+}
Added: incubator/sirona/trunk/agent/performance/jdbc/src/test/java/org/apache/sirona/jdbc/HsqlDBTest.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/performance/jdbc/src/test/java/org/apache/sirona/jdbc/HsqlDBTest.java?rev=1539076&view=auto
==============================================================================
--- incubator/sirona/trunk/agent/performance/jdbc/src/test/java/org/apache/sirona/jdbc/HsqlDBTest.java (added)
+++ incubator/sirona/trunk/agent/performance/jdbc/src/test/java/org/apache/sirona/jdbc/HsqlDBTest.java Tue Nov 5 17:25:15 2013
@@ -0,0 +1,66 @@
+/*
+ * 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.sirona.jdbc;
+
+import org.apache.sirona.Role;
+import org.apache.sirona.counters.Counter;
+import org.apache.sirona.repositories.Repository;
+import org.hsqldb.jdbcDriver;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Proxy;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.Statement;
+
+import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+public class HsqlDBTest {
+ @BeforeClass
+ public static void init() {
+ MonitoringDriver.load();
+ }
+
+ @Test
+ public void driverMonitoring() throws Exception {
+ final Connection connection = DriverManager.getConnection("jdbc:monitoring:hsqldb:mem:monitoring?delegateDriver=" + jdbcDriver.class.getName(), "SA", "");
+ assertNotNull(connection);
+ assertTrue(Proxy.isProxyClass(connection.getClass()));
+ final InvocationHandler handler = Proxy.getInvocationHandler(connection);
+ assertThat(handler, instanceOf(MonitoredConnection.class));
+
+ final String create = "CREATE TABLE Address (Nr INTEGER, Name VARCHAR(128));";
+ final Statement statement = connection.createStatement();
+ statement.execute(create);
+ assertEquals(1, Repository.INSTANCE.getCounter(new Counter.Key(Role.JDBC, create)).getMaxConcurrency(), 0.);
+
+ final String insert = "INSERT INTO Address (Nr, Name) VALUES(1, 'foo')";
+ final PreparedStatement preparedStatement = connection.prepareStatement(insert);
+ preparedStatement.execute();
+ assertEquals(1, Repository.INSTANCE.getCounter(new Counter.Key(Role.JDBC, insert)).getMaxConcurrency(), 0.);
+ preparedStatement.execute();
+ assertEquals(1, Repository.INSTANCE.getCounter(new Counter.Key(Role.JDBC, insert)).getMaxConcurrency(), 0.);
+ assertEquals(2, Repository.INSTANCE.getCounter(new Counter.Key(Role.JDBC, insert)).getHits(), 0.);
+ }
+}
Added: incubator/sirona/trunk/agent/performance/jpa/pom.xml
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/performance/jpa/pom.xml?rev=1539076&view=auto
==============================================================================
--- incubator/sirona/trunk/agent/performance/jpa/pom.xml (added)
+++ incubator/sirona/trunk/agent/performance/jpa/pom.xml Tue Nov 5 17:25:15 2013
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <artifactId>sirona-performance</artifactId>
+ <groupId>org.apache.sirona</groupId>
+ <version>0.1-incubating-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>sirona-jpa</artifactId>
+ <version>0.1-incubating-SNAPSHOT</version>
+ <name>Apache Sirona Incubator :: Agent :: Performance :: JPA</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.geronimo.specs</groupId>
+ <artifactId>geronimo-jpa_2.0_spec</artifactId>
+ <version>1.1</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.sirona</groupId>
+ <artifactId>sirona-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.sirona</groupId>
+ <artifactId>sirona-aop</artifactId>
+ <exclusions>
+ <exclusion>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-proxy</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
+ <dependency>
+ <groupId>org.hsqldb</groupId>
+ <artifactId>hsqldb</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.openjpa</groupId>
+ <artifactId>openjpa</artifactId>
+ <version>2.2.2</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ </dependency>
+ </dependencies>
+</project>
\ No newline at end of file
Added: incubator/sirona/trunk/agent/performance/jpa/src/main/java/org/apache/sirona/jpa/JPAProxyFactory.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/performance/jpa/src/main/java/org/apache/sirona/jpa/JPAProxyFactory.java?rev=1539076&view=auto
==============================================================================
--- incubator/sirona/trunk/agent/performance/jpa/src/main/java/org/apache/sirona/jpa/JPAProxyFactory.java (added)
+++ incubator/sirona/trunk/agent/performance/jpa/src/main/java/org/apache/sirona/jpa/JPAProxyFactory.java Tue Nov 5 17:25:15 2013
@@ -0,0 +1,103 @@
+/*
+ * 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.sirona.jpa;
+
+import org.apache.sirona.Role;
+import org.apache.sirona.aop.AbstractPerformanceInterceptor;
+import org.apache.sirona.util.ClassLoaders;
+
+import java.io.Serializable;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+
+public final class JPAProxyFactory {
+ // more designed as internal than user friendly, that's why it is not in aop module
+ public static Object monitor(final Class<?>[] classes, final Object instance, final Role role, final boolean cascade) {
+ return classes[0].cast(
+ Proxy.newProxyInstance(ClassLoaders.current(), classes, new JSEMonitoringHandler(instance, role, cascade)));
+ }
+
+ private JPAProxyFactory() {
+ // no-op
+ }
+
+ private static class JSEMonitoringHandler extends AbstractPerformanceInterceptor<Invocation> implements InvocationHandler {
+ private final Object instance;
+ private final Role role;
+ private final boolean cascade;
+
+ public JSEMonitoringHandler(final Object instance, final Role role, final boolean cascade) {
+ this.instance = instance;
+ this.role = role;
+ this.cascade = cascade;
+ }
+
+ @Override
+ public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
+ if ("toString".equals(method.getName())) {
+ return "MonitoringProxy[" + instance + "]";
+ }
+
+ final Object o = doInvoke(new Invocation(instance, method, args));
+ final Class<?> returnType = method.getReturnType();
+ if (cascade && returnType.isInterface()) { // not java.*
+ return monitor(classes(returnType, o), o, role, cascade);
+ }
+ return o;
+ }
+
+ @Override
+ protected Object proceed(final Invocation invocation) throws Throwable {
+ try {
+ return invocation.method.invoke(invocation.target, invocation.args);
+ } catch (final InvocationTargetException ite) {
+ throw ite.getCause();
+ }
+ }
+
+ @Override
+ protected String getCounterName(final Invocation invocation) {
+ return getCounterName(invocation.target, invocation.method);
+ }
+
+ @Override
+ protected Role getRole() {
+ return role;
+ }
+
+ protected Class<?>[] classes(final Class<?> returnType, final Object o) {
+ if (Serializable.class.isInstance(o)) {
+ return new Class<?>[] { returnType, Serializable.class };
+ }
+ return new Class<?>[] { returnType };
+ }
+ }
+
+ private static class Invocation {
+ private final Object target;
+ private final Method method;
+ private final Object[] args;
+
+ private Invocation(final Object target, final Method method, final Object[] args) {
+ this.target = target;
+ this.method = method;
+ this.args = args;
+ }
+ }
+}
Added: incubator/sirona/trunk/agent/performance/jpa/src/main/java/org/apache/sirona/jpa/MonitoringPersistence.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/performance/jpa/src/main/java/org/apache/sirona/jpa/MonitoringPersistence.java?rev=1539076&view=auto
==============================================================================
--- incubator/sirona/trunk/agent/performance/jpa/src/main/java/org/apache/sirona/jpa/MonitoringPersistence.java (added)
+++ incubator/sirona/trunk/agent/performance/jpa/src/main/java/org/apache/sirona/jpa/MonitoringPersistence.java Tue Nov 5 17:25:15 2013
@@ -0,0 +1,174 @@
+/*
+ * 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.sirona.jpa;
+
+import org.apache.sirona.Role;
+import org.apache.sirona.configuration.Configuration;
+import org.apache.sirona.counters.Unit;
+
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.spi.PersistenceProvider;
+import javax.persistence.spi.PersistenceUnitInfo;
+import javax.persistence.spi.ProviderUtil;
+import java.io.Serializable;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.Map;
+
+import static org.apache.sirona.jpa.JPAProxyFactory.monitor;
+
+public class MonitoringPersistence implements PersistenceProvider {
+ public static final Role ROLE = new Role("jpa", Unit.Time.NANOSECOND);
+
+ private static final String DELEGATE_PROVIDER_KEY = Configuration.CONFIG_PROPERTY_PREFIX + "jpa.provider";
+ private static final String DEFAULT_PROVIDER = System.getProperty(DELEGATE_PROVIDER_KEY);
+ private static final Class<?>[] PROXY_API = new Class<?>[] { EntityManagerFactory.class, Serializable.class};
+
+ private static final String[] PROVIDERS = {
+ "org.apache.openjpa.persistence.PersistenceProviderImpl",
+ "org.hibernate.jpa.HibernatePeristenceProvider",
+ "org.hibernate.ejb.HibernatePeristence",
+ "org.eclipse.persistence.jpa.PersistenceProvider",
+ "oracle.toplink.essentials.ejb.cmp3.EntityManagerFactoryProvider",
+ "oracle.toplink.essentials.PersistenceProvider",
+ "me.prettyprint.hom.CassandraPersistenceProvider",
+ "org.datanucleus.jpa.PersistenceProviderImpl",
+ "com.orientechnologies.orient.core.db.object.jpa.OJPAPersistenceProvider",
+ "com.orientechnologies.orient.object.jpa.OJPAPersistenceProvider",
+ "com.spaceprogram.simplejpa.PersistenceProviderImpl"
+ };
+
+ private volatile PersistenceProvider delegate;
+
+ @Override
+ public EntityManagerFactory createEntityManagerFactory(final String unit, final Map map) {
+ final PersistenceProvider persistenceProvider = findDelegate(map);
+ final ClassLoader tccl = tccl();
+
+ final ClassLoader hack = new OverridePersistenceXmlClassLoader(tccl, persistenceProvider.getClass().getName());
+ Thread.currentThread().setContextClassLoader(hack);
+ try {
+ final EntityManagerFactory entityManagerFactory = persistenceProvider.createEntityManagerFactory(unit, map);
+ if (entityManagerFactory == null) {
+ return null;
+ }
+ return EntityManagerFactory.class.cast(
+ monitor(PROXY_API, entityManagerFactory, ROLE, true));
+ } finally {
+ Thread.currentThread().setContextClassLoader(tccl);
+ }
+ }
+
+ @Override
+ public EntityManagerFactory createContainerEntityManagerFactory(final PersistenceUnitInfo info, final Map map) {
+ final PersistenceProvider persistenceProvider = findDelegate(map);
+ final EntityManagerFactory containerEntityManagerFactory = persistenceProvider.createContainerEntityManagerFactory(
+ PersistenceUnitInfo.class.cast(Proxy.newProxyInstance(tccl(), new Class<?>[]{PersistenceUnitInfo.class}, new ProviderAwareHandler(persistenceProvider.getClass().getName(), info))),
+ map);
+ if (containerEntityManagerFactory == null) {
+ return null;
+ }
+ return EntityManagerFactory.class.cast(
+ monitor(PROXY_API, containerEntityManagerFactory, ROLE, true));
+ }
+
+ @Override
+ public ProviderUtil getProviderUtil() { // we suppose it is loaded later than createXXXEMF so we'll get the delegate
+ return loadOrGuessDelegate(null).getProviderUtil();
+ }
+
+ private PersistenceProvider findDelegate(final Map map) {
+ if (map == null) {
+ return loadOrGuessDelegate(null);
+ }
+ return loadOrGuessDelegate(String.class.cast(map.get(DELEGATE_PROVIDER_KEY)));
+ }
+
+ private PersistenceProvider loadOrGuessDelegate(final String name) {
+ if (delegate == null) {
+ synchronized (this) {
+ if (delegate == null) {
+ if (name == null) {
+ if (DEFAULT_PROVIDER != null) {
+ try {
+ delegate = newPersistence(DEFAULT_PROVIDER);
+ } catch (final Exception e) {
+ throw new IllegalStateException(new ClassNotFoundException("Can't instantiate '" + DEFAULT_PROVIDER + "'"));
+ }
+ } else {
+ for (final String provider : PROVIDERS) {
+ try {
+ delegate = newPersistence(provider);
+ if (delegate != null) {
+ break;
+ }
+ } catch (final Throwable th2) {
+ // no-op
+ }
+ }
+ }
+
+ if (delegate == null) {
+ throw new IllegalStateException(new ClassNotFoundException("Can't find a delegate"));
+ }
+ } else {
+ try {
+ delegate = newPersistence(name);
+ } catch (final Exception e) {
+ throw new IllegalStateException(new ClassNotFoundException("Can't instantiate '" + name + "'"));
+ }
+ }
+ }
+ }
+ }
+ if (name != null && !delegate.getClass().getName().equals(name)) {
+ try {
+ return newPersistence(name);
+ } catch (final Exception e) {
+ throw new IllegalStateException(new ClassNotFoundException("Can't instantiate '" + name + "'"));
+ }
+ }
+ return delegate;
+ }
+
+ private static ClassLoader tccl() {
+ return Thread.currentThread().getContextClassLoader();
+ }
+
+ private static PersistenceProvider newPersistence(final String name) throws Exception {
+ return PersistenceProvider.class.cast(tccl().loadClass(name).newInstance());
+ }
+
+ private static class ProviderAwareHandler implements InvocationHandler {
+ private final String provider;
+ private final PersistenceUnitInfo info;
+
+ public ProviderAwareHandler(final String provider, final PersistenceUnitInfo info) {
+ this.provider = provider;
+ this.info = info;
+ }
+
+ @Override
+ public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
+ if ("getPersistenceProviderClassName".equals(method.getName())) {
+ return provider;
+ }
+ return method.invoke(info, args);
+ }
+ }
+}
Added: incubator/sirona/trunk/agent/performance/jpa/src/main/java/org/apache/sirona/jpa/OverridePersistenceXmlClassLoader.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/performance/jpa/src/main/java/org/apache/sirona/jpa/OverridePersistenceXmlClassLoader.java?rev=1539076&view=auto
==============================================================================
--- incubator/sirona/trunk/agent/performance/jpa/src/main/java/org/apache/sirona/jpa/OverridePersistenceXmlClassLoader.java (added)
+++ incubator/sirona/trunk/agent/performance/jpa/src/main/java/org/apache/sirona/jpa/OverridePersistenceXmlClassLoader.java Tue Nov 5 17:25:15 2013
@@ -0,0 +1,142 @@
+/*
+ * 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.sirona.jpa;
+
+import org.apache.sirona.MonitoringException;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.URLStreamHandler;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.LinkedList;
+
+public class OverridePersistenceXmlClassLoader extends ClassLoader {
+ private static final String PERSISTENCE_XML = "META-INF/persistence.xml";
+ private static final String PERSISTENCE_PROVIDER = MonitoringPersistence.class.getName();
+ public static final String NO_PROVIDER = "<provider></provider>";
+
+ private final String replacement;
+
+ public OverridePersistenceXmlClassLoader(final ClassLoader parent, final String replacement) {
+ super(parent);
+ this.replacement = replacement;
+ }
+
+ @Override // don't load anything from here
+ protected Class<?> loadClass(final String name, final boolean resolve) throws ClassNotFoundException {
+ return super.loadClass(name, resolve);
+ }
+
+ @Override
+ public URL getResource(final String name) {
+ final URL url = super.getResource(name);
+ if (PERSISTENCE_XML.equals(name) && url != null) {
+ return newUrl(url, slurp(url));
+ }
+ return url;
+ }
+
+ @Override
+ public Enumeration<URL> getResources(final String name) throws IOException {
+ final Enumeration<URL> urls = super.getResources(name);
+ if (PERSISTENCE_XML.equals(name)) {
+ final Collection<URL> overrided = new LinkedList<URL>();
+ while (urls.hasMoreElements()) {
+ final URL url = urls.nextElement();
+ overrided.add(newUrl(url, slurp(url)));
+ }
+ return Collections.enumeration(overrided);
+ }
+ return urls;
+ }
+
+ private URL newUrl(final URL url, final String slurp) {
+ if (slurp.contains(PERSISTENCE_PROVIDER)) {
+ final String afterReplace = slurp.replace(PERSISTENCE_PROVIDER, replacement).replace(NO_PROVIDER, "");
+ try {
+ return new URL(url.getProtocol(), url.getHost(), url.getPort(), url.getFile(), new ConstantURLStreamHandler(afterReplace));
+ } catch (final MalformedURLException e) {
+ // no-op
+ }
+ }
+ return url;
+ }
+
+ private static String slurp(final URL url) {
+ InputStream is = null;
+ try {
+ is = url.openStream();
+ final ByteArrayOutputStream out = new ByteArrayOutputStream();
+ final byte[] buffer = new byte[1024];
+ int length;
+ while ((length = is.read(buffer)) != -1) {
+ out.write(buffer, 0, length);
+ }
+ return new String(out.toByteArray());
+ } catch (final IOException e) {
+ throw new MonitoringException(e);
+ } finally {
+ // no need to close out
+ try {
+ if (is != null) {
+ is.close();
+ }
+ } catch (IOException e) {
+ // no-op
+ }
+ }
+ }
+
+ private static class ConstantURLStreamHandler extends URLStreamHandler {
+ private final String value;
+
+ private ConstantURLStreamHandler(final String value) {
+ this.value = value;
+ }
+
+ @Override
+ protected URLConnection openConnection(final URL u) throws IOException {
+ return new ConstantURLConnection(u, value);
+ }
+ }
+
+ private static class ConstantURLConnection extends URLConnection {
+ private final String value;
+
+ private ConstantURLConnection(final URL url, final String value) {
+ super(url);
+ this.value = value;
+ }
+
+ @Override
+ public void connect() throws IOException {
+ // no-op
+ }
+
+ @Override
+ public InputStream getInputStream() throws IOException {
+ return new ByteArrayInputStream(value.getBytes());
+ }
+ }
+}
Added: incubator/sirona/trunk/agent/performance/jpa/src/main/resources/META-INF/services/javax.persistence.spi.PersistenceProvider
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/performance/jpa/src/main/resources/META-INF/services/javax.persistence.spi.PersistenceProvider?rev=1539076&view=auto
==============================================================================
--- incubator/sirona/trunk/agent/performance/jpa/src/main/resources/META-INF/services/javax.persistence.spi.PersistenceProvider (added)
+++ incubator/sirona/trunk/agent/performance/jpa/src/main/resources/META-INF/services/javax.persistence.spi.PersistenceProvider Tue Nov 5 17:25:15 2013
@@ -0,0 +1 @@
+org.apache.sirona.jpa.MonitoringPersistence
Added: incubator/sirona/trunk/agent/performance/jpa/src/test/java/org/apache/sirona/jpa/EMFTest.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/performance/jpa/src/test/java/org/apache/sirona/jpa/EMFTest.java?rev=1539076&view=auto
==============================================================================
--- incubator/sirona/trunk/agent/performance/jpa/src/test/java/org/apache/sirona/jpa/EMFTest.java (added)
+++ incubator/sirona/trunk/agent/performance/jpa/src/test/java/org/apache/sirona/jpa/EMFTest.java Tue Nov 5 17:25:15 2013
@@ -0,0 +1,77 @@
+/*
+ * 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.sirona.jpa;
+
+import org.apache.sirona.counters.Counter;
+import org.apache.sirona.repositories.Repository;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.Persistence;
+import javax.persistence.spi.PersistenceUnitInfo;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.Collection;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+public class EMFTest {
+ @Before
+ @After
+ public void reset() {
+ Repository.INSTANCE.clear();
+ }
+
+ @Test
+ public void newEmfJSe() {
+ final EntityManagerFactory emf = Persistence.createEntityManagerFactory("test-jse");
+ assertNotNull(emf);
+ emf.close();
+
+ assertCreateCalled();
+ }
+
+ @Test
+ public void newEmfJavaEE() {
+ final EntityManagerFactory emf = new MonitoringPersistence().createContainerEntityManagerFactory(
+ PersistenceUnitInfo.class.cast(Proxy.newProxyInstance(getClass().getClassLoader(), new Class<?>[]{PersistenceUnitInfo.class}, new InvocationHandler() {
+ @Override
+ public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
+ if (boolean.class.equals(method.getReturnType())) {
+ return false;
+ }
+ return null;
+ }
+ })), null);
+ assertNotNull(emf);
+ emf.close();
+
+ assertCreateCalled();
+ }
+
+ private static void assertCreateCalled() {
+ final Collection<Counter> counters = Repository.INSTANCE.counters();
+ assertEquals(1, counters.size());
+
+ final Counter counter = counters.iterator().next();
+ assertEquals(1, counter.getHits());
+ }
+}
Added: incubator/sirona/trunk/agent/performance/jpa/src/test/java/org/apache/sirona/jpa/QueryTest.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/performance/jpa/src/test/java/org/apache/sirona/jpa/QueryTest.java?rev=1539076&view=auto
==============================================================================
--- incubator/sirona/trunk/agent/performance/jpa/src/test/java/org/apache/sirona/jpa/QueryTest.java (added)
+++ incubator/sirona/trunk/agent/performance/jpa/src/test/java/org/apache/sirona/jpa/QueryTest.java Tue Nov 5 17:25:15 2013
@@ -0,0 +1,119 @@
+/*
+ * 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.sirona.jpa;
+
+import org.apache.sirona.counters.Counter;
+import org.apache.sirona.jpa.entity.Person;
+import org.apache.sirona.repositories.Repository;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.EntityTransaction;
+import javax.persistence.Persistence;
+
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+public class QueryTest {
+ @Before
+ @After
+ public void reset() {
+ Repository.INSTANCE.clear();
+ }
+
+ @Test
+ public void simpleFind() {
+ final EntityManagerFactory emf = Persistence.createEntityManagerFactory("test-jse");
+ assertNotNull(emf);
+ reset(); // get rid of init counter
+
+ try {
+ final EntityManager em = emf.createEntityManager();
+ assertNotNull(em);
+
+ assertCounter("createEntityManager");
+
+ reset(); // get rid of createEntityManager counter
+ try {
+ em.find(Person.class, 0L);
+ assertCounter("find");
+ reset(); // get rid of em.find() counter
+ } finally {
+ em.close();
+ assertCounter("EntityManagerImpl.close");
+ }
+
+ reset(); // get rid of em.close() counter
+ } finally {
+ emf.close();
+ }
+ assertCounter("EntityManagerFactoryImpl.close");
+ }
+
+ @Test
+ public void createNamedQuery() {
+ final EntityManagerFactory emf = Persistence.createEntityManagerFactory("test-jse");
+
+ try {
+ { // init
+ final EntityManager em = emf.createEntityManager();
+ try {
+ final EntityTransaction transaction = em.getTransaction();
+ transaction.begin();
+ try {
+ final Person p = new Person();
+ p.setName("sirona");
+
+ em.persist(p);
+ transaction.commit();
+ } catch (final Exception e) {
+ transaction.rollback();
+ }
+ } finally {
+ em.close();
+ }
+ }
+
+ { // checks
+ final EntityManager em = emf.createEntityManager();
+ try {
+ reset();
+ em.createNamedQuery("Person.findByName", Person.class).setParameter("name", "sirona").getSingleResult();
+ assertCounter("createNamedQuery");
+ } finally {
+ em.close();
+ }
+ }
+ } finally {
+ emf.close();
+ }
+ }
+
+ private static void assertCounter(final String method) {
+ assertTrue(Repository.INSTANCE.counters().iterator().hasNext());
+
+ final Counter counter = Repository.INSTANCE.counters().iterator().next();
+ assertEquals(1, counter.getHits());
+ assertThat(counter.getKey().getName(), containsString(method));
+ }
+}
Added: incubator/sirona/trunk/agent/performance/jpa/src/test/java/org/apache/sirona/jpa/entity/Address.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/performance/jpa/src/test/java/org/apache/sirona/jpa/entity/Address.java?rev=1539076&view=auto
==============================================================================
--- incubator/sirona/trunk/agent/performance/jpa/src/test/java/org/apache/sirona/jpa/entity/Address.java (added)
+++ incubator/sirona/trunk/agent/performance/jpa/src/test/java/org/apache/sirona/jpa/entity/Address.java Tue Nov 5 17:25:15 2013
@@ -0,0 +1,53 @@
+/*
+ * 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.sirona.jpa.entity;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.ManyToOne;
+
+@Entity
+public class Address {
+ @Id
+ @GeneratedValue
+ private long id;
+ private String street;
+
+ @ManyToOne
+ private Person person;
+
+ public long getId() {
+ return id;
+ }
+
+ public String getStreet() {
+ return street;
+ }
+
+ public void setStreet(final String street) {
+ this.street = street;
+ }
+
+ public Person getPerson() {
+ return person;
+ }
+
+ public void setPerson(final Person person) {
+ this.person = person;
+ }
+}
Added: incubator/sirona/trunk/agent/performance/jpa/src/test/java/org/apache/sirona/jpa/entity/Person.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/performance/jpa/src/test/java/org/apache/sirona/jpa/entity/Person.java?rev=1539076&view=auto
==============================================================================
--- incubator/sirona/trunk/agent/performance/jpa/src/test/java/org/apache/sirona/jpa/entity/Person.java (added)
+++ incubator/sirona/trunk/agent/performance/jpa/src/test/java/org/apache/sirona/jpa/entity/Person.java Tue Nov 5 17:25:15 2013
@@ -0,0 +1,55 @@
+/*
+ * 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.sirona.jpa.entity;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.NamedQuery;
+import javax.persistence.OneToMany;
+import java.util.LinkedList;
+import java.util.List;
+
+@Entity
+@NamedQuery(name = "Person.findByName", query = "select p from Person p where p.name = :name")
+public class Person {
+ @Id
+ @GeneratedValue
+ private long id;
+
+ private String name;
+
+ @OneToMany(cascade = { CascadeType.ALL }, mappedBy = "person")
+ private List<Address> addresses = new LinkedList<Address>();
+
+ public long getId() {
+ return id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(final String name) {
+ this.name = name;
+ }
+
+ public List<Address> getAddresses() {
+ return addresses;
+ }
+}