View Javadoc

1   /*
2    * $Id: DefaultAppBloodhound.java 23284 2011-10-31 23:07:39Z mike.schilling $
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.PreferredObjectSelector;
15  import org.mule.config.i18n.MessageFactory;
16  import org.mule.module.launcher.descriptor.ApplicationDescriptor;
17  import org.mule.module.launcher.descriptor.DescriptorParser;
18  import org.mule.module.launcher.descriptor.EmptyApplicationDescriptor;
19  import org.mule.module.launcher.descriptor.PropertiesDescriptorParser;
20  import org.mule.module.launcher.plugin.PluginDescriptor;
21  import org.mule.module.launcher.plugin.PluginDescriptorParser;
22  import org.mule.module.reboot.MuleContainerBootstrapUtils;
23  import org.mule.util.FileUtils;
24  import org.mule.util.FilenameUtils;
25  import org.mule.util.PropertiesUtils;
26  
27  import java.io.File;
28  import java.io.IOException;
29  import java.util.Collection;
30  import java.util.HashMap;
31  import java.util.Iterator;
32  import java.util.Map;
33  import java.util.Properties;
34  import java.util.Set;
35  
36  import javax.imageio.spi.ServiceRegistry;
37  
38  import org.apache.commons.collections.MultiMap;
39  import org.apache.commons.collections.map.MultiValueMap;
40  import org.apache.commons.io.filefilter.WildcardFileFilter;
41  
42  /**
43   *
44   */
45  public class DefaultAppBloodhound implements AppBloodhound
46  {
47  
48      // file extension -> parser implementation
49      protected Map<String, DescriptorParser> parserRegistry = new HashMap<String, DescriptorParser>();
50      public static final String SYSTEM_PROPERTY_OVERRIDE = "-O";
51  
52      public DefaultAppBloodhound()
53      {
54          // defaults first
55          parserRegistry.put("properties", new PropertiesDescriptorParser());
56  
57          final Iterator<DescriptorParser> it = ServiceRegistry.lookupProviders(DescriptorParser.class);
58  
59          MultiMap overrides = new MultiValueMap();
60          while (it.hasNext())
61          {
62              final DescriptorParser parser = it.next();
63              overrides.put(parser.getSupportedFormat(), parser);
64          }
65          mergeParserOverrides(overrides);
66      }
67  
68      public ApplicationDescriptor fetch(String appName) throws IOException
69      {
70          final File appsDir = MuleContainerBootstrapUtils.getMuleAppsDir();
71          File appDir = new File(appsDir, appName);
72          if (!appDir.exists())
73          {
74              throw new MuleRuntimeException(
75                      MessageFactory.createStaticMessage(
76                              String.format("Application directory does not exist: '%s'", appDir)));
77          }
78          // list mule-deploy.* files
79          @SuppressWarnings("unchecked")
80          Collection<File> deployFiles = FileUtils.listFiles(appDir, new WildcardFileFilter("mule-deploy.*"), null);
81          if (deployFiles.size() > 1)
82          {
83              // TODO need some kind of an InvalidAppFormatException
84              throw new MuleRuntimeException(
85                      MessageFactory.createStaticMessage(
86                              String.format("More than one mule-deploy descriptors found in application '%s'", appName)));
87          }
88  
89          ApplicationDescriptor desc;
90  
91          // none found, return defaults
92          if (deployFiles.isEmpty())
93          {
94              desc = new EmptyApplicationDescriptor(appName);
95          }
96          else
97          {
98              // lookup the implementation by extension
99              final File descriptorFile = deployFiles.iterator().next();
100             final String ext = FilenameUtils.getExtension(descriptorFile.getName());
101             final DescriptorParser descriptorParser = parserRegistry.get(ext);
102 
103             if (descriptorParser == null)
104             {
105                 // TODO need some kind of an InvalidAppFormatException
106                 throw new MuleRuntimeException(
107                         MessageFactory.createStaticMessage(
108                                 String.format("Unsupported deployment descriptor format for app '%s': %s", appName, ext)));
109             }
110 
111             desc = descriptorParser.parse(descriptorFile);
112             // app name is external to the deployment descriptor
113             desc.setAppName(appName);
114         }
115 
116         // get a ref to an optional app props file (right next to the descriptor)
117         final File appPropsFile = new File(appDir, ApplicationDescriptor.DEFAULT_APP_PROPERTIES_RESOURCE);
118         setApplicationProperties(desc, appPropsFile);
119 
120         final Set<PluginDescriptor> plugins = new PluginDescriptorParser(desc, appDir).parse();
121         desc.setPlugins(plugins);
122 
123         return desc;
124 
125     }
126 
127     public void setApplicationProperties(ApplicationDescriptor desc, File appPropsFile) throws IOException
128     {
129         // ugh, no straightforward way to convert a HashTable to a map
130         Map<String, String> m = new HashMap<String, String>();
131 
132         if (appPropsFile.exists() && appPropsFile.canRead())
133         {
134             final Properties props = PropertiesUtils.loadProperties(appPropsFile.toURI().toURL());
135             for (Object key : props.keySet())
136             {
137                 m.put(key.toString(), props.getProperty(key.toString()));
138             }
139         }
140 
141         // Override with any system properties prepended with "-O" for ("override"))
142         Properties sysProps = System.getProperties();
143         for (Map.Entry<Object, Object> entry : sysProps.entrySet())
144         {
145             String key = entry.getKey().toString();
146             if (key.startsWith(SYSTEM_PROPERTY_OVERRIDE))
147             {
148                 m.put(key.substring(SYSTEM_PROPERTY_OVERRIDE.length()), entry.getValue().toString());
149             }
150         }
151         desc.setAppProperties(m);
152     }
153 
154     /**
155      * Merge default and discovered overrides for descriptor parsers, taking weight into account
156      *
157      * @param overrides discovered parser overrides
158      */
159     protected void mergeParserOverrides(MultiMap overrides)
160     {
161         PreferredObjectSelector<DescriptorParser> selector = new PreferredObjectSelector<DescriptorParser>();
162 
163         for (Map.Entry<String, DescriptorParser> entry : parserRegistry.entrySet())
164         {
165             @SuppressWarnings("unchecked")
166             final Collection<DescriptorParser> candidates = (Collection<DescriptorParser>) overrides.get(entry.getKey());
167 
168             if (candidates != null)
169             {
170                 parserRegistry.put(entry.getKey(), selector.select(candidates.iterator()));
171             }
172         }
173 
174     }
175 }