onami-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From danielman...@apache.org
Subject svn commit: r1418469 - in /incubator/onami/trunk/autobind/aop/src/main/java/org/apache/onami: ./ autobind/ autobind/aop/ autobind/aop/feature/
Date Fri, 07 Dec 2012 20:53:41 GMT
Author: danielmanzke
Date: Fri Dec  7 20:53:39 2012
New Revision: 1418469

URL: http://svn.apache.org/viewvc?rev=1418469&view=rev
Log:
[ONAMI-23] reenable configuration of autobind

- added missing files

Added:
    incubator/onami/trunk/autobind/aop/src/main/java/org/apache/onami/   (with props)
    incubator/onami/trunk/autobind/aop/src/main/java/org/apache/onami/autobind/   (with props)
    incubator/onami/trunk/autobind/aop/src/main/java/org/apache/onami/autobind/aop/   (with
props)
    incubator/onami/trunk/autobind/aop/src/main/java/org/apache/onami/autobind/aop/ClassMatcher.java
    incubator/onami/trunk/autobind/aop/src/main/java/org/apache/onami/autobind/aop/GuiceMethodInterceptor.java
    incubator/onami/trunk/autobind/aop/src/main/java/org/apache/onami/autobind/aop/Intercept.java
    incubator/onami/trunk/autobind/aop/src/main/java/org/apache/onami/autobind/aop/Invoke.java
    incubator/onami/trunk/autobind/aop/src/main/java/org/apache/onami/autobind/aop/MethodMatcher.java
    incubator/onami/trunk/autobind/aop/src/main/java/org/apache/onami/autobind/aop/feature/
  (with props)
    incubator/onami/trunk/autobind/aop/src/main/java/org/apache/onami/autobind/aop/feature/InterceptorFeature.java
    incubator/onami/trunk/autobind/aop/src/main/java/org/apache/onami/autobind/aop/feature/package-info.java
    incubator/onami/trunk/autobind/aop/src/main/java/org/apache/onami/autobind/aop/package-info.java

Propchange: incubator/onami/trunk/autobind/aop/src/main/java/org/apache/onami/
------------------------------------------------------------------------------
    bugtraq:number = true

Propchange: incubator/onami/trunk/autobind/aop/src/main/java/org/apache/onami/autobind/
------------------------------------------------------------------------------
    bugtraq:number = true

Propchange: incubator/onami/trunk/autobind/aop/src/main/java/org/apache/onami/autobind/aop/
------------------------------------------------------------------------------
    bugtraq:number = true

Added: incubator/onami/trunk/autobind/aop/src/main/java/org/apache/onami/autobind/aop/ClassMatcher.java
URL: http://svn.apache.org/viewvc/incubator/onami/trunk/autobind/aop/src/main/java/org/apache/onami/autobind/aop/ClassMatcher.java?rev=1418469&view=auto
==============================================================================
--- incubator/onami/trunk/autobind/aop/src/main/java/org/apache/onami/autobind/aop/ClassMatcher.java
(added)
+++ incubator/onami/trunk/autobind/aop/src/main/java/org/apache/onami/autobind/aop/ClassMatcher.java
Fri Dec  7 20:53:39 2012
@@ -0,0 +1,45 @@
+package org.apache.onami.autobind.aop;
+
+/*
+ * 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.
+ */
+
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import org.aopalliance.intercept.MethodInterceptor;
+
+/**
+ * This Annotation marks a Method, which returns an Object of Type
+ * {@link Matcher}. This Matcher is used by Guice, to decide if a
+ * {@link MethodInterceptor} should be invoked for that {@link Class}.
+ *
+ * <pre>@ClassMatcher
+ * public Matcher<? super Class<?>> getClassMatcher()
+ * {
+ *     return Matchers.any();
+ * }</pre>
+ */
+@Documented
+@Retention( RUNTIME )
+@Target( { METHOD } )
+public @interface ClassMatcher
+{
+}

