#!/usr/bin/env python
#
# Copyright 2007 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.
#
"""Serves content for "script" handlers using the Java runtime."""


import google
import os
import os.path
import sys
import threading

from google.appengine.api import appinfo
from google.appengine.tools.devappserver2 import http_runtime
from google.appengine.tools.devappserver2 import instance
from google.appengine.tools.devappserver2 import java_application


# TODO: figure out what's needed to react to file changes

class JavaRuntimeInstanceFactory(instance.InstanceFactory):
  """A factory that creates new Java runtime Instances."""

  START_URL_MAP = appinfo.URLMap(
      url='/_ah/start',
      script='_java_app',
      login='admin')
  WARMUP_URL_MAP = appinfo.URLMap(
      url='/_ah/warmup',
      script='_java_app',
      login='admin')
  FILE_CHANGE_INSTANCE_RESTART_POLICY = instance.ALWAYS

  def __init__(self, request_data, runtime_config_getter, module_configuration):
    """Initializer for JavaRuntimeInstanceFactory.

    Args:
      request_data: A wsgi_request_info.WSGIRequestInfo that will be provided
          with request information for use by API stubs.
      runtime_config_getter: A function that can be called without arguments
          and returns the runtime_config_pb2.RuntimeConfig containing the
          configuration for the runtime.
      module_configuration: An application_configuration.ModuleConfiguration
          instance respresenting the configuration of the module that owns the
          runtime.
    """
    super(JavaRuntimeInstanceFactory, self).__init__(request_data, 1)
    self._runtime_config_getter = runtime_config_getter
    self._module_configuration = module_configuration
    self._application_lock = threading.Lock()
    self._java_application = java_application.JavaApplication(
        self._module_configuration)
    self._java_command = self._make_java_command()

  def _make_java_command(self):
    # We should be in .../google/appengine/tools/devappserver2/java_runtime.py
    # and we want to find .../google/appengine/tools and thence
    # .../google/appengine/tools/java/lib

    java_home = os.environ.get('JAVA_HOME')

    if java_home and os.path.exists(java_home):
      java_bin = os.path.join(java_home, 'bin/java')
    else:
      java_bin = 'java'

    java_dir = os.environ['APP_ENGINE_JAVA_PATH']

    if not java_dir or not os.path.exists(java_dir):
      tools_dir = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
      java_dir = os.path.join(tools_dir, 'java')

    java_lib_dir = os.path.join(java_dir, 'lib')
    assert os.path.isdir(java_lib_dir), java_lib_dir
    class_path = os.path.join(java_lib_dir, 'appengine-tools-api.jar')
    assert os.path.isfile(class_path), class_path
    jdk_overrides_jar = os.path.join(java_lib_dir, 'override',
                                     'appengine-dev-jdk-overrides.jar')
    assert os.path.isfile(jdk_overrides_jar), jdk_overrides_jar
    return [
        java_bin,
        '-cp', class_path,
        '-Dappengine.sdk.root=' + java_dir,
        '-Xbootclasspath/p:' + jdk_overrides_jar,
    ] + (['-XstartOnFirstThread'] if sys.platform == 'darwin' else []) + [
        'com.google.appengine.tools.development.'
            'devappserver2.StandaloneInstance'
    ]

  def get_restart_directories(self):
    """Returns a list of directories where changes trigger a restart.

    Returns:
      A list of directories where changes trigger a restart.
    """
    # TODO: implement
    return []

  def files_changed(self):
    """Called when a file relevant to the factory *might* have changed."""
    # TODO: implement

  def configuration_changed(self, config_changes):
    """Called when the configuration of the module has changed.

    Args:
      config_changes: A set containing the changes that occured. See the
          *_CHANGED constants in the application_configuration module.
    """
    # TODO: implement

  def new_instance(self, instance_id, expect_ready_request=False):
    """Create and return a new Instance.

    Args:
      instance_id: A string or integer representing the unique (per module) id
          of the instance.
      expect_ready_request: If True then the instance will be sent a special
          request (i.e. /_ah/warmup or /_ah/start) before it can handle external
          requests.

    Returns:
      The newly created instance.Instance.
    """

    def instance_config_getter():
      runtime_config = self._runtime_config_getter()
      runtime_config.instance_id = str(instance_id)
      return runtime_config

    env = self._java_application.get_environment()

    with self._application_lock:
      proxy = http_runtime.HttpRuntimeProxy(
          self._java_command,
          instance_config_getter,
          self._module_configuration,
          env=env,
          start_process_flavor=http_runtime.START_PROCESS_FILE)

    return instance.Instance(self.request_data,
                             instance_id,
                             proxy,
                             self.max_concurrent_requests,
                             self.max_background_threads,
                             expect_ready_request)
