3 # Copyright 2007 Google Inc.
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
17 """Serves content for "script" handlers using the Java runtime."""
27 from google
.appengine
.api
import appinfo
28 from google
.appengine
.tools
.devappserver2
import http_runtime
29 from google
.appengine
.tools
.devappserver2
import instance
30 from google
.appengine
.tools
.devappserver2
import java_application
32 # TODO: figure out what's needed to react to file changes
35 class JavaRuntimeInstanceFactory(instance
.InstanceFactory
):
36 """A factory that creates new Java runtime Instances."""
38 START_URL_MAP
= appinfo
.URLMap(
42 WARMUP_URL_MAP
= appinfo
.URLMap(
46 FILE_CHANGE_INSTANCE_RESTART_POLICY
= instance
.ALWAYS
48 def __init__(self
, request_data
, runtime_config_getter
, module_configuration
):
49 """Initializer for JavaRuntimeInstanceFactory.
52 request_data: A wsgi_request_info.WSGIRequestInfo that will be provided
53 with request information for use by API stubs.
54 runtime_config_getter: A function that can be called without arguments
55 and returns the runtime_config_pb2.RuntimeConfig containing the
56 configuration for the runtime.
57 module_configuration: An application_configuration.ModuleConfiguration
58 instance representing the configuration of the module that owns the
61 super(JavaRuntimeInstanceFactory
, self
).__init
__(request_data
, 1)
62 self
._runtime
_config
_getter
= runtime_config_getter
63 self
._module
_configuration
= module_configuration
64 self
._application
_lock
= threading
.Lock()
65 self
._java
_application
= java_application
.JavaApplication(
66 self
._module
_configuration
)
67 self
._java
_command
= self
._make
_java
_command
()
69 def _make_java_command(self
):
70 # We should be in .../google/appengine/tools/devappserver2/java_runtime.py
71 # and we want to find .../google/appengine/tools and thence
72 # .../google/appengine/tools/java/lib
74 java_home
= os
.environ
.get('JAVA_HOME')
76 if java_home
and os
.path
.exists(java_home
):
77 java_bin
= os
.path
.join(java_home
, 'bin/java')
81 java_dir
= os
.environ
.get('APP_ENGINE_JAVA_PATH', None)
83 if not java_dir
or not os
.path
.exists(java_dir
):
84 tools_dir
= os
.path
.abspath(os
.path
.dirname(os
.path
.dirname(__file__
)))
85 java_dir
= os
.path
.join(tools_dir
, 'java')
87 java_lib_dir
= os
.path
.join(java_dir
, 'lib')
88 assert os
.path
.isdir(java_lib_dir
), java_lib_dir
89 class_path
= os
.path
.join(java_lib_dir
, 'appengine-tools-api.jar')
90 assert os
.path
.isfile(class_path
), class_path
91 jdk_overrides_jar
= os
.path
.join(java_lib_dir
, 'override',
92 'appengine-dev-jdk-overrides.jar')
93 assert os
.path
.isfile(jdk_overrides_jar
), jdk_overrides_jar
98 '-Dappengine.sdk.root=' + java_dir
,
99 '-Xbootclasspath/p:' + jdk_overrides_jar
,
101 if sys
.platform
== 'darwin':
102 args
.append('-XstartOnFirstThread')
103 args
.extend(self
._runtime
_config
_getter
().java_config
.jvm_args
)
105 'com.google.appengine.tools.development.devappserver2.'
106 'StandaloneInstance')
109 def get_restart_directories(self
):
110 """Returns a list of directories where changes trigger a restart.
113 A list of directories where changes trigger a restart.
118 def files_changed(self
):
119 """Called when a file relevant to the factory *might* have changed."""
122 def configuration_changed(self
, config_changes
):
123 """Called when the configuration of the module has changed.
126 config_changes: A set containing the changes that occured. See the
127 *_CHANGED constants in the application_configuration module.
131 def new_instance(self
, instance_id
, expect_ready_request
=False):
132 """Create and return a new Instance.
135 instance_id: A string or integer representing the unique (per module) id
137 expect_ready_request: If True then the instance will be sent a special
138 request (i.e. /_ah/warmup or /_ah/start) before it can handle external
142 The newly created instance.Instance.
145 def instance_config_getter():
146 runtime_config
= self
._runtime
_config
_getter
()
147 runtime_config
.instance_id
= str(instance_id
)
148 return runtime_config
150 env
= self
._java
_application
.get_environment()
151 runtime_config
= instance_config_getter()
152 for env_entry
in runtime_config
.environ
:
153 env
[env_entry
.key
] = env_entry
.value
155 with self
._application
_lock
:
156 proxy
= http_runtime
.HttpRuntimeProxy(
158 instance_config_getter
,
159 self
._module
_configuration
,
161 start_process_flavor
=http_runtime
.START_PROCESS_FILE
)
163 return instance
.Instance(self
.request_data
,
166 self
.max_concurrent_requests
,
167 self
.max_background_threads
,
168 expect_ready_request
)