//<OLATCE-103>
/**
* <a href="http://www.openolat.org">
* OpenOLAT - Online Learning and Training</a><br>
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); <br>
* you may not use this file except in compliance with the License.<br>
* You may obtain a copy of the License at the
* <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
* <p>
* Unless required by applicable law or agreed to in writing,<br>
* software distributed under the License is distributed on an "AS IS" BASIS, <br>
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
* See the License for the specific language governing permissions and <br>
* limitations under the License.
* <p>
* Initial code contributed and copyrighted by<br>
* BPS Bildungsportal Sachsen GmbH, http://www.bps-system.de
* <p>
*/
package de.bps.course.nodes.vc.provider.adobe;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.net.URLConnection;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.ws.rs.core.UriBuilder;
import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import org.apache.commons.lang.NotImplementedException;
import org.olat.core.gui.UserRequest;
import org.olat.core.gui.control.Controller;
import org.olat.core.gui.control.WindowControl;
import org.olat.core.helpers.Settings;
import org.olat.core.id.Identity;
import org.olat.core.id.UserConstants;
import org.olat.core.logging.AssertException;
import org.olat.core.logging.LogDelegator;
import org.olat.core.util.Encoder;
import org.olat.core.util.StringHelper;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import de.bps.course.nodes.vc.VCConfiguration;
import de.bps.course.nodes.vc.provider.VCProvider;
/**
*
* Description:<br>
* Virtual classroom provider for Adobe Connect.
*
* <P>
* Initial Date: 09.12.2010 <br>
* @author skoeber
*/
public class AdobeConnectProvider extends LogDelegator implements VCProvider {
private static final String CONTENT_TYPE = "application/x-www-form-urlencoded";
private static final String COOKIE = "BREEZESESSION=";
protected static final String PREFIX = "olat-";
private static final String DATE_FORMAT = "yyyy-MM-dd'T'HH:mm";
protected static String DEFAULT_TEMPLATE = "default";
// configuration
private static AdobeConnectConfiguration defaultConfig;
private boolean enabled;
private String providerId;
private String displayName;
private String protocol;
private int port;
private String baseUrl;
private String adminLogin;
private String adminPassword;
private String accountId;
private Map<String, String> templates;
private boolean guestAccessAllowedDefault;
private boolean guestStartMeetingAllowedDefault;
private boolean useMeetingDatesDefault;
private boolean showOptions;
private String userType;
// runtime data
private String cookie;
/**
* Constructor for internal use to create new instance
* @param providerId
* @param protocol
* @param port
* @param baseUrl
* @param adminLogin
* @param adminPassword
*/
private AdobeConnectProvider(String providerId, String displayName, String protocol, int port, String baseUrl, String adminLogin, String adminPassword,
String accountId, Map<String, String> templates, boolean guestAccessAllowedDefault, boolean guestStartMeetingAllowedDefault,
boolean showOptions, String userType) {
setProviderId(providerId);
setDisplayName(displayName);
setProtocol(protocol);
setPort(port);
setBaseUrl(baseUrl);
setAdminLogin(adminLogin);
setAdminPassword(adminPassword);
setAccountId(accountId);
setTemplates(templates);
setGuestAccessAllowedDefault(guestAccessAllowedDefault);
setGuestStartMeetingAllowedDefault(guestStartMeetingAllowedDefault);
setShowOptions(showOptions);
setUserType(userType);
}
/**
* Public constructor, mostly used by spring<br/>
* <b>Important</b> when using: set configuration manually!
*/
public AdobeConnectProvider() {
//
}
@Override
public boolean createClassroom(String roomId, String name, String description, Date begin, Date end, VCConfiguration config) {
if(existsClassroom(roomId, config)) return true;
if(!loginAdmin()) {
logError("Cannot login to Adobe Connect. Please check module configuration and Adobe Connect connectivity.", null);
return false;
}
// begin and end can be NULL, see interface description
if(begin == null) begin = new Date();
if(end == null) end = new Date(begin.getTime() + 365*24*60*60*1000); // preset one year
// formatter for begin and end
SimpleDateFormat sd = new SimpleDateFormat(DATE_FORMAT);
// find my-meetings
Map<String, String> parameters = new HashMap<String, String>();
parameters.put("action", "sco-shortcuts");
Document responseDoc = getResponseDocument(sendRequest(parameters));
if(!evaluateOk(responseDoc)) return false;
String folderScoId = null;
// use my-meetings folder
String result = evaluate(responseDoc, "//sco[@type=\"my-meetings\"]");
if(result != null && !result.isEmpty()) {
folderScoId = evaluate(responseDoc, "//sco[@type=\"my-meetings\"]/attribute::sco-id");
}
// my-meetings folder not found, fallback to meetings
if(folderScoId == null) {
result = evaluate(responseDoc, "//sco[@type=\"meetings\"]");
if(result != null && !result.isEmpty()) {
folderScoId = evaluate(responseDoc, "//sco[@type=\"meetings\"]/attribute::sco-id");
}
}
// meetings folder not found, error case
if(folderScoId == null) return false;
// folder found where to insert the new meeting
// create new meeting
parameters = new HashMap<String, String>();
parameters.put("action", "sco-update");
parameters.put("type", "meeting");
parameters.put("name", PREFIX + roomId);
parameters.put("folder-id", folderScoId);
parameters.put("date-begin", sd.format(begin));
parameters.put("date-end", sd.format(end));
parameters.put("url-path", PREFIX + roomId);
String templateId = ((AdobeConnectConfiguration)config).getTemplateKey();
if(templateId != null && !templateId.equals(DEFAULT_TEMPLATE))
parameters.put("source-sco-id", templateId);
responseDoc = getResponseDocument(sendRequest(parameters));
if(!evaluateOk(responseDoc)) return false;
// adjust permissions
String meetingScoId = evaluate(responseDoc, "//sco/attribute::sco-id");
parameters.clear();
parameters.put("action", "permissions-update");
parameters.put("acl-id", meetingScoId);
parameters.put("principal-id", "public-access");
if(((AdobeConnectConfiguration)config).isGuestAccessAllowed())
parameters.put("permission-id", "view-hidden");
else
parameters.put("permission-id", "remove");
responseDoc = getResponseDocument(sendRequest(parameters));
if(!evaluateOk(responseDoc)) return false;
logout();
return true;
}
@Override
public boolean updateClassroom(String roomId, String name, String description, Date begin, Date end, VCConfiguration config) {
if(!existsClassroom(roomId, config)) return false;
if(!loginAdmin()) throw new AssertException("Cannot login to Adobe Connect. Please check module configuration and that Adobe Connect is available.");
String scoId = getScoIdFor(roomId);
if(scoId == null) return false;
// formatter for begin and end
SimpleDateFormat sd = new SimpleDateFormat(DATE_FORMAT);
Map<String, String> parameters = new HashMap<String, String>();
// update meeting configuration
parameters.put("action", "sco-update");
parameters.put("sco-id", scoId);
if(begin != null)
parameters.put("date-begin", sd.format(begin));
if(end != null)
parameters.put("date-end", sd.format(end));
String templateId = ((AdobeConnectConfiguration)config).getTemplateKey();
if(templateId != null && !templateId.equals(DEFAULT_TEMPLATE))
parameters.put("source-sco-id", templateId);
Document responseDoc = getResponseDocument(sendRequest(parameters));
if(!evaluateOk(responseDoc)) return false;
// adjust permissions
parameters.clear();
parameters.put("action", "permissions-update");
parameters.put("acl-id", scoId);
parameters.put("principal-id", "public-access");
if(((AdobeConnectConfiguration)config).isGuestAccessAllowed())
parameters.put("permission-id", "view-hidden");
else
parameters.put("permission-id", "remove");
responseDoc = getResponseDocument(sendRequest(parameters));
if(!evaluateOk(responseDoc)) return false;
logout();
return true;
}
@Override
public boolean removeClassroom(String roomId, VCConfiguration config) {
if(!existsClassroom(roomId, config)) return true;
if(!loginAdmin()) throw new AssertException("Cannot login to Adobe Connect. Please check module configuration and that Adobe Connect is available.");
String scoId = getScoIdFor(roomId);
Map<String, String> parameters = new HashMap<String, String>();
parameters.put("action", "sco-delete");
parameters.put("sco-id", scoId);
Document responseDoc = getResponseDocument(sendRequest(parameters));
if(!evaluateOk(responseDoc)) return false;
logout();
return true;
}
private String getScoIdFor(String roomId) {
Map<String, String> parameters = new HashMap<String, String>();
parameters.put("action", "sco-search-by-field");
parameters.put("query", PREFIX + roomId);
parameters.put("filter-type", "meeting");
Document responseDoc = getResponseDocument(sendRequest(parameters));
if(!evaluateOk(responseDoc)) return null;
Object result = evaluate(responseDoc, "//sco/url-path[text()='/" + PREFIX + roomId + "/']", XPathConstants.NODESET);
if(result == null) return null;
NodeList nodes = (NodeList) result;
if(nodes.getLength() == 1) {
String scoId = evaluate(responseDoc, "//sco[1]/attribute::sco-id");
return scoId;
}
else if(nodes.getLength() > 1)
throw new AssertException("More than one Adobe Connect room found for one course node!");
else
return null;
}
@Override
public URL createClassroomUrl(String roomId, Identity identity, VCConfiguration config) {
URL url = null;
URI uri = UriBuilder.fromUri(protocol + "://" + baseUrl).port(port)
.path(PREFIX + roomId).queryParam("session", cookie).build();
try {
url = uri.toURL();
} catch (MalformedURLException e) {
logWarn("Cannot create access URL to Adobe Connect meeting for id \"" + PREFIX + roomId + "\" and user \"" + identity.getName() + "\"", e);
}
return url;
}
@Override
public URL createClassroomGuestUrl(String roomId, Identity identity, VCConfiguration config) {
URL url = null;
URI uri = UriBuilder.fromUri(protocol + "://" + baseUrl).port(port)
.path(PREFIX + roomId).queryParam("guestName", identity.getName()).build();
try {
url = uri.toURL();
} catch (MalformedURLException e) {
logWarn("Cannot create access URL to Adobe Connect meeting for id \"" + PREFIX + roomId + "\" and user \"" + identity.getName() + "\"", e);
}
return url;
}
@Override
public boolean existsClassroom(String roomId, VCConfiguration config) {
if(!loginAdmin()) return false;
Map<String, String> parameters = new HashMap<String, String>();
parameters.put("action", "sco-search-by-field");
parameters.put("query", PREFIX + roomId);
parameters.put("filter-type", "meeting");
Document responseDoc = getResponseDocument(sendRequest(parameters));
if(!evaluateOk(responseDoc)) return false;
Object result = evaluate(responseDoc, "//sco/url-path[text()='/" + PREFIX + roomId + "/']", XPathConstants.NODESET);
logout();
if(result == null) return false;
NodeList nodes = (NodeList) result;
if(nodes.getLength() == 1)
return true;
else if(nodes.getLength() > 1)
throw new AssertException("More than one Adobe Connect room found for one course node!");
else
return false;
}
protected List<String> findClassrooms(String name) {
List<String> results = new ArrayList<String>();
if(!loginAdmin()) return results;
Map<String, String> parameters = new HashMap<String, String>();
parameters.put("action", "sco-search-by-field");
parameters.put("field", "name");
parameters.put("query", name);
parameters.put("filter-type", "meeting");
Document responseDoc = getResponseDocument(sendRequest(parameters));
if(!evaluateOk(responseDoc)) {
logError("Invalid response when searching for classrooms with the name \"" + name + "\"", null);
return results;
}
Object result = evaluate(responseDoc, "descendant-or-self::sco-search-by-field-info/child::sco/child::name", XPathConstants.NODESET);
logout();
if(result == null) if(isLogDebugEnabled()) logDebug("Search for Adobe Connect classrooms with name \"" + name + "\" with no results");
NodeList nodes = (NodeList) result;
for(int i=0; i<nodes.getLength(); i++) {
Node node = nodes.item(i);
String roomId = node.getFirstChild().getNodeValue();
results.add(roomId);
}
return results;
}
@Override
public boolean createModerator(Identity identity, String roomId) {
if(!loginAdmin()) return false;
Map<String, String> parameters = new HashMap<String, String>();
// create user
parameters.put("action", "principal-update");
parameters.put("first-name", identity.getUser().getProperty(UserConstants.FIRSTNAME, null));
parameters.put("last-name", identity.getUser().getProperty(UserConstants.LASTNAME, null));
parameters.put("login", PREFIX + identity.getName());
parameters.put("password", Encoder.md5hash(identity.getName() + "@" + Settings.getApplicationName()));
parameters.put("type", userType);
parameters.put("has-children", "false");
Document responseDoc = getResponseDocument(sendRequest(parameters));
if(!evaluateOk(responseDoc)) {
boolean exists = false;
String error = evaluate(responseDoc, "/results/status[1]/attribute::code");
if(error.equals("invalid")) {
error = evaluate(responseDoc, "/results[1]/status[1]/invalid/attribute::subcode");
exists = error.equals("duplicate");
}
if(!exists) return false;
}
// search the user
String principalId = getPrincipalIdFor(identity);
if(principalId == null) return false; // error case
// create permissions for the meeting
String scoId = getScoIdFor(roomId);
if(scoId == null) return false;
parameters.clear();
parameters.put("action", "permissions-update");
parameters.put("acl-id", scoId);
parameters.put("principal-id", principalId);
parameters.put("permission-id", "host");
String response = sendRequest(parameters);
responseDoc = getResponseDocument(response);
logout();
return evaluateOk(responseDoc);
}
@Override
public boolean createUser(Identity identity, String roomId) {
throw new NotImplementedException("method createUser not yet implemented");
}
@Override
public boolean createGuest(Identity identity, String roomId) {
throw new NotImplementedException("method createGuest not yet implemented");
}
@Override
public String getProviderId() {
return providerId;
}
@Override
public String getDisplayName() {
return displayName;
}
@Override
public VCProvider newInstance() {
AdobeConnectProvider newInstance = new AdobeConnectProvider(providerId, displayName, protocol, port, baseUrl, adminLogin, adminPassword, accountId, templates,
guestAccessAllowedDefault, guestStartMeetingAllowedDefault, showOptions, userType);
return newInstance;
}
@Override
public Controller createDisplayController(UserRequest ureq, WindowControl wControl, String roomId, String name, String description,
boolean isModerator, boolean readOnly, VCConfiguration config) {
AdobeDisplayController displayCtr = new AdobeDisplayController(ureq, wControl, roomId, name, description, isModerator, readOnly, (AdobeConnectConfiguration) config, this);
return displayCtr;
}
@Override
public Controller createConfigController(UserRequest ureq, WindowControl wControl, String roomId, VCConfiguration config) {
AdobeConfigController configCtr = new AdobeConfigController(ureq, wControl, roomId, this, (AdobeConnectConfiguration) config);
return configCtr;
}
@Override
public boolean login(Identity identity, String password) {
if(cookie == null) createCookie();
Map<String,String> parameters = new HashMap<String, String>();
parameters.put("action", "login");
if(accountId != null) parameters.put("account-id", accountId);
parameters.put("login", PREFIX + identity.getName());
parameters.put("password", Encoder.md5hash(identity.getName() + "@" + Settings.getApplicationName()));
Document responseDoc = getResponseDocument(sendRequest(parameters));
return evaluateOk(responseDoc);
}
private boolean loginAdmin() {
if(cookie == null) createCookie();
Map<String,String> parameters = new HashMap<String, String>();
parameters.put("action", "login");
if(accountId != null) parameters.put("account-id", accountId);
parameters.put("login", adminLogin);
parameters.put("password", adminPassword);
Document responseDoc = getResponseDocument(sendRequest(parameters));
boolean success = evaluateOk(responseDoc);
if(!success) {
logWarn("Admin login to Adobe Connect failed", null);
}
return success;
}
private boolean logout() {
if(cookie == null) return true;
Map<String,String> parameters = new HashMap<String, String>();
parameters.put("action", "logout");
Document responseDoc = getResponseDocument(sendRequest(parameters));
cookie = null;
return evaluateOk(responseDoc);
}
private boolean createCookie() {
Map<String, String> parameters = new HashMap<String, String>();
parameters.put("action", "common-info");
String response = sendRequest(parameters);
Document responseDoc = getResponseDocument(response);
boolean success = evaluateOk(responseDoc);
if (success) {
// get cookie
String result = evaluate(responseDoc, "/results/common[1]/cookie[1]/text()");
cookie = result;
}
return success;
}
private String getPrincipalIdFor(Identity identity) {
Map<String, String> parameters = new HashMap<String, String>();
parameters.put("action", "principal-list");
parameters.put("filter-type", userType);
parameters.put("filter-type", "user");
parameters.put("filter-login", PREFIX + identity.getName());
String response = sendRequest(parameters);
Document responseDoc = getResponseDocument(response);
boolean success = evaluateOk(responseDoc);
if(!success) return null;
// get principalId
NodeList nodes = (NodeList) evaluate(responseDoc, "//principal", XPathConstants.NODESET);
if(nodes == null) return null; // error case
if(nodes.getLength() == 1) {
String principalId = evaluate(responseDoc, "//principal[1]/attribute::principal-id");
return principalId;
} else if(nodes.getLength() > 1) {
throw new AssertException("Multiple Adobe Connect users with the same login name found: " + identity.getName());
} else return null;
}
private Document getResponseDocument(String response) {
DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
domFactory.setNamespaceAware(true); // never forget this!
DocumentBuilder builder;
Document doc = null;
try {
builder = domFactory.newDocumentBuilder();
InputSource is = new InputSource(new StringReader(response));
doc = builder.parse(is);
} catch (ParserConfigurationException e) {
if(isLogDebugEnabled()) logDebug("Error while creating DOM parser.");
} catch (SAXException e) {
if(isLogDebugEnabled()) logDebug("Error while parsing result XML document.");
} catch (IOException e) {
if(isLogDebugEnabled()) logDebug("Error while reading response.");
}
return doc;
}
private boolean evaluateOk(Document responseDoc) {
String result = evaluate(responseDoc, "/results/status[1]/attribute::code");
if(result == null || result.isEmpty())
return false;
return result.equals("ok");
}
private String evaluate(Document responseDoc, String expression) {
Object result = evaluate(responseDoc, expression, XPathConstants.STRING);
if(result == null || !(result instanceof String))
return new String();
return (String)result;
}
private Object evaluate(Document responseDoc, String expression, QName type) {
if(responseDoc == null) return null;
XPathFactory factory = XPathFactory.newInstance();
XPath xpath = factory.newXPath();
XPathExpression expr;
Object result;
try {
expr = xpath.compile(expression);
result = expr.evaluate(responseDoc, type);
} catch (XPathExpressionException e) {
result = null;
}
return result;
}
private String sendRequest(Map<String, String> parameters) {
URL url = createRequestUrl(parameters);
URLConnection urlConn;
try {
urlConn = url.openConnection();
// setup url connection
urlConn.setDoOutput(true);
urlConn.setUseCaches(false);
// add content type
urlConn.setRequestProperty("Content-Type", CONTENT_TYPE);
// add cookie information
if(cookie != null) urlConn.setRequestProperty("Cookie", COOKIE + cookie);
// send request
urlConn.connect();
// read response
BufferedReader input = new BufferedReader(new InputStreamReader(urlConn.getInputStream()));
StringBuilder response= new StringBuilder();
String line;
while( (line = input.readLine()) != null ) response.append(line);
input.close();
if(isLogDebugEnabled()) {
logDebug("Requested URL: " + url);
logDebug("Response: " + response);
}
return response.toString();
} catch (IOException e) {
logError("Sending request to Adobe Connect failed. Request: " + url.toString(), e);
return "";
}
}
private URL createRequestUrl(Map<String, String> parameters) {
UriBuilder ubu = UriBuilder.fromUri(protocol + "://" + baseUrl).port(port).path("api").path("xml");
for(String key : parameters.keySet()) {
ubu.queryParam(key, parameters.get(key));
}
URL url = null;
try {
url = ubu.build().toURL();
} catch (Exception e) {
logWarn("Error while creating URL for Adobe Connect request.", e);
// try to build the URL in a naiv way below
}
if(url == null) {
// error case, try the naiv way
try {
StringBuilder sb = new StringBuilder(protocol + "://" + baseUrl + ":" + port + "/api/xml");
if(!parameters.isEmpty()) sb.append("?");
for(String key : parameters.keySet()) {
sb.append(key + "=" + parameters.get(key) + "&");
}
sb.replace(sb.length(), sb.length(), "");
url = new URL(sb.toString());
} catch (MalformedURLException e) {
logError("Error while creating URL for Adobe Connect request. Please check the configuration!", e);
}
}
return url;
}
@Override
public boolean isProviderAvailable() {
Map<String, String> parameters = new HashMap<String, String>();
parameters.put("action", "common-info");
Document responseDoc = getResponseDocument(sendRequest(parameters));
return evaluateOk(responseDoc);
}
@Override
public VCConfiguration createNewConfiguration() {
AdobeConnectConfiguration config = new AdobeConnectConfiguration();
config.setProviderId(providerId);
config.setGuestAccessAllowed(defaultConfig.isGuestAccessAllowed());
config.setGuestStartMeetingAllowed(defaultConfig.isGuestStartMeetingAllowed());
config.setUseMeetingDates(defaultConfig.isUseMeetingDates());
return config;
}
@Override
public Map<String, String> getTemplates() {
if(templates == null) templates = Collections.emptyMap();
return templates;
}
////////////////////////////
// setters used by spring //
////////////////////////////
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public void setProviderId(String providerId) {
this.providerId = providerId;
}
public void setDisplayName(String displayName) {
this.displayName = displayName;
}
public void setProtocol(String protocol) {
this.protocol = protocol;
}
public void setPort(int port) {
this.port = port;
}
public void setBaseUrl(String baseUrl) {
this.baseUrl = baseUrl;
}
public void setAdminLogin(String adminLogin) {
this.adminLogin = adminLogin;
}
public void setAdminPassword(String adminPassword) {
this.adminPassword = adminPassword;
}
public void setAccountId(String accountId) {
if(StringHelper.containsNonWhitespace(accountId)) {
this.accountId = accountId;
} else {
this.accountId = null;
}
}
public void setTemplates(Map<String,String> templates) {
this.templates = templates;
List<Map.Entry<String, String>> entries = new ArrayList<Map.Entry<String, String>>(templates.entrySet());
for(Map.Entry<String, String> entry:entries) {
if(!StringHelper.containsNonWhitespace(entry.getKey()) || !StringHelper.containsNonWhitespace(entry.getValue())) {
templates.remove(entry.getKey());
}
}
}
public void setGuestAccessAllowedDefault(boolean guestAccessAllowedDefault) {
this.guestAccessAllowedDefault = guestAccessAllowedDefault;
}
public void setGuestStartMeetingAllowedDefault(boolean guestStartMeetingAllowedDefault) {
this.guestStartMeetingAllowedDefault = guestStartMeetingAllowedDefault;
}
public void setUseMeetingDatesDefault(boolean useMeetingDatesDefault) {
this.useMeetingDatesDefault = useMeetingDatesDefault;
}
public void setShowOptions(boolean showOptions) {
this.showOptions = showOptions;
}
public void setUserType(String userType) {
this.userType = userType;
}
public void setDefaultConfig(AdobeConnectConfiguration config) {
defaultConfig = config;
defaultConfig.setProviderId(providerId);
}
/////////////////////////////
// getters used internally //
/////////////////////////////
@Override
public boolean isEnabled() {
return enabled;
}
protected String getProtocol() {
return protocol;
}
protected int getPort() {
return port;
}
protected String getBaseUrl() {
return baseUrl;
}
protected String getAdminLogin() {
return adminLogin;
}
protected String getAdminPassword() {
return adminPassword;
}
protected String getAccountId() {
return accountId;
}
protected boolean isGuestAccessAllowedDefault() {
return guestAccessAllowedDefault;
}
protected boolean isGuestStartMeetingAllowedDefault() {
return guestStartMeetingAllowedDefault;
}
protected boolean isUseMeetingDatesDefault() {
return useMeetingDatesDefault;
}
protected boolean isShowOptions() {
return showOptions;
}
protected String getUserType() {
return userType;
}
}
//</OLATCE-103>