Author: dhanji
Date: Mon Dec 29 22:32:41 2008
New Revision: 749

Modified:
    trunk/servlet/src/com/google/inject/servlet/FilterChainInvocation.java
    trunk/servlet/src/com/google/inject/servlet/FilterDefinition.java
    trunk/servlet/src/com/google/inject/servlet/FiltersModuleBuilder.java
    trunk/servlet/src/com/google/inject/servlet/ManagedFilterPipeline.java
    trunk/servlet/src/com/google/inject/servlet/ManagedServletPipeline.java
    trunk/servlet/src/com/google/inject/servlet/ServletDefinition.java
    trunk/servlet/src/com/google/inject/servlet/ServletModule.java
    trunk/servlet/src/com/google/inject/servlet/ServletsModuleBuilder.java
    trunk/servlet/src/com/google/inject/servlet/UriPatternMatcher.java
    trunk/servlet/src/com/google/inject/servlet/UriPatternType.java
    trunk/servlet/test/com/google/inject/servlet/FilterDefinitionTest.java
     
trunk/servlet/test/com/google/inject/servlet/ServletDefinitionPathsTest.java
    trunk/servlet/test/com/google/inject/servlet/ServletDefinitionTest.java
     
trunk/servlet/test/com/google/inject/servlet/ServletPipelineRequestDispatcherTest.java

Log:
Some cleanups from Jesse's last comments. Performance improvements (minor).  
Next CL handles more cleanups, multiple modules, and better error checking.

Modified:  
trunk/servlet/src/com/google/inject/servlet/FilterChainInvocation.java
==============================================================================
--- trunk/servlet/src/com/google/inject/servlet/FilterChainInvocation.java      
 
(original)
+++ trunk/servlet/src/com/google/inject/servlet/FilterChainInvocation.java      
 
Mon Dec 29 22:32:41 2008
@@ -57,8 +57,7 @@
      //dispatch down the chain while there are more filters
      if (index < filterDefinitions.size()) {
        filterDefinitions.get(index).doFilter(servletRequest,  
servletResponse, this);
-    }
-    else {
+    } else {

        //we've reached the end of the filterchain, let's try to dispatch to  
a servlet
        final boolean serviced = servletPipeline.service(servletRequest,  
servletResponse);

Modified: trunk/servlet/src/com/google/inject/servlet/FilterDefinition.java
==============================================================================
--- trunk/servlet/src/com/google/inject/servlet/FilterDefinition.java    
(original)
+++ trunk/servlet/src/com/google/inject/servlet/FilterDefinition.java   Mon  
Dec 29 22:32:41 2008
@@ -15,13 +15,13 @@
   */
  package com.google.inject.servlet;

+import com.google.common.collect.Iterators;
  import com.google.inject.Injector;
  import com.google.inject.Key;
  import java.io.IOException;
  import java.util.Collections;
  import java.util.Enumeration;
  import java.util.HashMap;
-import java.util.Iterator;
  import java.util.Map;
  import java.util.concurrent.atomic.AtomicReference;
  import javax.servlet.Filter;
@@ -54,7 +54,7 @@
    }

    private boolean shouldFilter(String uri) {
-    return patternMatcher.matches(uri, pattern);
+    return patternMatcher.matches(uri);
    }

    public void init(final ServletContext servletContext, Injector injector)  
throws ServletException {
@@ -63,7 +63,6 @@
      this.filter.set(filter);

      //initialize our filter with the configured context params and servlet  
context
-    //noinspection  
OverlyComplexAnonymousInnerClass,AnonymousInnerClassWithTooManyMethods
      filter.init(new FilterConfig() {
        public String getFilterName() {
          return filterKey.toString();
@@ -78,18 +77,7 @@
        }

        public Enumeration getInitParameterNames() {
-        //noinspection  
InnerClassTooDeeplyNested,AnonymousInnerClassWithTooManyMethods
-        return new Enumeration() {
-          private final Iterator<String> paramNames =  
initParams.keySet().iterator();
-
-          public boolean hasMoreElements() {
-            return paramNames.hasNext();
-          }
-
-          public Object nextElement() {
-            return paramNames.next();
-          }
-        };
+        return Iterators.asEnumeration(initParams.keySet().iterator());
        }
      });
    }

