| /******************************************************************************* |
| * Copyright (c) 2004, 2009 Eugene Kuleshov 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: |
| * Eugene Kuleshov - initial API and implementation |
| *******************************************************************************/ |
| |
| package org.eclipse.mylyn.internal.web.tasks; |
| |
| import static org.eclipse.mylyn.internal.web.tasks.Util.isPresent; |
| |
| import java.io.ByteArrayInputStream; |
| import java.io.IOException; |
| import java.text.SimpleDateFormat; |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.Date; |
| import java.util.Iterator; |
| import java.util.LinkedHashMap; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.regex.Matcher; |
| import java.util.regex.Pattern; |
| |
| import org.apache.commons.codec.EncoderException; |
| import org.apache.commons.codec.net.URLCodec; |
| import org.apache.commons.httpclient.Header; |
| import org.apache.commons.httpclient.HostConfiguration; |
| import org.apache.commons.httpclient.HttpClient; |
| import org.apache.commons.httpclient.HttpException; |
| import org.apache.commons.httpclient.HttpMethod; |
| import org.apache.commons.httpclient.methods.GetMethod; |
| import org.apache.commons.httpclient.methods.PostMethod; |
| import org.apache.commons.lang.StringEscapeUtils; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.Status; |
| import org.eclipse.mylyn.commons.net.AbstractWebLocation; |
| import org.eclipse.mylyn.commons.net.AuthenticationCredentials; |
| import org.eclipse.mylyn.commons.net.AuthenticationType; |
| import org.eclipse.mylyn.commons.net.WebLocation; |
| import org.eclipse.mylyn.commons.net.WebUtil; |
| import org.eclipse.mylyn.tasks.core.AbstractRepositoryConnector; |
| import org.eclipse.mylyn.tasks.core.IRepositoryManager; |
| import org.eclipse.mylyn.tasks.core.IRepositoryQuery; |
| import org.eclipse.mylyn.tasks.core.ITask; |
| import org.eclipse.mylyn.tasks.core.TaskRepository; |
| import org.eclipse.mylyn.tasks.core.data.TaskAttribute; |
| import org.eclipse.mylyn.tasks.core.data.TaskAttributeMapper; |
| import org.eclipse.mylyn.tasks.core.data.TaskData; |
| import org.eclipse.mylyn.tasks.core.data.TaskDataCollector; |
| import org.eclipse.mylyn.tasks.core.data.TaskMapper; |
| import org.eclipse.mylyn.tasks.core.sync.ISynchronizationSession; |
| import org.eclipse.mylyn.tasks.ui.TaskRepositoryLocationUiFactory; |
| import org.eclipse.mylyn.tasks.ui.TasksUi; |
| |
| import com.sun.syndication.feed.module.DCModule; |
| import com.sun.syndication.feed.synd.SyndEntry; |
| import com.sun.syndication.feed.synd.SyndFeed; |
| import com.sun.syndication.io.SyndFeedInput; |
| import com.sun.syndication.io.XmlReader; |
| |
| /** |
| * Generic connector for web based issue tracking systems |
| * |
| * @author Eugene Kuleshov |
| */ |
| public class WebRepositoryConnector extends AbstractRepositoryConnector { |
| |
| public static final String REPOSITORY_TYPE = "web"; //$NON-NLS-1$ |
| |
| public static final String PROPERTY_TASK_CREATION_URL = "taskCreationUrl"; //$NON-NLS-1$ |
| |
| public static final String PROPERTY_TASK_URL = "taskUrl"; //$NON-NLS-1$ |
| |
| public static final String PROPERTY_QUERY_URL = "queryUrl"; //$NON-NLS-1$ |
| |
| public static final String PROPERTY_QUERY_METHOD = "queryMethod"; //$NON-NLS-1$ |
| |
| public static final String PROPERTY_QUERY_REGEXP = "queryPattern"; //$NON-NLS-1$ |
| |
| public static final String PROPERTY_LOGIN_FORM_URL = "loginFormUrl"; //$NON-NLS-1$ |
| |
| public static final String PROPERTY_LOGIN_TOKEN_REGEXP = "loginTokenPattern"; //$NON-NLS-1$ |
| |
| public static final String PROPERTY_LOGIN_REQUEST_METHOD = "loginRequestMethod"; //$NON-NLS-1$ |
| |
| public static final String PROPERTY_LOGIN_REQUEST_URL = "loginRequestUrl"; //$NON-NLS-1$ |
| |
| public static final String PARAM_PREFIX = "param_"; //$NON-NLS-1$ |
| |
| public static final String PARAM_SERVER_URL = "serverUrl"; //$NON-NLS-1$ |
| |
| public static final String PARAM_USER_ID = "userId"; //$NON-NLS-1$ |
| |
| public static final String PARAM_PASSWORD = "password"; //$NON-NLS-1$ |
| |
| public static final String PARAM_LOGIN_TOKEN = "loginToken"; //$NON-NLS-1$ |
| |
| public static final String REQUEST_POST = "POST"; //$NON-NLS-1$ |
| |
| public static final String REQUEST_GET = "GET"; //$NON-NLS-1$ |
| |
| private static final String COMPLETED_STATUSES = "completed|fixed|resolved|invalid|verified|deleted|closed|done"; //$NON-NLS-1$ |
| |
| public static final String KEY_TASK_PREFIX = "taskPrefix"; //$NON-NLS-1$ |
| |
| public static final String KEY_QUERY_TEMPLATE = "UrlTemplate"; //$NON-NLS-1$ |
| |
| public static final String KEY_QUERY_PATTERN = "Regexp"; //$NON-NLS-1$ |
| |
| private static final String USER_AGENT = "WebTemplatesConnector"; //$NON-NLS-1$ |
| |
| private final static Date DEFAULT_DATE = new Date(0); |
| |
| @Override |
| public String getConnectorKind() { |
| return REPOSITORY_TYPE; |
| } |
| |
| @Override |
| public String getLabel() { |
| return Messages.WebRepositoryConnector_Web_Template_Advanced_; |
| } |
| |
| @Override |
| public boolean canCreateNewTask(TaskRepository repository) { |
| return repository.hasProperty(PROPERTY_TASK_CREATION_URL); |
| } |
| |
| @Override |
| public boolean canCreateTaskFromKey(TaskRepository repository) { |
| return repository.hasProperty(PROPERTY_TASK_URL); |
| } |
| |
| @Override |
| public boolean canSynchronizeTask(TaskRepository taskRepository, ITask task) { |
| return false; |
| } |
| |
| // @Override |
| // public AbstractTask createTaskFromExistingId(TaskRepository repository, final String id, IProgressMonitor monitor) |
| // throws CoreException { |
| // if (REPOSITORY_TYPE.equals(repository.getConnectorKind())) { |
| // String taskPrefix = evaluateParams(repository.getProperty(PROPERTY_TASK_URL), repository); |
| // |
| // final WebTask task = new WebTask(id, id, taskPrefix, repository.getRepositoryUrl(), REPOSITORY_TYPE); |
| // |
| // RetrieveTitleFromUrlJob job = new RetrieveTitleFromUrlJob(taskPrefix + id) { |
| // @Override |
| // protected void setTitle(String pageTitle) { |
| // task.setSummary(pageTitle); |
| // TasksUiPlugin.getTaskList().notifyTaskChanged(task, false); |
| // } |
| // }; |
| // job.schedule(); |
| // |
| // return task; |
| // } |
| // |
| // return null; |
| // } |
| |
| @Override |
| public TaskData getTaskData(TaskRepository repository, String taskId, IProgressMonitor monitor) |
| throws CoreException { |
| String taskPrefix = evaluateParams(repository.getProperty(PROPERTY_TASK_URL), repository); |
| TaskData taskData = createTaskData(repository, taskId); |
| TaskMapper mapper = new TaskMapper(taskData, true); |
| mapper.setCreationDate(DEFAULT_DATE); |
| mapper.setTaskUrl(taskPrefix + taskId); |
| mapper.setValue(KEY_TASK_PREFIX, taskPrefix); |
| // bug 300310: only update the summary on forced refreshes |
| mapper.setSummary(taskId); |
| try { |
| String pageTitle = WebUtil.getTitleFromUrl(new WebLocation(taskPrefix + taskId), monitor); |
| if (pageTitle != null) { |
| mapper.setSummary(pageTitle); |
| } |
| } catch (IOException e) { |
| // log to error log? |
| } |
| taskData.getRoot() |
| .getMappedAttribute(TaskAttribute.SUMMARY) |
| .getMetaData() |
| .putValue("forced", Boolean.TRUE.toString()); |
| return taskData; |
| } |
| |
| @SuppressWarnings("restriction") |
| @Override |
| public String getRepositoryUrlFromTaskUrl(String url) { |
| if (url == null) { |
| return null; |
| } |
| |
| // lookup repository using task prefix url |
| IRepositoryManager repositoryManager = TasksUi.getRepositoryManager(); |
| for (TaskRepository repository : repositoryManager.getRepositories(getConnectorKind())) { |
| String taskUrl = evaluateParams(repository.getProperty(PROPERTY_TASK_URL), repository); |
| if (taskUrl != null && !taskUrl.equals("") && url.startsWith(taskUrl)) { //$NON-NLS-1$ |
| return repository.getRepositoryUrl(); |
| } |
| } |
| |
| for (IRepositoryQuery query : org.eclipse.mylyn.internal.tasks.ui.util.TasksUiInternal.getTaskList() |
| .getQueries()) { |
| TaskRepository repository = repositoryManager.getRepository(query.getConnectorKind(), |
| query.getRepositoryUrl()); |
| if (repository != null) { |
| String queryUrl = evaluateParams(query.getAttribute(KEY_TASK_PREFIX), // |
| getQueryParams(query), repository); |
| if (queryUrl != null && !queryUrl.equals("") && url.startsWith(queryUrl)) { //$NON-NLS-1$ |
| return query.getRepositoryUrl(); |
| } |
| } |
| } |
| return null; |
| } |
| |
| public static Map<String, String> getQueryParams(IRepositoryQuery query) { |
| Map<String, String> params = new LinkedHashMap<String, String>(); |
| Map<String, String> attributes = query.getAttributes(); |
| for (String name : attributes.keySet()) { |
| if (name.startsWith(WebRepositoryConnector.PARAM_PREFIX)) { |
| params.put(name, attributes.get(name)); |
| } |
| } |
| return params; |
| } |
| |
| @Override |
| public String getTaskIdFromTaskUrl(String url) { |
| if (url == null) { |
| return null; |
| } |
| |
| IRepositoryManager repositoryManager = TasksUi.getRepositoryManager(); |
| for (TaskRepository repository : repositoryManager.getRepositories(getConnectorKind())) { |
| String start = evaluateParams(repository.getProperty(PROPERTY_TASK_URL), repository); |
| if (start != null && url.startsWith(start)) { |
| return url.substring(start.length()); |
| } |
| } |
| return null; |
| } |
| |
| @Override |
| public String getTaskUrl(String repositoryUrl, String taskId) { |
| IRepositoryManager repositoryManager = TasksUi.getRepositoryManager(); |
| TaskRepository repository = repositoryManager.getRepository(getConnectorKind(), repositoryUrl); |
| if (repository != null) { |
| String prefix = evaluateParams(repository.getProperty(PROPERTY_TASK_URL), repository); |
| return prefix + taskId; |
| } |
| return null; |
| } |
| |
| @Override |
| public IStatus performQuery(TaskRepository repository, IRepositoryQuery query, TaskDataCollector resultCollector, |
| ISynchronizationSession session, IProgressMonitor monitor) { |
| Map<String, String> queryParameters = getQueryParams(query); |
| String queryUrl = evaluateParams(query.getUrl(), queryParameters, repository); |
| try { |
| String content = fetchResource(queryUrl, queryParameters, repository); |
| |
| String taskPrefixAttribute = query.getAttribute(KEY_TASK_PREFIX); |
| if (!Util.isPresent(taskPrefixAttribute)) { |
| return performRssQuery(content, monitor, resultCollector, repository); |
| } else { |
| String taskPrefix = evaluateParams(taskPrefixAttribute, queryParameters, repository); |
| String queryPattern = evaluateParams(query.getAttribute(KEY_QUERY_PATTERN), queryParameters, repository); |
| return performQuery(content, queryPattern, taskPrefix, monitor, resultCollector, repository); |
| } |
| } catch (IOException e) { |
| String msg = e.getMessage() == null ? e.toString() : e.getMessage(); |
| return new Status(IStatus.ERROR, TasksWebPlugin.ID_PLUGIN, IStatus.ERROR, // |
| Messages.WebRepositoryConnector_Could_not_fetch_resource + queryUrl + "\n" + msg, e); //$NON-NLS-1$ |
| } |
| } |
| |
| @Override |
| public boolean isRepositoryConfigurationStale(TaskRepository repository, IProgressMonitor monitor) |
| throws CoreException { |
| return false; |
| } |
| |
| @Override |
| public void updateRepositoryConfiguration(TaskRepository repository, IProgressMonitor monitor) throws CoreException { |
| // ignore |
| } |
| |
| @Override |
| public void updateTaskFromTaskData(TaskRepository repository, ITask task, TaskData taskData) { |
| preProcessTaskData(task, taskData); |
| |
| TaskMapper mapper = new TaskMapper(taskData); |
| if (Util.isPresent(mapper.getValue(KEY_TASK_PREFIX))) { |
| task.setAttribute(KEY_TASK_PREFIX, mapper.getValue(KEY_TASK_PREFIX)); |
| task.setTaskKey(task.getTaskId()); |
| } else { |
| // do not show task id for RSS items |
| task.setTaskKey(null); |
| } |
| mapper.applyTo(task); |
| } |
| |
| private void preProcessTaskData(ITask task, TaskData taskData) { |
| if (task.getSummary() != null && task.getSummary().length() > 0) { |
| // bug 300310: if task already has a summary, keep it |
| TaskAttribute summaryAttribute = taskData.getRoot().getMappedAttribute(TaskAttribute.SUMMARY); |
| if (summaryAttribute != null && Boolean.parseBoolean(summaryAttribute.getMetaData().getValue("forced"))) { |
| summaryAttribute.setValue(task.getSummary()); |
| } |
| } |
| } |
| |
| public static IStatus performQuery(String resource, String regexp, String taskPrefix, IProgressMonitor monitor, |
| TaskDataCollector resultCollector, TaskRepository repository) { |
| NamedPattern p = new NamedPattern(regexp, Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL |
| | Pattern.UNICODE_CASE | Pattern.CANON_EQ); |
| |
| Matcher matcher = p.matcher(resource); |
| |
| if (!matcher.find()) { |
| return Status.OK_STATUS; |
| } else { |
| boolean isCorrect = true; |
| do { |
| if (p.getGroups().isEmpty()) { |
| // "classic" mode, no named patterns |
| if (matcher.groupCount() < 2) { |
| isCorrect = false; |
| } |
| if (matcher.groupCount() >= 1) { |
| String id = matcher.group(1); |
| String description = matcher.groupCount() > 1 ? cleanup(matcher.group(2), repository) : null; |
| description = unescapeHtml(description); |
| |
| TaskData data = createTaskData(repository, id); |
| TaskMapper mapper = new TaskMapper(data, true); |
| mapper.setCreationDate(DEFAULT_DATE); |
| mapper.setTaskUrl(taskPrefix + id); |
| mapper.setSummary(description); |
| mapper.setValue(KEY_TASK_PREFIX, taskPrefix); |
| resultCollector.accept(data); |
| } |
| } else { |
| String id = p.group("Id", matcher); //$NON-NLS-1$ |
| String description = p.group("Description", matcher); //$NON-NLS-1$ |
| if (id == null || description == null) { |
| isCorrect = false; |
| } |
| if (id != null) { |
| description = unescapeHtml(description); |
| |
| String owner = unescapeHtml(cleanup(p.group("Owner", matcher), repository)); //$NON-NLS-1$ |
| String type = unescapeHtml(cleanup(p.group("Type", matcher), repository)); //$NON-NLS-1$ |
| |
| TaskData data = createTaskData(repository, id); |
| TaskMapper mapper = new TaskMapper(data, true); |
| mapper.setCreationDate(DEFAULT_DATE); |
| mapper.setTaskUrl(taskPrefix + id); |
| mapper.setSummary(description); |
| mapper.setValue(KEY_TASK_PREFIX, taskPrefix); |
| mapper.setOwner(owner); |
| mapper.setTaskKind(type); |
| |
| String status = p.group("Status", matcher); //$NON-NLS-1$ |
| if (status != null) { |
| if (COMPLETED_STATUSES.contains(status.toLowerCase())) { |
| // TODO set actual completion date here |
| mapper.setCompletionDate(DEFAULT_DATE); |
| } |
| } |
| |
| resultCollector.accept(data); |
| } |
| } |
| } while (matcher.find() && !monitor.isCanceled()); |
| |
| if (isCorrect) { |
| return Status.OK_STATUS; |
| } else { |
| return new Status(IStatus.ERROR, TasksWebPlugin.ID_PLUGIN, IStatus.ERROR, |
| Messages.WebRepositoryConnector_Require_two_matching_groups, null); |
| } |
| } |
| } |
| |
| private static TaskData createTaskData(TaskRepository taskRepository, String id) { |
| TaskData data = new TaskData(new TaskAttributeMapper(taskRepository), WebRepositoryConnector.REPOSITORY_TYPE, |
| taskRepository.getRepositoryUrl(), id); |
| data.setPartial(true); |
| return data; |
| } |
| |
| private static String unescapeHtml(String text) { |
| if (text == null) { |
| return ""; //$NON-NLS-1$ |
| } |
| return StringEscapeUtils.unescapeHtml(text); |
| } |
| |
| private static String cleanup(String text, TaskRepository repository) { |
| if (text == null) { |
| return null; |
| } |
| |
| // Has to disable this for now. See bug 166737 and bug 166936 |
| // try { |
| // text = URLDecoder.decode(text, repository.getCharacterEncoding()); |
| // } catch (UnsupportedEncodingException ex) { |
| // // ignore |
| // } |
| |
| text = text.replaceAll("<!--.+?-->", ""); //$NON-NLS-1$ //$NON-NLS-2$ |
| |
| String[] tokens = text.split(" |\\t|\\n|\\r"); //$NON-NLS-1$ |
| StringBuilder sb = new StringBuilder(); |
| String sep = ""; //$NON-NLS-1$ |
| for (String token : tokens) { |
| if (token.length() > 0) { |
| sb.append(sep).append(token); |
| sep = " "; //$NON-NLS-1$ |
| } |
| } |
| |
| return sb.toString(); |
| } |
| |
| public static IStatus performRssQuery(String content, IProgressMonitor monitor, TaskDataCollector resultCollector, |
| TaskRepository repository) { |
| SyndFeedInput input = new SyndFeedInput(); |
| try { |
| SyndFeed feed = input.build(new XmlReader(new ByteArrayInputStream(content.getBytes()))); |
| |
| SimpleDateFormat df = new SimpleDateFormat("yy-MM-dd HH:mm"); //$NON-NLS-1$ |
| |
| Iterator<?> it; |
| for (it = feed.getEntries().iterator(); it.hasNext();) { |
| SyndEntry entry = (SyndEntry) it.next(); |
| |
| String author = entry.getAuthor(); |
| if (author == null) { |
| DCModule module = (DCModule) entry.getModule("http://purl.org/dc/elements/1.1/"); //$NON-NLS-1$ |
| author = module.getCreator(); |
| } |
| |
| Date date = entry.getUpdatedDate(); |
| if (date == null) { |
| date = entry.getPublishedDate(); |
| } |
| if (date == null) { |
| DCModule module = (DCModule) entry.getModule("http://purl.org/dc/elements/1.1/"); //$NON-NLS-1$ |
| date = module.getDate(); |
| } |
| |
| String entryUri = entry.getLink(); |
| if (entryUri == null) { |
| entryUri = entry.getUri(); |
| } |
| |
| String entrTitle = entry.getTitle(); |
| |
| TaskData data = createTaskData(repository, entryUri.replaceAll("-", "%2D")); //$NON-NLS-1$ //$NON-NLS-2$ |
| TaskMapper schema = new TaskMapper(data, true); |
| schema.setSummary(((date == null ? "" : df.format(date) + " - ") + entrTitle)); //$NON-NLS-1$ //$NON-NLS-2$ |
| schema.setCreationDate(date); |
| schema.setOwner(author); |
| schema.setTaskUrl(entryUri); |
| resultCollector.accept(data); |
| } |
| return Status.OK_STATUS; |
| } catch (Exception e) { |
| String msg = e.getMessage() == null ? e.toString() : e.getMessage(); |
| return new Status(IStatus.ERROR, TasksWebPlugin.ID_PLUGIN, IStatus.ERROR, // |
| Messages.WebRepositoryConnector_Failed_to_parse_RSS_feed + "\"" + msg + "\"", e); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| } |
| |
| public static String fetchResource(String url, Map<String, String> params, TaskRepository repository) |
| throws IOException { |
| HttpClient client = new HttpClient(); |
| WebUtil.configureHttpClient(client, USER_AGENT); |
| AbstractWebLocation location = new TaskRepositoryLocationUiFactory().createWebLocation(repository); |
| HostConfiguration hostConfiguration = WebUtil.createHostConfiguration(client, location, null); |
| |
| loginRequestIfNeeded(client, hostConfiguration, params, repository); |
| |
| GetMethod method = new GetMethod(url); |
| // method.setFollowRedirects(false); |
| return requestResource(url, client, hostConfiguration, method); |
| } |
| |
| private static void loginRequestIfNeeded(HttpClient client, HostConfiguration hostConfiguration, |
| Map<String, String> params, TaskRepository repository) throws HttpException, IOException { |
| if (repository.getCredentials(AuthenticationType.REPOSITORY) == null |
| || !isPresent(repository.getProperty(PROPERTY_LOGIN_REQUEST_URL))) { |
| return; |
| } |
| |
| String loginFormUrl = evaluateParams(repository.getProperty(PROPERTY_LOGIN_FORM_URL), params, repository); |
| String loginToken = evaluateParams(repository.getProperty(PROPERTY_LOGIN_TOKEN_REGEXP), params, repository); |
| if (isPresent(loginFormUrl) || isPresent(loginToken)) { |
| GetMethod method = new GetMethod(loginFormUrl); |
| // method.setFollowRedirects(false); |
| String loginFormPage = requestResource(loginFormUrl, client, hostConfiguration, method); |
| if (loginFormPage != null) { |
| Pattern p = Pattern.compile(loginToken); |
| Matcher m = p.matcher(loginFormPage); |
| if (m.find()) { |
| params.put(PARAM_PREFIX + PARAM_LOGIN_TOKEN, m.group(1)); |
| } |
| } |
| } |
| |
| String loginRequestUrl = evaluateParams(repository.getProperty(PROPERTY_LOGIN_REQUEST_URL), params, repository); |
| requestResource(loginRequestUrl, client, hostConfiguration, getLoginMethod(params, repository)); |
| } |
| |
| public static HttpMethod getLoginMethod(Map<String, String> params, TaskRepository repository) { |
| String requestMethod = repository.getProperty(PROPERTY_LOGIN_REQUEST_METHOD); |
| String requestTemplate = repository.getProperty(PROPERTY_LOGIN_REQUEST_URL); |
| String requestUrl = evaluateParams(requestTemplate, params, repository); |
| |
| if (REQUEST_GET.equals(requestMethod)) { |
| return new GetMethod(requestUrl); |
| // method.setFollowRedirects(false); |
| } |
| |
| int n = requestUrl.indexOf('?'); |
| if (n == -1) { |
| return new PostMethod(requestUrl); |
| } |
| |
| PostMethod postMethod = new PostMethod(requestUrl.substring(0, n)); |
| // TODO this does not take into account escaped values |
| n = requestTemplate.indexOf('?'); |
| String[] requestParams = requestTemplate.substring(n + 1).split("&"); //$NON-NLS-1$ |
| for (String requestParam : requestParams) { |
| String[] nv = requestParam.split("="); //$NON-NLS-1$ |
| if (nv.length == 1) { |
| postMethod.addParameter(nv[0], ""); //$NON-NLS-1$ |
| } else { |
| String value = evaluateParams(nv[1], getParams(repository, params), false); |
| postMethod.addParameter(nv[0], value); |
| } |
| } |
| return postMethod; |
| } |
| |
| private static String requestResource(String url, HttpClient client, HostConfiguration hostConfiguration, |
| HttpMethod method) throws IOException, HttpException { |
| String refreshUrl = null; |
| try { |
| client.executeMethod(hostConfiguration, method); |
| // int statusCode = client.executeMethod(method); |
| // if (statusCode == 300 || statusCode == 301 || statusCode == 302 || statusCode == 303 || statusCode == 307) { |
| // Header location = method.getResponseHeader("Location"); |
| // if (location != null) { |
| // refreshUrl = location.getValue(); |
| // if (!refreshUrl.startsWith("/")) { |
| // refreshUrl = "/" + refreshUrl; |
| // } |
| // } |
| // } |
| |
| refreshUrl = getRefreshUrl(url, method); |
| if (refreshUrl == null) { |
| return method.getResponseBodyAsString(); |
| } |
| } finally { |
| method.releaseConnection(); |
| } |
| |
| method = new GetMethod(refreshUrl); |
| try { |
| client.executeMethod(hostConfiguration, method); |
| return method.getResponseBodyAsString(); |
| } finally { |
| method.releaseConnection(); |
| } |
| } |
| |
| private static String getRefreshUrl(String url, HttpMethod method) { |
| Header refreshHeader = method.getResponseHeader("Refresh"); //$NON-NLS-1$ |
| if (refreshHeader == null) { |
| return null; |
| } |
| String value = refreshHeader.getValue(); |
| int n = value.indexOf(";url="); //$NON-NLS-1$ |
| if (n == -1) { |
| return null; |
| } |
| value = value.substring(n + 5); |
| int requestPath; |
| if (value.charAt(0) == '/') { |
| int colonSlashSlash = url.indexOf("://"); //$NON-NLS-1$ |
| requestPath = url.indexOf('/', colonSlashSlash + 3); |
| } else { |
| requestPath = url.lastIndexOf('/'); |
| } |
| |
| String refreshUrl; |
| if (requestPath == -1) { |
| refreshUrl = url + "/" + value; //$NON-NLS-1$ |
| } else { |
| refreshUrl = url.substring(0, requestPath + 1) + value; |
| } |
| return refreshUrl; |
| } |
| |
| public static String evaluateParams(String value, Map<String, String> params, TaskRepository repository) { |
| return evaluateParams(value, getParams(repository, params), true); |
| } |
| |
| public static String evaluateParams(String value, TaskRepository repository) { |
| return evaluateParams(value, getParams(repository, null), true); |
| } |
| |
| private static String evaluateParams(String value, Map<String, String> params, boolean encode) { |
| if (value == null || value.indexOf("${") == -1) { //$NON-NLS-1$ |
| return value; |
| } |
| |
| int n = 0; |
| int n1 = value.indexOf("${"); //$NON-NLS-1$ |
| StringBuilder evaluatedValue = new StringBuilder(value.length()); |
| while (n1 > -1) { |
| evaluatedValue.append(value.substring(n, n1)); |
| int n2 = value.indexOf("}", n1); //$NON-NLS-1$ |
| if (n2 > -1) { |
| String key = value.substring(n1 + 2, n2); |
| if (PARAM_SERVER_URL.equals(key) || PARAM_USER_ID.equals(key) || PARAM_PASSWORD.equals(key)) { |
| evaluatedValue.append(evaluateParams(params.get(key), params, false)); |
| } else { |
| String val = evaluateParams(params.get(PARAM_PREFIX + key), params, false); |
| evaluatedValue.append(encode ? encode(val) : val); |
| } |
| } |
| n = n2 + 1; |
| n1 = value.indexOf("${", n2); //$NON-NLS-1$ |
| } |
| if (n > -1) { |
| evaluatedValue.append(value.substring(n)); |
| } |
| return evaluatedValue.toString(); |
| } |
| |
| private static Map<String, String> getParams(TaskRepository repository, Map<String, String> params) { |
| Map<String, String> mergedParams = new LinkedHashMap<String, String>(repository.getProperties()); |
| mergedParams.put(PARAM_SERVER_URL, repository.getRepositoryUrl()); |
| AuthenticationCredentials credentials = repository.getCredentials(AuthenticationType.REPOSITORY); |
| if (credentials != null) { |
| mergedParams.put(PARAM_USER_ID, credentials.getUserName()); |
| mergedParams.put(PARAM_PASSWORD, credentials.getPassword()); |
| } |
| if (params != null) { |
| mergedParams.putAll(params); |
| } |
| return mergedParams; |
| } |
| |
| private static String encode(String value) { |
| try { |
| return new URLCodec().encode(value); |
| } catch (EncoderException ex) { |
| return value; |
| } |
| } |
| |
| public static List<String> getTemplateVariables(String value) { |
| if (value == null) { |
| return Collections.emptyList(); |
| } |
| |
| List<String> vars = new ArrayList<String>(); |
| Matcher m = Pattern.compile("\\$\\{(.+?)\\}").matcher(value); //$NON-NLS-1$ |
| while (m.find()) { |
| vars.add(m.group(1)); |
| } |
| return vars; |
| } |
| |
| @Override |
| public boolean hasLocalCompletionState(TaskRepository taskRepository, ITask task) { |
| return true; |
| } |
| |
| @Override |
| public boolean hasTaskChanged(TaskRepository taskRepository, ITask task, TaskData taskData) { |
| preProcessTaskData(task, taskData); |
| return new TaskMapper(taskData).hasChanges(task); |
| } |
| |
| } |