Added: incubator/onami/trunk/autobind/aop/src/main/java/org/apache/onami/autobind/aop/GuiceMethodInterceptor.java
URL: http://svn.apache.org/viewvc/incubator/onami/trunk/autobind/aop/src/main/java/org/apache/onami/autobind/aop/GuiceMethodInterceptor.java?rev=1418469&view=auto
==============================================================================
--- incubator/onami/trunk/autobind/aop/src/main/java/org/apache/onami/autobind/aop/GuiceMethodInterceptor.java
(added)
+++ incubator/onami/trunk/autobind/aop/src/main/java/org/apache/onami/autobind/aop/GuiceMethodInterceptor.java
Fri Dec  7 20:53:39 2012
@@ -0,0 +1,59 @@
+package org.apache.onami.autobind.aop;
+
+/*
+ * 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.
+ */
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+
+import org.aopalliance.intercept.MethodInterceptor;
+
+import com.google.inject.matcher.Matcher;
+
+/**
+ * If you don't want to use the {@link Invoke}, {@link MethodMatcher} and
+ * {@link ClassMatcher} Annotation, your {@link MethodInterceptor} could inherit
+ * of this class.
+ */
+public abstract class GuiceMethodInterceptor
+    implements MethodInterceptor
+{
+
+    public static Type CLASS_MATCHER_TYPE;
+
+    public static Type METHOD_MATCHER_TYPE;
+
+    static
+    {
+        try
+        {
+            CLASS_MATCHER_TYPE =
+                GuiceMethodInterceptor.class.getMethod( "getClassMatcher", new Class<?>[0]
).getGenericReturnType();
+            METHOD_MATCHER_TYPE =
+                GuiceMethodInterceptor.class.getMethod( "getMethodMatcher", new Class<?>[0]
).getGenericReturnType();
+        }
+        catch ( Exception e )
+        {
+            // ignore
+        }
+    }
+
+    public abstract Matcher<? super Class<?>> getClassMatcher();
+
+    public abstract Matcher<? super Method> getMethodMatcher();
+
+}

Added: incubator/onami/trunk/autobind/aop/src/main/java/org/apache/onami/autobind/aop/Intercept.java
URL: http://svn.apache.org/viewvc/incubator/onami/trunk/autobind/aop/src/main/java/org/apache/onami/autobind/aop/Intercept.java?rev=1418469&view=auto
==============================================================================
--- incubator/onami/trunk/autobind/aop/src/main/java/org/apache/onami/autobind/aop/Intercept.java
(added)
+++ incubator/onami/trunk/autobind/aop/src/main/java/org/apache/onami/autobind/aop/Intercept.java
Fri Dec  7 20:53:39 2012
@@ -0,0 +1,44 @@
+package org.apache.onami.autobind.aop;
+
+/*
+ * 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.
+ */
+
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import org.aopalliance.intercept.MethodInterceptor;
+
+/**
+ * This is an Annotation, which can be used to create a {@link MethodMatcher},
+ * so an {@link MethodInterceptor} knows which Method to monitor.
+ *
+ * <pre>@Intercept
+ * public String sayHello()
+ * {
+ *     return "yeahhh!!!";
+ * }</pre>
+ */
+@Documented
+@Retention( RUNTIME )
+@Target( { METHOD } )
+public @interface Intercept
+{
+}

Added: incubator/onami/trunk/autobind/aop/src/main/java/org/apache/onami/autobind/aop/Invoke.java
URL: http://svn.apache.org/viewvc/incubator/onami/trunk/autobind/aop/src/main/java/org/apache/onami/autobind/aop/Invoke.java?rev=1418469&view=auto
==============================================================================
--- incubator/onami/trunk/autobind/aop/src/main/java/org/apache/onami/autobind/aop/Invoke.java
(added)
+++ incubator/onami/trunk/autobind/aop/src/main/java/org/apache/onami/autobind/aop/Invoke.java
Fri Dec  7 20:53:39 2012
@@ -0,0 +1,43 @@
+package org.apache.onami.autobind.aop;
+
+/*
+ * 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.
+ */
+
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * This Annotation marks a Method, which should be invoked for each Method,
+ * which is matching the Criterias of this Interceptor.
+ *
+ * <pre>@Invoke
+ * public Object invoke( MethodInvocation invocation )
+ *     throws Throwable
+ * {
+ *     return invocation.proceed();
+ * }</pre>
+ */
+@Documented
+@Retention( RUNTIME )
+@Target( { METHOD } )
+public @interface Invoke
+{
+}

Added: incubator/onami/trunk/autobind/aop/src/main/java/org/apache/onami/autobind/aop/MethodMatcher.java
URL: http://svn.apache.org/viewvc/incubator/onami/trunk/autobind/aop/src/main/java/org/apache/onami/autobind/aop/MethodMatcher.java?rev=1418469&view=auto
==============================================================================
--- incubator/onami/trunk/autobind/aop/src/main/java/org/apache/onami/autobind/aop/MethodMatcher.java
(added)
+++ incubator/onami/trunk/autobind/aop/src/main/java/org/apache/onami/autobind/aop/MethodMatcher.java
Fri Dec  7 20:53:39 2012
@@ -0,0 +1,46 @@
+package org.apache.onami.autobind.aop;
+
+/*
+ * 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.
+ */
+
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import java.lang.reflect.Method;
+
+import org.aopalliance.intercept.MethodInterceptor;
+
+/**
+ * This Annotation marks a Method, which returns an Object of Type
+ * {@link Matcher}. This Matcher is used by Guice, to decide if a
+ * {@link MethodInterceptor} should be invoked for that {@link Method}.
+ *
+ * <pre>@MethodMatcher
+ * public Matcher<? super Method> getMethodMatcher()
+ * {
+ *     return Matchers.annotatedWith( Intercept.class );
+ * }
+ */
+@Documented
+@Retention( RUNTIME )
+@Target( { METHOD } )
+public @interface MethodMatcher
+{
+}

