Save This Page
Home » jboss-5.0.0.CR1-src » org » jboss » deployment » scanner » [javadoc | source]
    1   /*
    2    * JBoss, Home of Professional Open Source
    3    * Copyright 2005, JBoss Inc., and individual contributors as indicated
    4    * by the @authors tag. See the copyright.txt in the distribution for a
    5    * full listing of individual contributors.
    6    *
    7    * This is free software; you can redistribute it and/or modify it
    8    * under the terms of the GNU Lesser General Public License as
    9    * published by the Free Software Foundation; either version 2.1 of
   10    * the License, or (at your option) any later version.
   11    *
   12    * This software is distributed in the hope that it will be useful,
   13    * but WITHOUT ANY WARRANTY; without even the implied warranty of
   14    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
   15    * Lesser General Public License for more details.
   16    *
   17    * You should have received a copy of the GNU Lesser General Public
   18    * License along with this software; if not, write to the Free
   19    * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
   20    * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
   21    */
   22   package org.jboss.deployment.scanner;
   23   
   24   import java.io.File;
   25   import java.io.IOException;
   26   import java.net.MalformedURLException;
   27   import java.net.URL;
   28   import java.net.URLConnection;
   29   import java.util.ArrayList;
   30   import java.util.Collections;
   31   import java.util.Comparator;
   32   import java.util.HashSet;
   33   import java.util.Iterator;
   34   import java.util.LinkedList;
   35   import java.util.List;
   36   import java.util.Set;
   37   import java.util.StringTokenizer;
   38   
   39   import javax.management.MBeanServer;
   40   import javax.management.ObjectName;
   41   
   42   import org.jboss.deployment.DefaultDeploymentSorter;
   43   import org.jboss.deployment.IncompleteDeploymentException;
   44   import org.jboss.mx.util.JMXExceptionDecoder;
   45   import org.jboss.net.protocol.URLLister;
   46   import org.jboss.net.protocol.URLListerFactory;
   47   import org.jboss.net.protocol.URLLister.URLFilter;
   48   import org.jboss.system.server.ServerConfig;
   49   import org.jboss.system.server.ServerConfigLocator;
   50   import org.jboss.util.NullArgumentException;
   51   import org.jboss.util.StringPropertyReplacer;
   52   
   53   /**
   54    * A URL-based deployment scanner.  Supports local directory
   55    * scanning for file-based urls.
   56    *
   57    * @jmx:mbean extends="org.jboss.deployment.scanner.DeploymentScannerMBean"
   58    *
   59    * @version <tt>$Revision: 74292 $</tt>
   60    * @author  <a href="mailto:jason@planet57.com">Jason Dillon</a>
   61    * @author <a href="mailto:dimitris@jboss.org">Dimitris Andreadis</a>
   62    */
   63   public class URLDeploymentScanner extends AbstractDeploymentScanner
   64      implements DeploymentScanner, URLDeploymentScannerMBean
   65   {
   66      /** A set of deployment URLs to skip **/
   67      protected Set skipSet = Collections.synchronizedSet(new HashSet());
   68      
   69      /** The list of URLs to scan. */
   70      protected List urlList = Collections.synchronizedList(new ArrayList());
   71   
   72      /** A set of scanned urls which have been deployed. */
   73      protected Set deployedSet = Collections.synchronizedSet(new HashSet());
   74   
   75      /** Helper for listing local/remote directory URLs */
   76      protected URLListerFactory listerFactory = new URLListerFactory();
   77      
   78      /** The server's home directory, for relative paths. */
   79      protected File serverHome;
   80   
   81      protected URL serverHomeURL;
   82   
   83      /** A sorter urls from a scaned directory to allow for coarse dependency
   84       ordering based on file type
   85       */
   86      protected Comparator sorter;
   87   
   88      /** Allow a filter for scanned directories */
   89      protected URLFilter filter;
   90      
   91      protected IncompleteDeploymentException lastIncompleteDeploymentException;
   92      
   93      /** Whether to search inside directories whose names containing no dots */
   94      protected boolean doRecursiveSearch = true;
   95      
   96      /**
   97       * @jmx:managed-attribute
   98       */
   99      public void setRecursiveSearch (boolean recurse)
  100      {
  101         doRecursiveSearch = recurse;
  102      }
  103      
  104      /**
  105       * @jmx:managed-attribute
  106       */
  107      public boolean getRecursiveSearch ()
  108      {
  109         return doRecursiveSearch;
  110      }
  111      
  112      /**
  113       * @jmx:managed-attribute
  114       */
  115      public void setURLList(final List list)
  116      {
  117         if (list == null)
  118            throw new NullArgumentException("list");
  119   
  120         // start out with a fresh list
  121         urlList.clear();
  122   
  123         Iterator iter = list.iterator();
  124         while (iter.hasNext())
  125         {
  126            URL url = (URL)iter.next();
  127            if (url == null)
  128               throw new NullArgumentException("list element");
  129   
  130            addURL(url);
  131         }
  132         
  133         log.debug("URL list: " + urlList);
  134      }
  135   
  136      /**
  137       * @jmx:managed-attribute
  138       *
  139       * @param classname    The name of a Comparator class.
  140       */
  141      public void setURLComparator(String classname)
  142         throws ClassNotFoundException, IllegalAccessException,
  143         InstantiationException
  144      {
  145         sorter = (Comparator)Thread.currentThread().getContextClassLoader().loadClass(classname).newInstance();
  146      }
  147   
  148      /**
  149       * @jmx:managed-attribute
  150       */
  151      public String getURLComparator()
  152      {
  153         if (sorter == null)
  154            return null;
  155         return sorter.getClass().getName();
  156      }
  157   
  158      /**
  159       * @jmx:managed-attribute
  160       *
  161       * @param classname    The name of a FileFilter class.
  162       */
  163      public void setFilter(String classname)
  164      throws ClassNotFoundException, IllegalAccessException, InstantiationException
  165      {
  166         Class filterClass = Thread.currentThread().getContextClassLoader().loadClass(classname);
  167         filter = (URLFilter) filterClass.newInstance();
  168      }
  169   
  170      /**
  171       * @jmx:managed-attribute
  172       */
  173      public String getFilter()
  174      {
  175         if (filter == null)
  176            return null;
  177         return filter.getClass().getName();
  178      }
  179   
  180      
  181      /**
  182       * @jmx:managed-attribute
  183       *
  184       * @param filter The URLFilter instance
  185       */
  186      public void setFilterInstance(URLFilter filter)
  187      {
  188         this.filter = filter;
  189      }
  190   
  191      /**
  192       * @jmx:managed-attribute
  193       */
  194      public URLFilter getFilterInstance()
  195      {
  196         return filter;
  197      }
  198   
  199      /**
  200       * @jmx:managed-attribute
  201       */
  202      public List getURLList()
  203      {
  204         // too bad, List isn't a cloneable
  205         return new ArrayList(urlList);
  206      }
  207   
  208      /**
  209       * @jmx:managed-operation
  210       */
  211      public void addURL(final URL url)
  212      {
  213         if (url == null)
  214            throw new NullArgumentException("url");
  215         
  216         try
  217         {
  218            // check if this is a valid url
  219            url.openConnection().connect();
  220         }
  221         catch (IOException e)
  222         {
  223            // either a bad configuration (non-existent url) or a transient i/o error
  224            log.warn("addURL(), caught " + e.getClass().getName() + ": " + e.getMessage());
  225         }
  226         urlList.add(url);
  227         
  228         log.debug("Added url: " + url);
  229      }
  230   
  231      /**
  232       * @jmx:managed-operation
  233       */
  234      public void removeURL(final URL url)
  235      {
  236         if (url == null)
  237            throw new NullArgumentException("url");
  238   
  239         boolean success = urlList.remove(url);
  240         if (success)
  241         {
  242            log.debug("Removed url: " + url);
  243         }
  244      }
  245   
  246      /**
  247       * @jmx:managed-operation
  248       */
  249      public boolean hasURL(final URL url)
  250      {
  251         if (url == null)
  252            throw new NullArgumentException("url");
  253   
  254         return urlList.contains(url);
  255      }
  256   
  257      /**
  258       * Temporarily ignore changes (addition, updates, removal) to a particular
  259       * deployment, identified by its deployment URL. The deployment URL is different
  260       * from the 'base' URLs that are scanned by the scanner (e.g. the full path to
  261       * deploy/jmx-console.war vs. deploy/). This can be used to avoid an attempt
  262       * by the scanner to deploy/redeploy/undeploy a URL that is being modified.
  263       * 
  264       * To re-enable scanning of changes for a URL, use resumeDeployment(URL, boolean).
  265       *
  266       * @jmx:managed-operation
  267       */
  268      public void suspendDeployment(URL url)
  269      {
  270         if (url == null)
  271            throw new NullArgumentException("url");
  272         
  273         if (skipSet.add(url))
  274            log.debug("Deployment URL added to skipSet: " + url);
  275         else
  276            throw new IllegalStateException("Deployment URL already suspended: " + url);
  277      }
  278   
  279      /**
  280       * Re-enables scanning of a particular deployment URL, previously suspended
  281       * using suspendDeployment(URL). If the markUpToDate flag is true then the
  282       * deployment module will be considered up-to-date during the next scan.
  283       * If the flag is false, at the next scan the scanner will check the
  284       * modification date to decide if the module needs deploy/redeploy/undeploy.
  285       *
  286       * @jmx:managed-operation
  287       */
  288      public void resumeDeployment(URL url, boolean markUpToDate)
  289      {
  290         if (url == null)
  291            throw new NullArgumentException("url");
  292         
  293         if (skipSet.contains(url))
  294         {
  295            if (markUpToDate)
  296            {
  297               // look for the deployment and mark it as uptodate
  298               for (Iterator i = deployedSet.iterator(); i.hasNext(); )
  299               {
  300                  DeployedURL deployedURL = (DeployedURL)i.next();
  301                  if (deployedURL.url.equals(url))
  302                  {
  303                     // the module could have been removed..
  304                     log.debug("Marking up-to-date: " + url);                  
  305                     deployedURL.deployed();
  306                     break;
  307                  }
  308               }
  309            }
  310            // don't skip this url anymore
  311            skipSet.remove(url);
  312            log.debug("Deployment URL removed from skipSet: " + url);
  313         }
  314         else
  315         {
  316            throw new IllegalStateException("Deployment URL not suspended: " + url);
  317         }
  318      }
  319   
  320      /**
  321       * Lists all urls deployed by the scanner, each URL on a new line.
  322       *
  323       * @jmx:managed-operation
  324       */
  325      public String listDeployedURLs()
  326      {
  327         StringBuffer sbuf = new StringBuffer();
  328         for (Iterator i = deployedSet.iterator(); i.hasNext(); )
  329         {
  330            URL url = ((DeployedURL)i.next()).url;
  331            if (sbuf.length() > 0)
  332            {
  333               sbuf.append("\n").append(url);
  334            } 
  335            else 
  336            {
  337               sbuf.append(url);
  338            }
  339         }
  340         return sbuf.toString();
  341      }
  342   
  343      /////////////////////////////////////////////////////////////////////////
  344      //                  Management/Configuration Helpers                   //
  345      /////////////////////////////////////////////////////////////////////////
  346   
  347      /**
  348       * @jmx:managed-attribute
  349       */
  350      public void setURLs(final String listspec) throws MalformedURLException
  351      {
  352         if (listspec == null)
  353            throw new NullArgumentException("listspec");
  354   
  355         List list = new LinkedList();
  356   
  357         StringTokenizer stok = new StringTokenizer(listspec, ",");
  358         while (stok.hasMoreTokens())
  359         {
  360            String urlspec = stok.nextToken().trim();
  361            log.debug("Adding URL from spec: " + urlspec);
  362   
  363            URL url = makeURL(urlspec);
  364            log.debug("URL: " + url);
  365            
  366            list.add(url);
  367         }
  368   
  369         setURLList(list);
  370      }
  371   
  372      /**
  373       * A helper to make a URL from a full url, or a filespec.
  374       */
  375      protected URL makeURL(String urlspec) throws MalformedURLException
  376      {
  377         // First replace URL with appropriate properties
  378         //
  379         urlspec = StringPropertyReplacer.replaceProperties (urlspec);
  380         return new URL(serverHomeURL, urlspec);
  381      }
  382   
  383      /**
  384       * @jmx:managed-operation
  385       */
  386      public void addURL(final String urlspec) throws MalformedURLException
  387      {
  388         addURL(makeURL(urlspec));
  389      }
  390   
  391      /**
  392       * @jmx:managed-operation
  393       */
  394      public void removeURL(final String urlspec) throws MalformedURLException
  395      {
  396         removeURL(makeURL(urlspec));
  397      }
  398   
  399      /**
  400       * @jmx:managed-operation
  401       */
  402      public boolean hasURL(final String urlspec) throws MalformedURLException
  403      {
  404         return hasURL(makeURL(urlspec));
  405      }
  406   
  407      /**
  408       * A helper to deploy the given URL with the deployer.
  409       */
  410      protected void deploy(final DeployedURL du)
  411      {
  412         // If the deployer is null simply ignore the request
  413         if (deployer == null)
  414            return;
  415         
  416         try
  417         {
  418            if (log.isTraceEnabled())
  419               log.trace("Deploying: " + du);
  420   
  421            deployer.deploy(du.url);
  422         }
  423         catch (IncompleteDeploymentException e)
  424         {
  425            lastIncompleteDeploymentException = e;
  426         }
  427         catch (Exception e)
  428         {
  429            log.debug("Failed to deploy: " + du, e);
  430         }
  431   
  432         du.deployed();
  433   
  434         if (!deployedSet.contains(du))
  435         {
  436            deployedSet.add(du);
  437         }
  438      }
  439   
  440      /**
  441       * A helper to undeploy the given URL from the deployer.
  442       */
  443      protected void undeploy(final DeployedURL du)
  444      {
  445         try
  446         {
  447            if (log.isTraceEnabled())
  448               log.trace("Undeploying: " + du);
  449   
  450            deployer.undeploy(du.url);
  451            deployedSet.remove(du);
  452         }
  453         catch (Exception e)
  454         {
  455            log.error("Failed to undeploy: " + du, e);
  456         }
  457      }
  458   
  459      /**
  460       * Checks if the url is in the deployed set.
  461       */
  462      protected boolean isDeployed(final URL url)
  463      {
  464         DeployedURL du = new DeployedURL(url);
  465         return deployedSet.contains(du);
  466      }
  467   
  468      public synchronized void scan() throws Exception
  469      {
  470         lastIncompleteDeploymentException = null;
  471         if (urlList == null)
  472            throw new IllegalStateException("not initialized");
  473   
  474         updateSorter();
  475   
  476         boolean trace = log.isTraceEnabled();
  477         List urlsToDeploy = new LinkedList();
  478   
  479         // Scan for deployments
  480         if (trace)
  481         {
  482            log.trace("Scanning for new deployments");
  483         }
  484         synchronized (urlList)
  485         {
  486            for (Iterator i = urlList.iterator(); i.hasNext();)
  487            {
  488               URL url = (URL) i.next();
  489               try
  490               {
  491                  if (url.toString().endsWith("/"))
  492                  {
  493                     // treat URL as a collection
  494                     URLLister lister = listerFactory.createURLLister(url);
  495                     
  496                     // listMembers() will throw an IOException if collection url does not exist
  497                     urlsToDeploy.addAll(lister.listMembers(url, filter, doRecursiveSearch));
  498                  } 
  499                  else
  500                  {
  501                     // treat URL as a deployable unit
  502                     
  503                     // throws IOException if this URL does not exist
  504                     url.openConnection().connect();
  505                     urlsToDeploy.add(url);
  506                  }
  507               }
  508               catch (IOException e)
  509               {
  510                  // Either one of the configured URLs is bad, i.e. points to a non-existent
  511                  // location, or it ends with a '/' but it is not a directory (so it
  512                  // is really user's fault), OR some other hopefully transient I/O error
  513                  // happened (e.g. out of file descriptors?) so log a warning.
  514                  log.warn("Scan URL, caught " + e.getClass().getName() + ": " + e.getMessage());
  515                  
  516                  // We need to return because at least one of the listed URLs will
  517                  // return no results, and so all deployments starting from that point
  518                  // (e.g. deploy/) will get undeployed, see JBAS-3107.
  519                  // On the other hand, in case of a bad configuration nothing will get
  520                  // deployed. If really want independence of e.g. 2 deploy urls, more
  521                  // than one URLDeploymentScanners can be setup.
  522                  return;
  523               }
  524            }
  525         }
  526   
  527         if (trace)
  528         {
  529            log.trace("Updating existing deployments");
  530         }
  531         LinkedList urlsToRemove = new LinkedList();
  532         LinkedList urlsToCheckForUpdate = new LinkedList();
  533         synchronized (deployedSet)
  534         {
  535            // remove previously deployed URLs no longer needed
  536            for (Iterator i = deployedSet.iterator(); i.hasNext();)
  537            {
  538               DeployedURL deployedURL = (DeployedURL) i.next();
  539               
  540               if (skipSet.contains(deployedURL.url))
  541               {
  542                  if (trace)
  543                     log.trace("Skipping update/removal check for: " + deployedURL.url);
  544               }
  545               else
  546               {
  547                  if (urlsToDeploy.contains(deployedURL.url))
  548                  {
  549                     urlsToCheckForUpdate.add(deployedURL);
  550                  }
  551                  else
  552                  {
  553                     urlsToRemove.add(deployedURL);
  554                  }
  555               }
  556            }
  557         }
  558   
  559         // ********
  560         // Undeploy
  561         // ********
  562   
  563         for (Iterator i = urlsToRemove.iterator(); i.hasNext();)
  564         {
  565            DeployedURL deployedURL = (DeployedURL) i.next();
  566            if (trace)
  567            {
  568               log.trace("Removing " + deployedURL.url);
  569            }
  570            undeploy(deployedURL);
  571         }
  572   
  573         // ********
  574         // Redeploy
  575         // ********
  576   
  577         // compute the DeployedURL list to update
  578         ArrayList urlsToUpdate = new ArrayList(urlsToCheckForUpdate.size());
  579         for (Iterator i = urlsToCheckForUpdate.iterator(); i.hasNext();)
  580         {
  581            DeployedURL deployedURL = (DeployedURL) i.next();
  582            if (deployedURL.isModified())
  583            {
  584               if (trace)
  585               {
  586                  log.trace("Re-deploying " + deployedURL.url);
  587               }
  588               urlsToUpdate.add(deployedURL);
  589            }
  590         }
  591   
  592         // sort to update list
  593         Collections.sort(urlsToUpdate, new Comparator()
  594         {
  595            public int compare(Object o1, Object o2)
  596            {
  597               return sorter.compare(((DeployedURL) o1).url, ((DeployedURL) o2).url);
  598            }
  599         });
  600   
  601         // Undeploy in order
  602         for (int i = urlsToUpdate.size() - 1; i >= 0;i--)
  603         {
  604            undeploy((DeployedURL) urlsToUpdate.get(i));
  605         }
  606   
  607         // Deploy in order
  608         for (int i = 0; i < urlsToUpdate.size();i++)
  609         {
  610            deploy((DeployedURL) urlsToUpdate.get(i));
  611         }
  612   
  613         // ******
  614         // Deploy
  615         // ******
  616   
  617         Collections.sort(urlsToDeploy, sorter);
  618         for (Iterator i = urlsToDeploy.iterator(); i.hasNext();)
  619         {
  620            URL url = (URL) i.next();
  621            DeployedURL deployedURL = new DeployedURL(url);
  622            if (deployedSet.contains(deployedURL) == false)
  623            {
  624               if (skipSet.contains(url))
  625               {
  626                  if (trace)
  627                     log.trace("Skipping deployment of: " + url);
  628               }
  629               else
  630               {
  631                  if (trace)
  632                     log.trace("Deploying " + deployedURL.url);
  633                  
  634                  deploy(deployedURL);
  635               }
  636            }
  637            i.remove();
  638            // Check to see if mainDeployer suffix list has changed.
  639            // if so, then resort
  640            if (i.hasNext() && updateSorter())
  641            {
  642               Collections.sort(urlsToDeploy, sorter);
  643               i = urlsToDeploy.iterator();
  644            }
  645         }
  646   
  647         // Validate that there are still incomplete deployments
  648         if (lastIncompleteDeploymentException != null)
  649         {
  650            try
  651            {
  652               Object[] args = {};
  653               String[] sig = {};
  654               getServer().invoke(getDeployer(),
  655                                  "checkIncompleteDeployments", args, sig);
  656            }
  657            catch (Exception e)
  658            {
  659               Throwable t = JMXExceptionDecoder.decode(e);
  660               log.error(t);
  661            }
  662         }
  663      }
  664   
  665      protected boolean updateSorter()
  666      {
  667         // Check to see if mainDeployer suffix list has changed.
  668         if (sorter instanceof DefaultDeploymentSorter)
  669         {
  670            DefaultDeploymentSorter defaultSorter = (DefaultDeploymentSorter)sorter;
  671            if (defaultSorter.getSuffixOrder() != mainDeployer.getSuffixOrder())
  672            {
  673               defaultSorter.setSuffixOrder(mainDeployer.getSuffixOrder());
  674               return true;
  675            }
  676         }
  677         return false;
  678      }
  679   
  680      /////////////////////////////////////////////////////////////////////////
  681      //                     Service/ServiceMBeanSupport                     //
  682      /////////////////////////////////////////////////////////////////////////
  683   
  684      public ObjectName preRegister(MBeanServer server, ObjectName name)
  685         throws Exception
  686      {
  687         // get server's home for relative paths, need this for setting
  688         // attribute final values, so we need to do it here
  689         ServerConfig serverConfig = ServerConfigLocator.locate();
  690         serverHome = serverConfig.getServerHomeDir();
  691         serverHomeURL = serverConfig.getServerHomeURL();
  692   
  693         return super.preRegister(server, name);
  694      }
  695   
  696      protected void createService() throws Exception
  697      {
  698         // Perform a couple of sanity checks
  699         if (this.filter == null)
  700         {
  701            throw new IllegalStateException("'FilterInstance' attribute not configured");
  702         }
  703         if (this.sorter == null)
  704         {
  705            throw new IllegalStateException("'URLComparator' attribute not configured");
  706         }
  707         // ok, proceed with normal createService()
  708         super.createService();
  709      }
  710      
  711      /////////////////////////////////////////////////////////////////////////
  712      //                           DeployedURL                               //
  713      /////////////////////////////////////////////////////////////////////////
  714   
  715      /**
  716       * A container and help class for a deployed URL.
  717       * should be static at this point, with the explicit scanner ref, but I'm (David) lazy.
  718       */
  719      protected class DeployedURL
  720      {
  721         public URL url;
  722         /** The url to check to decide if we need to redeploy */
  723         public URL watchUrl;
  724         
  725         public long deployedLastModified;
  726   
  727         public DeployedURL(final URL url)
  728         {
  729            this.url = url;
  730         }
  731   
  732         public void deployed()
  733         {
  734            deployedLastModified = getLastModified();
  735         }
  736         public boolean isFile()
  737         {
  738            return url.getProtocol().equals("file");
  739         }
  740   
  741         public File getFile()
  742         {
  743            return new File(url.getFile());
  744         }
  745   
  746         public boolean isRemoved()
  747         {
  748            if (isFile())
  749            {
  750               File file = getFile();
  751               return !file.exists();
  752            }
  753            return false;
  754         }
  755   
  756         public long getLastModified()
  757         {
  758            if (watchUrl == null)
  759            {
  760               try
  761               {
  762                  Object o = getServer().invoke(
  763                        getDeployer(),
  764                        "getWatchUrl",
  765                        new Object[] { url },
  766                        new String[] { URL.class.getName() }
  767                        );
  768                  watchUrl = o == null ? url : (URL)o;
  769                  getLog().debug("Watch URL for: " + url + " -> " + watchUrl);
  770               }
  771               catch (Exception e)
  772               {
  773                  watchUrl = url;
  774                  getLog().debug("Unable to obtain watchUrl from deployer. Use url: " + url, e);
  775               }
  776            }
  777   
  778            try
  779            {
  780               URLConnection connection;
  781               if (watchUrl != null)
  782               {
  783                  connection = watchUrl.openConnection();
  784               } 
  785               else
  786               {
  787                  connection = url.openConnection();
  788               }
  789               long lastModified = connection.getLastModified();
  790   
  791               return lastModified;
  792            }
  793            catch (java.io.IOException e)
  794            {
  795               log.warn("Failed to check modification of deployed url: " + url, e);
  796            }
  797            return -1;
  798         }
  799   
  800         public boolean isModified()
  801         {
  802            long lastModified = getLastModified();
  803            if (lastModified == -1)
  804            {
  805               // ignore errors fetching the timestamp - see bug 598335
  806               return false;
  807            }
  808            return deployedLastModified != lastModified;
  809         }
  810   
  811         public int hashCode()
  812         {
  813            return url.hashCode();
  814         }
  815   
  816         public boolean equals(final Object other)
  817         {
  818            if (other instanceof DeployedURL)
  819            {
  820               return ((DeployedURL)other).url.equals(this.url);
  821            }
  822            return false;
  823         }
  824   
  825         public String toString()
  826         {
  827            return super.toString() +
  828            "{ url=" + url +
  829            ", deployedLastModified=" + deployedLastModified +
  830            " }";
  831         }
  832      }
  833   }

Save This Page
Home » jboss-5.0.0.CR1-src » org » jboss » deployment » scanner » [javadoc | source]