KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > alfresco > repo > service > StoreRedirectorProxyFactory


1 /*
2  * Copyright (C) 2005 Alfresco, Inc.
3  *
4  * Licensed under the Mozilla Public License version 1.1
5  * with a permitted attribution clause. You may obtain a
6  * copy of the License at
7  *
8  * http://www.alfresco.org/legal/license.txt
9  *
10  * Unless required by applicable law or agreed to in writing,
11  * software distributed under the License is distributed on an
12  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13  * either express or implied. See the License for the specific
14  * language governing permissions and limitations under the
15  * License.
16  */

17 package org.alfresco.repo.service;
18
19 import java.lang.reflect.InvocationHandler JavaDoc;
20 import java.lang.reflect.InvocationTargetException JavaDoc;
21 import java.lang.reflect.Method JavaDoc;
22 import java.lang.reflect.Proxy JavaDoc;
23 import java.util.Collection JavaDoc;
24 import java.util.Collections JavaDoc;
25 import java.util.HashMap JavaDoc;
26 import java.util.Map JavaDoc;
27
28 import org.alfresco.service.ServiceException;
29 import org.alfresco.service.cmr.repository.NodeRef;
30 import org.alfresco.service.cmr.repository.StoreRef;
31 import org.alfresco.util.ParameterCheck;
32 import org.apache.commons.logging.Log;
33 import org.apache.commons.logging.LogFactory;
34 import org.springframework.beans.factory.FactoryBean;
35 import org.springframework.beans.factory.InitializingBean;
36
37 /**
38  * This factory provides component redirection based on Store or Node References
39  * passed into the component.
40  *
41  * Redirection is driven by StoreRef and NodeRef parameters. If none are given
42  * in the method call, the default component is called. Otherwise, the store
43  * type is extracted from these parameters and the appropriate component called
44  * for the store type.
45  *
46  * An error is thrown if multiple store types are found.
47  *
48  * @author David Caruana
49  *
50  * @param <I> The component interface class
51  */

