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 }