#!/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 os
import os.path
import sys
import threading

import google

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 representing 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.get('APP_ENGINE_JAVA_PATH', None)

    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

    args = [
        java_bin,
        '-cp', class_path,
        '-Dappengine.sdk.root=' + java_dir,
        '-Xbootclasspath/p:' + jdk_overrides_jar,
    ]
    if sys.platform == 'darwin':
      args.append('-XstartOnFirstThread')
    args.extend(self._runtime_config_getter().java_config.jvm_args)
    args.append(
        'com.google.appengine.tools.development.devappserver2.'
        'StandaloneInstance')
    return args

  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()
    runtime_config = instance_config_getter()
    for env_entry in runtime_config.environ:
      env[env_entry.key] = env_entry.value

    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)
