bump product version to 5.0.4.1
[LibreOffice.git] / jurt / com / sun / star / lib / uno / bridges / java_remote / ProxyFactory.java
blobf7876acb7dec205fa975c232c66f51bb0789adf2
1 /*
2 * This file is part of the LibreOffice project.
4 * This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 * This file incorporates work covered by the following license notice:
10 * Licensed to the Apache Software Foundation (ASF) under one or more
11 * contributor license agreements. See the NOTICE file distributed
12 * with this work for additional information regarding copyright
13 * ownership. The ASF licenses this file to you under the Apache
14 * License, Version 2.0 (the "License"); you may not use this file
15 * except in compliance with the License. You may obtain a copy of
16 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
19 package com.sun.star.lib.uno.bridges.java_remote;
21 import com.sun.star.bridge.XBridge;
22 import com.sun.star.lib.util.AsynchronousFinalizer;
23 import com.sun.star.uno.IQueryInterface;
24 import com.sun.star.uno.Type;
25 import com.sun.star.uno.UnoRuntime;
27 import java.lang.reflect.InvocationHandler;
28 import java.lang.reflect.Method;
29 import java.lang.reflect.Proxy;
31 /**
32 * A factory for proxies specific to the <code>java_remote_bridge</code>.
34 * <p>Eventually, this class should be united with all other proxy classes
35 * specific to certain bridges (for example, the JNI bridge), resulting in a
36 * generic proxy class.</p>
38 final class ProxyFactory {
39 public ProxyFactory(RequestHandler requestHandler, XBridge bridge) {
40 this.requestHandler = requestHandler;
41 this.bridge = bridge;
44 public Object create(String oid, Type type) {
45 return Proxy.newProxyInstance(
46 getClass().getClassLoader(),
47 new Class[] { com.sun.star.lib.uno.Proxy.class,
48 IQueryInterface.class, type.getZClass() },
49 new Handler(oid, type));
52 public boolean isProxy(Object obj) {
53 if (Proxy.isProxyClass(obj.getClass())) {
54 InvocationHandler h = Proxy.getInvocationHandler(obj);
55 return h instanceof Handler && ((Handler) h).matches(this);
56 } else {
57 return false;
61 public void dispose() throws InterruptedException {
62 asynchronousFinalizer.drain();
65 public static XBridge getBridge(Object obj) {
66 if (Proxy.isProxyClass(obj.getClass())) {
67 InvocationHandler h = Proxy.getInvocationHandler(obj);
68 if (h instanceof Handler) {
69 return ((Handler) h).getBridge();
72 return null;
75 static int getDebugCount() {
76 synchronized (debugCountLock) {
77 return debugCount;
81 private static void incrementDebugCount() {
82 synchronized (debugCountLock) {
83 ++debugCount;
87 private static void decrementDebugCount() {
88 synchronized (debugCountLock) {
89 --debugCount;
93 private final class Handler implements InvocationHandler {
94 public Handler(String oid, Type type) {
95 this.oid = oid;
96 this.type = type;
97 incrementDebugCount();
100 public boolean matches(ProxyFactory factory) {
101 return ProxyFactory.this == factory;
104 public XBridge getBridge() {
105 return bridge;
108 public Object invoke(Object proxy, Method method, Object[] args)
109 throws Throwable
111 if (method.equals(METHOD_EQUALS) || method.equals(METHOD_IS_SAME)) {
112 return Boolean.valueOf(args[0] != null
113 && oid.equals(UnoRuntime.generateOid(args[0])));
114 } else if (method.equals(METHOD_HASH_CODE)) {
115 return Integer.valueOf(oid.hashCode());
116 } else if (method.equals(METHOD_TO_STRING)) {
117 return "[Proxy:" + System.identityHashCode(proxy) + "," + oid
118 + "," + type + "]";
119 } else if (method.equals(METHOD_QUERY_INTERFACE)) {
120 // See the comment in java_remote_bridge.mapInterfaceTo for one
121 // reason why this implementation must not satisfy a request for
122 // a super-interface with a proxy itself:
123 return args[0].equals(type) ? proxy
124 : request("queryInterface", args);
125 } else if (method.equals(METHOD_GET_OID)) {
126 return oid;
127 } else {
128 return request(method.getName(), args);
132 @Override
133 protected void finalize() {
134 decrementDebugCount();
135 asynchronousFinalizer.add(new AsynchronousFinalizer.Job() {
136 public void run() throws Throwable {
137 request("release", null);
142 private Object request(String operation, Object[] args) throws Throwable
144 Object res = requestHandler.sendRequest(oid, type, operation, args);
145 // Avoid early finalization of this object, while an invoke ->
146 // request call is still ongoing; as finalize also calls request,
147 // this should fulfil the condition from The Java Language
148 // Specification, 3rd ed., that "if an object's finalizer can result
149 // in synchronization on that object, then that object must be alive
150 // and considered reachable whenever a lock is held on it:"
151 synchronized (this) {
152 ++dummy;
154 return res;
157 private final String oid;
158 private final Type type;
159 @SuppressWarnings("unused")
160 private int dummy = 0;
163 private static final Method METHOD_EQUALS;
164 private static final Method METHOD_HASH_CODE;
165 private static final Method METHOD_TO_STRING;
166 private static final Method METHOD_QUERY_INTERFACE;
167 private static final Method METHOD_IS_SAME;
168 private static final Method METHOD_GET_OID;
169 static {
170 try {
171 METHOD_EQUALS = Object.class.getMethod(
172 "equals", new Class[] { Object.class });
173 METHOD_HASH_CODE = Object.class.getMethod(
174 "hashCode", (Class[]) null);
175 METHOD_TO_STRING = Object.class.getMethod(
176 "toString", (Class[]) null);
177 METHOD_QUERY_INTERFACE = IQueryInterface.class.getMethod(
178 "queryInterface", new Class[] { Type.class });
179 METHOD_IS_SAME = IQueryInterface.class.getMethod(
180 "isSame", new Class[] { Object.class });
181 METHOD_GET_OID = IQueryInterface.class.getMethod(
182 "getOid", (Class[]) null);
183 } catch (NoSuchMethodException e) {
184 throw new ExceptionInInitializerError(e);
188 private static final Object debugCountLock = new Object();
189 private static int debugCount = 0;
191 private final RequestHandler requestHandler;
192 private final XBridge bridge;
193 private final AsynchronousFinalizer asynchronousFinalizer =
194 new AsynchronousFinalizer();