| /* |
| * 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(); |
| } |
| } |