View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
4   //  ------------------------------------------------------------------------
5   //  All rights reserved. This program and the accompanying materials
6   //  are made available under the terms of the Eclipse Public License v1.0
7   //  and Apache License v2.0 which accompanies this distribution.
8   //
9   //      The Eclipse Public License is available at
10  //      http://www.eclipse.org/legal/epl-v10.html
11  //
12  //      The Apache License v2.0 is available at
13  //      http://www.opensource.org/licenses/apache2.0.php
14  //
15  //  You may elect to redistribute this code under either of these licenses.
16  //  ========================================================================
17  //
18  
19  package org.eclipse.jetty.websocket.common.events.annotated;
20  
21  import java.io.InputStream;
22  import java.io.Reader;
23  import java.lang.reflect.InvocationTargetException;
24  import java.lang.reflect.Method;
25  
26  import org.eclipse.jetty.util.log.Log;
27  import org.eclipse.jetty.util.log.Logger;
28  import org.eclipse.jetty.websocket.api.Session;
29  import org.eclipse.jetty.websocket.api.WebSocketException;
30  import org.eclipse.jetty.websocket.api.util.QuoteUtil;
31  
32  public class EventMethod
33  {
34      private static final Logger LOG = Log.getLogger(EventMethod.class);
35  
36      private static Object[] dropFirstArg(Object[] args)
37      {
38          if (args.length == 1)
39          {
40              return new Object[0];
41          }
42          Object ret[] = new Object[args.length - 1];
43          System.arraycopy(args,1,ret,0,ret.length);
44          return ret;
45      }
46  
47      protected Class<?> pojo;
48      protected Method method;
49      private boolean hasSession = false;
50      private boolean isStreaming = false;
51      private Class<?>[] paramTypes;
52  
53      public EventMethod(Class<?> pojo, Method method)
54      {
55          this.pojo = pojo;
56          this.paramTypes = method.getParameterTypes();
57          this.method = method;
58          identifyPresentParamTypes();
59      }
60  
61      public EventMethod(Class<?> pojo, String methodName, Class<?>... paramTypes)
62      {
63          try
64          {
65              this.pojo = pojo;
66              this.paramTypes = paramTypes;
67              this.method = pojo.getMethod(methodName,paramTypes);
68              identifyPresentParamTypes();
69          }
70          catch (NoSuchMethodException | SecurityException e)
71          {
72              LOG.warn("Cannot use method {}({}): {}",methodName,paramTypes,e.getMessage());
73              this.method = null;
74          }
75      }
76  
77      public void call(Object obj, Object... args)
78      {
79          if ((this.pojo == null) || (this.method == null))
80          {
81              LOG.warn("Cannot execute call: pojo={}, method={}",pojo,method);
82              return; // no call event method determined
83          }
84          if (obj == null)
85          {
86              LOG.warn("Cannot call {} on null object",this.method);
87              return;
88          }
89          if (args.length > paramTypes.length)
90          {
91              Object trimArgs[] = dropFirstArg(args);
92              call(obj,trimArgs);
93              return;
94          }
95          if (args.length < paramTypes.length)
96          {
97              throw new IllegalArgumentException("Call arguments length [" + args.length + "] must always be greater than or equal to captured args length ["
98                      + paramTypes.length + "]");
99          }
100 
101         try
102         {
103             this.method.invoke(obj,args);
104         }
105         catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e)
106         {
107             String err = String.format("Cannot call method %s on %s with args: %s",method,pojo, QuoteUtil.join(args,","));
108             throw new WebSocketException(err,e);
109         }
110     }
111 
112     public Method getMethod()
113     {
114         return method;
115     }
116 
117     protected Class<?>[] getParamTypes()
118     {
119         return this.paramTypes;
120     }
121 
122     private void identifyPresentParamTypes()
123     {
124         this.hasSession = false;
125         this.isStreaming = false;
126 
127         if (paramTypes == null)
128         {
129             return;
130         }
131 
132         for (Class<?> paramType : paramTypes)
133         {
134             if (Session.class.isAssignableFrom(paramType))
135             {
136                 this.hasSession = true;
137             }
138             if (Reader.class.isAssignableFrom(paramType) || InputStream.class.isAssignableFrom(paramType))
139             {
140                 this.isStreaming = true;
141             }
142         }
143     }
144 
145     public boolean isHasSession()
146     {
147         return hasSession;
148     }
149 
150     public boolean isStreaming()
151     {
152         return isStreaming;
153     }
154 }