Propchange: incubator/onami/trunk/autobind/aop/src/main/java/org/apache/onami/autobind/aop/feature/
------------------------------------------------------------------------------
    bugtraq:number = true

Added: incubator/onami/trunk/autobind/aop/src/main/java/org/apache/onami/autobind/aop/feature/InterceptorFeature.java
URL: http://svn.apache.org/viewvc/incubator/onami/trunk/autobind/aop/src/main/java/org/apache/onami/autobind/aop/feature/InterceptorFeature.java?rev=1418469&view=auto
==============================================================================
--- incubator/onami/trunk/autobind/aop/src/main/java/org/apache/onami/autobind/aop/feature/InterceptorFeature.java
(added)
+++ incubator/onami/trunk/autobind/aop/src/main/java/org/apache/onami/autobind/aop/feature/InterceptorFeature.java
Fri Dec  7 20:53:39 2012
@@ -0,0 +1,166 @@
+package org.apache.onami.autobind.aop.feature;
+
+/*
+ * 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.
+ */
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.inject.Singleton;
+import javax.interceptor.Interceptor;
+
+import org.aopalliance.intercept.MethodInterceptor;
+import org.aopalliance.intercept.MethodInvocation;
+import org.apache.onami.autobind.aop.ClassMatcher;
+import org.apache.onami.autobind.aop.GuiceMethodInterceptor;
+import org.apache.onami.autobind.aop.Invoke;
+import org.apache.onami.autobind.aop.MethodMatcher;
+import org.apache.onami.autobind.install.BindingStage;
+import org.apache.onami.autobind.scanner.features.BindingScannerFeature;
+
+import com.google.inject.matcher.Matcher;
+import com.google.inject.matcher.Matchers;
+
+
+@Singleton
+public class InterceptorFeature extends BindingScannerFeature {
+	private Logger _logger = Logger.getLogger(InterceptorFeature.class.getName());
+
+	@Override
+	public BindingStage accept(Class<Object> annotatedClass, Map<String, Annotation>
annotations) {
+		if (annotations.containsKey(Interceptor.class.getName())) {
+			return BindingStage.BOOT;
+		}
+		return BindingStage.IGNORE;
+	}
+
+	@SuppressWarnings("unchecked")
+	@Override
+	public void process(Class<Object> annotatedClass, Map<String, Annotation> annotations)
{
+		MethodInterceptor interceptor;
+		final Object possibleInterceptor = injector.getInstance(annotatedClass);
+
+		Matcher<? super Class<?>> classMatcher = null;
+		Matcher<? super Method> methodMatcher = null;
+		if (possibleInterceptor instanceof GuiceMethodInterceptor) {
+			interceptor = (MethodInterceptor) possibleInterceptor;
+			GuiceMethodInterceptor guiceInterceptor = (GuiceMethodInterceptor) interceptor;
+			classMatcher = guiceInterceptor.getClassMatcher();
+			methodMatcher = guiceInterceptor.getMethodMatcher();
+		} else {
+			Method[] declaredMethods = annotatedClass.getDeclaredMethods();
+			Map<Class<? extends Annotation>, Method> methods = new HashMap<Class<?
extends Annotation>, Method>();
+
+			for (Method method : declaredMethods) {
+				Annotation[] methodAnnotations = method.getAnnotations();
+				for (Annotation methodAnnotation : methodAnnotations) {
+					methods.put(methodAnnotation.annotationType(), method);
+				}
+			}
+			try {
+				if (methods.containsKey(ClassMatcher.class)) {
+					Method method = methods.get(ClassMatcher.class);
+					Type genericReturnType = method.getGenericReturnType();
+					if (GuiceMethodInterceptor.CLASS_MATCHER_TYPE.equals(genericReturnType)) {
+						classMatcher = (Matcher<? super Class<?>>) method.invoke(
+							possibleInterceptor, new Object[0]);
+					} else {
+						_logger.log(Level.WARNING,
+							"Return Type of the annotated @ClassMatcher-Method, does not return: "
+									+ GuiceMethodInterceptor.CLASS_MATCHER_TYPE
+									+ " instead it returns " + genericReturnType);
+					}
+				}
+
+				if (methods.containsKey(MethodMatcher.class)) {
+					Method method = methods.get(MethodMatcher.class);
+					Type genericReturnType = method.getGenericReturnType();
+					if (GuiceMethodInterceptor.METHOD_MATCHER_TYPE.equals(genericReturnType)) {
+						methodMatcher = (Matcher<? super Method>) method.invoke(
+							possibleInterceptor, new Object[0]);
+					} else {
+						_logger.log(Level.WARNING,
+							"Return Type of the annotated @MethodMatcher-Method, does not return: "
+									+ GuiceMethodInterceptor.METHOD_MATCHER_TYPE
+									+ " instead it returns " + genericReturnType);
+					}
+				}
+			} catch (Exception e) {
+				_logger
+					.log(
+						Level.WARNING,
+						"Skipping process(..) of \""
+								+ annotatedClass
+								+ "\", because an Exception occured while trying to invoke a Method of the found
Intercepter.",
+						e);
+				return;
+			}
+
+			if (possibleInterceptor instanceof MethodInterceptor) {
+				interceptor = (MethodInterceptor) possibleInterceptor;
+			} else {
+				if (methods.containsKey(Invoke.class)) {
+					final Method method = methods.get(Invoke.class);
+					Class<?>[] parameterTypes = method.getParameterTypes();
+					if (parameterTypes != null && parameterTypes.length == 1
+							&& parameterTypes[0] == MethodInvocation.class) {
+						interceptor = new MethodInterceptor() {
+							@Override
+							public Object invoke(MethodInvocation invocation) throws Throwable {
+								return method.invoke(possibleInterceptor, invocation);
+							}
+						};
+					} else {
+						_logger
+							.log(
+								Level.WARNING,
+								"Skipping \""
+										+ annotatedClass
+										+ "\", because the Parameter of the with @Invoke annotated Method \""
+										+ method.getName()
+										+ "\" doesn't match the expected one. "
+										+ method.getName() + "(MethodInvocation invocation)");
+						return;
+					}
+				} else {
+					_logger.log(Level.WARNING, "Skipping \"" + annotatedClass
+							+ "\" is either Child of \""
+							+ GuiceMethodInterceptor.class.getName() + "\" / \""
+							+ MethodInterceptor.class.getName()
+							+ "\" nor has a Method annotated with \"" + Invoke.class.getName()
+							+ "\"");
+					return;
+				}
+			}
+		}
+
+		if (classMatcher == null) {
+			classMatcher = Matchers.any();
+		}
+
+		if (methodMatcher == null) {
+			methodMatcher = Matchers.any();
+		}
+
+		_binder.bindInterceptor(classMatcher, methodMatcher, interceptor);
+	}
+}
\ No newline at end of file

