View Javadoc

1   /*
2    * $Id: DefaultMuleConfiguration.java 22396 2011-07-12 21:26:04Z 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.config;
12  
13  import org.mule.api.MuleContext;
14  import org.mule.api.config.MuleConfiguration;
15  import org.mule.api.config.MuleProperties;
16  import org.mule.api.context.MuleContextAware;
17  import org.mule.api.lifecycle.FatalException;
18  import org.mule.api.lifecycle.Initialisable;
19  import org.mule.api.lifecycle.Startable;
20  import org.mule.config.i18n.CoreMessages;
21  import org.mule.util.FileUtils;
22  import org.mule.util.NumberUtils;
23  import org.mule.util.StringUtils;
24  import org.mule.util.UUID;
25  
26  import java.io.File;
27  import java.io.IOException;
28  import java.net.InetAddress;
29  import java.net.UnknownHostException;
30  import java.nio.charset.Charset;
31  import java.util.HashMap;
32  import java.util.Map;
33  
34  import javax.xml.parsers.SAXParserFactory;
35  
36  import org.apache.commons.lang.BooleanUtils;
37  import org.apache.commons.logging.Log;
38  import org.apache.commons.logging.LogFactory;
39  
40  /**
41   * Configuration info. which can be set when creating the MuleContext but becomes
42   * immutable after starting the MuleContext.
43   */
44  public class DefaultMuleConfiguration implements MuleConfiguration, MuleContextAware
45  {
46  
47      public static final String[] DEFAULT_STACKTRACE_FILTER = (
48              "org.mule.processor.AbstractInterceptingMessageProcessor," +
49              "org.mule.processor.chain")
50              .split(",");
51  
52      /**
53       * When false (default), some internal Mule entries are removed from exception stacktraces for readability.
54       * @see #stackTraceFilter
55       */
56      public static boolean fullStackTraces = false;
57  
58      /**
59       * When false (default), only a summary of the root exception
60       * and trail is provided. If this flag is false, full exception information is reported.
61       * Switching on DEBUG level logging with automatically set this flag to true.
62       */
63      public static boolean verboseExceptions = false;
64  
65      /**
66       * A comma-separated list of internal packages/classes which are removed from sanitized stacktraces.
67       * Matching is done via string.startsWith().
68       * @see #fullStackTraces
69       */
70      public static String[] stackTraceFilter = DEFAULT_STACKTRACE_FILTER;
71  
72      private boolean synchronous = false;
73  
74      /**
75       * The type of model used for the internal system model where system created
76       * services are registered
77       */
78      private String systemModelType = "seda";
79  
80      private String encoding = "UTF-8";
81  
82      /**
83       * When running sychronously, return events can be received over transports that
84       * support ack or replyTo This property determines how long to wait for a receive
85       */
86      private int responseTimeout = 10000;
87  
88      /**
89       * The default transaction timeout value used if no specific transaction time out
90       * has been set on the transaction config
91       */
92      private int defaultTransactionTimeout = 30000;
93      
94      /**
95       * The default queue timeout value used when polling queues.
96       */
97      private int defaultQueueTimeout = 200;
98  
99      /**
100      * The default graceful shutdown timeout used when shutting stopping mule cleanly
101      * without message loss.
102      */
103     private int shutdownTimeout = 5000;
104 
105     /**
106      * Where Mule stores any runtime files to disk. Note that in container
107      * mode each app will have its working dir set one level under this dir
108      * (with app's name) in the {@link #setMuleContext} callback.
109      *
110      */
111     private String workingDirectory = "./.mule";
112 
113     /**
114      * Whether the server instance is running in client mode, which means that some
115      * services will not be started
116      */
117     private boolean clientMode = false;
118 
119     /** the unique id for this Mule instance */
120     private String id;
121 
122     /** If this node is part of a cluster then this is the shared cluster Id */
123     private String clusterId = "";
124 
125     /** The domain name that this instance belongs to. */
126     private String domainId;
127 
128     // Debug options
129     
130     private boolean cacheMessageAsBytes = true;
131 
132     private boolean cacheMessageOriginalPayload = true;
133 
134     private boolean enableStreaming = true;
135 
136     private boolean autoWrapMessageAwareTransform = true;
137     
138     protected transient Log logger = LogFactory.getLog(DefaultMuleConfiguration.class);
139 
140     private MuleContext muleContext;
141     private boolean containerMode;
142 
143     /**
144      * By default the Mule Expression parser will perform basic syntax checking on expressions in order to provide
145      * early feedback if an expression is malformed.  Part of the check is checking that all open braces are closed at
146      * some point. For some expressions such as groovy, there could be a scenario where a brace is deliberately used without
147      * being closed; this would cause the validation to fail.  Users can turn off validation using this flag.
148      */
149     private boolean validateExpressions = true;
150 
151     /**
152      * Generic string/string map of properties in addition to standard Mule props.
153      * Used as an extension point e.g. in MMC.
154      */
155     private Map<String, String> extendedProperties = new HashMap<String, String>();
156 
157     public DefaultMuleConfiguration()
158     {
159         this(false);
160     }
161 
162     public DefaultMuleConfiguration(boolean containerMode)  
163     {
164         this.containerMode = containerMode;
165         
166         // Apply any settings which come from the JVM system properties.
167         applySystemProperties();
168         
169         if (id == null)
170         {
171             id = UUID.getUUID();
172         }
173 
174         if (domainId == null)
175         {
176             try
177             {
178                 domainId = InetAddress.getLocalHost().getHostName();
179             }
180             catch (UnknownHostException e)
181             {
182                 logger.warn(e);
183                 domainId = "org.mule";
184             }
185         }
186         
187         try
188         {
189             validateEncoding();
190             validateXML();
191         }
192         catch (FatalException e)
193         {
194             throw new RuntimeException(e);
195         }
196     }
197 
198     public void setMuleContext(MuleContext context)
199     {
200         this.muleContext = context;
201         if (containerMode)
202         {
203             final String muleHome = System.getProperty("mule.home");
204             // in container mode the id is the app name, have each app isolate its work dir
205             if (!isStandalone()) {
206                 // fallback to current dir as a parent
207                 this.workingDirectory = String.format("%s/%s", getWorkingDirectory(), getId());
208             }
209             else
210             {
211                 this.workingDirectory = String.format("%s/%s/%s", muleHome.trim(), getWorkingDirectory(), getId());
212             }
213         }
214         else if (isStandalone())
215         {
216             this.workingDirectory = String.format("%s/%s", getWorkingDirectory(), getId());
217         }
218     }
219 
220     /**
221      * Apply any settings which come from the JVM system properties.
222      */
223     protected void applySystemProperties() 
224     {
225         String p;
226         
227         p = System.getProperty(MuleProperties.MULE_ENCODING_SYSTEM_PROPERTY);
228         if (p != null)
229         {
230             encoding = p;
231         }
232         else
233         {
234             System.setProperty(MuleProperties.MULE_ENCODING_SYSTEM_PROPERTY, encoding);
235         }
236         p = System.getProperty(MuleProperties.SYSTEM_PROPERTY_PREFIX + "endpoints.synchronous");
237         if (p != null)
238         {
239             synchronous = BooleanUtils.toBoolean(p);
240         }
241         p = System.getProperty(MuleProperties.SYSTEM_PROPERTY_PREFIX + "systemModelType");
242         if (p != null)
243         {
244             systemModelType = p;
245         }
246         p = System.getProperty(MuleProperties.SYSTEM_PROPERTY_PREFIX + "timeout.synchronous");
247         if (p != null)
248         {
249             responseTimeout = NumberUtils.toInt(p);
250         }
251         p = System.getProperty(MuleProperties.SYSTEM_PROPERTY_PREFIX + "timeout.transaction");
252         if (p != null)
253         {
254             defaultTransactionTimeout = NumberUtils.toInt(p);
255         }
256 
257         p = System.getProperty(MuleProperties.SYSTEM_PROPERTY_PREFIX + "workingDirectory");
258         if (p != null)
259         {
260             workingDirectory = p;
261         }
262         p = System.getProperty(MuleProperties.SYSTEM_PROPERTY_PREFIX + "clientMode");
263         if (p != null)
264         {
265             clientMode = BooleanUtils.toBoolean(p);
266         }
267         p = System.getProperty(MuleProperties.SYSTEM_PROPERTY_PREFIX + "serverId");
268         if (p != null)
269         {
270             id = p;
271         }
272         p = System.getProperty(MuleProperties.SYSTEM_PROPERTY_PREFIX + "domainId");
273         if (p != null)
274         {
275             domainId = p;
276         }
277         p = System.getProperty(MuleProperties.SYSTEM_PROPERTY_PREFIX + "message.cacheBytes");
278         if (p != null)
279         {
280             cacheMessageAsBytes = BooleanUtils.toBoolean(p);
281         }
282         p = System.getProperty(MuleProperties.SYSTEM_PROPERTY_PREFIX + "message.cacheOriginal");
283         if (p != null)
284         {
285             cacheMessageOriginalPayload = BooleanUtils.toBoolean(p);
286         }
287         p = System.getProperty(MuleProperties.SYSTEM_PROPERTY_PREFIX + "streaming.enable");
288         if (p != null)
289         {
290             enableStreaming = BooleanUtils.toBoolean(p);
291         }
292         p = System.getProperty(MuleProperties.SYSTEM_PROPERTY_PREFIX + "transform.autoWrap");
293         if (p != null)
294         {
295             autoWrapMessageAwareTransform = BooleanUtils.toBoolean(p);
296         }
297         p = System.getProperty(MuleProperties.SYSTEM_PROPERTY_PREFIX + "stacktrace.full");
298         if (p != null)
299         {
300             fullStackTraces = false;
301         }
302         p = System.getProperty(MuleProperties.SYSTEM_PROPERTY_PREFIX + "stacktrace.filter");
303         if (p != null)
304         {
305             stackTraceFilter = p.split(",");
306         }
307 
308         p = System.getProperty(MuleProperties.SYSTEM_PROPERTY_PREFIX + "verbose.exceptions");
309         if (p != null)
310         {
311             verboseExceptions = BooleanUtils.toBoolean(p);
312         }
313         else
314         {
315             verboseExceptions = logger.isDebugEnabled();
316         }
317 
318         p = System.getProperty(MuleProperties.SYSTEM_PROPERTY_PREFIX + "validate.expressions");
319         if (p != null)
320         {
321             validateExpressions = Boolean.valueOf(p);
322         }
323     }
324 
325     protected void validateEncoding() throws FatalException
326     {
327         //Check we have a valid and supported encoding
328         if (!Charset.isSupported(encoding))
329         {
330             throw new FatalException(CoreMessages.propertyHasInvalidValue("encoding", encoding), this);
331         }
332     }
333 
334     /**
335      * Mule needs a proper JAXP implementation and will complain when run with a plain JDK
336      * 1.4. Use the supplied launcher or specify a proper JAXP implementation via
337      * <code>-Djava.endorsed.dirs</code>. See the following URLs for more information:
338      * <ul>
339      * <li><a href="http://xerces.apache.org/xerces2-j/faq-general.html#faq-4">Xerces</a>
340      * <li><a href="http://xml.apache.org/xalan-j/faq.html#faq-N100D6">Xalan</a>
341      * <li><a href="http://java.sun.com/j2se/1.4.2/docs/guide/standards/">Endorsed Standards Override Mechanism</a>
342      * </ul>
343      */
344     protected void validateXML() throws FatalException
345     {
346         SAXParserFactory f = SAXParserFactory.newInstance();
347         if (f == null || f.getClass().getName().indexOf("crimson") != -1)
348         {
349             throw new FatalException(CoreMessages.valueIsInvalidFor(f.getClass().getName(),
350                 "javax.xml.parsers.SAXParserFactory"), this);
351         }
352     }
353 
354     public void setDefaultSynchronousEndpoints(boolean synchronous)
355     {
356         if (verifyContextNotStarted())
357         {
358             this.synchronous = synchronous;
359         }
360     }
361 
362     public int getDefaultResponseTimeout()
363     {
364         return responseTimeout;
365     }
366 
367     public void setDefaultResponseTimeout(int responseTimeout)
368     {
369         if (verifyContextNotStarted())
370         {
371             this.responseTimeout = responseTimeout;
372         }
373     }
374 
375     public String getWorkingDirectory()
376     {
377         return workingDirectory;
378     }
379 
380     public String getMuleHomeDirectory()
381     {
382         return System.getProperty(MuleProperties.MULE_HOME_DIRECTORY_PROPERTY);
383     }
384 
385     public void setWorkingDirectory(String workingDirectory)
386     {
387         if (verifyContextNotInitialized())
388         {
389             try
390             {
391                 File canonicalFile = FileUtils.openDirectory(workingDirectory);
392                 this.workingDirectory = canonicalFile.getCanonicalPath();
393             }
394             catch (IOException e)
395             {
396                 throw new IllegalArgumentException(CoreMessages.initialisationFailure(
397                     "Invalid working directory").getMessage(), e);
398             }
399         }
400     }
401 
402     public int getDefaultTransactionTimeout()
403     {
404         return defaultTransactionTimeout;
405     }
406 
407     public void setDefaultTransactionTimeout(int defaultTransactionTimeout)
408     {
409         if (verifyContextNotStarted())
410         {
411             this.defaultTransactionTimeout = defaultTransactionTimeout;
412         }
413     }
414 
415 
416     public boolean isValidateExpressions()
417     {
418         return validateExpressions;
419     }
420 
421     public boolean isClientMode()
422     {
423         return clientMode;
424     }
425 
426     public String getDefaultEncoding()
427     {
428         return encoding;
429     }
430 
431     public void setDefaultEncoding(String encoding)
432     {
433         if (verifyContextNotInitialized())
434         {
435             this.encoding = encoding;
436         }
437     }
438 
439     public String getId()
440     {
441         return id;
442     }
443 
444     public void setId(String id)
445     {
446         if (verifyContextNotInitialized())
447         {
448             if (StringUtils.isBlank(id))
449             {
450                 throw new IllegalArgumentException("Cannot set server id to null/blank");
451             }
452             this.id = id;
453         }
454     }
455 
456     public void setClusterId(String clusterId)
457     {
458         this.clusterId = clusterId;
459     }
460 
461     public String getDomainId()
462     {
463         return domainId;
464     }
465 
466     public void setDomainId(String domainId)
467     {
468         if (verifyContextNotInitialized())
469         {
470             this.domainId = domainId;
471         }
472     }
473 
474     public String getSystemModelType()
475     {
476         return systemModelType;
477     }
478 
479     public void setSystemModelType(String systemModelType)
480     {
481         if (verifyContextNotStarted())
482         {
483             this.systemModelType = systemModelType;
484         }
485     }
486 
487     public void setClientMode(boolean clientMode)
488     {
489         if (verifyContextNotStarted())
490         {
491             this.clientMode = clientMode;
492         }
493     }
494 
495     public String getSystemName()
496     {
497         return domainId + "." + clusterId + "." + id;
498     }
499     
500     public boolean isAutoWrapMessageAwareTransform()
501     {
502         return autoWrapMessageAwareTransform;
503     }
504 
505     public void setAutoWrapMessageAwareTransform(boolean autoWrapMessageAwareTransform)
506     {
507         if (verifyContextNotStarted())
508         {
509             this.autoWrapMessageAwareTransform = autoWrapMessageAwareTransform;
510         }
511     }
512 
513     public boolean isCacheMessageAsBytes()
514     {
515         return cacheMessageAsBytes;
516     }
517 
518     public void setCacheMessageAsBytes(boolean cacheMessageAsBytes)
519     {
520         if (verifyContextNotStarted())
521         {
522             this.cacheMessageAsBytes = cacheMessageAsBytes;
523         }
524     }
525 
526     public boolean isCacheMessageOriginalPayload()
527     {
528         return cacheMessageOriginalPayload;
529     }
530 
531     public void setCacheMessageOriginalPayload(boolean cacheMessageOriginalPayload)
532     {
533         if (verifyContextNotStarted())
534         {
535             this.cacheMessageOriginalPayload = cacheMessageOriginalPayload;
536         }
537     }
538 
539     public boolean isEnableStreaming()
540     {
541         return enableStreaming;
542     }
543 
544     public void setEnableStreaming(boolean enableStreaming)
545     {
546         if (verifyContextNotStarted())
547         {
548             this.enableStreaming = enableStreaming;
549         }
550     }
551 
552     protected boolean verifyContextNotInitialized()
553     {
554         if (muleContext != null && muleContext.getLifecycleManager().isPhaseComplete(Initialisable.PHASE_NAME))
555         {
556             logger.warn("Cannot modify MuleConfiguration once the MuleContext has been initialized.  Modification will be ignored.");
557             return false;
558         }
559         else
560         {
561             return true;
562         }
563     }
564     
565     protected boolean verifyContextNotStarted()
566     {
567         if (muleContext != null && muleContext.getLifecycleManager().isPhaseComplete(Startable.PHASE_NAME))
568         {
569             logger.warn("Cannot modify MuleConfiguration once the MuleContext has been started.  Modification will be ignored.");
570             return false;
571         }
572         else
573         {
574             return true;
575         }
576     }
577 
578     public int getDefaultQueueTimeout()
579     {
580         return defaultQueueTimeout;
581     }
582 
583     public void setDefaultQueueTimeout(int defaultQueueTimeout)
584     {
585         if (verifyContextNotStarted())
586         {
587             this.defaultQueueTimeout = defaultQueueTimeout;
588         }
589     }
590 
591     public int getShutdownTimeout()
592     {
593         return shutdownTimeout;
594     }
595 
596     public void setShutdownTimeout(int shutdownTimeout)
597     {
598         if (verifyContextNotStarted())
599         {
600             this.shutdownTimeout = shutdownTimeout;
601         }
602     }
603 
604     public boolean isContainerMode()
605     {
606         return this.containerMode;
607     }
608 
609     /**
610      * The setting is only editable before the context has been initialized, change requests ignored afterwards.
611      */
612     public void setContainerMode(boolean containerMode)
613     {
614         if (verifyContextNotInitialized())
615         {
616             this.containerMode = containerMode;
617         }
618     }
619 
620     public boolean isStandalone()
621     {
622         // this is our best guess
623         return getMuleHomeDirectory() != null;
624     }
625 
626     public Map<String, String> getExtendedProperties()
627     {
628         return extendedProperties;
629     }
630 
631     public void setExtendedProperties(Map<String, String> extendedProperties)
632     {
633         this.extendedProperties = extendedProperties;
634     }
635 
636     public void setExtendedProperty(String name, String value)
637     {
638         this.extendedProperties.put(name, value);
639     }
640 
641     public String getExtendedProperty(String name)
642     {
643         return this.extendedProperties.get(name);
644     }
645 
646     @Override
647     public int hashCode()
648     {
649         final int prime = 31;
650         int result = 1;
651         result = prime * result + (autoWrapMessageAwareTransform ? 1231 : 1237);
652         result = prime * result + (cacheMessageAsBytes ? 1231 : 1237);
653         result = prime * result + (cacheMessageOriginalPayload ? 1231 : 1237);
654         result = prime * result + (clientMode ? 1231 : 1237);
655         result = prime * result + defaultQueueTimeout;
656         result = prime * result + defaultTransactionTimeout;
657         result = prime * result + ((domainId == null) ? 0 : domainId.hashCode());
658         result = prime * result + (enableStreaming ? 1231 : 1237);
659         result = prime * result + ((encoding == null) ? 0 : encoding.hashCode());
660         result = prime * result + ((id == null) ? 0 : id.hashCode());
661         result = prime * result + responseTimeout;
662         result = prime * result + shutdownTimeout;
663         result = prime * result + (synchronous ? 1231 : 1237);
664         result = prime * result + ((systemModelType == null) ? 0 : systemModelType.hashCode());
665         result = prime * result + ((workingDirectory == null) ? 0 : workingDirectory.hashCode());
666         result = prime * result + (containerMode ? 1231 : 1237);
667         return result;
668     }
669 
670     @Override
671     public boolean equals(Object obj)
672     {
673         if (this == obj) return true;
674         if (obj == null) return false;
675         if (getClass() != obj.getClass()) return false;
676         DefaultMuleConfiguration other = (DefaultMuleConfiguration) obj;
677         if (autoWrapMessageAwareTransform != other.autoWrapMessageAwareTransform) return false;
678         if (cacheMessageAsBytes != other.cacheMessageAsBytes) return false;
679         if (cacheMessageOriginalPayload != other.cacheMessageOriginalPayload) return false;
680         if (clientMode != other.clientMode) return false;
681         if (defaultQueueTimeout != other.defaultQueueTimeout) return false;
682         if (defaultTransactionTimeout != other.defaultTransactionTimeout) return false;
683         if (domainId == null)
684         {
685             if (other.domainId != null) return false;
686         }
687         else if (!domainId.equals(other.domainId)) return false;
688         if (enableStreaming != other.enableStreaming) return false;
689         if (encoding == null)
690         {
691             if (other.encoding != null) return false;
692         }
693         else if (!encoding.equals(other.encoding)) return false;
694         if (id == null)
695         {
696             if (other.id != null) return false;
697         }
698         else if (!id.equals(other.id)) return false;
699         if (responseTimeout != other.responseTimeout) return false;
700         if (shutdownTimeout != other.shutdownTimeout) return false;
701         if (synchronous != other.synchronous) return false;
702         if (systemModelType == null)
703         {
704             if (other.systemModelType != null) return false;
705         }
706         else if (!systemModelType.equals(other.systemModelType)) return false;
707         if (workingDirectory == null)
708         {
709             if (other.workingDirectory != null) return false;
710         }
711         else if (!workingDirectory.equals(other.workingDirectory)) return false;
712 
713         if (containerMode != other.containerMode) return false;
714 
715         return true;
716     }
717 
718 }