Modified:  
trunk/servlet/src/com/google/inject/servlet/FiltersModuleBuilder.java
==============================================================================
--- trunk/servlet/src/com/google/inject/servlet/FiltersModuleBuilder.java       
 
(original)
+++ trunk/servlet/src/com/google/inject/servlet/FiltersModuleBuilder.java       
 
Mon Dec 29 22:32:41 2008
@@ -78,7 +78,7 @@

        for (String pattern : uriPatterns) {
          filterDefinitions.add(
-            new FilterDefinition(pattern, filterKey,  
UriPatternType.get(uriPatternType),
+            new FilterDefinition(pattern, filterKey,  
UriPatternType.get(uriPatternType, pattern),
                  contextParams));
        }
      }

Modified:  
trunk/servlet/src/com/google/inject/servlet/ManagedFilterPipeline.java
==============================================================================
--- trunk/servlet/src/com/google/inject/servlet/ManagedFilterPipeline.java      
 
(original)
+++ trunk/servlet/src/com/google/inject/servlet/ManagedFilterPipeline.java      
 
Mon Dec 29 22:32:41 2008
@@ -41,7 +41,6 @@
  class ManagedFilterPipeline implements FilterPipeline{
    private final List<FilterDefinition> filterDefinitions;

-  //TODO make these setter for testing?
    @Inject
    private final ManagedServletPipeline servletPipeline = null;

@@ -86,7 +85,7 @@
        initPipeline(servletContext.get());
      }

-    //obtain the servlet pipeline to dispatch against (we use  
getInstance() to avoid holding refs)
+    //obtain the servlet pipeline to dispatch against
      new FilterChainInvocation(filterDefinitions, servletPipeline,  
proceedingFilterChain)
          .doFilter(withDispatcher(request, servletPipeline), response);


Modified:  
trunk/servlet/src/com/google/inject/servlet/ManagedServletPipeline.java
==============================================================================
--- trunk/servlet/src/com/google/inject/servlet/ManagedServletPipeline.java     
 
(original)
+++ trunk/servlet/src/com/google/inject/servlet/ManagedServletPipeline.java     
 
Mon Dec 29 22:32:41 2008
@@ -30,7 +30,8 @@
   * @author [email protected] (Dhanji R. Prasanna)
   * @see ManagedFilterPipeline
   */
