View Javadoc

1   /*
2    * This file is part of Domingo
3    * an Open Source Java-API to Lotus Notes/Domino
4    * hosted at http://domingo.sourceforge.net
5    *
6    * Copyright (c) 2003-2007 Beck et al. projects GmbH Munich, Germany (http://www.bea.de)
7    *
8    * This library is free software; you can redistribute it and/or
9    * modify it under the terms of the GNU Lesser General Public
10   * License as published by the Free Software Foundation; either
11   * version 2.1 of the License, or (at your option) any later version.
12   *
13   * This library is distributed in the hope that it will be useful,
14   * but WITHOUT ANY WARRANTY; without even the implied warranty of
15   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16   * Lesser General Public License for more details.
17   *
18   * You should have received a copy of the GNU Lesser General Public
19   * License along with this library; if not, write to the Free Software
20   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
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  //  private static final String LOCATION_PATTERN = "(http://|notes:///)(([^!:@]*):([^!:@]*)(@?))?([^!:@/]*)(!!|/)(.*)";
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             // todo what to do with the context?
191 //            String locationUri = context.toString();
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 }