View Javadoc

1   /*
2      Copyright 2009 Ramon Servadei
3   
4      Licensed under the Apache License, Version 2.0 (the "License");
5      you may not use this file except in compliance with the License.
6      You may obtain a copy of the License at
7   
8          http://www.apache.org/licenses/LICENSE-2.0
9   
10     Unless required by applicable law or agreed to in writing, software
11     distributed under the License is distributed on an "AS IS" BASIS,
12     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13     See the License for the specific language governing permissions and
14     limitations under the License.
15   */
16  package fulmine.distribution;
17  
18  import org.apache.commons.logging.Log;
19  
20  import fulmine.context.IFulmineContext;
21  import fulmine.context.IRemoteUpdateHandler;
22  import fulmine.model.field.IntegerField;
23  import fulmine.model.field.StringField;
24  import fulmine.rpc.IRpcDefinition;
25  import fulmine.rpc.IRpcResult;
26  import fulmine.util.Utils;
27  import fulmine.util.log.AsyncLog;
28  import fulmine.util.reference.Values;
29  import fulmine.util.reference.is;
30  
31  /**
32   * A standard implementation.
33   * 
34   * @author Ramon Servadei
35   */
36  public final class RemoteUpdateInvoker implements IRemoteUpdateInvoker
37  {
38      private final static Log LOG = new AsyncLog(RemoteUpdateInvoker.class);
39  
40      /**
41       * System property to define the timeout (in milliseconds) for waiting for
42       * RPC invocations.
43       * 
44       * @see #DEFAUL_RPC_TIMEOUT
45       */
46      public final static String RPC_TIMEOUT_PROPERTY =
47          RemoteUpdateInvoker.class.getSimpleName() + ".rpcTimeout";
48  
49      /** The default RPC timeout, 5 seconds */
50      public final static String DEFAUL_RPC_TIMEOUT = "5000";
51  
52      /** RPC timeout */
53      private final static int TIMEOUT =
54          Integer.parseInt(System.getProperty(RPC_TIMEOUT_PROPERTY,
55              DEFAUL_RPC_TIMEOUT));
56  
57      /** Signals if the 'update remote container' RPC is available */
58      boolean available;
59  
60      /** The identity of the remote context this works for */
61      final String remoteContextIdentity;
62  
63      /** The context */
64      final IFulmineContext context;
65  
66      /**
67       * Standard constructor
68       * 
69       * @param remoteContextIdentity
70       *            the remote context identity this invoker handles.
71       */
72      public RemoteUpdateInvoker(String remoteContextIdentity,
73          IFulmineContext context)
74      {
75          super();
76          this.remoteContextIdentity = remoteContextIdentity;
77          this.context = context;
78      }
79  
80      public void procedureAvailable(String remoteContextIdentity,
81          IRpcDefinition rpcDefinition)
82      {
83          if (IRemoteUpdateHandler.RPC_NAME.equals(rpcDefinition.getName()))
84          {
85              // we have found it, schedule any pending invocations to be executed
86              if (LOG.isDebugEnabled())
87              {
88                  LOG.debug("Found 'update remote container' RPC for "
89                      + remoteContextIdentity);
90              }
91              synchronized (this)
92              {
93                  this.available = true;
94                  this.notifyAll();
95              }
96          }
97      }
98  
99      public void procedureUnavailable(String remoteContextIdentity,
100         IRpcDefinition rpcDefinition)
101     {
102         if (IRemoteUpdateHandler.RPC_NAME.equals(rpcDefinition.getName()))
103         {
104             if (LOG.isDebugEnabled())
105             {
106                 LOG.debug("Lost 'update remote container' RPC for "
107                     + remoteContextIdentity);
108             }
109             synchronized (this)
110             {
111                 this.available = false;
112             }
113         }
114     }
115 
116     public IRpcResult invoke(String remoteContextIdentity,
117         StringField identity, IntegerField type, IntegerField domain,
118         StringField fieldName, StringField valueAsString,
119         IntegerField permissionApp, IntegerField permissionCode,
120         StringField originatingRemoteContextIdentity)
121     {
122         if (LOG.isDebugEnabled())
123         {
124             LOG.debug("Invoking update remote container RPC with args "
125                 + new Values(remoteContextIdentity,
126                     IRemoteUpdateHandler.RPC_NAME, identity, type, domain,
127                     fieldName, valueAsString, permissionApp, permissionCode,
128                     originatingRemoteContextIdentity));
129         }
130         synchronized (this)
131         {
132             while (!this.available)
133             {
134                 if (LOG.isDebugEnabled())
135                 {
136                     LOG.debug("RPC to update remote container is not available, waiting until it is...");
137                 }
138                 try
139                 {
140                     this.wait(TIMEOUT);
141                 }
142                 catch (InterruptedException e)
143                 {
144                     Utils.logException(LOG, this, e);
145                 }
146             }
147         }
148         return this.context.invoke(remoteContextIdentity,
149             IRemoteUpdateHandler.RPC_NAME, identity, type, domain, fieldName,
150             valueAsString, permissionApp, permissionCode,
151             originatingRemoteContextIdentity);
152     }
153 
154     @Override
155     public int hashCode()
156     {
157         final int prime = 31;
158         int result = 1;
159         result =
160             prime
161                 * result
162                 + ((this.remoteContextIdentity == null) ? 0
163                     : this.remoteContextIdentity.hashCode());
164         return result;
165     }
166 
167     @Override
168     public boolean equals(Object obj)
169     {
170         if (is.same(this, obj))
171         {
172             return true;
173         }
174         if (is.differentClass(this, obj))
175         {
176             return false;
177         }
178         RemoteUpdateInvoker other = (RemoteUpdateInvoker) obj;
179         return is.eq(this.remoteContextIdentity, other.remoteContextIdentity);
180     }
181 
182 }