View Javadoc

1   /*
2    * $Id: DefaultMuleConfiguration.java 20570 2010-12-09 20:04:42Z aperepel $
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 org.apache.commons.lang.BooleanUtils;
27  import org.apache.commons.logging.Log;
28  import org.apache.commons.logging.LogFactory;
29  
30  import java.net.InetAddress;
31  import java.net.UnknownHostException;
32  import java.nio.charset.Charset;
33  
34  import javax.xml.parsers.SAXParserFactory;
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.chain")
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) in the {@link #setMuleContext} callback.
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             final String muleHome = System.getProperty("mule.home");
200             // in container mode the id is the app name, have each app isolate its work dir
201             if (StringUtils.isBlank(muleHome)) {
202                 // fallback to current dir as a parent
203                 this.workingDirectory = String.format("%s/%s", getWorkingDirectory(), getId());
204             }
205             else
206             {
207                 this.workingDirectory = String.format("%s/%s/%s", muleHome.trim(), getWorkingDirectory(), getId());
208             }
209         }
210     }
211 
212     /**
213      * Apply any settings which come from the JVM system properties.
214      */
215     protected void applySystemProperties() 
216     {
217         String p;
218         
219         p = System.getProperty(MuleProperties.MULE_ENCODING_SYSTEM_PROPERTY);
220         if (p != null)
221         {
222             encoding = p;
223         }
224         else
225         {
226             System.setProperty(MuleProperties.MULE_ENCODING_SYSTEM_PROPERTY, encoding);
227         }
228         p = System.getProperty(MuleProperties.SYSTEM_PROPERTY_PREFIX + "endpoints.synchronous");
229         if (p != null)
230         {
231             synchronous = BooleanUtils.toBoolean(p);
232         }
233         p = System.getProperty(MuleProperties.SYSTEM_PROPERTY_PREFIX + "systemModelType");
234         if (p != null)
235         {
236             systemModelType = p;
237         }
238         p = System.getProperty(MuleProperties.SYSTEM_PROPERTY_PREFIX + "timeout.synchronous");
239         if (p != null)
240         {
241             responseTimeout = NumberUtils.toInt(p);
242         }
243         p = System.getProperty(MuleProperties.SYSTEM_PROPERTY_PREFIX + "timeout.transaction");
244         if (p != null)
245         {
246             defaultTransactionTimeout = NumberUtils.toInt(p);
247         }
248 
249         p = System.getProperty(MuleProperties.SYSTEM_PROPERTY_PREFIX + "workingDirectory");
250         if (p != null)
251         {
252             workingDirectory = p;
253         }
254         p = System.getProperty(MuleProperties.SYSTEM_PROPERTY_PREFIX + "clientMode");
255         if (p != null)
256         {
257             clientMode = BooleanUtils.toBoolean(p);
258         }
259         p = System.getProperty(MuleProperties.SYSTEM_PROPERTY_PREFIX + "serverId");
260         if (p != null)
261         {
262             id = p;
263         }
264         p = System.getProperty(MuleProperties.SYSTEM_PROPERTY_PREFIX + "clusterId");
265         if (p != null)
266         {
267             clusterId = p;
268         }
269         p = System.getProperty(MuleProperties.SYSTEM_PROPERTY_PREFIX + "domainId");
270         if (p != null)
271         {
272             domainId = p;
273         }
274         p = System.getProperty(MuleProperties.SYSTEM_PROPERTY_PREFIX + "message.cacheBytes");
275         if (p != null)
276         {
277             cacheMessageAsBytes = BooleanUtils.toBoolean(p);
278         }
279         p = System.getProperty(MuleProperties.SYSTEM_PROPERTY_PREFIX + "message.cacheOriginal");
280         if (p != null)
281         {
282             cacheMessageOriginalPayload = BooleanUtils.toBoolean(p);
283         }
284         p = System.getProperty(MuleProperties.SYSTEM_PROPERTY_PREFIX + "streaming.enable");
285         if (p != null)
286         {
287             enableStreaming = BooleanUtils.toBoolean(p);
288         }
289         p = System.getProperty(MuleProperties.SYSTEM_PROPERTY_PREFIX + "transform.autoWrap");
290         if (p != null)
291         {
292             autoWrapMessageAwareTransform = BooleanUtils.toBoolean(p);
293         }
294         p = System.getProperty(MuleProperties.SYSTEM_PROPERTY_PREFIX + "stacktrace.full");
295         if (p != null)
296         {
297             fullStackTraces = false;
298         }
299         p = System.getProperty(MuleProperties.SYSTEM_PROPERTY_PREFIX + "stacktrace.filter");
300         if (p != null)
301         {
302             stackTraceFilter = p.split(",");
303         }
304 
305         p = System.getProperty(MuleProperties.SYSTEM_PROPERTY_PREFIX + "verbose.exceptions");
306         if (p != null)
307         {
308             verboseExceptions = BooleanUtils.toBoolean(p);
309         }
310         else
311         {
312             verboseExceptions = logger.isDebugEnabled();
313         }
314 
315         p = System.getProperty(MuleProperties.SYSTEM_PROPERTY_PREFIX + "validate.expressions");
316         if (p != null)
317         {
318             validateExpressions = Boolean.valueOf(p);
319         }
320     }
321 
322     protected void validateEncoding() throws FatalException
323     {
324         //Check we have a valid and supported encoding
325         if (!Charset.isSupported(encoding))
326         {
327             throw new FatalException(CoreMessages.propertyHasInvalidValue("encoding", encoding), this);
328         }
329     }
330 
331     /**
332      * Mule needs a proper JAXP implementation and will complain when run with a plain JDK
333      * 1.4. Use the supplied launcher or specify a proper JAXP implementation via
334      * <code>-Djava.endorsed.dirs</code>. See the following URLs for more information:
335      * <ul>
336      * <li><a href="http://xerces.apache.org/xerces2-j/faq-general.html#faq-4">Xerces</a>
337      * <li><a href="http://xml.apache.org/xalan-j/faq.html#faq-N100D6">Xalan</a>
338      * <li><a href="http://java.sun.com/j2se/1.4.2/docs/guide/standards/">Endorsed Standards Override Mechanism</a>
339      * </ul>
340      */
341     protected void validateXML() throws FatalException
342     {
343         SAXParserFactory f = SAXParserFactory.newInstance();
344         if (f == null || f.getClass().getName().indexOf("crimson") != -1)
345         {
346             throw new FatalException(CoreMessages.valueIsInvalidFor(f.getClass().getName(),
347                 "javax.xml.parsers.SAXParserFactory"), this);
348         }
349     }
350 
351     public void setDefaultSynchronousEndpoints(boolean synchronous)
352     {
353         if (verifyContextNotStarted())
354         {
355             this.synchronous = synchronous;
356         }
357     }
358 
359     public int getDefaultResponseTimeout()
360     {
361         return responseTimeout;
362     }
363 
364     public void setDefaultResponseTimeout(int responseTimeout)
365     {
366         if (verifyContextNotStarted())
367         {
368             this.responseTimeout = responseTimeout;
369         }
370     }
371 
372     public String getWorkingDirectory()
373     {
374         return workingDirectory;
375     }
376 
377     public String getMuleHomeDirectory()
378     {
379         return System.getProperty(MuleProperties.MULE_HOME_DIRECTORY_PROPERTY);
380     }
381 
382     public void setWorkingDirectory(String workingDirectory)
383     {
384         if (verifyContextNotInitialized())
385         {
386             // fix windows backslashes in absolute paths, convert them to forward ones
387             this.workingDirectory = FileUtils.newFile(workingDirectory).getAbsolutePath().replaceAll("\\\\", "/");
388         }
389     }
390 
391     public int getDefaultTransactionTimeout()
392     {
393         return defaultTransactionTimeout;
394     }
395 
396     public void setDefaultTransactionTimeout(int defaultTransactionTimeout)
397     {
398         if (verifyContextNotStarted())
399         {
400             this.defaultTransactionTimeout = defaultTransactionTimeout;
401         }
402     }
403 
404 
405     public boolean isValidateExpressions()
406     {
407         return validateExpressions;
408     }
409 
410     public boolean isClientMode()
411     {
412         return clientMode;
413     }
414 
415     public String getDefaultEncoding()
416     {
417         return encoding;
418     }
419 
420     public void setDefaultEncoding(String encoding)
421     {
422         if (verifyContextNotInitialized())
423         {
424             this.encoding = encoding;
425         }
426     }
427 
428     public String getId()
429     {
430         return id;
431     }
432 
433     public void setId(String id)
434     {
435         if (verifyContextNotInitialized())
436         {
437             if (StringUtils.isBlank(id))
438             {
439                 throw new IllegalArgumentException("Cannot set server id to null/blank");
440             }
441             this.id = id;
442         }
443     }
444 
445     public String getClusterId()
446     {
447         return clusterId;
448     }
449 
450     public void setClusterId(String clusterId)
451     {
452         if (verifyContextNotInitialized())
453         {
454             this.clusterId = clusterId;
455         }
456     }
457 
458     public String getDomainId()
459     {
460         return domainId;
461     }
462 
463     public void setDomainId(String domainId)
464     {
465         if (verifyContextNotInitialized())
466         {
467             this.domainId = domainId;
468         }
469     }
470 
471     public String getSystemModelType()
472     {
473         return systemModelType;
474     }
475 
476     public void setSystemModelType(String systemModelType)
477     {
478         if (verifyContextNotStarted())
479         {
480             this.systemModelType = systemModelType;
481         }
482     }
483 
484     public void setClientMode(boolean clientMode)
485     {
486         if (verifyContextNotStarted())
487         {
488             this.clientMode = clientMode;
489         }
490     }
491 
492     public String getSystemName()
493     {
494         return domainId + "." + clusterId + "." + id;
495     }
496     
497     public boolean isAutoWrapMessageAwareTransform()
498     {
499         return autoWrapMessageAwareTransform;
500     }
501 
502     public void setAutoWrapMessageAwareTransform(boolean autoWrapMessageAwareTransform)
503     {
504         if (verifyContextNotStarted())
505         {
506             this.autoWrapMessageAwareTransform = autoWrapMessageAwareTransform;
507         }
508     }
509 
510     public boolean isCacheMessageAsBytes()
511     {
512         return cacheMessageAsBytes;
513     }
514 
515     public void setCacheMessageAsBytes(boolean cacheMessageAsBytes)
516     {
517         if (verifyContextNotStarted())
518         {
519             this.cacheMessageAsBytes = cacheMessageAsBytes;
520         }
521     }
522 
523     public boolean isCacheMessageOriginalPayload()
524     {
525         return cacheMessageOriginalPayload;
526     }
527 
528     public void setCacheMessageOriginalPayload(boolean cacheMessageOriginalPayload)
529     {
530         if (verifyContextNotStarted())
531         {
532             this.cacheMessageOriginalPayload = cacheMessageOriginalPayload;
533         }
534     }
535 
536     public boolean isEnableStreaming()
537     {
538         return enableStreaming;
539     }
540 
541     public void setEnableStreaming(boolean enableStreaming)
542     {
543         if (verifyContextNotStarted())
544         {
545             this.enableStreaming = enableStreaming;
546         }
547     }
548 
549     protected boolean verifyContextNotInitialized()
550     {
551         if (muleContext != null && muleContext.getLifecycleManager().isPhaseComplete(Initialisable.PHASE_NAME))
552         {
553             logger.warn("Cannot modify MuleConfiguration once the MuleContext has been initialized.  Modification will be ignored.");
554             return false;
555         }
556         else
557         {
558             return true;
559         }
560     }
561     
562     protected boolean verifyContextNotStarted()
563     {
564         if (muleContext != null && muleContext.getLifecycleManager().isPhaseComplete(Startable.PHASE_NAME))
565         {
566             logger.warn("Cannot modify MuleConfiguration once the MuleContext has been started.  Modification will be ignored.");
567             return false;
568         }
569         else
570         {
571             return true;
572         }
573     }
574 
575     public int getDefaultQueueTimeout()
576     {
577         return defaultQueueTimeout;
578     }
579 
580     public void setDefaultQueueTimeout(int defaultQueueTimeout)
581     {
582         if (verifyContextNotStarted())
583         {
584             this.defaultQueueTimeout = defaultQueueTimeout;
585         }
586     }
587 
588     public int getShutdownTimeout()
589     {
590         return shutdownTimeout;
591     }
592 
593     public void setShutdownTimeout(int shutdownTimeout)
594     {
595         if (verifyContextNotStarted())
596         {
597             this.shutdownTimeout = shutdownTimeout;
598         }
599     }
600 
601     public boolean isContainerMode()
602     {
603         return this.containerMode;
604     }
605 
606     @Override
607     public int hashCode()
608     {
609         final int prime = 31;
610         int result = 1;
611         result = prime * result + (autoWrapMessageAwareTransform ? 1231 : 1237);
612         result = prime * result + (cacheMessageAsBytes ? 1231 : 1237);
613         result = prime * result + (cacheMessageOriginalPayload ? 1231 : 1237);
614         result = prime * result + (clientMode ? 1231 : 1237);
615         result = prime * result + ((clusterId == null) ? 0 : clusterId.hashCode());
616         result = prime * result + defaultQueueTimeout;
617         result = prime * result + defaultTransactionTimeout;
618         result = prime * result + ((domainId == null) ? 0 : domainId.hashCode());
619         result = prime * result + (enableStreaming ? 1231 : 1237);
620         result = prime * result + ((encoding == null) ? 0 : encoding.hashCode());
621         result = prime * result + ((id == null) ? 0 : id.hashCode());
622         result = prime * result + responseTimeout;
623         result = prime * result + shutdownTimeout;
624         result = prime * result + (synchronous ? 1231 : 1237);
625         result = prime * result + ((systemModelType == null) ? 0 : systemModelType.hashCode());
626         result = prime * result + ((workingDirectory == null) ? 0 : workingDirectory.hashCode());
627         result = prime * result + (containerMode ? 1231 : 1237);
628         return result;
629     }
630 
631     @Override
632     public boolean equals(Object obj)
633     {
634         if (this == obj) return true;
635         if (obj == null) return false;
636         if (getClass() != obj.getClass()) return false;
637         DefaultMuleConfiguration other = (DefaultMuleConfiguration) obj;
638         if (autoWrapMessageAwareTransform != other.autoWrapMessageAwareTransform) return false;
639         if (cacheMessageAsBytes != other.cacheMessageAsBytes) return false;
640         if (cacheMessageOriginalPayload != other.cacheMessageOriginalPayload) return false;
641         if (clientMode != other.clientMode) return false;
642         if (clusterId == null)
643         {
644             if (other.clusterId != null) return false;
645         }
646         else if (!clusterId.equals(other.clusterId)) return false;
647         if (defaultQueueTimeout != other.defaultQueueTimeout) return false;
648         if (defaultTransactionTimeout != other.defaultTransactionTimeout) return false;
649         if (domainId == null)
650         {
651             if (other.domainId != null) return false;
652         }
653         else if (!domainId.equals(other.domainId)) return false;
654         if (enableStreaming != other.enableStreaming) return false;
655         if (encoding == null)
656         {
657             if (other.encoding != null) return false;
658         }
659         else if (!encoding.equals(other.encoding)) return false;
660         if (id == null)
661         {
662             if (other.id != null) return false;
663         }
664         else if (!id.equals(other.id)) return false;
665         if (responseTimeout != other.responseTimeout) return false;
666         if (shutdownTimeout != other.shutdownTimeout) return false;
667         if (synchronous != other.synchronous) return false;
668         if (systemModelType == null)
669         {
670             if (other.systemModelType != null) return false;
671         }
672         else if (!systemModelType.equals(other.systemModelType)) return false;
673         if (workingDirectory == null)
674         {
675             if (other.workingDirectory != null) return false;
676         }
677         else if (!workingDirectory.equals(other.workingDirectory)) return false;
678 
679         if (containerMode != other.containerMode) return false;
680 
681         return true;
682     }
683 
684 }