View Javadoc

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