-
Notifications
You must be signed in to change notification settings - Fork 14
Expand file tree
/
Copy pathRvdConfiguration.java
More file actions
388 lines (349 loc) · 17.2 KB
/
RvdConfiguration.java
File metadata and controls
388 lines (349 loc) · 17.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
package org.restcomm.connect.rvd;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import javax.servlet.ServletContext;
import org.restcomm.connect.rvd.commons.http.SslMode;
import org.restcomm.connect.rvd.configuration.CustomIntegerConverter;
import org.restcomm.connect.rvd.configuration.RestcommConfig;
import org.restcomm.connect.rvd.exceptions.RestcommConfigNotFound;
import org.restcomm.connect.rvd.exceptions.RestcommConfigurationException;
import org.restcomm.connect.rvd.exceptions.XmlParserException;
import org.restcomm.connect.rvd.http.utils.UriUtils;
import org.restcomm.connect.rvd.logging.system.LoggingHelper;
import org.restcomm.connect.rvd.logging.system.RvdLoggers;
import org.restcomm.connect.rvd.configuration.RvdConfig;
import org.restcomm.connect.rvd.utils.RvdUtils;
import com.thoughtworks.xstream.XStream;
import org.restcomm.connect.rvd.utils.XmlParser;
/**
* Configuration settings for RVD. Contains both static hardcoded and loaded values.
*
* Besides hardcoded values, information form rvd.xml as well as proxied values from restcomm.xml
* are contained. It also provides vary basic logic so that default values are returned too.
* For example if 'videoSupport' configuration option is missing, it will return false (and not null).
*
* rvd.xml and restcomm.xml configuration options are applied in the following way:
*
* restcomm.xml based will be loaded first if available. Any option defined in rvd.xml will override
* these values if the option is defined (i.e.the XML element is there even if empty).
*
* @author otsakir@gmail.com - Orestis Tsakiridis
*/
public class RvdConfiguration {
static Logger logger = RvdLoggers.local;
// these defaults are used when there are no values defined in the configuration files
public static final SslMode DEFAULT_SSL_MODE = SslMode.strict;
public static final boolean DEFAULT_USE_HOSTNAME_TO_RESOLVE_RELATIVE_URL = true;
public static final boolean DEFAULT_USE_ABSOLUTE_APPLICATION_URL = false;
public static final boolean DEFAULT_USSD_SUPPORT = true;
public static final String DEFAULT_WELCOME_MESSAGE = "Welcome to Telestax Restcom Visual Designer Demo";
private static final String WORKSPACE_DIRECTORY_NAME = "workspace";
public static final String PROTO_DIRECTORY_PREFIX = "_proto";
public static final String REST_SERVICES_PATH = "services"; // the "services" from the /restcomm-rvd/services/apps/... path
public static final String USERS_DIRECTORY_NAME = "@users";
public static final String WAVS_DIRECTORY_NAME = "wavs";
private static final String RVD_PROJECT_VERSION = "1.12"; // version for rvd project syntax
private static final String PACKAGING_VERSION = "1.0";
private static final String RAS_APPLICATION_VERSION = "2"; // version of the RAS application specification
public static final String STICKY_PREFIX = "sticky_"; // a prefix for rvd sticky variable names
public static final String MODULE_PREFIX = "module_"; // a prefix for rvd module-scoped variable names
public static final String CORE_VARIABLE_PREFIX = "core_"; // a prefix for rvd variables that come from Restcomm parameters
public static final String PACKAGING_DIRECTORY_NAME = "packaging";
// http client (ES)
public static final int DEFAULT_ES_TIMEOUT = 5000; // milliseconds
// application logging
public static final String PROJECT_LOG_FILENAME = "rvdapp"; //will produce rvdapp.log, rvdapp-1.log etc.
public static final int PROJECT_LOG_BACKLOG_COUNT = 3; // the number of rotated files besides the main log file
public static final int PROJECT_LOG_ROTATION_SIZE = 300000;
// App Store
public static final String DEFAULT_APPSTORE_DOMAIN = "apps.restcomm.com";
// the names of the parameters supplied by restcomm request when starting an application
public static final HashSet<String> builtinRestcommParameters = new HashSet<String>(Arrays.asList(new String[]
{"CallSid","AccountSid","From","To","Body","CallStatus","ApiVersion","Direction","CallerName",
"CallTimestamp", "ForwardedFrom", "SmsSid", "SmsStatus", "InstanceId","ReferTarget","Transferor","Transferee"}));
public static final String RESTCOMM_HEADER_PREFIX = "SipHeader_"; // the prefix added to HTTP headers from Restcomm
public static final String RESTCOMM_HEADER_PREFIX_DIAL = "DialSipHeader_"; // another prefix
// File upload
public static final String DEFAULT_MEDIA_ALLOWED_EXTENSIONS = "wav|mp4"; // only allow upload of media files whose name matches this pattern i.e. file extension ends in .wav or .mp4
private Integer maxMediaFileSize; // Maximum size allowed for media file uploads (in bytes). If set to null no limit is enforced
private String workspaceBasePath;
private RvdConfig rvdConfig; // the configuration settings from rvd.xml
private RestcommConfig restcommConfig;
private String contextRootPath; // e.g. a/path/ending/in/slash/
private String contextPath; // e.g. /restcomm-rvd
private URI restcommBaseUri;
private Integer externalServiceTimeout;
private Boolean videoSupport;
private SslMode sslMode;
private String hostnameOverride;
private Boolean useHostnameToResolveRelativeUrl;
private String baseUrl;
private Boolean useAbsoluteApplicationUrl;
private boolean ussdSupport;
// whitelabeling configuration
private String welcomeMessage;
// package-private constructor to be used from RvdConfigurationBuilder
RvdConfiguration() {
}
public RvdConfiguration(ServletContext servletContext) {
this(servletContext.getContextPath(), servletContext.getRealPath("/"));
}
public RvdConfiguration(String contextPath, String contextRootPath) {
this.contextRootPath = RvdUtils.addTrailingSlashIfMissing(contextRootPath);
this.contextPath = contextPath;
logger.info("context filesystem root path is " + this.contextRootPath);
logger.info("context path is " + this.contextPath);
load();
}
public RvdConfiguration(String workspaceBasePath, RvdConfig rvdConfig, RestcommConfig restcommConfig, String contextPath, String contextRootPath, URI restcommBaseUri) {
this.workspaceBasePath = workspaceBasePath;
this.rvdConfig = rvdConfig;
this.restcommConfig = restcommConfig;
this.contextPath = contextPath;
this.contextRootPath = contextRootPath;
this.restcommBaseUri = restcommBaseUri;
}
private void load() {
// load configuration from rvd.xml file
rvdConfig = loadRvdXmlConfig(contextRootPath + "WEB-INF/rvd.xml");
// workspaceBasePath option
String workspaceBasePath = contextRootPath + WORKSPACE_DIRECTORY_NAME;
if (rvdConfig.getWorkspaceLocation() != null && !"".equals(rvdConfig.getWorkspaceLocation()) ) {
if ( rvdConfig.getWorkspaceLocation().startsWith("/") )
workspaceBasePath = rvdConfig.getWorkspaceLocation(); // this is an absolute path
else
workspaceBasePath = contextRootPath + rvdConfig.getWorkspaceLocation(); // this is a relative path hooked under RVD context
}
this.workspaceBasePath = workspaceBasePath;
RvdLoggers.global.info("workspace located under " + workspaceBasePath);
// try load configuration from restcomm.war/.../restcomm.xml file
try {
restcommConfig = loadRestcommXmlConfig(contextRootPath + "../restcomm.war/WEB-INF/conf/restcomm.xml");
} catch (RestcommConfigNotFound e) {
// fallback to local configuration
try {
restcommConfig = loadRestcommXmlConfig(contextRootPath + "WEB-INF/restcomm.xml");
} catch (RestcommConfigNotFound restcommConfigNotFound) {
restcommConfig = null;
logger.log(Level.WARN, "could not load restcomm configuration");
}
}
// video support
this.videoSupport = rvdConfig.getVideoSupport();
// maxMediaFileSize
maxMediaFileSize = rvdConfig.getMaxMediaFileSize();
// sslMode
if (restcommConfig != null)
sslMode = restcommConfig.getSslMode();
if (rvdConfig.getSslMode() != null)
sslMode = SslMode.valueOf(rvdConfig.getSslMode());
if (sslMode == null)
sslMode = DEFAULT_SSL_MODE;
// hostnameOverride (hostname in restcomm.xml)
if (restcommConfig != null)
hostnameOverride = restcommConfig.getHostname();
if (rvdConfig.getHostnameOverride() != null)
hostnameOverride = rvdConfig.getHostnameOverride();
// useHostnameToResolveRelativeUrl
if (restcommConfig != null)
useHostnameToResolveRelativeUrl = restcommConfig.getUseHostnameToResolveRelativeUrl();
if (rvdConfig.getUseHostnameToResolveRelativeUrl() != null)
useHostnameToResolveRelativeUrl = rvdConfig.getUseHostnameToResolveRelativeUrl();
if (useHostnameToResolveRelativeUrl == null)
useHostnameToResolveRelativeUrl = DEFAULT_USE_HOSTNAME_TO_RESOLVE_RELATIVE_URL;
// baseUrl
if (! RvdUtils.isEmpty(rvdConfig.getBaseUrl()) )
baseUrl = rvdConfig.getBaseUrl();
// useAbsoluteApplicationUrl
if (! RvdUtils.isEmpty(rvdConfig.useAbsoluteApplicationUrl()))
useAbsoluteApplicationUrl = rvdConfig.useAbsoluteApplicationUrl();
else
useAbsoluteApplicationUrl = DEFAULT_USE_ABSOLUTE_APPLICATION_URL;
// ussd support
if ( RvdUtils.isEmpty(rvdConfig.getUssdSupport()) )
ussdSupport = DEFAULT_USSD_SUPPORT;
else {
try {
ussdSupport = Boolean.parseBoolean(rvdConfig.getUssdSupport());
} catch ( Exception e) {
ussdSupport = DEFAULT_USSD_SUPPORT;
logger.warn(LoggingHelper.buildMessage(RvdConfiguration.class,"load",null,"Error parsing rvd.xml:ussd/enabled option. Falling back to default: " + ussdSupport),e);
}
}
// load whitelabeling configuration
loadWhitelabelConfig(contextRootPath + "WEB-INF/whitelabel.xml");
}
/**
* Loads rvd.xml into an RvdConfig. Returns null if the file is not found
* @param pathToXml
* @return
*/
public static RvdConfig loadRvdXmlConfig(String pathToXml) {
try {
FileInputStream input = new FileInputStream(pathToXml);
XStream xstream = new XStream();
xstream.alias("rvd", RvdConfig.class);
xstream.omitField(RvdConfig.class, "corsWhitelist");
xstream.omitField(RvdConfig.class, "ussd");
xstream.registerConverter(new CustomIntegerConverter());
RvdConfig rvdConfig = (RvdConfig) xstream.fromXML( input );
// read some more configuration options that xstream fails to read in a clean way
XmlParser xml = new XmlParser(pathToXml);
rvdConfig.setAllowedCorsOrigins(xml.getElementList("/rvd/corsWhitelist/origin"));
rvdConfig.setUssdSupport(xml.getElementContent("/rvd/ussdSupport"));
return rvdConfig;
} catch (FileNotFoundException e) {
logger.warn(LoggingHelper.buildMessage(RvdConfiguration.class,"loadRvdXmlConfig",null,"RVD configuration file not found: " + pathToXml));
return null;
} catch (XmlParserException e) {
logger.warn(LoggingHelper.buildMessage(RvdConfiguration.class,"loadRvdXmlConfig",null,"Error parsing RVD configuration file: " + pathToXml), e);
return null;
}
}
/**
* Load configuration options from restcomm.xml that are needed by RVD. Return null in case of failure.
*
* @param pathToXml
* @return a valid RestcommConfig object or null
*/
private RestcommConfig loadRestcommXmlConfig(String pathToXml) throws RestcommConfigNotFound {
try {
RestcommConfig restcommConfig = new RestcommConfig(pathToXml);
return restcommConfig;
} catch (RestcommConfigNotFound e) {
throw e;
} catch (RestcommConfigurationException e) {
logger.log(Level.ERROR, e.getMessage(), e);
return null;
}
}
private void loadWhitelabelConfig(String pathToXml) {
welcomeMessage = DEFAULT_WELCOME_MESSAGE;
try {
XmlParser xml = new XmlParser(pathToXml);
String value = xml.getElementContent("/whitelabel/welcomeMessage");
if (value != null)
welcomeMessage = value;
logger.info("Loaded whitelabeling information: " + pathToXml);
} catch (XmlParserException e) {
if ( e.getCause() instanceof FileNotFoundException)
logger.info("No whitelabeling file found (" + pathToXml + "). Hardcoded defaults will be used.");
else
logger.error(LoggingHelper.buildMessage(RvdConfiguration.class,"loadWhitelabelConfig",null,"Error parsing whitelabeling configuration file: " + pathToXml), e);
return;
}
}
public String getWorkspaceBasePath() {
return this.workspaceBasePath;
}
public String getProjectBasePath(String projectName) {
return this.workspaceBasePath + File.separator + projectName;
}
public static String getRvdProjectVersion() {
return RVD_PROJECT_VERSION;
}
public static String getPackagingVersion() {
return PACKAGING_VERSION;
}
public static String getRasApplicationVersion() {
return RAS_APPLICATION_VERSION;
}
public static Set<String> getRestcommParameterNames() {
return builtinRestcommParameters;
}
public SslMode getSslMode() {
return sslMode;
}
public Integer getExternalServiceTimeout() {
if (externalServiceTimeout != null)
return externalServiceTimeout;
if (rvdConfig != null && rvdConfig.getExternalServiceTimeout() != null && rvdConfig.getExternalServiceTimeout().trim().length() > 0) {
try {
this.externalServiceTimeout = Integer.parseInt(rvdConfig.getExternalServiceTimeout());
} catch (NumberFormatException e) {
logger.warn(LoggingHelper.buildMessage(getClass(),"getExternalServiceTimeout",null,"Cannot parse RVD ES timeout configuration setting. Will use default: " + DEFAULT_ES_TIMEOUT + (e.getMessage() != null ? " - " + e.getMessage() : "")));
this.externalServiceTimeout = DEFAULT_ES_TIMEOUT;
}
} else {
this.externalServiceTimeout = DEFAULT_ES_TIMEOUT;
}
return this.externalServiceTimeout;
}
public boolean getUseHostnameToResolveRelativeUrl() {
return useHostnameToResolveRelativeUrl;
}
public String getHostnameOverride() {
return hostnameOverride;
}
// this is lazy loaded because HttpConnector enumeration (done in resolve()) fails otherwise
public URI getRestcommBaseUri() {
if (this.restcommBaseUri == null) {
// check rvd.xml override first
String rawUrl = rvdConfig.getRestcommBaseUrl();
if ( ! RvdUtils.isEmpty(rawUrl) ) {
try {
URI uri = new URI(rawUrl);
if ( ! RvdUtils.isEmpty(uri.getScheme()) && !RvdUtils.isEmpty(uri.getHost()) )
this.restcommBaseUri = uri;
} catch (URISyntaxException e) { /* do nothing */}
}
// if no override value in rvd.xml use the automatic way
if (this.restcommBaseUri == null) {
UriUtils uriUtils = new UriUtils(this);
try {
URI uri = new URI("/");
this.restcommBaseUri = uriUtils.resolve(uri);
} catch (URISyntaxException e) { /* we should never reach here */
throw new IllegalStateException();
}
}
logger.info("using restcomm server at " + this.restcommBaseUri.toString());
}
return restcommBaseUri;
}
/*
* Returns a relative url to the base of the application service. Controllers are located under it.
* Currently hardcoded to /restcomm-rvd/services/apps/
*
* @return relative url to the application service
*/
public String getApplicationsRelativeUrl() {
return "/restcomm-rvd/services/apps";
}
// package private setter to be used from RvdConfigurationBuilder only
void setRestcommBaseUri(URI uri) {
this.restcommBaseUri = uri;
}
public Integer getMaxMediaFileSize() {
return maxMediaFileSize;
}
public Boolean getVideoSupport() {
return RvdUtils.isTrue(videoSupport);
}
public RvdConfig getRawRvdConfig() {
return rvdConfig;
}
public String getBaseUrl() {
return baseUrl;
}
public Boolean useAbsoluteApplicationUrl() {
return useAbsoluteApplicationUrl;
}
public String getContextPath() {
return contextPath;
}
public boolean isUssdSupport() {
return ussdSupport;
}
public String getWelcomeMessage() {
return welcomeMessage;
}
}