52 public class StoreRedirectorProxyFactory<I> implements FactoryBean, InitializingBean
53 {
54     // Logger
55
private static final Log logger = LogFactory.getLog(StoreRedirectorProxyFactory.class);
56
57     // The component interface class
58
private Class JavaDoc<I> proxyInterface = null;
59
60     // The default component binding
61
private I defaultBinding = null;
62
63     // The map of store types to component bindings
64
private Map JavaDoc<String JavaDoc, I> redirectedProtocolBindings = null;
65
66     // the map if more specific store Refs to component bindings
67
private Map JavaDoc<StoreRef, I> redirectedStoreBindings = null;
68
69     // The proxy responsible for redirection based on store type
70
private I redirectorProxy = null;
71
72     /**
73      * Sets the proxy interface
74      *
75      * @param proxyInterface
76      * the proxy interface
77      */

78     public void setProxyInterface(Class JavaDoc<I> proxyInterface)
79     {
80         this.proxyInterface = proxyInterface;
81     }
82
83     /**
84      * Sets the default component binding
85      *
86      * @param binding
87      * the component to call by default
88      */

89     public void setDefaultBinding(I defaultBinding)
90     {
91         this.defaultBinding = defaultBinding;
92     }
93
94     /**
95      * Sets the binding of store type (protocol string) to component
96      *
97      * @param bindings
98      * the bindings
99      */

100     public void setRedirectedProtocolBindings(Map JavaDoc<String JavaDoc, I> protocolBindings)
101     {
102         this.redirectedProtocolBindings = protocolBindings;
103     }
104
105     /**
106      * Sets the binding of store type (protocol string) to component
107      *
108      * @param bindings
109      * the bindings
110      */

111     public void setRedirectedStoreBindings(Map JavaDoc<String JavaDoc, I> storeBindings)
112     {
113         redirectedStoreBindings = new HashMap JavaDoc<StoreRef, I>(storeBindings.size());
114         for(String JavaDoc ref : storeBindings.keySet())
115         {
116             redirectedStoreBindings.put(new StoreRef(ref), storeBindings.get(ref));
117         }
118     }
119
120     
121     /* (non-Javadoc)
122      * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
123      */

124     public void afterPropertiesSet() throws ServiceException
125     {
126         ParameterCheck.mandatory("Proxy Interface", proxyInterface);
127         ParameterCheck.mandatory("Default Binding", defaultBinding);
128
129         // Setup the redirector proxy
130
this.redirectorProxy = (I)Proxy.newProxyInstance(proxyInterface.getClassLoader(), new Class JavaDoc[] { proxyInterface, StoreRedirector.class }, new RedirectorInvocationHandler());
131     }
132
133     
134     /* (non-Javadoc)
135      * @see org.springframework.beans.factory.FactoryBean#getObject()
136      */

137     public I getObject()
138     {
139         return redirectorProxy;
140     }
141
142     
143     /* (non-Javadoc)
144      * @see org.springframework.beans.factory.FactoryBean#getObjectType()
145      */

146     public Class JavaDoc getObjectType()
147     {
148         return proxyInterface;
149     }
150
151     
152     /* (non-Javadoc)
153      * @see org.springframework.beans.factory.FactoryBean#isSingleton()
154      */

155     public boolean isSingleton()
156     {
157         return true;
158     }
159
160     
161     /**
162      * Invocation handler that redirects based on store type
163      */

164     /* package */class RedirectorInvocationHandler implements InvocationHandler JavaDoc, StoreRedirector
165     {
166         
167         /* (non-Javadoc)
168          * @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object[])
169          */

170         public Object JavaDoc invoke(Object JavaDoc proxy, Method JavaDoc method, Object JavaDoc[] args) throws Throwable JavaDoc
171         {
172             // Handle StoreRedirector Interface
173
if (method.getDeclaringClass().equals(StoreRedirector.class))
174             {
175                 return method.invoke(this, args);
176             }
177
178             // Otherwise, determine the apropriate implementation to invoke for
179
// the service interface method
180
Object JavaDoc binding = null;
181             StoreRef storeRef = getStoreRef(args);
182             if (storeRef == null)
183             {
184                 binding = StoreRedirectorProxyFactory.this.defaultBinding;
185             }
186             else
187             {
188                 if (StoreRedirectorProxyFactory.this.redirectedStoreBindings != null)
189                 {
190                     binding = StoreRedirectorProxyFactory.this.redirectedStoreBindings.get(storeRef);
191                 }
192                 if ((binding == null) && (StoreRedirectorProxyFactory.this.redirectedProtocolBindings != null))
193                 {
194                     binding = StoreRedirectorProxyFactory.this.redirectedProtocolBindings.get(storeRef.getProtocol());
195                 }
196                 if (binding == null)
197                 {
198                     binding = StoreRedirectorProxyFactory.this.defaultBinding;
199                 }
200                 if (binding == null)
201                 {
202                     throw new ServiceException("Store type " + storeRef + " is not supported");
203                 }
204             }
205
206             if (logger.isDebugEnabled())
207                 logger.debug("Redirecting method " + method + " based on store type " + storeRef);
208
209             try
210             {
211                 // Invoke the appropriate binding
212
return method.invoke(binding, args);
213             }
214             catch (InvocationTargetException JavaDoc e)
215             {
216                 throw e.getTargetException();
217             }
218         }
219         
220
221         /**
222          * Determine store type from array of method arguments
223          *
224          * @param args the method arguments
225          * @return the store type (or null, if one is not specified)
226          */

227         private StoreRef getStoreRef(Object JavaDoc[] args)
228         {
229             StoreRef storeRef = null;
230
231             if(args == null)
232             {
233                 return null;
234             }
235             
236             for (Object JavaDoc arg : args)
237             {
238                 // Extract store type from argument, if store type provided
239
StoreRef argStoreRef = null;
240                 if (arg instanceof NodeRef)
241                 {
242                     argStoreRef = ((NodeRef) arg).getStoreRef();
243                 }
244                 else if (arg instanceof StoreRef)
245                 {
246                     argStoreRef = ((StoreRef) arg);
247                 }
248
249                 // Only allow one store type
250
if (argStoreRef != null)
251                 {
252                     if (storeRef != null && !storeRef.equals(argStoreRef))
253                     {
254                         throw new ServiceException("Multiple store types are not supported - types " + storeRef + " and " + argStoreRef + " passed");
255                     }
256                     storeRef = argStoreRef;
257                 }
258             }
259
260             return storeRef;
261         }
262         
263
264         /* (non-Javadoc)
265          * @see org.alfresco.repo.service.StoreRedirector#getSupportedStoreProtocols()
266          */

267         public Collection JavaDoc<String JavaDoc> getSupportedStoreProtocols()
268         {
269             return Collections.unmodifiableCollection(StoreRedirectorProxyFactory.this.redirectedProtocolBindings.keySet());
270         }
271
272         
273         /* (non-Javadoc)
274          * @see org.alfresco.repo.service.StoreRedirector#getSupportedStores()
275          */

276         public Collection JavaDoc<StoreRef> getSupportedStores()
277         {
278             return Collections.unmodifiableCollection(StoreRedirectorProxyFactory.this.redirectedStoreBindings.keySet());
279         }
280
281     }
282 }
283
Popular Tags