View Javadoc

1   /*
2    wsmo4j - a WSMO API and Reference Implementation
3    
4    Copyright (c) 2004-2005, OntoText Lab. / SIRMA
5    University of Innsbruck, Austria 
6    
7    This library is free software; you can redistribute it and/or modify it under
8    the terms of the GNU Lesser General Public License as published by the Free
9    Software Foundation; either version 2.1 of the License, or (at your option)
10   any later version.
11   This library is distributed in the hope that it will be useful, but WITHOUT
12   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13   FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
14   details.
15   You should have received a copy of the GNU Lesser General Public License along
16   with this library; if not, write to the Free Software Foundation, Inc.,
17   59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18   */
19  
20  package com.ontotext.wsmo4j.factory;
21  
22  import java.lang.reflect.Method;
23  import java.lang.reflect.InvocationHandler;
24  import java.lang.reflect.Proxy;
25  import java.util.*;
26  
27  import org.omwg.ontology.*;
28  import org.wsmo.common.Identifier;
29  import org.wsmo.common.Entity;
30  import org.wsmo.common.exception.SynchronisationException;
31  
32  import org.wsmo.factory.Factory;
33  
34  /**
35   * <p>Title: </p>
36   * <p>Description: </p>
37   * <p>Copyright: Copyright (c) 2004-2005</p>
38   * <p>Company: Ontotext Lab., Sirma AI</p>
39   * @author unascribed
40   * @version 1.0
41   */
42  
43  public class IDReference implements InvocationHandler {
44      private Identifier handle;
45  
46      private Entity ref = null;
47  
48      private LinkedList invokeQueue;
49  
50      private Class[] supportedInterfaces;
51  
52      private IDReference(Identifier handle, Class[] ifaces) {
53          this.handle = handle;
54          this.supportedInterfaces = ifaces;
55          invokeQueue = new LinkedList();
56      }
57  
58      public boolean isResolved() {
59          return ref != null;
60      }
61      
62      Class[] getSupportedInterfaces() {
63          return supportedInterfaces;
64      }
65  
66      void setDelegate(Entity delegate) {
67          if (ref != null
68                  && 0 == delegate.getIdentifier().toString().compareTo(
69                          ref.getIdentifier().toString()))
70              return;
71          if (delegate instanceof Proxy)
72              throw new RuntimeException("cannot set a Proxy as Delegate!");
73          ref = delegate;
74          for (Iterator i = invokeQueue.iterator(); i.hasNext();) {
75              try {
76                  Object[] args = (Object[]) i.next();
77                  invoke(args[0], (Method) args[1], (Object[]) args[2]);
78              }
79              catch (Throwable t) {
80                  throw new RuntimeException("Could not apply the proxy call history!", t);
81              }
82          }
83          invokeQueue.clear();
84      }
85  
86      public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
87          // handle Entity.getIdentifier();
88          if (0 == method.getName().compareTo("getIdentifier"))
89              return handle;
90          // route since we have a deleagte already set
91          if (ref != null) {
92              return method.invoke(ref, args);
93          }
94          if (0 == method.getName().compareTo("hashCode")) {
95              return method.invoke(handle, args);
96          }
97          if (0 == method.getName().compareTo("equals")) {
98              if (args[0] instanceof Proxy) {
99                  Object temp = Proxy.getInvocationHandler(args[0]);
100                 if (temp instanceof IDReference) {
101                     IDReference invocHandler = (IDReference) temp;
102                     if (invocHandler.getSupportedInterfaces() == getSupportedInterfaces()
103                             && invocHandler.handle.equals(handle)) {
104                         return Boolean.TRUE;
105                     }
106                 }
107             }
108             return Boolean.FALSE;
109         }
110         // handle Object's public methods 'hashCode', 'toString', equals
111         if (method.getDeclaringClass().equals(Object.class)) {
112             //            if (ref != null)
113             //                return method.invoke(ref, args);
114             return method.invoke(handle, args);
115         }
116         
117         // try to resolve it
118         Entity temp = null;
119         for (int i = 0; i < supportedInterfaces.length; i++) {
120             temp = Factory.getLocatorManager().lookup(handle, supportedInterfaces[i]);
121             if (temp != null) {
122                 setDelegate(temp);
123                 return method.invoke(ref, args);
124             }
125         }
126 
127         // if not resolved try to work with the proxy
128         if (method.getReturnType() == void.class) {
129             invokeQueue.add(new Object[] { proxy, method, args });
130             return null;
131         }
132         if (method.getReturnType() == Set.class) {
133             return new LinkedHashSet();
134         }
135         if (method.getReturnType() == List.class) {
136             return new LinkedList();
137         }
138         if (method.getReturnType() == Map.class) {
139             return new HashMap();
140         }
141         if (method.getReturnType() == Ontology.class) {
142             return null;
143         }
144 		throw new SynchronisationException(handle.toString());
145     }
146 
147     static Object createNewReference(Identifier id, Class[] ifaces) {
148         // @todo: some runtime checks to ensure that there is no impl already created
149         // @todo: some threadsafty should be added to avoid multiple refs with single id to be
150         //   created across the active treads
151         Object obj = null;
152         //        ClassLoader loader = Thread.currentThread().getContextClassLoader();
153         ClassLoader loader = Identifier.class.getClassLoader();
154         try {
155             obj = Proxy.newProxyInstance(loader, ifaces, new IDReference(id, ifaces));
156         }
157         catch (RuntimeException ia) {
158             loader = null;
159         }
160 
161         if (obj == null && loader == null)
162             loader = Thread.currentThread().getContextClassLoader();
163         try {
164             obj = Proxy.newProxyInstance(loader, ifaces, new IDReference(id, ifaces));
165         }
166         catch (RuntimeException ia) {
167             loader = null;
168         }
169 
170         if (obj == null && loader == null)
171             loader = ClassLoader.getSystemClassLoader();
172 
173         obj = Proxy.newProxyInstance(loader, ifaces, new IDReference(id, ifaces));
174 
175         return obj;
176     }
177 }