1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 package de.bea.domingo.map;
24
25 import java.util.regex.Matcher;
26 import java.util.regex.Pattern;
27
28 /***
29 * Location of a Notes database.
30 *
31 * @author <a href="mailto:kriede@users.sourceforge.net">Kurt Riede</a>
32 */
33 public final class NotesLocation {
34
35 /*** Protocol of a notes location. */
36 public static final String NOTES_PROTOCOL = "notes:///";
37
38 /*** Protocol of a notes location. */
39 public static final String HTTP_PROTOCOL = "http://";
40
41 /*** Regular expression pattern for protocol section. */
42 private static final String PROTOCOL_PATTERN = "(" + NOTES_PROTOCOL + "|" + HTTP_PROTOCOL + ")";
43
44 /*** Regulare expression pattern for credentials section. */
45 private static final String CREDENTIALS_PATTERN = "(([^!:@]*):([^!:@]*)(@?))?";
46
47 /*** Regular expression pattern for parsing server section. */
48 private static final String SERVER_PATTERN1 = "([^!:@]*(://d+)?)";
49
50 /*** Regular expression pattern for parsing server section. */
51 private static final String SERVER_PATTERN2 = "([^!:@/]*(://d+)?)";
52
53 /*** Regular expression pattern for parsing path section. */
54 private static final String PATH_PATTERN1 = "((!!)(.*))?";
55
56 /*** Regular expression pattern for parsing path section. */
57 private static final String PATH_PATTERN2 = "((/)(.*))?";
58
59 /*** Regular expression pattern for parsing locations. */
60 private static final String LOCATION_PATTERN1 = PROTOCOL_PATTERN + CREDENTIALS_PATTERN + SERVER_PATTERN1 + PATH_PATTERN1;
61
62 /*** Regular expression pattern for parsing locations. */
63 private static final String LOCATION_PATTERN2 = PROTOCOL_PATTERN + CREDENTIALS_PATTERN + SERVER_PATTERN2 + PATH_PATTERN2;
64
65
66
67 /*** Position of protokol token in location pattern matcher. */
68 private static final int PROTOCOL_TOKEN = 1;
69
70 /*** Position of username token in location pattern matcher. */
71 private static final int USERNAME_TOKEN = 3;
72
73 /*** Position of password token in location pattern matcher. */
74 private static final int PASSWORD_TOKEN = 4;
75
76 /*** Position of server token in location pattern matcher. */
77 private static final int SERVER_TOKEN = 6;
78
79 /*** Position of path token in location pattern matcher. */
80 private static final int PATH_TOKEN = 10;
81
82 /*** Alternative identifier for the local host. */
83 private static final String LOKAL_HOST = "lokal";
84
85 /*** Standard identifier for the local host. */
86 public static final String LOCAL_HOST = "local";
87
88 /***
89 * The unparsed location string of a location.
90 *
91 * <p><b>Example:</b><br/>
92 * <code>notes:///mail-server/acme!!mail/my-mail-db.nsf</code></p>
93 */
94 private String mLocation = null;
95
96 /***
97 * The protocol of the location.
98 *
99 * <p><b>Example:</b><br/>
100 * <code>notes:</code>.
101 */
102 private String mProtocol = null;
103
104 /***
105 * The server of the location. <p> <b>Example: </b> <br/><code>MyServer/Acme</code>.
106 */
107 private String mServer = null;
108
109 /***
110 * The path of the location.
111 *
112 * <p><b>Example:</b>
113 * <br/><code>mail/my-mail-db.nsf</code>.</p>
114 */
115 private String mPath = null;
116
117 /*** the IIOP username */
118 private String mUsername = null;
119
120 /*** the IIOP password */
121 private String mPassword = null;
122
123 /***
124 * Factory method for Location objects.
125 *
126 * @param location the location as url-like string
127 * @return the location object
128 */
129 public static synchronized NotesLocation getInstance(final String location) {
130 return new NotesLocation((NotesLocation) null, location);
131 }
132
133 /***
134 * Factory method for local Location.
135 *
136 * @param context parent location
137 * @param server the server
138 * @param path the path
139 * @return the new Location
140 */
141 public static synchronized NotesLocation getInstance(final NotesLocation context, final String server, final String path) {
142 if (context != null && context.isLocal()) {
143 return new NotesLocation(server, path);
144 } else {
145 return new NotesLocation(context, path);
146 }
147 }
148
149 /***
150 * Constructor.
151 *
152 * @param locationUri URI of location of database.
153 */
154 public NotesLocation(final String locationUri) {
155 setLocation(locationUri);
156 }
157
158 /***
159 * Constructor.
160 *
161 * @param context parent location
162 * @param path path relative to context
163 */
164 public NotesLocation(final NotesLocation context, final String path) {
165 if (context != null) {
166 String locationUri = context.toString();
167 int seperatorPos = locationUri.indexOf(getPathSep());
168 if (seperatorPos >= 0) {
169 locationUri = locationUri.substring(0, seperatorPos);
170 }
171 locationUri = locationUri + getPathSep() + path;
172 setLocation(locationUri);
173 } else if (path != null) {
174 setLocation(path);
175 } else {
176 throw new IllegalArgumentException("Must specify at least one of context or path");
177 }
178 }
179
180 /***
181 * Creates a new local location.
182 * This method doesn't handle IIOP locations.
183 *
184 * @param context parent location
185 * @param server the server
186 * @param path path relative to context
187 */
188 public NotesLocation(final NotesLocation context, final String server, final String path) {
189 if (context != null) {
190
191
192 String locationUri = NOTES_PROTOCOL + server + getPathSep() + path;
193 setLocation(locationUri);
194 } else if (path != null) {
195 setLocation(path);
196 } else {
197 throw new RuntimeException("Invalid arguments to create a Notes location");
198 }
199 }
200
201 /***
202 * Constructor for local locations.
203 *
204 * @param server the server
205 * @param path the path
206 */
207 public NotesLocation(final String server, final String path) {
208 setLocation(NOTES_PROTOCOL + server + getPathSep() + path);
209 }
210
211 /***
212 * Sets the location string.
213 *
214 * @param locationUri URI of location of database.
215 */
216 protected void setLocation(final String locationUri) {
217 mLocation = locationUri;
218 parseLocation(mLocation);
219 }
220
221 /***
222 * Parses a notes location. <p> A notes location is built up like this:
223 * <br/><code>"notes:///" + server + "!!" + path</code> <br/>where server
224 * must be a valid notes server name or an empty string and path must be a
225 * valid path and file name of a notes database. </p>
226 *
227 * @throws IllegalArgumentException if the location string is invalid
228 */
229 private void parseLocation(final String location) throws IllegalArgumentException {
230 String pattern = location.indexOf("!!") >= 0 ? LOCATION_PATTERN1 : LOCATION_PATTERN2;
231 Matcher matcher = Pattern.compile(pattern).matcher(location);
232 if (!matcher.matches()) {
233 throw new IllegalArgumentException("Cannot parse location");
234 }
235 mProtocol = matcher.group(PROTOCOL_TOKEN);
236 mUsername = matcher.group(USERNAME_TOKEN);
237 mPassword = matcher.group(PASSWORD_TOKEN);
238 mServer = matcher.group(SERVER_TOKEN);
239 mPath = matcher.group(PATH_TOKEN);
240 normalize();
241 validate();
242 }
243
244 /***
245 * Normalizes the components of the location to empty or <code>null</code>-values.
246 */
247 private void normalize() {
248 if (mUsername != null && mUsername.length() == 0) {
249 mUsername = null;
250 }
251 if (mPassword != null && mPassword.length() == 0) {
252 mPassword = null;
253 }
254 if (mServer == null) {
255 mServer = "";
256 }
257 if (mServer.endsWith("/")) {
258 mServer = mServer.substring(0, mServer.length() - 1);
259 }
260 if (LOCAL_HOST.equals(mServer) || LOKAL_HOST.equals(mServer)) {
261 mServer = "";
262 }
263 if (mPath == null) {
264 mPath = "";
265 }
266 }
267
268 /***
269 * Validates the location.
270 *
271 * @throws IllegalArgumentException if the location is invalid
272 */
273 private void validate() throws IllegalArgumentException {
274 if (!HTTP_PROTOCOL.equals(mProtocol) && !NOTES_PROTOCOL.equals(mProtocol)) {
275 throw new IllegalArgumentException("Unknown protocol: " + mProtocol);
276 }
277 if (HTTP_PROTOCOL.equals(mProtocol) && mServer.length() == 0) {
278 throw new IllegalArgumentException("Http locations need a server");
279 }
280 if (mPassword != null && mUsername == null) {
281 throw new IllegalArgumentException("username missing");
282 }
283 if ((mUsername != null && mUsername.length() > 0) && (mServer.length() == 0)) {
284 throw new IllegalArgumentException("IIOP locations must specify a server");
285 }
286 }
287
288 /***
289 * Returns the IIOP Password.
290 *
291 * @return String
292 * @deprecated use {@link #getPassword()} instead
293 */
294 public String getIIOPPasswd() {
295 return mPassword;
296 }
297
298 /***
299 * Returns the IIOP Password.
300 *
301 * @return String
302 */
303 public String getPassword() {
304 return mPassword;
305 }
306
307 /***
308 * Returns the IIOP Username.
309 *
310 * @return String
311 * @deprecated use {@link #getUsername()} instead
312 */
313 public String getIIOPUser() {
314 return mUsername;
315 }
316
317 /***
318 * Returns the IIOP Username.
319 *
320 * @return String
321 */
322 public String getUsername() {
323 return mUsername;
324 }
325
326 /***
327 * Returns the path of the notes location.
328 *
329 * @return the path of the notes location.
330 */
331 public String getPath() {
332 return mPath;
333 }
334
335 /***
336 * Returns the local location corresponding to this location.
337 * If the location is already local, this instance is returned.
338 * If the location is not local, a new location is returned where
339 * the host of the location is changed to the local host.
340 *
341 * @return local location
342 */
343 public NotesLocation getLocalLocation() {
344 if (isIIOP() || isLocal()) {
345 return this;
346 }
347 return new NotesLocation(getProtocol() + LOCAL_HOST + "!!" + getPath());
348 }
349
350 /***
351 * Checks if a notes location is local or not.
352 *
353 * @return <code>true</code> if the location is local, else
354 * <code>false</code>
355 */
356 public boolean isLocal() {
357 return LOCAL_HOST.equals(mServer) || LOKAL_HOST.equals(mServer) || "".equals(mServer);
358 }
359
360 /***
361 * Checks if the notes location is a IIOP location or not.
362 *
363 * @return <code>true</code> if it is a IIOP location, else <code>false</code>
364 */
365 public boolean isIIOP() {
366 return mUsername != null;
367 }
368
369 /***
370 * Checks if the notes location is using the HTTP protocol.
371 * @return <code>true</code> if the protocol is HTTP, else <code>false</code>
372 */
373 public boolean isHttp() {
374 return mProtocol.equals(HTTP_PROTOCOL);
375 }
376
377 /***
378 * Returns the host of the notes location or <code>null</code> if it's an
379 * IIOP location.
380 *
381 * @return the host of the notes location.
382 */
383 public String getHost() {
384 return mServer;
385 }
386
387 /***
388 * Returns the server part of a location. If the location is a local
389 * location or an IIOP location, then the server the empty string, else the
390 * name of the server.
391 *
392 * @return server part of a location
393 */
394 public String getServer() {
395 if (isIIOP()) {
396 return "";
397 } else {
398 return mServer;
399 }
400 }
401
402 /***
403 * Returns a string representing the local server.
404 * In case of DIIOP (Corba), this must be the empty string,
405 * in case of local call this must be the string <code>"local"</code>.
406 *
407 * @return local server
408 */
409 public String getLocalServer() {
410 if (isIIOP()) {
411 return "";
412 } else {
413 return LOCAL_HOST;
414 }
415 }
416
417 /***
418 * Returns the separator string between host and path
419 * in locations.
420 *
421 * @return separator string between host and path
422 */
423 protected String getPathSep() {
424 return "!!";
425 }
426
427 /***
428 * Returns the protocol of the location.
429 *
430 * @return protocol of location
431 */
432 public String getProtocol() {
433 return mProtocol;
434 }
435
436 /***
437 * @return the location as a string
438 */
439 public String toString() {
440 return mLocation;
441 }
442 }