blob: 22abf244af7bab9dbdd17cb28c95987315680652 [file] [log] [blame]
/*
* Copyright 2011 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.web.bindery.requestfactory.server;
import com.google.gwt.dev.asm.Type;
import com.google.web.bindery.requestfactory.vm.impl.OperationKey;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.SortedSet;
/**
* Provides access to payload deobfuscation services.
*/
class Deobfuscator {
public static class Builder {
private Deobfuscator d = new Deobfuscator();
{
d.domainToClientType = new HashMap<String, List<String>>();
d.operationData = new HashMap<OperationKey, OperationData>();
d.typeTokens = new HashMap<String, String>();
}
public Builder addClientToDomainMapping(String domainBinaryName, SortedSet<Type> value) {
List<String> clientBinaryNames;
switch (value.size()) {
case 0:
clientBinaryNames = Collections.emptyList();
break;
case 1:
clientBinaryNames = Collections.singletonList(value.first().getClassName());
break;
default:
clientBinaryNames = new ArrayList<String>(value.size());
for (Type t : value) {
clientBinaryNames.add(t.getClassName());
}
clientBinaryNames = Collections.unmodifiableList(clientBinaryNames);
}
d.domainToClientType.put(domainBinaryName, clientBinaryNames);
return this;
}
public Builder addClientToDomainMappings(Map<Type, SortedSet<Type>> data) {
for (Map.Entry<Type, SortedSet<Type>> entry : data.entrySet()) {
String domainBinaryName = entry.getKey().getClassName();
SortedSet<Type> value = entry.getValue();
addClientToDomainMapping(domainBinaryName, value);
}
return this;
}
public Builder addOperation(OperationKey key, OperationData data) {
d.operationData.put(key, data);
return this;
}
public Builder addOperationData(Map<OperationKey, OperationData> operationData) {
d.operationData.putAll(operationData);
return this;
}
public Builder addRawTypeToken(String token, String binaryName) {
d.typeTokens.put(token, binaryName);
return this;
}
public Builder addRawTypeTokens(Map<String, String> typeTokens) {
for (Map.Entry<String, String> entry : typeTokens.entrySet()) {
addRawTypeToken(entry.getKey(), entry.getValue());
}
return this;
}
public Builder addTypeTokens(Map<String, Type> typeTokens) {
for (Map.Entry<String, Type> entry : typeTokens.entrySet()) {
d.typeTokens.put(entry.getKey(), entry.getValue().getClassName());
}
return this;
}
public Deobfuscator build() {
Deobfuscator toReturn = d;
toReturn.domainToClientType = Collections.unmodifiableMap(toReturn.domainToClientType);
toReturn.operationData = Collections.unmodifiableMap(toReturn.operationData);
toReturn.typeTokens = Collections.unmodifiableMap(toReturn.typeTokens);
d = null;
return toReturn;
}
public Builder merge(Deobfuscator deobfuscator) {
d.domainToClientType.putAll(deobfuscator.domainToClientType);
d.operationData.putAll(deobfuscator.operationData);
d.typeTokens.putAll(deobfuscator.typeTokens);
return this;
}
}
/**
* Maps domain types (e.g Foo) to client proxy types (e.g. FooAProxy,
* FooBProxy).
*/
private Map<String, List<String>> domainToClientType;
private Map<OperationKey, OperationData> operationData;
/**
* Map of obfuscated ids to binary class names.
*/
private Map<String, String> typeTokens;
Deobfuscator() {
}
/**
* Returns the client proxy types whose {@code @ProxyFor} is exactly
* {@code binaryTypeName}. Ordered such that the most-derived types will be
* iterated over first.
*/
public List<String> getClientProxies(String binaryTypeName) {
return domainToClientType.get(binaryTypeName);
}
/**
* Returns a method descriptor that should be invoked on the service object.
*/
public String getDomainMethodDescriptor(String operation) {
OperationData data = getData(operation);
return data == null ? null : data.getDomainMethodDescriptor();
}
public String getRequestContext(String operation) {
OperationData data = getData(operation);
return data == null ? null : data.getRequestContext();
}
public String getRequestContextMethodDescriptor(String operation) {
OperationData data = getData(operation);
return data == null ? null : data.getClientMethodDescriptor();
}
public String getRequestContextMethodName(String operation) {
OperationData data = getData(operation);
return data == null ? null : data.getMethodName();
}
/**
* Returns a type's binary name based on an obfuscated token.
*/
public String getTypeFromToken(String token) {
return typeTokens.get(token);
}
private OperationData getData(String operation) {
OperationData data = operationData.get(new OperationKey(operation));
return data;
}
}