Package com.google.appengine.tools.development

Source Code of com.google.appengine.tools.development.StreamHandlerFactory

// Copyright 2008 Google Inc. All Rights Reserved.

package com.google.appengine.tools.development;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLStreamHandler;
import java.net.URLStreamHandlerFactory;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;

/**
* A {@link URLStreamHandlerFactory} which installs
* {@link URLStreamHandler URLStreamHandlers} that App Engine needs to support.
* (For example, the "http" and "https" protocols).  This factory returns
* handlers that delegate to the
* {@link com.google.appengine.api.urlfetch.URLFetchService} when running in an
* App Engine container, and returns the default handlers when running outside
* an App Engine container.
*
*/
public class StreamHandlerFactory implements URLStreamHandlerFactory {

  private static boolean factoryIsInstalled;

  /**
   * Need to access this method via reflection because it is protected on
   * {@link URL}.
   */ private static final Method GET_URL_STREAM_HANDLER;

  static {
    Method m = null;
    try {
      m = URL.class.getDeclaredMethod("getURLStreamHandler", String.class);
      m.setAccessible(true);
    } catch (NoSuchMethodException e) {
      Logger.getLogger(StreamHandlerFactory.class.getName()).info(
          "Unable to register default URLStreamHandlers.  You will be unable to "
              + "access http and https URLs outside the App Engine environment.");
    }
    GET_URL_STREAM_HANDLER = m;
  }

  private Map<String, URLStreamHandler> handlers = new HashMap<String, URLStreamHandler>();

  /**
   * Installs this StreamHandlerFactory.
   *
   * @throws IllegalStateException if a factory has already been installed, and
   * it is not a StreamHandlerFactory.
   * @throws RuntimeException if an unexpected, catastrophic failure occurs
   * while installing the handler.
   */
  public static void install() {
    synchronized (StreamHandlerFactory.class) {
      if (!factoryIsInstalled) {
        StreamHandlerFactory factory = new StreamHandlerFactory();

        try {
          URL.setURLStreamHandlerFactory(factory);
        } catch (Error e) {

          Object currentFactory;

          try {
            Field f = URL.class.getDeclaredField("factory");
            f.setAccessible(true);
            currentFactory = f.get(null);
          } catch (Exception ex) {
            throw new RuntimeException("Failed to find the currently installed factory", ex);
          }

          if (currentFactory == null) {
            throw new RuntimeException("The current factory is null, but we were unable "
                + "to set a new factory", e);
          }

          String currentFactoryType = currentFactory.getClass().getName();
          if (currentFactoryType.equals(StreamHandlerFactory.class.getName())) {
            factoryIsInstalled = true;
            return;
          }

          throw new IllegalStateException("A factory of type " + currentFactoryType +
              " has already been installed");
        }
      }
    }
  }

  private StreamHandlerFactory() {
    for (String protocol : Arrays.asList("http", "https")) {
      URLStreamHandler fallbackHandler = getFallbackStreamHandler(protocol);
      handlers.put(protocol, new LocalURLFetchServiceStreamHandler(fallbackHandler));
    }
  }

  @Override
  public URLStreamHandler createURLStreamHandler(String protocol) {
    return handlers.get(protocol);
  }

  /**
   * All calls to this method must take place before we register the
   * stream handler factory with URL.
   */
  private static URLStreamHandler getFallbackStreamHandler(String protocol) {
    if (GET_URL_STREAM_HANDLER == null) {
      return null;
    }
    URLStreamHandler existingHandler =
        (URLStreamHandler) invoke(null, GET_URL_STREAM_HANDLER, protocol);
    if (existingHandler.getClass().getName().equals(
            LocalURLFetchServiceStreamHandler.class.getName())) {
      Method getFallbackHandler =
          getDeclaredMethod(existingHandler.getClass(), "getFallbackHandler");
      return (URLStreamHandler) invoke(existingHandler, getFallbackHandler);
    }
    return existingHandler;
  }

  static Object invoke(Object target, Method m, Object... args) {
    try {
      return m.invoke(target, args);
    } catch (IllegalAccessException e) {
      throw new RuntimeException(e);
    } catch (InvocationTargetException e) {
      if (e.getTargetException() instanceof RuntimeException) {
        throw (RuntimeException) e.getTargetException();
      }
      throw new RuntimeException(e.getTargetException());
    }
  }

  static Method getDeclaredMethod(Class<?> cls, String methodName, Class<?>... args) {
    try {
      Method m = cls.getDeclaredMethod(methodName, args);
      m.setAccessible(true);
      return m;
    } catch (NoSuchMethodException e) {
      throw new RuntimeException(e);
    }
  }
}
TOP

Related Classes of com.google.appengine.tools.development.StreamHandlerFactory

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.