-...@singleton class ManagedServletPipeline {
+...@singleton
+class ManagedServletPipeline {
    private final List<ServletDefinition> servletDefinitions;

    public ManagedServletPipeline(List<ServletDefinition>  
servletDefinitions) {
@@ -63,7 +64,11 @@
      }
    }

-  public RequestDispatcher getRequestDispatcher(String path) {
+  /**
+   * @return Returns a request dispatcher wrapped with a servlet mapped to
+   * the given path or null if no mapping was found.
+   */
+  RequestDispatcher getRequestDispatcher(String path) {
      for (final ServletDefinition servletDefinition : servletDefinitions) {
        if (servletDefinition.shouldServe(path)) {
          return new RequestDispatcher() {

Modified: trunk/servlet/src/com/google/inject/servlet/ServletDefinition.java
==============================================================================
--- trunk/servlet/src/com/google/inject/servlet/ServletDefinition.java   
(original)
+++ trunk/servlet/src/com/google/inject/servlet/ServletDefinition.java  Mon  
Dec 29 22:32:41 2008
@@ -15,13 +15,13 @@
   */
  package com.google.inject.servlet;

+import com.google.common.collect.Iterators;
  import com.google.inject.Injector;
  import com.google.inject.Key;
  import java.io.IOException;
  import java.util.Collections;
  import java.util.Enumeration;
  import java.util.HashMap;
-import java.util.Iterator;
  import java.util.Map;
  import java.util.concurrent.atomic.AtomicReference;
  import javax.servlet.ServletConfig;
@@ -57,16 +57,15 @@
    }

    boolean shouldServe(String uri) {
-    return patternMatcher.matches(uri, pattern);
+    return patternMatcher.matches(uri);
    }

    public void init(final ServletContext servletContext, Injector injector)  
throws ServletException {
-    //TODO this absolutely must be a singleton, and so is only initialized  
once
+    //TODO(dhanji): this absolutely must be a singleton, and so is only  
initialized once
      HttpServlet httpServlet = injector.getInstance(servletKey);
      this.httpServlet.set(httpServlet);

      //initialize our servlet with the configured context params and  
servlet context
-    //noinspection  
OverlyComplexAnonymousInnerClass,AnonymousInnerClassWithTooManyMethods
      httpServlet.init(new ServletConfig() {
        public String getServletName() {
          return servletKey.toString();
@@ -81,18 +80,7 @@
        }

        public Enumeration getInitParameterNames() {
-        //noinspection  
InnerClassTooDeeplyNested,AnonymousInnerClassWithTooManyMethods
-        return new Enumeration() {
-          private final Iterator<String> paramNames =  
initParams.keySet().iterator();
-
-          public boolean hasMoreElements() {
-            return paramNames.hasNext();
-          }
-
-          public Object nextElement() {
-            return paramNames.next();
-          }
-        };
+        return Iterators.asEnumeration(initParams.keySet().iterator());
        }
      });
    }
@@ -132,8 +120,8 @@
     * We need to suppress deprecation coz we use HttpServletRequestWrapper,  
which implements
     * deprecated API for backwards compatibility.
     */
-  @SuppressWarnings({ "JavaDoc", "deprecation" }) void doService(
-      final ServletRequest servletRequest, ServletResponse servletResponse)
+  @SuppressWarnings({ "JavaDoc", "deprecation" })
+  void doService(final ServletRequest servletRequest, ServletResponse  
servletResponse)
        throws ServletException, IOException {

      //noinspection OverlyComplexAnonymousInnerClass

Modified: trunk/servlet/src/com/google/inject/servlet/ServletModule.java
==============================================================================
--- trunk/servlet/src/com/google/inject/servlet/ServletModule.java       
(original)
+++ trunk/servlet/src/com/google/inject/servlet/ServletModule.java      Mon Dec 
 
29 22:32:41 2008
@@ -38,8 +38,7 @@
   * objects so you can inject the request, response, session, etc.
   *
   * <p>
- * <strong>
- * As of Guice 2.0, you can subclass this module to register servlets and
+ * You should subclass this module to register servlets and
   * filters in the {...@link #configureServlets()} method.
   *
   * @author [email protected] (Bob Lee)

Modified:  
trunk/servlet/src/com/google/inject/servlet/ServletsModuleBuilder.java
==============================================================================
--- trunk/servlet/src/com/google/inject/servlet/ServletsModuleBuilder.java      
 
(original)
+++ trunk/servlet/src/com/google/inject/servlet/ServletsModuleBuilder.java      
 
Mon Dec 29 22:32:41 2008
@@ -77,7 +77,7 @@

        for (String pattern : uriPatterns) {
          servletDefinitions.add(
-            new ServletDefinition(pattern, servletKey,  
UriPatternType.get(uriPatternType),
+            new ServletDefinition(pattern, servletKey,  
UriPatternType.get(uriPatternType, pattern),
                  contextParams));
        }
      }

Modified: trunk/servlet/src/com/google/inject/servlet/UriPatternMatcher.java
==============================================================================
--- trunk/servlet/src/com/google/inject/servlet/UriPatternMatcher.java   
(original)
+++ trunk/servlet/src/com/google/inject/servlet/UriPatternMatcher.java  Mon  
Dec 29 22:32:41 2008
@@ -17,30 +17,25 @@
  package com.google.inject.servlet;

  /**
- * <p>
- * A general interface for matching a URI against a URI pattern.  
Guice-servlet provides
- * regex and servlet-style pattern matching out of the box.
- * </p>
+ * A general interface for matching a URI against a URI pattern.  
Guice-servlet provides regex and
+ * servlet-style pattern matching out of the box.
   *
   * @author [email protected] (Dhanji R. Prasanna)
- * @see com.google.inject.servlet.Servlets#configure() Binding Servlets.
   */
  interface UriPatternMatcher {
-    /**
-     * @param uri A "contextual" (i.e. relative) Request URI, *not* a  
complete one.
-     * @param pattern A String containing some pattern that this service  
can match against.
-     * @return Returns true if the uri matches the pattern.
-     */
-    boolean matches(String uri, String pattern);
+  /**
+   * @param uri A "contextual" (i.e. relative) Request URI, *not* a  
complete one.
+   * @return Returns true if the uri matches the pattern.
+   */
+  boolean matches(String uri);

-    /**
-     * @param pattern A String containing some pattern that this service  
can match against.
-     * @return Returns a canonical servlet path from this pattern. For  
instance, if the
-     * pattern is {...@code /home/*} then the path extracted will be {...@code 
 
/home}. Each pattern
-     * matcher implementation must decide and publish what a canonical  
path represents.
-     *
-     * NOTE(dhanji) This method returns null for the regex pattern matcher.
-     *
-     */
-    String extractPath(String pattern);
+  /**
+   * @param pattern A String containing some pattern that this service can  
match against.
+   * @return Returns a canonical servlet path from this pattern. For  
instance, if the pattern is
+   *         {...@code /home/*} then the path extracted will be {...@code  
/home}. Each pattern matcher
+   *         implementation must decide and publish what a canonical path  
represents.
+   *
+   *         NOTE(dhanji): This method returns null for the regex pattern  
matcher.
+   */
+  String extractPath(String pattern);
  }

Modified: trunk/servlet/src/com/google/inject/servlet/UriPatternType.java
==============================================================================
--- trunk/servlet/src/com/google/inject/servlet/UriPatternType.java      
(original)
+++ trunk/servlet/src/com/google/inject/servlet/UriPatternType.java     Mon Dec 
 
29 22:32:41 2008
@@ -15,18 +15,20 @@
   */
  package com.google.inject.servlet;

+import java.util.regex.Pattern;
+
  /**
   * An enumeration of the available URI-pattern matching styles
   */
  enum UriPatternType {
    SERVLET, REGEX;

-  public static UriPatternMatcher get(UriPatternType type) {
+  public static UriPatternMatcher get(UriPatternType type, String pattern)  
{
      switch (type) {
        case SERVLET:
-        return new ServletStyleUriPatternMatcher();
+        return new ServletStyleUriPatternMatcher(pattern);
        case REGEX:
-        return new RegexUriPatternMatcher();
+        return new RegexUriPatternMatcher(pattern);
        default:
          return null;
      }
@@ -38,16 +40,33 @@
     * @author [email protected] (Dhanji R. Prasanna)
     */
    private static class ServletStyleUriPatternMatcher implements  
UriPatternMatcher {
-    public boolean matches(String uri, String pattern) {
+    private final String pattern;
+    private final Kind patternKind;
+
+    private static enum Kind { PREFIX, SUFFIX, LITERAL, }
+
+    public ServletStyleUriPatternMatcher(String pattern) {
+      if (pattern.startsWith("*")) {
+        this.pattern = pattern.substring(1);
+        this.patternKind = Kind.PREFIX;
+      } else if (pattern.endsWith("*")) {
+        this.pattern = pattern.substring(0, pattern.length() - 1);
+        this.patternKind = Kind.SUFFIX;
+      } else {
+        this.pattern = pattern;
+        this.patternKind = Kind.LITERAL;
+      }
+    }
+
+    public boolean matches(String uri) {
        if (null == uri) {
          return false;
        }

-      if (pattern.startsWith("*")) {
-        return uri.endsWith(pattern.substring(1));
-      }
-      else if (pattern.endsWith("*")) {
-        return uri.startsWith(pattern.substring(0, pattern.length() - 1));
+      if (patternKind == Kind.PREFIX) {
+        return uri.endsWith(pattern);
+      } else if (patternKind == Kind.SUFFIX) {
+        return uri.startsWith(pattern);
        }

        //else treat as a literal
@@ -75,13 +94,19 @@

    /**
     * Matchers URIs using a regular expression.
-   * NOTE(dhanji) No path info is available when using regex mapping.
+   * NOTE(dhanji): No path info is available when using regex mapping.
     *
     * @author [email protected] (Dhanji R. Prasanna)
     */
    private static class RegexUriPatternMatcher implements UriPatternMatcher  
{
-    public boolean matches(String uri, String pattern) {
-      return null != uri && uri.matches(pattern);
+    private final Pattern pattern;
+
+    public RegexUriPatternMatcher(String pattern) {
+      this.pattern = Pattern.compile(pattern);
+    }
+
+    public boolean matches(String uri) {
+      return null != uri && this.pattern.matcher(uri).matches();
      }

      public String extractPath(String pattern) {

Modified:  
trunk/servlet/test/com/google/inject/servlet/FilterDefinitionTest.java
==============================================================================
--- trunk/servlet/test/com/google/inject/servlet/FilterDefinitionTest.java      
 
(original)
+++ trunk/servlet/test/com/google/inject/servlet/FilterDefinitionTest.java      
 
Mon Dec 29 22:32:41 2008
@@ -38,8 +38,9 @@
        put("ahsd124124", "as124124124dasdok");
      }};

-    final FilterDefinition filterDef = new FilterDefinition("/*",  
Key.get(Filter.class),
-        UriPatternType.get(UriPatternType.SERVLET), initParams);
+    String pattern = "/*";
+    final FilterDefinition filterDef = new FilterDefinition(pattern,  
Key.get(Filter.class),
+        UriPatternType.get(UriPatternType.SERVLET, pattern), initParams);
      assert filterDef.getFilter() instanceof MockFilter;

      ServletContext servletContext = createMock(ServletContext.class);
@@ -75,8 +76,9 @@

      replay(injector, request);

-    final FilterDefinition filterDef = new FilterDefinition("/*",  
Key.get(Filter.class),
-        UriPatternType.get(UriPatternType.SERVLET), new HashMap<String,  
String>());
+    String pattern = "/*";
+    final FilterDefinition filterDef = new FilterDefinition(pattern,  
Key.get(Filter.class),
+        UriPatternType.get(UriPatternType.SERVLET, pattern), new  
HashMap<String, String>());
      assert filterDef.getFilter() instanceof MockFilter;

      //should fire on mockfilter now
@@ -122,8 +124,9 @@

      replay(injector, request);

-    final FilterDefinition filterDef = new FilterDefinition("/*",  
Key.get(Filter.class),
-        UriPatternType.get(UriPatternType.SERVLET), new HashMap<String,  
String>());
+    String pattern = "/*";
+    final FilterDefinition filterDef = new FilterDefinition(pattern,  
Key.get(Filter.class),
+        UriPatternType.get(UriPatternType.SERVLET, pattern), new  
HashMap<String, String>());
      assert filterDef.getFilter() instanceof MockFilter;

      //should fire on mockfilter now

Modified:  
trunk/servlet/test/com/google/inject/servlet/ServletDefinitionPathsTest.java
==============================================================================
---  
trunk/servlet/test/com/google/inject/servlet/ServletDefinitionPathsTest.java    
 
(original)
+++  
trunk/servlet/test/com/google/inject/servlet/ServletDefinitionPathsTest.java    
 
Mon Dec 29 22:32:41 2008
@@ -84,7 +84,7 @@
      replay(injector, request);

      ServletDefinition servletDefinition = new ServletDefinition(mapping,  
Key.get(HttpServlet.class),
-        UriPatternType.get(UriPatternType.SERVLET), new HashMap<String,  
String>());
+        UriPatternType.get(UriPatternType.SERVLET, mapping), new  
HashMap<String, String>());

      servletDefinition.init(null, injector);
      servletDefinition.doService(request, response);
@@ -167,7 +167,7 @@
      replay(injector, request);

      ServletDefinition servletDefinition = new ServletDefinition(mapping,  
Key.get(HttpServlet.class),
-        UriPatternType.get(UriPatternType.SERVLET), new HashMap<String,  
String>());
+        UriPatternType.get(UriPatternType.SERVLET, mapping), new  
HashMap<String, String>());

      servletDefinition.init(null, injector);
      servletDefinition.doService(request, response);
@@ -250,7 +250,7 @@
      replay(injector, request);

      ServletDefinition servletDefinition = new ServletDefinition(mapping,  
Key.get(HttpServlet.class),
-        UriPatternType.get(UriPatternType.REGEX), new HashMap<String,  
String>());
+        UriPatternType.get(UriPatternType.REGEX, mapping), new  
HashMap<String, String>());

      servletDefinition.init(null, injector);
      servletDefinition.doService(request, response);

Modified:  
trunk/servlet/test/com/google/inject/servlet/ServletDefinitionTest.java
==============================================================================
--- trunk/servlet/test/com/google/inject/servlet/ServletDefinitionTest.java     
 
(original)
+++ trunk/servlet/test/com/google/inject/servlet/ServletDefinitionTest.java     
 
Mon Dec 29 22:32:41 2008
@@ -62,8 +62,9 @@
        }
      };

-    final ServletDefinition servletDefinition = new ServletDefinition("/*",
-        Key.get(HttpServlet.class),  
UriPatternType.get(UriPatternType.SERVLET), initParams);
+    String pattern = "/*";
+    final ServletDefinition servletDefinition = new  
ServletDefinition(pattern,
+        Key.get(HttpServlet.class),  
UriPatternType.get(UriPatternType.SERVLET, pattern), initParams);

      ServletContext servletContext = createMock(ServletContext.class);
      final String contextName = "thing__!@@44__SRV" + getClass();

Modified:  
trunk/servlet/test/com/google/inject/servlet/ServletPipelineRequestDispatcherTest.java
==============================================================================
---  
trunk/servlet/test/com/google/inject/servlet/ServletPipelineRequestDispatcherTest.java
   
(original)
+++  
trunk/servlet/test/com/google/inject/servlet/ServletPipelineRequestDispatcherTest.java
   
Mon Dec 29 22:32:41 2008
@@ -48,8 +48,9 @@
        + new Date() + UUID.randomUUID();

    public final void testIncludeManagedServlet() throws IOException,  
ServletException {
-    final ServletDefinition servletDefinition = new  
ServletDefinition("blah.html",
-        Key.get(HttpServlet.class),  
UriPatternType.get(UriPatternType.SERVLET),
+    String pattern = "blah.html";
+    final ServletDefinition servletDefinition = new  
ServletDefinition(pattern,
+        Key.get(HttpServlet.class),  
UriPatternType.get(UriPatternType.SERVLET, pattern),
          new HashMap<String, String>());

      final Injector injector = createMock(Injector.class);
@@ -79,7 +80,7 @@

      final RequestDispatcher dispatcher = new ManagedServletPipeline(
          Arrays.asList(servletDefinition))
-        .getRequestDispatcher("blah.html");
+        .getRequestDispatcher(pattern);

      assertNotNull(dispatcher);
      dispatcher.include(mockRequest, createMock(HttpServletResponse.class));
@@ -90,8 +91,9 @@
    }

    public final void testForwardToManagedServlet() throws IOException,  
ServletException {
-    final ServletDefinition servletDefinition = new  
ServletDefinition("blah.html",
-        Key.get(HttpServlet.class),  
UriPatternType.get(UriPatternType.SERVLET),
+    String pattern = "blah.html";
+    final ServletDefinition servletDefinition = new  
ServletDefinition(pattern,
+        Key.get(HttpServlet.class),  
UriPatternType.get(UriPatternType.SERVLET, pattern),
          new HashMap<String, String>());

      final Injector injector = createMock(Injector.class);
@@ -128,7 +130,7 @@

      final RequestDispatcher dispatcher = new ManagedServletPipeline(
          Arrays.asList(servletDefinition))
-        .getRequestDispatcher("blah.html");
+        .getRequestDispatcher(pattern);

      assertNotNull(dispatcher);
      dispatcher.forward(mockRequest, mockResponse);
@@ -153,8 +155,9 @@

    public final void forwardToManagedServletFailureOnCommittedBuffer()
        throws IOException, ServletException {
-    final ServletDefinition servletDefinition = new  
ServletDefinition("blah.html",
-        Key.get(HttpServlet.class),  
UriPatternType.get(UriPatternType.SERVLET),
+    String pattern = "blah.html";
+    final ServletDefinition servletDefinition = new  
ServletDefinition(pattern,
+        Key.get(HttpServlet.class),  
UriPatternType.get(UriPatternType.SERVLET, pattern),
          new HashMap<String, String>());

      final Injector injector = createMock(Injector.class);
@@ -183,7 +186,7 @@

      final RequestDispatcher dispatcher = new ManagedServletPipeline(
          Arrays.asList(servletDefinition))
-        .getRequestDispatcher("blah.html");
+        .getRequestDispatcher(pattern);

      assertNotNull(dispatcher);


--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"google-guice-dev" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to 
[email protected]
For more options, visit this group at 
http://groups.google.com/group/google-guice-dev?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to