View Javadoc

1   //========================================================================
2   //Copyright 2006-2007 Sabre Holdings.
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   //http://www.apache.org/licenses/LICENSE-2.0
8   //Unless required by applicable law or agreed to in writing, software
9   //distributed under the License is distributed on an "AS IS" BASIS,
10  //WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11  //See the License for the specific language governing permissions and
12  //limitations under the License.
13  //========================================================================
14  
15  package org.mortbay.jetty.ant;
16  
17  import java.io.File;
18  import java.util.ArrayList;
19  import java.util.Iterator;
20  import java.util.List;
21  
22  import org.apache.tools.ant.BuildException;
23  import org.apache.tools.ant.Task;
24  import org.apache.tools.ant.taskdefs.Property;
25  import org.mortbay.jetty.RequestLog;
26  import org.mortbay.jetty.ant.types.Connectors;
27  import org.mortbay.jetty.ant.types.SystemProperties;
28  import org.mortbay.jetty.ant.types.UserRealms;
29  import org.mortbay.jetty.ant.types.WebApp;
30  import org.mortbay.jetty.ant.utils.ServerProxy;
31  import org.mortbay.jetty.ant.utils.TaskLog;
32  import org.mortbay.util.Scanner;
33  
34  /**
35   * Ant task for running a Jetty server.
36   *
37   * @author Jakub Pawlowicz
38   */
39  public class JettyRunTask extends Task
40  {
41  
42      /** Temporary files directory. */
43      private File tempDirectory;
44  
45      /** List of web applications to be deployed. */
46      private List webapps = new ArrayList();
47  
48      /** Location of jetty.xml file. */
49      private File jettyXml;
50  
51      /** List of server connectors. */
52      private Connectors connectors = null;
53  
54      /** Server request logger object. */
55      private RequestLog requestLog;
56  
57      /** List of user realms. */
58      private UserRealms userRealms;
59  
60      /** List of system properties to be set. */
61      private SystemProperties systemProperties;
62  
63      /**
64       * Creates a new <code>WebApp</code> Ant object.
65       *
66       * @return a WebApp object.
67       */
68      public void addWebApp(WebApp webapp)
69      {
70          webapps.add(webapp);
71      }
72  
73      /**
74       * Adds a new Ant's connector tag object if it have not been created yet.
75       */
76      public void addConnectors(Connectors connectors)
77      {
78          if (this.connectors != null)
79          {
80              throw new BuildException("Only one <connectors> tag is allowed!");
81          }
82  
83          this.connectors = connectors;
84      }
85  
86      /**
87       * @return a new Ant's connector tag object if it have not been created yet.
88       */
89      public void addUserRealms(UserRealms realms)
90      {
91          if (this.userRealms != null)
92          {
93              throw new BuildException("Only one <userRealms> tag is allowed!");
94          }
95  
96          this.userRealms = realms;
97      }
98  
99      public void addSystemProperties(SystemProperties systemProperties)
100     {
101         if (this.systemProperties != null)
102         {
103             throw new BuildException("Only one <systemProperties> tag is allowed!");
104         }
105 
106         this.systemProperties = systemProperties;
107     }
108 
109     public File getTempDirectory()
110     {
111         return tempDirectory;
112     }
113 
114     public void setTempDirectory(File tempDirectory)
115     {
116         this.tempDirectory = tempDirectory;
117     }
118 
119     public File getJettyXml()
120     {
121         return jettyXml;
122     }
123 
124     public void setJettyXml(File jettyXml)
125     {
126         this.jettyXml = jettyXml;
127     }
128 
129     public void setRequestLog(String className)
130     {
131         try
132         {
133             this.requestLog = (RequestLog) Class.forName(className).newInstance();
134         }
135         catch (InstantiationException e)
136         {
137             throw new BuildException("Request logger instantiation exception: " + e);
138         }
139         catch (IllegalAccessException e)
140         {
141             throw new BuildException("Request logger instantiation exception: " + e);
142         }
143         catch (ClassNotFoundException e)
144         {
145             throw new BuildException("Unknown request logger class: " + className);
146         }
147     }
148 
149     public String getRequestLog()
150     {
151         if (requestLog != null)
152         {
153             return requestLog.getClass().getName();
154         }
155 
156         return "";
157     }
158 
159     /**
160      * Executes this Ant task. The build flow is being stopped until Jetty
161      * server stops.
162      *
163      * @throws BuildException
164      */
165     public void execute() throws BuildException
166     {
167         TaskLog.setTask(this);
168         TaskLog.log("Configuring Jetty for project: " + getProject().getName());
169         WebApplicationProxyImpl.setBaseTempDirectory(tempDirectory);
170         setSystemProperties();
171 
172         List connectorsList = (connectors != null ? connectors.getConnectors()
173                 : Connectors.DEFAULT_CONNECTORS);
174         List userRealmsList = (userRealms != null ? userRealms.getUserRealms() : new ArrayList());
175         ServerProxy server = new ServerProxyImpl(connectorsList, userRealmsList, requestLog,
176                 jettyXml);
177 
178 				try 
179 				{
180 	        Iterator iterator = webapps.iterator();
181 	        while (iterator.hasNext())
182 	        {
183 	            WebApp webAppConfiguration = (WebApp) iterator.next();
184 	            WebApplicationProxyImpl webApp = new WebApplicationProxyImpl(webAppConfiguration
185 	                    .getName());
186 	            webApp.setSourceDirectory(webAppConfiguration.getWarFile());
187 	            webApp.setContextPath(webAppConfiguration.getContextPath());
188 	            webApp.setWebXml(webAppConfiguration.getWebXmlFile());
189 	            webApp.setJettyEnvXml(webAppConfiguration.getJettyEnvXml());
190 	            webApp.setClassPathFiles(webAppConfiguration.getClassPathFiles());
191 	            webApp.setLibrariesConfiguration(webAppConfiguration.getLibrariesConfiguration());
192 	            webApp.setExtraScanTargetsConfiguration(webAppConfiguration
193 	                    .getScanTargetsConfiguration());
194 	            webApp.setContextHandlers(webAppConfiguration.getContextHandlers());
195 	            webApp.setWebDefaultXmlFile(webAppConfiguration.getWebDefaultXmlFile());
196 
197 	            server.addWebApplication(webApp, webAppConfiguration.getScanIntervalSeconds());
198 	        }
199 				} 
200 				catch (Exception e) {
201 					throw new BuildException(e);
202 				}
203 				
204         server.start();
205     }
206 
207     /**
208      * Starts a new thread which scans project files and automatically reloads a
209      * container on any changes.
210      *
211      * @param scanIntervalSeconds
212      *
213      * @param webapp
214      * @param appContext
215      */
216     static void startScanner(final WebApplicationProxyImpl webApp, int scanIntervalSeconds)
217     {
218         List scanList = new ArrayList();
219         scanList.add(webApp.getWebXmlFile());
220         scanList.addAll(webApp.getLibraries());
221         scanList.addAll(webApp.getExtraScanTargets());
222 
223         Scanner.Listener changeListener = new Scanner.BulkListener()
224         {
225 
226             public void filesChanged(List changedFiles)
227             {
228                 if (hasAnyFileChanged(changedFiles))
229                 {
230                     try
231                     {
232                         webApp.stop();
233                         webApp.applyConfiguration();
234                         webApp.start();
235                     }
236                     catch (Exception e)
237                     {
238                         e.printStackTrace();
239                     }
240                 }
241             }
242 
243             /**
244              * Checks if any file in this particular application has changed.
245              * This is not that easy, because some applications may use the same
246              * class'es directory.
247              *
248              * @param changedFiles list of changed files.
249              * @return true if any of passed files has changed, false otherwise.
250              */
251             private boolean hasAnyFileChanged(List changedFiles)
252             {
253                 Iterator changes = changedFiles.iterator();
254                 while (changes.hasNext())
255                 {
256                     String className = (String) changes.next();
257                     if (webApp.isFileScanned(className))
258                     {
259                         return true;
260                     }
261                 }
262 
263                 return false;
264             }
265         };
266 
267         TaskLog.log("Web application '" + webApp.getName() + "': starting scanner at interval of "
268                 + scanIntervalSeconds + " seconds.");
269 
270         Scanner scanner = new Scanner();
271         scanner.setScanInterval(scanIntervalSeconds);
272         scanner.addListener(changeListener);
273         scanner.setScanDirs(scanList);
274         scanner.setReportExistingFilesOnStartup(false);
275         scanner.start();
276     }
277 
278     /**
279      * Sets the system properties.
280      */
281     private void setSystemProperties()
282     {
283         if (systemProperties != null)
284         {
285             Iterator propertiesIterator = systemProperties.getSystemProperties().iterator();
286             while (propertiesIterator.hasNext())
287             {
288                 Property property = ((Property) propertiesIterator.next());
289                 SystemProperties.setIfNotSetAlready(property);
290             }
291         }
292     }
293 }