blob: f19992dd4027a289d5606673144b26b9e673642b [file] [log] [blame]
/*******************************************************************************
* /*******************************************************************************
* * Copyright (c) 2009, 2016 Xored Software Inc and others.
* * All rights reserved. This program and the accompanying materials
* * are made available under the terms of the Eclipse Public License v1.0
* * which accompanies this distribution, and is available at
* * http://www.eclipse.org/legal/epl-v10.html
* *
* * Contributors:
* * Xored Software Inc - initial API and implementation and/or initial documentation
* *******************************************************************************/
package org.eclipse.rcptt.launching.rap;
import java.net.URI;
import java.net.URISyntaxException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationType;
import org.eclipse.debug.core.ILaunchManager;
public class RAPLaunchConfigValidator {
public static final int ERR_SERVLET_PATH = 6001;
public static final int ERR_PORT = 6004;
public static final int ERR_URL = 6005;
public static final int ERR_TIMEOUT = 6007;
public static final int ERR_ENTRY_POINT = 6008;
public static final int ERR_SERVLET_BUNDLE = 6009;
public static final int ERR_DATA_LOCATION = 6010;
public static final int ERR_CONTEXT_PATH = 6011;
public static final int ERR_SERVLET_PATH_LEADING_SLASH = 60012;
public static final int ERR_SERVLET_PATH_INVALID = 60013;
public static final int ERR_CONTEXT_PATH_LEADING_SLASH = 60014;
public static final int WARN_OSGI_FRAMEWORK = 7002;
public static final int WARN_WS_WRONG = 7003;
private static final String RAP_LAUNCH_CONFIG_TYPE = "org.eclipse.rap.ui.launch.RAPLauncher"; //$NON-NLS-1$
private static final String EMPTY = ""; //$NON-NLS-1$
private final RAPLaunchConfig config;
public RAPLaunchConfigValidator(final RAPLaunchConfig config) {
this.config = config;
}
public IStatus[] validate() {
List<IStatus> states = new ArrayList<IStatus>();
try {
addNonOKState(states, validateServletPath());
addNonOKState(states, validatePort());
addNonOKState(states, validateUniquePort());
addNonOKState(states, validateContextPath());
addNonOKState(states, validateURL());
addNonOKState(states, validateSessionTimeout());
addNonOKState(states, validateDataLocation());
} catch (CoreException e) {
String text = "An error occured while validating the launch configuration: {0}";
Object[] args = new Object[] { e.getLocalizedMessage() };
String msg = MessageFormat.format(text, args);
states.add(createError(msg, 0, e));
}
IStatus[] result = new IStatus[states.size()];
states.toArray(result);
return result;
}
/////////////////////
// Validation methods
private IStatus validateDataLocation() throws CoreException {
IStatus result = Status.OK_STATUS;
String dataLocation = config.getDataLocation();
if (dataLocation == null || dataLocation.length() == 0) {
String msg = "Instance Area must not be empty.";
result = createError(msg, ERR_DATA_LOCATION, null);
}
return result;
}
private IStatus validateServletPath() throws CoreException {
IStatus result = Status.OK_STATUS;
if (config.getOpenBrowser()) {
String servletPath = config.getServletPath();
if (servletPath == null || EMPTY.equals(servletPath)) {
String msg = "The servlet path must not be empty";
result = createError(msg, ERR_SERVLET_PATH, null);
} else if (!servletPath.startsWith("/")) {
String msg = "The servlet path must start with a slash.";
result = createError(msg, ERR_SERVLET_PATH_LEADING_SLASH, null);
} else if (containsChars(servletPath.substring(1), new char[] { '*', '/', '\\' })) {
String msg = "The servlet path contains invalid characters.";
result = createError(msg, ERR_SERVLET_PATH_INVALID, null);
}
}
return result;
}
private static boolean containsChars(String string, char[] chars) {
boolean hasInvalidChar = false;
String pattern = new String(chars);
for (int i = 0; !hasInvalidChar && i < string.length(); i++) {
if (pattern.indexOf(string.charAt(i)) != -1) {
hasInvalidChar = true;
}
}
return hasInvalidChar;
}
private IStatus validateContextPath() throws CoreException {
IStatus result = Status.OK_STATUS;
if (config.getUseManualContextPath()) {
String contextPath = config.getContextPath();
if (!contextPath.startsWith("/")) {
String msg = "The context path must start with a slash.";
result = createError(msg, ERR_CONTEXT_PATH_LEADING_SLASH, null);
} else if (!isValidContextPath(contextPath)) {
String unformatedMsg = "The context path contains invalid characters.";
String msg = MessageFormat.format(unformatedMsg, new Object[] { contextPath });
result = createError(msg, ERR_CONTEXT_PATH, null);
}
}
return result;
}
private boolean isValidContextPath(String contextPath) {
boolean result = true;
int length = contextPath.length();
if (contextPath.indexOf("//") != -1) {
result = false;
}
for (int i = 0; i < length && result; i++) {
char ch = contextPath.charAt(i);
boolean isLetterOrDigit = Character.isLetterOrDigit(ch);
boolean isValidSpecialChar = "/_-.".indexOf(ch) != -1;
if (!isLetterOrDigit && !isValidSpecialChar) {
result = false;
}
}
return result;
}
private IStatus validatePort() throws CoreException {
IStatus result = Status.OK_STATUS;
if (config.getUseManualPort()) {
int port = config.getPort();
if (port < RAPLaunchConfig.MIN_PORT_NUMBER || port > RAPLaunchConfig.MAX_PORT_NUMBER) {
String text = "Port number must be between {0} and {1}";
Object[] args = new Object[] {
new Integer(RAPLaunchConfig.MIN_PORT_NUMBER),
new Integer(RAPLaunchConfig.MAX_PORT_NUMBER)
};
String msg = MessageFormat.format(text, args);
result = createError(msg, ERR_PORT, null);
}
}
return result;
}
private IStatus validateUniquePort() throws CoreException {
IStatus result = Status.OK_STATUS;
if (config.getUseManualPort()) {
RAPLaunchConfig duplicate = null;
ILaunchConfiguration[] launchConfigs = getLaunchConfigs();
for (int i = 0; duplicate == null && i < launchConfigs.length; i++) {
RAPLaunchConfig otherConfig = new RAPLaunchConfig(launchConfigs[i]);
if (hasSamePort(otherConfig)) {
duplicate = otherConfig;
}
}
if (duplicate != null) {
String text = "The port {0,number,\\#} is already used by {1}";
Object[] args = new Object[] {
new Integer(config.getPort()),
duplicate.getName()
};
String msg = MessageFormat.format(text, args);
result = createWarning(msg, 0, null);
}
}
return result;
}
private IStatus validateURL() throws CoreException {
IStatus result = Status.OK_STATUS;
try {
String url = URLBuilder.fromLaunchConfig(config, 80, false);
new URI(url);
} catch (URISyntaxException exception) {
String text = "Servlet path and/or context path cause a malformed URL.";
result = createError(text, ERR_URL, exception);
}
return result;
}
private IStatus validateSessionTimeout() throws CoreException {
IStatus result = Status.OK_STATUS;
boolean isValid = config.getSessionTimeout() >= RAPLaunchConfig.MIN_SESSION_TIMEOUT;
if (!isValid) {
String msg = "Session timeout value must be a non-negative integer number.";
result = createError(msg, ERR_TIMEOUT, null);
}
return result;
}
private void addNonOKState(List<IStatus> states, IStatus state) {
if (state != null && !state.isOK()) {
states.add(state);
}
}
private IStatus createWarning(String msg, int code, Throwable thr) {
String pluginId = Activator.PLUGIN_ID;
return new Status(IStatus.WARNING, pluginId, code, msg, thr);
}
private IStatus createError(String msg, int code, Throwable thr) {
return new Status(IStatus.ERROR, Activator.PLUGIN_ID, code, msg, thr);
}
private static ILaunchConfiguration[] getLaunchConfigs() throws CoreException {
ILaunchManager launchManager = DebugPlugin.getDefault().getLaunchManager();
ILaunchConfigurationType type = launchManager.getLaunchConfigurationType(RAP_LAUNCH_CONFIG_TYPE);
return launchManager.getLaunchConfigurations(type);
}
private boolean hasSamePort(RAPLaunchConfig otherConfig) throws CoreException {
return otherConfig.getUseManualPort()
&& !config.getName().equals(otherConfig.getName())
&& config.getPort() == otherConfig.getPort();
}
}