001: /*
002: Copyright (c) 2003 eInnovation Inc. All rights reserved
003:
004: This library is free software; you can redistribute it and/or modify it under the terms
005: of the GNU Lesser General Public License as published by the Free Software Foundation;
006: either version 2.1 of the License, or (at your option) any later version.
007:
008: This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
009: without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
010: See the GNU Lesser General Public License for more details.
011: */
012:
013: /*--
014:
015: Copyright (C) 2001-2002 Anthony Eden.
016: All rights reserved.
017:
018: Redistribution and use in source and binary forms, with or without
019: modification, are permitted provided that the following conditions
020: are met:
021:
022: 1. Redistributions of source code must retain the above copyright
023: notice, this list of conditions, and the following disclaimer.
024:
025: 2. Redistributions in binary form must reproduce the above copyright
026: notice, this list of conditions, and the disclaimer that follows
027: these conditions in the documentation and/or other materials
028: provided with the distribution.
029:
030: 3. The name "JPublish" must not be used to endorse or promote products
031: derived from this software without prior written permission. For
032: written permission, please contact me@anthonyeden.com.
033:
034: 4. Products derived from this software may not be called "JPublish", nor
035: may "JPublish" appear in their name, without prior written permission
036: from Anthony Eden (me@anthonyeden.com).
037:
038: In addition, I request (but do not require) that you include in the
039: end-user documentation provided with the redistribution and/or in the
040: software itself an acknowledgement equivalent to the following:
041: "This product includes software developed by
042: Anthony Eden (http://www.anthonyeden.com/)."
043:
044: THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
045: WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
046: OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
047: DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT,
048: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
049: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
050: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
051: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
052: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
053: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
054: POSSIBILITY OF SUCH DAMAGE.
055:
056: For more information on JPublish, please see <http://www.jpublish.org/>.
057:
058: */
059: package com.openedit.util;
060:
061: import org.apache.commons.logging.Log;
062: import org.apache.commons.logging.LogFactory;
063:
064: /**
065: * Utility class for working with request paths.
066: *
067: * @author Anthony Eden
068: */
069: public final class PathUtilities {
070: private static final Log log = LogFactory
071: .getLog(PathUtilities.class);
072: private static final String WILDCARD = "*";
073:
074: /**
075: * Internal constructor.
076: */
077: public PathUtilities() {
078: // no op
079: }
080:
081: /**
082: * Get the parent of the given path.
083: *
084: * @param path The path for which to retrieve the parent
085: *
086: * @return The parent path. /sub/sub2/index.html -> /sub/sub2 If the given path is the root path ("/" or ""), return a blank string.
087: */
088: public static String extractDirectoryPath(String path) {
089: if ((path == null) || path.equals("") || path.equals("/")) {
090: return "";
091: }
092:
093: int lastSlashPos = path.lastIndexOf('/');
094:
095: if (lastSlashPos >= 0) {
096: return path.substring(0, lastSlashPos); //strip off the slash
097: } else {
098: return ""; //we expect people to add + "/somedir on their own
099: }
100: }
101:
102: /**
103: * Builds a path that might be within or one above a parent path String ret =
104: * buildRelative("../junk.txt","/a/b/c/something.html") Will return /a/b/junk.txt This code
105: * only returns a changed endPart if it starts with a dot .
106: *
107: * @param endPart
108: * @param fullParentPath
109: *
110: * @return
111: */
112: public static String buildRelative(String endPart,
113: String fullParentPath) {
114: String basepath = null;
115: if (fullParentPath != null) {
116: fullParentPath = fullParentPath.replace('\\', '/');
117: }
118: //TODO: Make this work with random number of dots
119:
120: //if we are dealing with relative path then we need to make sure the basepath ends with a /
121: if (endPart.startsWith(".") && (fullParentPath != null)
122: && !fullParentPath.endsWith("/")) {
123: //so with this function /examples/benchmark -> /examples/benchmark/
124: //is this parent a directory or a file, lets check for a .
125: int lastslash = fullParentPath.lastIndexOf("/");
126: int lastperiod = fullParentPath.lastIndexOf(".");
127:
128: if (lastslash > lastperiod) {
129: //must be a directory
130: basepath = fullParentPath;
131: }
132: }
133:
134: if (basepath == null) {
135: basepath = PathUtilities
136: .extractDirectoryPath(fullParentPath);
137: }
138: if (basepath == null) {
139: basepath = "";
140: }
141:
142: String relative = endPart;
143:
144: if (endPart.startsWith("..")) {
145: //strip the filename
146: if (basepath.endsWith("/")) {
147: basepath = basepath.substring(0, basepath.length() - 1);
148: }
149:
150: basepath = basepath.substring(0, basepath.lastIndexOf("/"));
151: relative = basepath + endPart.substring(2);
152: } else if (endPart.startsWith(".")) {
153: relative = basepath + endPart.substring(1);
154: }
155: if (!relative.startsWith("/")) {
156: relative = "/" + relative;
157: }
158: return relative;
159: }
160:
161: /**
162: * Extract the page name from the given path. The page name is the name of the file in the
163: * path without its suffix.
164: * i.e. /subpath/index.html -> index
165: *
166: * @param path The request path
167: *
168: * @return The page name
169: */
170: public static String extractPageName(String path) {
171: if (path == null) {
172: return null;
173: }
174: String newpath = path.replace('\\', '/');
175: int start = newpath.lastIndexOf("/");
176: if (start == -1) {
177: start = 0;
178: } else {
179: start++; //to remove slash
180: }
181: int dotIndex = newpath.lastIndexOf(".");
182:
183: if (dotIndex == -1 || start > dotIndex) {
184: return null;
185: }
186: String pageName = newpath.substring(start, dotIndex);
187:
188: return pageName;
189: }
190:
191: /**
192: * Extract the page path from the given request path. This method will return the path from
193: * the page root to the page descriptor file.
194: *
195: * /some/sub/dir/test.html -> /some/sub/dir/test
196: *
197: * @param path The request path
198: * @see extractDirectory
199: * @return The page path
200: */
201: public static String extractPagePath(String path) {
202: if (path != null && path.length() > 0) {
203: int lastDot = path.lastIndexOf(".");
204: if (lastDot > 1) {
205: String pagePath = path.substring(0, lastDot);
206: return pagePath;
207: }
208: }
209: return path;
210: }
211:
212: /**
213: * Return the page type extracting it from the path. For example: index.html would return
214: * "html" as the page type. If the type cannot be determined then this method returns null.
215: *
216: * @param path The path
217: *
218: * @return The page type
219: */
220: public static String extractPageType(String path) {
221: int dotIndex = path.lastIndexOf(".");
222:
223: if (dotIndex == -1) {
224: return null;
225: }
226:
227: String pageType = path.substring(dotIndex + 1);
228:
229: return pageType;
230: }
231:
232: /**
233: * Match a path which may contain a wildcard.
234: *
235: * @param requestPath The request path submitted by the client
236: * @param exPath The match path with * wildcard
237: *
238: * @return DOCME
239: */
240: public static boolean match(String requestPath, String wildcardPath) {
241: //log.debug("match(" + requestPath + "," + exPath + ")");
242: int wildcardIndex = wildcardPath.indexOf(WILDCARD);
243:
244: if (wildcardIndex == -1) {
245: return requestPath.equalsIgnoreCase(wildcardPath);
246: } else if (wildcardPath.charAt(0) == '*'
247: && wildcardPath.charAt(wildcardPath.length() - 1) == '*') {
248: String path = wildcardPath.substring(1, wildcardPath
249: .length() - 1);
250: return requestPath.indexOf(path) > -1;
251: } else if (wildcardIndex == (wildcardPath.length() - 1)) //ends with
252: {
253: //log.debug("Wildcard appears at end of match path.");
254: String checkString = wildcardPath.substring(0, wildcardPath
255: .length() - 1);
256:
257: //log.debug("String after wildcard removed: " + checkString);
258: boolean answer = requestPath.startsWith(checkString);
259:
260: //log.debug("Does " + requestPath + " start with " + checkString + "? " + answer);
261: return answer;
262: } else if (wildcardPath.charAt(0) == '*') {
263: String checkString = wildcardPath.substring(1);
264:
265: //log.debug("String after wildcard removed: " + checkString);
266: boolean answer = requestPath.endsWith(checkString);
267: return answer;
268: } else {
269: //log.debug("Wildcard appears in the middle of the string");
270: String preMatch = wildcardPath.substring(0, wildcardIndex);
271: String postMatch = wildcardPath
272: .substring(wildcardIndex + 1);
273:
274: return requestPath.startsWith(preMatch)
275: && requestPath.endsWith(postMatch);
276: }
277: }
278:
279: /**
280: * resolve a relative URL string against an absolute URL string.
281: *
282: * This method was adapted from the CalCom library at http://www.calcom.de
283: *
284: * <p>the absolute URL string is the start point for the
285: * relative path.</p>
286: *
287: * <p><b>Example:</b></p>
288: * <pre>
289: * relative path: ../images/test.jpg
290: * absolute path: file:/d:/eigene dateien/eigene bilder/
291: * result: file:/d:/eigene dateien/images/test.jpg
292: * </pre>
293: *
294: * @param relPath The relative URL string to resolve. Unlike the Calcom version, this may be
295: * an absolute path, if it starts with "/".
296: * @param absPath The absolute URL string to start at. Unlike the CalCom version, this may be a filename
297: * rather than just a path.
298: *
299: * @return the absolute URL string resulting from resolving relPath against absPath
300: *
301: * @author Ulrich Hilger
302: * @author CalCom
303: * @author <a href="http://www.calcom.de">http://www.calcom.de</a>
304: * @author <a href="mailto:info@calcom.de">info@calcom.de</a>
305: * @author Dennis Brown (eInnovation)
306: */
307: public static String resolveRelativePath(String relPath,
308: String absPath) {
309: // if relative path is really absolute, then ignore absPath (eInnovation change)
310: if (relPath.startsWith("/")) {
311: absPath = "";
312: }
313:
314: String newAbsPath = absPath;
315: String newRelPath = relPath;
316: if (relPath.startsWith("$")) {
317: return relPath;
318: } else if (absPath.endsWith("/")) {
319: newAbsPath = absPath.substring(0, absPath.length() - 1);
320: } else {
321: // absPath ends with a filename, remove it (eInnovation change)
322: int lastSlashIndex = absPath.lastIndexOf('/');
323: if (lastSlashIndex >= 0) {
324: newAbsPath = absPath.substring(0, lastSlashIndex);
325: } else {
326: newAbsPath = "";
327: }
328: }
329:
330: int relPos = newRelPath.indexOf("../");
331: while (relPos > -1) {
332: newRelPath = newRelPath.substring(relPos + 3);
333: int lastSlashInAbsPath = newAbsPath.lastIndexOf("/");
334: if (lastSlashInAbsPath >= 0) {
335: newAbsPath = newAbsPath.substring(0, newAbsPath
336: .lastIndexOf("/"));
337: } else {
338: // eInnovation change: fix potential exception
339: newAbsPath = "";
340: }
341: relPos = newRelPath.indexOf("../");
342: }
343: String returnedPath;
344: if (newRelPath.startsWith("/")) {
345: returnedPath = newAbsPath + newRelPath;
346: } else {
347: returnedPath = newAbsPath + "/" + newRelPath;
348: }
349:
350: // remove any "." references to current directory (eInnovation change)
351: // For example:
352: // "./junk" becomes "junk"
353: // "/./junk" becomes "/junk"
354: // "junk/." becomes "junk"
355: while (returnedPath.endsWith("/.")) {
356: returnedPath = returnedPath.substring(0, returnedPath
357: .length() - 2);
358: }
359: do {
360: int dotSlashIndex = returnedPath.lastIndexOf("./");
361: if (dotSlashIndex < 0) {
362: break;
363: } else if (dotSlashIndex == 0
364: || returnedPath.charAt(dotSlashIndex - 1) != '.') {
365: String firstSubstring;
366: if (dotSlashIndex > 0) {
367: firstSubstring = returnedPath.substring(0,
368: dotSlashIndex);
369: } else {
370: firstSubstring = "";
371: }
372: String secondSubstring;
373: if (dotSlashIndex + 2 < returnedPath.length()) {
374: secondSubstring = returnedPath.substring(
375: dotSlashIndex + 2, returnedPath.length());
376: } else {
377: secondSubstring = "";
378: }
379: returnedPath = firstSubstring + secondSubstring;
380: }
381: } while (true);
382:
383: return returnedPath;
384: }
385:
386: /**
387: * Pass in /sub/dir/path.html returns path.html
388: * @param inPath
389: * @return
390: */
391: public static String extractFileName(String path) {
392:
393: if (path == null) {
394: return null;
395: }
396: String newpath = path.replace('\\', '/');
397: int start = newpath.lastIndexOf("/");
398: if (start == -1) {
399: start = 0;
400: } else {
401: start = start + 1;
402: }
403: String pageName = newpath.substring(start, newpath.length());
404:
405: return pageName;
406: }
407:
408: public static String createDraftPath(String inPath) {
409: if (inPath != null) {
410: if (!inPath.contains(".draft.")) {
411: String root = PathUtilities.extractPagePath(inPath);
412: String p = root + ".draft."
413: + PathUtilities.extractPageType(inPath);
414: return p;
415: }
416: }
417: return inPath;
418: }
419:
420: public static String createLivePath(String inDraftPath) {
421: if (inDraftPath != null) {
422: if (inDraftPath.contains(".draft.")) {
423: return inDraftPath.replace(".draft", "");
424: }
425: }
426: return inDraftPath;
427: }
428:
429: public static String makeId(String inText) {
430: String id = inText;
431: id = id.replace("\\/", "_");
432: id = id.replace(".", "_");
433: id = id.replace(" ", "_");
434: if (id.charAt(0) == '_') {
435: id = id.substring(1, id.length());
436: }
437: return id;
438: }
439: }
|