View Javadoc

1   /*
2    * $Id: DefaultAppBloodhound.java 19191 2010-08-25 21:05:23Z tcarlson $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
5    *
6    * The software in this package is published under the terms of the CPAL v1.0
7    * license, a copy of which has been included with this distribution in the
8    * LICENSE.txt file.
9    */
10  
11  package org.mule.module.launcher;
12  
13  import org.mule.api.MuleRuntimeException;
14  import org.mule.config.i18n.MessageFactory;
15  import org.mule.module.launcher.descriptor.ApplicationDescriptor;
16  import org.mule.module.launcher.descriptor.DescriptorParser;
17  import org.mule.module.launcher.descriptor.EmptyApplicationDescriptor;
18  import org.mule.module.launcher.descriptor.Preferred;
19  import org.mule.module.launcher.descriptor.PropertiesDescriptorParser;
20  import org.mule.module.reboot.MuleContainerBootstrapUtils;
21  import org.mule.util.FileUtils;
22  import org.mule.util.FilenameUtils;
23  
24  import java.io.File;
25  import java.io.IOException;
26  import java.util.ArrayList;
27  import java.util.Collection;
28  import java.util.Collections;
29  import java.util.Comparator;
30  import java.util.HashMap;
31  import java.util.Iterator;
32  import java.util.Map;
33  
34  import javax.imageio.spi.ServiceRegistry;
35  
36  import org.apache.commons.collections.MultiMap;
37  import org.apache.commons.collections.map.MultiValueMap;
38  import org.apache.commons.io.filefilter.WildcardFileFilter;
39  
40  /**
41   *
42   */
43  public class DefaultAppBloodhound implements AppBloodhound
44  {
45  
46      // file extension -> parser implementation
47      protected Map<String, DescriptorParser> parserRegistry = new HashMap<String, DescriptorParser>();
48  
49      public DefaultAppBloodhound()
50      {
51          // defaults first
52          parserRegistry.put("properties", new PropertiesDescriptorParser());
53  
54          final Iterator<DescriptorParser> it = ServiceRegistry.lookupProviders(DescriptorParser.class);
55  
56          MultiMap overrides = new MultiValueMap();
57          while (it.hasNext())
58          {
59              final DescriptorParser parser = it.next();
60              overrides.put(parser.getSupportedFormat(), parser);
61          }
62          mergeParserOverrides(overrides);
63      }
64  
65      public ApplicationDescriptor fetch(String appName) throws IOException
66      {
67          final File appsDir = MuleContainerBootstrapUtils.getMuleAppsDir();
68          File appDir = new File(appsDir, appName);
69          if(!appDir.exists())
70          {
71              throw new MuleRuntimeException(
72                      MessageFactory.createStaticMessage(
73                              String.format("Application directory does not exist '%s'", appName)));
74          }
75          // list mule-deploy.* files
76          @SuppressWarnings("unchecked")
77          Collection<File> deployFiles = FileUtils.listFiles(appDir, new WildcardFileFilter("mule-deploy.*"), null);
78  
79          // none found, return defaults
80          if (deployFiles.isEmpty())
81          {
82              return new EmptyApplicationDescriptor(appName);
83          }
84  
85          if (deployFiles.size() > 1)
86          {
87              // TODO need some kind of an InvalidAppFormatException
88              throw new MuleRuntimeException(
89                      MessageFactory.createStaticMessage(
90                              String.format("More than one mule-deploy descriptors found in application '%s'", appName)));
91          }
92  
93          // lookup the implementation by extension
94          final File descriptorFile = deployFiles.iterator().next();
95          final String ext = FilenameUtils.getExtension(descriptorFile.getName());
96          final DescriptorParser descriptorParser = parserRegistry.get(ext);
97  
98          if (descriptorParser == null)
99          {
100             // TODO need some kind of an InvalidAppFormatException
101             throw new MuleRuntimeException(
102                     MessageFactory.createStaticMessage(
103                             String.format("Unsupported deployment descriptor format for app '%s': %s", appName, ext)));
104         }
105 
106         ApplicationDescriptor desc = descriptorParser.parse(descriptorFile);
107         // app name is external to the deployment descriptor
108         desc.setAppName(appName);
109         return desc;
110 
111     }
112 
113     /**
114      * Merge default and discovered overrides for descriptor parsers, taking weight into account
115      *
116      * @param overrides discovered parser overrides
117      */
118     protected void mergeParserOverrides(MultiMap overrides)
119     {
120         // for each key in default parser registry
121         for (Map.Entry<String, DescriptorParser> entry : parserRegistry.entrySet())
122         {
123             @SuppressWarnings("unchecked")
124             final Collection<DescriptorParser> candidates = (Collection<DescriptorParser>) overrides.get(entry.getKey());
125 
126             if (candidates == null)
127             {
128                 continue;
129             }
130             // if any override candidates found, sort by weight reverse
131             final ArrayList<DescriptorParser> sorted = new ArrayList<DescriptorParser>(candidates);
132             final Comparator<DescriptorParser> annotationComparator = new Comparator<DescriptorParser>()
133             {
134                 public int compare(DescriptorParser p1, DescriptorParser p2)
135                 {
136                     final Preferred ann1 = p1.getClass().getAnnotation(Preferred.class);
137                     final Preferred ann2 = p2.getClass().getAnnotation(Preferred.class);
138 
139                     if (ann1 == null && ann2 == null)
140                     {
141                         return 0;
142                     }
143 
144                     if (ann1 != null && ann2 == null)
145                     {
146                         return 1;
147                     }
148 
149                     if (ann1 == null)
150                     {
151                         return -1;
152                     }
153 
154                     // else compare annotation weights
155                     return new Integer(ann1.weight()).compareTo(ann2.weight());
156                 }
157             };
158             Collections.sort(sorted, Collections.reverseOrder(annotationComparator));
159 
160             // put the top one in the registry
161             parserRegistry.put(entry.getKey(), sorted.get(0));
162         }
163 
164     }
165 }