blob: 5699c9a3e0f134d84c1dd6100942d2197c313532 [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.vm.impl;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
/**
* Resolves payload type tokens to binary class names.
*/
public class TypeTokenResolver {
/**
* Constructs {@link TypeTokenResolver} instances.
*/
public static class Builder {
private TypeTokenResolver d = new TypeTokenResolver();
/**
* To be removed as well.
*/
public Builder addTypeToken(String token, String binaryName) {
d.typeTokens.put(token, binaryName);
return this;
}
public TypeTokenResolver build() {
TypeTokenResolver toReturn = d;
toReturn.typeTokens = Collections.unmodifiableMap(toReturn.typeTokens);
toReturn.referencedTypes =
Collections.unmodifiableSet(new HashSet<String>(toReturn.typeTokens.values()));
d = null;
return toReturn;
}
/**
* Adds data from a single InputStream to the state accumulated by the
* Builder.
*/
public void load(InputStream in) throws IOException {
Properties props = new Properties();
props.load(in);
for (Map.Entry<Object, Object> entry : props.entrySet()) {
addTypeToken(entry.getKey().toString(), entry.getValue().toString());
}
in.close();
}
}
public static final String TOKEN_MANIFEST = "META-INF/requestFactory/typeTokens";
/**
* Loads all resources on path {@value #TOKEN_MANIFEST} and creates a
* TypeTokenResolver.
*/
public static TypeTokenResolver loadFromClasspath() throws IOException {
Builder builder;
boolean mustLoad = true;
try {
// Look for a pre-cooked Builder type
Class<?> maybeBuilderImpl =
Class.forName(TypeTokenResolver.class.getName() + "BuilderImpl", false, Thread
.currentThread().getContextClassLoader());
builder = maybeBuilderImpl.asSubclass(Builder.class).newInstance();
mustLoad = false;
} catch (ClassNotFoundException ignored) {
// Try manifest-based approach
builder = new Builder();
} catch (InstantiationException e) {
throw new RuntimeException("Could not instantiate TypeTokenResolverImpl", e);
} catch (IllegalAccessException e) {
throw new RuntimeException("Could not instantiate TypeTokenResolverImpl", e);
}
Enumeration<URL> locations =
Thread.currentThread().getContextClassLoader().getResources(TOKEN_MANIFEST);
if (mustLoad && !locations.hasMoreElements()) {
throw new RuntimeException("No token manifest found. Did the RequestFactory annotation"
+ " processor run? Check classpath for " + TOKEN_MANIFEST + " file and ensure that"
+ " your proxy types are compiled with the requestfactory-apt.jar on javac's classpath.");
}
while (locations.hasMoreElements()) {
builder.load(locations.nextElement().openStream());
}
return builder.build();
}
/**
* The values of {@link #typeTokens}.
*/
private Set<String> referencedTypes;
/**
* Map of obfuscated ids to binary class names.
*/
private Map<String, String> typeTokens = new HashMap<String, String>();
public SortedMap<String, String> getAllTypeTokens() {
return new TreeMap<String, String>(typeTokens);
}
public String getTypeFromToken(String typeToken) {
return typeTokens.get(typeToken);
}
public boolean isReferencedType(String binaryName) {
return referencedTypes.contains(binaryName);
}
/**
* Closes the OutputStream.
*/
public void store(OutputStream out) throws IOException {
Properties props = new Properties();
props.putAll(typeTokens);
props.store(out, "GENERATED FILE -- DO NOT EDIT");
out.close();
}
}