Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
View | Details | Raw Unified | Return to bug 148090
Collapse All | Expand All

(-)src/org/eclipse/mylar/trac/tests/AllTracTests.java (+4 lines)
Lines 26-31 Link Here
26
		suite.addTestSuite(TracXmlRpcTest.class);
26
		suite.addTestSuite(TracXmlRpcTest.class);
27
		suite.addTestSuite(TracSearchTest.class);
27
		suite.addTestSuite(TracSearchTest.class);
28
		suite.addTestSuite(TracTicketTest.class);
28
		suite.addTestSuite(TracTicketTest.class);
29
		suite.addTestSuite(TracXmlRpcRepositoryTest.class);
30
		suite.addTestSuite(TracXmlRpcRepositorySearchTest.class);
31
		suite.addTestSuite(Trac09RepositoryTest.class);
32
		suite.addTestSuite(Trac09RepositorySearchTest.class);
29
		//$JUnit-END$
33
		//$JUnit-END$
30
		return suite;
34
		return suite;
31
	}
35
	}
(-)src/org/eclipse/mylar/trac/tests/Trac09RepositoryTest.java (+39 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2006 - 2006 Mylar eclipse.org project and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     Mylar project committers - initial API and implementation
10
 *******************************************************************************/
11
12
package org.eclipse.mylar.trac.tests;
13
14
import java.net.URL;
15
16
import org.eclipse.mylar.internal.trac.core.ITracRepository;
17
import org.eclipse.mylar.internal.trac.core.Trac09Repository;
18
import org.eclipse.mylar.internal.trac.core.ITracRepository.Version;
19
import org.eclipse.mylar.trac.tests.support.AbstractTracRepositoryFactory;
20
21
/**
22
 * @author Steffen Pingel
23
 */
24
public class Trac09RepositoryTest extends AbstractTracRepositoryTest {
25
26
	public Trac09RepositoryTest() {
27
		super(new AbstractTracRepositoryFactory() {
28
			protected ITracRepository createRepository(String url, String username, String password) throws Exception {
29
				return new Trac09Repository(new URL(url), Version.TRAC_0_9, username, password);
30
			}
31
		});
32
	}
33
34
	public void testValidateAnonymousLogin() throws Exception {
35
		factory.connect(Constants.TEST_REPOSITORY1_URL, "", "");
36
		factory.repository.validate();
37
	}
38
39
}
(-)src/org/eclipse/mylar/trac/tests/Trac09RepositorySearchTest.java (+34 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2006 - 2006 Mylar eclipse.org project and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     Mylar project committers - initial API and implementation
10
 *******************************************************************************/
11
12
package org.eclipse.mylar.trac.tests;
13
14
import java.net.URL;
15
16
import org.eclipse.mylar.internal.trac.core.ITracRepository;
17
import org.eclipse.mylar.internal.trac.core.Trac09Repository;
18
import org.eclipse.mylar.internal.trac.core.ITracRepository.Version;
19
import org.eclipse.mylar.trac.tests.support.AbstractTracRepositoryFactory;
20
21
/**
22
 * @author Steffen Pingel
23
 */
24
public class Trac09RepositorySearchTest extends AbstractTracRepositorySearchTest {
25
26
	public Trac09RepositorySearchTest() {
27
		super(new AbstractTracRepositoryFactory() {
28
			protected ITracRepository createRepository(String url, String username, String password) throws Exception {
29
				return new Trac09Repository(new URL(url), Version.TRAC_0_9, username, password);
30
			}
31
		});
32
	}
33
34
}
(-)src/org/eclipse/mylar/internal/trac/core/Trac09Repository.java (+248 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2006 - 2006 Mylar eclipse.org project and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     Mylar project committers - initial API and implementation
10
 *******************************************************************************/
11
12
package org.eclipse.mylar.internal.trac.core;
13
14
import java.io.BufferedInputStream;
15
import java.io.BufferedReader;
16
import java.io.IOException;
17
import java.io.InputStream;
18
import java.io.InputStreamReader;
19
import java.net.HttpURLConnection;
20
import java.net.URL;
21
import java.security.KeyManagementException;
22
import java.security.NoSuchAlgorithmException;
23
import java.util.HashMap;
24
import java.util.List;
25
import java.util.Map;
26
import java.util.StringTokenizer;
27
28
import javax.security.auth.login.LoginException;
29
30
import org.eclipse.mylar.internal.core.util.MylarStatusHandler;
31
import org.eclipse.mylar.internal.trac.MylarTracPlugin;
32
import org.eclipse.mylar.internal.trac.model.TracSearch;
33
import org.eclipse.mylar.internal.trac.model.TracSearchFilter;
34
import org.eclipse.mylar.internal.trac.model.TracTicket;
35
import org.eclipse.mylar.internal.trac.model.TracSearchFilter.CompareOperator;
36
import org.eclipse.mylar.internal.trac.model.TracTicket.Key;
37
38
public class Trac09Repository extends AbstractTracRepository {
39
40
	private static final String TICKET_SUMMARY_PREFIX = " <h2 class=\"summary\">";
41
42
	private static final String TICKET_SUMMARY_POSTFIX = "</h2>";
43
44
	private InputStream in;
45
46
	private String authCookie;
47
48
	public Trac09Repository(URL url, Version version, String username, String password) {
49
		super(url, version, username, password);
50
	}
51
52
	public void close() {
53
		if (in != null) {
54
			try {
55
				in.close();
56
			} catch (IOException e) {
57
				MylarStatusHandler.log(e, "Error closing connection");
58
			}
59
			in = null;
60
		}
61
	}
62
63
	public void connect(String serverURL) throws TracException {
64
		try {
65
			connectInternal(new URL(serverURL));
66
		} catch (TracException e) {
67
			throw e;
68
		} catch (Exception e) {
69
			throw new TracException(e);
70
		}
71
	}
72
73
	public void connectInternal(URL serverURL) throws IOException, KeyManagementException, NoSuchAlgorithmException,
74
			TracLoginException {
75
		for (int attempt = 0; attempt < 2; attempt++) {
76
			HttpURLConnection serverConnection = MylarTracPlugin.getHttpConnection(serverURL);
77
			setupSession(serverConnection);
78
79
			serverConnection.connect();
80
81
			int code = serverConnection.getResponseCode();
82
			if (code == HttpURLConnection.HTTP_UNAUTHORIZED || code == HttpURLConnection.HTTP_FORBIDDEN) {
83
				// retry to authenticate due to an expired session
84
				authCookie = null;
85
				continue;
86
			}
87
88
			in = new BufferedInputStream(serverConnection.getInputStream());
89
			return;
90
		}
91
92
		throw new TracLoginException();
93
	}
94
95
	private void setupSession(HttpURLConnection serverConnection) throws IOException, TracLoginException,
96
			KeyManagementException, NoSuchAlgorithmException {
97
		if (hasAuthenticationCredentials()) {
98
			if (authCookie == null) {
99
				// go through the /login page redirection
100
				HttpURLConnection loginConnection = MylarTracPlugin
101
						.getHttpConnection(new URL(repositoryUrl + LOGIN_URL));
102
				MylarTracPlugin.setAuthCredentials(loginConnection, username, password);
103
104
				loginConnection.connect();
105
106
				int code = loginConnection.getResponseCode();
107
				if (code == HttpURLConnection.HTTP_UNAUTHORIZED || code == HttpURLConnection.HTTP_FORBIDDEN) {
108
					throw new TracLoginException();
109
				}
110
111
				String cookie = loginConnection.getHeaderField("Set-Cookie");
112
				if (cookie == null) {
113
					throw new TracLoginException("Missing authorization cookie");
114
				}
115
116
				int index = cookie.indexOf(";");
117
				if (index >= 0) {
118
					cookie = cookie.substring(0, index);
119
				}
120
				authCookie = cookie;
121
			}
122
123
			serverConnection.setRequestProperty("Cookie", authCookie);
124
		}
125
	}
126
127
	/**
128
	 * Fetches the web site of a single ticket and returns the Trac ticket.
129
	 * 
130
	 * @param id
131
	 *            Trac id of ticket
132
	 * @throws LoginException
133
	 */
134
	public TracTicket getTicket(int id) throws TracException {
135
		connect(repositoryUrl + ITracRepository.TICKET_URL + id);
136
		try {
137
			BufferedReader reader = new BufferedReader(new InputStreamReader(in, ITracRepository.CHARSET));
138
			String line;
139
			while ((line = reader.readLine()) != null) {
140
				// look for heading tags in html output
141
				if (line.startsWith(TICKET_SUMMARY_PREFIX) && line.endsWith(TICKET_SUMMARY_POSTFIX)) {
142
					String summary = line.substring(TICKET_SUMMARY_PREFIX.length(), line.length()
143
							- TICKET_SUMMARY_POSTFIX.length());
144
145
					TracTicket ticket = new TracTicket(id);
146
					ticket.putBuiltinValue(Key.SUMMARY, summary);
147
					return ticket;
148
				}
149
			}
150
			throw new InvalidTicketException();
151
		} catch (IOException e) {
152
			throw new TracException(e);
153
		} finally {
154
			close();
155
		}
156
	}
157
158
	public void search(TracSearch query, List<TracTicket> tickets) throws TracException {
159
		connect(repositoryUrl + ITracRepository.QUERY_URL + query.toUrl());
160
		try {
161
			BufferedReader reader = new BufferedReader(new InputStreamReader(in, ITracRepository.CHARSET));
162
			String line;
163
164
			Map<String, String> constantValues = getExactMatchValues(query);
165
166
			// first line contains names of returned ticket fields
167
			line = reader.readLine();
168
			if (line == null) {
169
				throw new InvalidTicketException();
170
			}
171
			StringTokenizer t = new StringTokenizer(line, "\t");
172
			Key[] fields = new Key[t.countTokens()];
173
			for (int i = 0; i < fields.length; i++) {
174
				fields[i] = Key.fromKey(t.nextToken());
175
			}
176
177
			// create a ticket for each following line of output
178
			while ((line = reader.readLine()) != null) {
179
				t = new StringTokenizer(line, "\t");
180
				TracTicket ticket = new TracTicket();
181
				for (int i = 0; i < fields.length && t.hasMoreTokens(); i++) {
182
					if (fields[i] != null) {
183
						try {
184
							if (fields[i] == Key.ID) {
185
								ticket.setId(Integer.parseInt(t.nextToken()));
186
							} else if (fields[i] == Key.TIME) {
187
								ticket.setCreated(Integer.parseInt(t.nextToken()));
188
							} else if (fields[i] == Key.CHANGE_TIME) {
189
								ticket.setLastChanged(Integer.parseInt(t.nextToken()));
190
							} else {
191
								ticket.putBuiltinValue(fields[i], parseTicketValue(t.nextToken()));
192
							}
193
						} catch (NumberFormatException e) {
194
							MylarStatusHandler.log(e, "Error parsing repsonse: " + line);
195
						}
196
					}
197
				}
198
199
				if (ticket.isValid()) {
200
					for (String key : constantValues.keySet()) {
201
						ticket.putTracValue(key, parseTicketValue(constantValues.get(key)));
202
					}
203
204
					tickets.add(ticket);
205
				}
206
			}
207
		} catch (IOException e) {
208
			throw new TracException(e);
209
		} finally {
210
			close();
211
		}
212
	}
213
214
	/**
215
	 * Trac has sepcial encoding rules for the returned output: None is
216
	 * represented by "--".
217
	 */
218
	private String parseTicketValue(String value) {
219
		if ("--".equals(value)) {
220
			return "";
221
		}
222
		return value;
223
	}
224
225
	/**
226
	 * Extracts constant values from <code>query</code>. The Trac query
227
	 * script does not return fields that matched exactly againt a single value.
228
	 */
229
	private Map<String, String> getExactMatchValues(TracSearch query) {
230
		Map<String, String> values = new HashMap<String, String>();
231
		List<TracSearchFilter> filters = query.getFilters();
232
		for (TracSearchFilter filter : filters) {
233
			if (filter.getOperator() == CompareOperator.IS && filter.getValues().size() == 1) {
234
				values.put(filter.getFieldName(), filter.getValues().get(0));
235
			}
236
		}
237
		return values;
238
	}
239
240
	public void validate() throws TracException {
241
		try {
242
			connect(repositoryUrl + "/");
243
		} finally {
244
			close();
245
		}
246
	}
247
248
}

Return to bug 148090