Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 277 lines (236 sloc) 9.603 kb
7995c9f @graemerocher ignoring test temporarily, as due to infrastructure issues it is not …
graemerocher authored
1 /*
2 * Copyright 2004-2005 the original author or authors.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 import grails.util.GrailsUtil
18 import grails.util.Metadata
19 import grails.web.container.EmbeddableServer
20 import grails.web.container.EmbeddableServerFactory
21
22 import java.awt.event.ActionEvent
23 import java.awt.event.ActionListener
24 import java.net.ServerSocket
25
26 import org.codehaus.groovy.grails.cli.ScriptExitException
27 import org.codehaus.groovy.grails.cli.interactive.InteractiveMode
28 import org.codehaus.groovy.grails.compiler.GrailsProjectWatcher
29
30
31 /**
32 * Gant script that executes Grails using an embedded server.
33 *
34 * @author Graeme Rocher
35 *
36 * @since 0.4
37 */
38
39 includeTargets << grailsScript("_GrailsPlugins")
40
41 SCHEME_HTTP = "http"
42 SCHEME_HTTPS = "https"
43
44 // Keep track of whether we're running in HTTPS mode in case we need
45 // to restart the server.
46 usingSecureServer = false
47
48 grailsServer = null
49 grailsContext = null
50 autoRecompile = System.getProperty("disable.auto.recompile") ? !(System.getProperty("disable.auto.recompile").toBoolean()) : true
51
52 // How often should recompilation occur while the application is running (in seconds)?
53 // Defaults to 3s.
54 recompileFrequency = System.getProperty("recompile.frequency")
55 recompileFrequency = recompileFrequency ? recompileFrequency.toInteger() : 3
56
57 shouldPackageTemplates = true
58
59 // This isn't used within this script but may come in handy for scripts
60 // that depend on this one.
61 ant.path(id: "grails.runtime.classpath", runtimeClasspath)
62
63 /**
64 * Runs the application in dev mode, i.e. with class-reloading.
65 */
66 target(runApp: "Main implementation that executes a Grails application") {
67 runInline(SCHEME_HTTP, serverHost, serverPort, serverPortHttps)
68 }
69
70 /**
71 * Runs the application in dev mode over HTTPS.
72 */
73 target(runAppHttps: "Main implementation that executes a Grails application with an HTTPS listener") {
74 runInline(SCHEME_HTTPS, serverHost, serverPort, serverPortHttps)
75 }
76
77 /**
78 * Runs the application using the WAR file directly.
79 */
80 target (runWar : "Main implementation that executes a Grails application WAR") {
81 runWar(SCHEME_HTTP, serverHost, serverPort, serverPortHttps)
82 }
83
84 /**
85 * Runs the application over HTTPS using the WAR file directly.
86 */
87 target (runWarHttps : "Main implementation that executes a Grails application WAR") {
88 runWar(SCHEME_HTTPS, serverHost, serverPort, serverPortHttps)
89 }
90
91 private EmbeddableServerFactory loadServerFactory() {
92 def load = { name -> classLoader.loadClass(name).newInstance() }
93
94 String defaultServer = "org.grails.plugins.tomcat.TomcatServerFactory"
95 def containerClass = getPropertyValue("grails.server.factory", defaultServer)
96 EmbeddableServerFactory serverFactory
97 try {
98 serverFactory = load(containerClass)
99 }
100 catch (ClassNotFoundException cnfe) {
101 if (containerClass == defaultServer) {
102 grailsConsole.error "WARNING: No default container found, installing Tomcat.."
103 doInstallPlugin "tomcat", GrailsUtil.grailsVersion
104 pluginSettings.clearCache()
105 compilePlugins()
106 loadPlugins()
107 serverFactory = load(containerClass)
108 }
109 }
110 catch (Throwable e) {
111 grailsConsole.error e
112 event("StatusFinal", ["Failed to load container [$containerClass]: ${e.message}"])
113 exit(1)
114 }
115 return serverFactory
116 }
117
118 private runInline(scheme, host, httpPort, httpsPort) {
119 EmbeddableServerFactory serverFactory = loadServerFactory()
120 grailsServer = serverFactory.createInline("${basedir}/web-app", webXmlFile.absolutePath, serverContextPath, classLoader)
121 runServer server: grailsServer, host:host, httpPort: httpPort, httpsPort: httpsPort, scheme:scheme
122 startPluginScanner()
123 }
124
125 private runWar(scheme, host, httpPort, httpsPort) {
126 EmbeddableServerFactory serverFactory = loadServerFactory()
127 grailsServer = serverFactory.createForWAR(warName, serverContextPath)
128
129 Metadata.getCurrent().put(Metadata.WAR_DEPLOYED, "true")
130 runServer server:grailsServer, host:host, httpPort:httpPort, httpsPort: httpsPort, scheme: scheme
131 }
132
133 /**
134 * Runs the Server. You can pass these named arguments:
135 *
136 * server - The server instance to use (required).
137 * port - The network port the server is running on (used to display the URL) (required).
138 * scheme - The network scheme to display in the URL (optional; defaults to "http").
139 */
140 runServer = { Map args ->
141 try {
142 event("StatusUpdate", ["Running Grails application"])
143 def message = "Server running. Browse to http://${args.host ?: 'localhost'}:${args.httpPort}$serverContextPath"
144
145 EmbeddableServer server = args["server"]
146 if (server.hasProperty('eventListener')) {
147 server.eventListener = this
148 }
149 if (server.hasProperty('grailsConfig')) {
150 server.grailsConfig = config
151 }
152
153 profile("start server") {
154
155 try { new ServerSocket(args.httpPort).close() }
156 catch (IOException e) {
157 event("StatusError", ["Server failed to start for port $args.httpPort: $e.message"])
158 exit(1)
159 }
160
161 if (args.scheme == 'https') {
162
163 try { new ServerSocket(args.httpsPort).close() }
164 catch (IOException e) {
165 event("StatusError", ["Server failed to start for port $args.httpsPort: $e.message"])
166 exit(1)
167 }
168
169 usingSecureServer = true
170 server.startSecure args.host, args.httpPort, args.httpsPort
171
172 // Update the message to reflect the fact we are running HTTPS as well.
173 message += " or https://${args.host ?: 'localhost'}:${args.httpsPort}$serverContextPath"
174 }
175 else {
176 server.start args.host, args.httpPort
177 }
178 }
179 event("StatusFinal", [message])
180
181 boolean isWindows = System.getProperty("os.name").toLowerCase().indexOf("windows") != -1
182 if (isWindows) {
183 grailsConsole?.reader?.addTriggeredAction((char)3, new ActionListener() {
184 void actionPerformed(ActionEvent e) {
185 stopServer()
186 exit(0)
187 }
188 })
189 }
190 }
191 catch (Throwable t) {
192 if (t instanceof ScriptExitException) throw t
193 GrailsUtil.deepSanitize(t)
194 if (!(t instanceof SocketException) && !(t.cause instanceof SocketException)) {
195 grailsConsole.error t
196 }
197 event("StatusError", ["Server failed to start: $t"])
198 exit(1)
199 }
200 }
201
202 /**
203 * Starts the plugin scanner. Call this after starting the server if you
204 * want changes to artifacts automatically detected and loaded.
205 */
206 target(startPluginScanner: "Starts the plugin manager's scanner that detects changes to artifacts.") {
207 if(GrailsProjectWatcher.isReloadingAgentPresent() && !GrailsProjectWatcher.isActive()) {
208 projectWatcher = new GrailsProjectWatcher(projectCompiler, pluginManager)
209 projectWatcher.start()
210 }
211 }
212
213 target(stopPluginScanner: "Stops the plugin manager's scanner that detects changes to artifacts.") {
214 // do nothing, here for compatibility
215 }
216
217 /**
218 * Keeps the server alive and checks for changes in domain classes or
219 * source files under "src". If any changes are detected, the servlet
220 * container is restarted.
221 */
222 target(watchContext: "Watches the WEB-INF/classes directory for changes and restarts the server if necessary") {
223 depends(classpath)
224
225 if (InteractiveMode.current) {
226 Thread.start {
227 def im = InteractiveMode.current
228 im.grailsServer = grailsServer
229 im.run()
230 }
231 }
232
233 keepServerAlive()
234 }
235
236 target(keepServerAlive: "Idles the script, ensuring that the server stays running.") {
237 def keepRunning = true
238 def killFile = new File("${basedir}/.kill-run-app")
239 if (killFile.exists()) {
240 grailsConsole.warning ".kill-run-app file exists - perhaps a previous server stop didn't work?. Deleting and continuing anyway."
241 killFile.delete()
242 }
243
244 while (keepRunning && Boolean.getBoolean("TomcatKillSwitch.active")) {
245 sleep(recompileFrequency * 1000)
246
247 // Check whether the kill file exists. This is a hack for the
248 // functional tests so that we can stop the servers that are
249 // started.
250 if (killFile.exists()) {
251 grailsConsole.updateStatus "Stopping server..."
252 grailsServer.stop()
253 killFile.delete()
254 keepRunning = false
255 }
256 }
257 }
258
259 target(stopServer: "Stops the Grails servlet container") {
260 if (grailsServer) {
261 try {
262 grailsServer.stop()
263 }
264 catch (Throwable e) {
265 grailsConsole.error "Error stopping server: ${e.message}", e
266 }
267
268 try {
269 stopPluginScanner()
270 }
271 catch (Throwable e) {
272 grailsConsole.error "Error stopping plugin change scanner: ${e.message}", e
273 }
274 }
275 event("StatusFinal", ["Server stopped"])
276 }
Something went wrong with that request. Please try again.