Added: incubator/onami/trunk/autobind/aop/src/main/java/org/apache/onami/autobind/aop/feature/package-info.java
URL: http://svn.apache.org/viewvc/incubator/onami/trunk/autobind/aop/src/main/java/org/apache/onami/autobind/aop/feature/package-info.java?rev=1418469&view=auto
==============================================================================
--- incubator/onami/trunk/autobind/aop/src/main/java/org/apache/onami/autobind/aop/feature/package-info.java
(added)
+++ incubator/onami/trunk/autobind/aop/src/main/java/org/apache/onami/autobind/aop/feature/package-info.java
Fri Dec  7 20:53:39 2012
@@ -0,0 +1,21 @@
+/**
+ * TODO fill me
+ */
+package org.apache.onami.autobind.aop.feature;
+
+/*
+ * 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.
+ */

Added: incubator/onami/trunk/autobind/aop/src/main/java/org/apache/onami/autobind/aop/package-info.java
URL: http://svn.apache.org/viewvc/incubator/onami/trunk/autobind/aop/src/main/java/org/apache/onami/autobind/aop/package-info.java?rev=1418469&view=auto
==============================================================================
--- incubator/onami/trunk/autobind/aop/src/main/java/org/apache/onami/autobind/aop/package-info.java
(added)
+++ incubator/onami/trunk/autobind/aop/src/main/java/org/apache/onami/autobind/aop/package-info.java
Fri Dec  7 20:53:39 2012
@@ -0,0 +1,21 @@
+/**
+ * TODO fill me
+ */
+package org.apache.onami.autobind.aop;
+
+/*
+ * 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.
+ */



Mime
View raw message