001: /*
002: * Copyright 2007 Google Inc.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License"); you may not
005: * use this file except in compliance with the License. You may obtain a copy of
006: * the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
012: * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
013: * License for the specific language governing permissions and limitations under
014: * the License.
015: */
016: package com.google.gwt.dev.shell.ie;
017:
018: import com.google.gwt.dev.shell.LowLevel;
019:
020: import org.eclipse.swt.internal.ole.win32.COMObject;
021:
022: import java.util.Map;
023:
024: /**
025: * A proxy object that allows you to override behavior in an existing COM
026: * object. This is used primarily for fixing up the
027: * {@link org.eclipse.swt.browser.Browser} object's 'window.external' handling.
028: */
029: class COMObjectProxy extends COMObject {
030:
031: private static final int MAX_METHODS_WRAPPED = 23;
032:
033: private COMObject target;
034:
035: /**
036: * Construct a proxy object.
037: *
038: * @param argCounts must be the same array of argCounts used to contruct the
039: * wrapped object.
040: */
041: public COMObjectProxy(int[] argCounts) {
042: // Construct myself as a COMObject, even though my vtbl will never
043: // actually be used, I need to castable to a COMObject when I injected
044: // myself into the ObjectMap.
045: super (argCounts);
046:
047: // Because I will never be called through my vtbl, I can free my OS
048: // memory created in the superclass ctor and remove myself from the
049: // ObjectMap. If this didn't work, we'd be leaking memory when
050: // the last release is called (unless we assume that method index 2 was
051: // Release(), which actually is likely a safe assumption.)
052: dispose();
053:
054: // Make sure the interface isn't too big.
055: if (argCounts != null
056: && argCounts.length >= MAX_METHODS_WRAPPED) {
057: throw new IllegalArgumentException("No more than "
058: + MAX_METHODS_WRAPPED
059: + " methods can be wrapped right now.");
060: }
061: }
062:
063: /**
064: * Interpose this object in front of an existing object.
065: */
066: public void interpose(COMObject victim) {
067: if (this .target != null) {
068: throw new IllegalStateException(
069: "interpose() can only be called once");
070: }
071:
072: // Hang onto the object we're wrapping so that we can delegate later.
073: this .target = victim;
074:
075: // Get the COMObject ObjectMap so that we can hijack the target's slot.
076: Map<Integer, COMObject> objectMap = (Map<Integer, COMObject>) LowLevel
077: .snatchFieldObjectValue(COMObject.class, null,
078: "ObjectMap");
079: Integer ppVtableTarget = new Integer(target.getAddress());
080:
081: // First, make sure that the target is still actually in the map.
082: // If it isn't still in there, then the caller is using me incorrectly.
083: COMObject currValue = objectMap.get(ppVtableTarget);
084: if (currValue != target) {
085: throw new IllegalStateException(
086: "target object is not currently mapped");
087: }
088:
089: // Replace target's entry in COMObject's (vtbl -> instance) map with
090: // a reference to this object instead. Calls still come in on the
091: // target's vtbl, but COMObject will route them to me instead,
092: // so that I can hook/delegate them.
093: objectMap.put(ppVtableTarget, this );
094: }
095:
096: @Override
097: public int method0(int[] args) {
098: return target.method0(args);
099: }
100:
101: @Override
102: public int method1(int[] args) {
103: return target.method1(args);
104: }
105:
106: @Override
107: public int method10(int[] args) {
108: return target.method10(args);
109: }
110:
111: @Override
112: public int method11(int[] args) {
113: return target.method11(args);
114: }
115:
116: @Override
117: public int method12(int[] args) {
118: return target.method12(args);
119: }
120:
121: @Override
122: public int method13(int[] args) {
123: return target.method13(args);
124: }
125:
126: @Override
127: public int method14(int[] args) {
128: return target.method14(args);
129: }
130:
131: @Override
132: public int method15(int[] args) {
133: return target.method15(args);
134: }
135:
136: @Override
137: public int method16(int[] args) {
138: return target.method16(args);
139: }
140:
141: @Override
142: public int method17(int[] args) {
143: return target.method17(args);
144: }
145:
146: @Override
147: public int method18(int[] args) {
148: return target.method18(args);
149: }
150:
151: @Override
152: public int method19(int[] args) {
153: return target.method19(args);
154: }
155:
156: @Override
157: public int method2(int[] args) {
158: return target.method2(args);
159: }
160:
161: @Override
162: public int method20(int[] args) {
163: return target.method20(args);
164: }
165:
166: @Override
167: public int method21(int[] args) {
168: return target.method21(args);
169: }
170:
171: @Override
172: public int method22(int[] args) {
173: return target.method22(args);
174: }
175: }
|