/******************************************************************************* * Copyright (c) 2009 IBM Corporation 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: * IBM Corporation - initial API and implementation * Zend Technologies *******************************************************************************/ package org.eclipse.php.internal.debug.core.pathmapper; import java.util.Iterator; import java.util.LinkedList; import java.util.StringTokenizer; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * This class represents path-style entities (file-system paths, URLs). Paths * are case insensitive. * * @author michael */ public class VirtualPath implements Cloneable { private static final Pattern VOLNAME = Pattern.compile("([A-Za-z]:)[/\\\\](.*)"); //$NON-NLS-1$ private static final Pattern PROTOCOL = Pattern.compile("([A-Za-z]*://)(.*)"); //$NON-NLS-1$ private LinkedList<String> segments; private String device; private char sepChar; /** * Constructs new abstract path instance * * @param path * Full path */ public VirtualPath(String path) { if (path == null) { throw new NullPointerException(); } if (path.startsWith("\\\\")) { // Network path //$NON-NLS-1$ sepChar = '\\'; device = "\\\\"; //$NON-NLS-1$ path = path.substring(2); } if (path.startsWith("\\")) { //$NON-NLS-1$ sepChar = '\\'; device = "\\"; //$NON-NLS-1$ path = path.substring(1); } else { Matcher m = VOLNAME.matcher(path); if (m.matches()) { // Windows path sepChar = '\\'; device = m.group(1) + "\\"; // correct path from //$NON-NLS-1$ // C:/ to C:\ path = m.group(2); } else if (path.startsWith("/")) { // Unix path //$NON-NLS-1$ sepChar = '/'; device = "/"; //$NON-NLS-1$ } else { m = PROTOCOL.matcher(path); if (m.matches()) { // URL sepChar = '/'; device = m.group(1); path = m.group(2); } else { throw new IllegalArgumentException("Illegal or not full path: " + path);//$NON-NLS-1$ } } } StringTokenizer st = new StringTokenizer(path, "/\\"); //$NON-NLS-1$ segments = new LinkedList<String>(); while (st.hasMoreTokens()) { String segment = st.nextToken(); if (segment.length() > 0) { segments.add(segment); } } } /** * Checks whether the given path is absolute * * @param path * @return <code>true</code> if given path is the absolute one, otherwise * <code>false</code> */ public static boolean isAbsolute(String path) { return (path.startsWith("\\\\") || VOLNAME.matcher(path).matches() //$NON-NLS-1$ || path.startsWith("/") || PROTOCOL.matcher(path).matches()); //$NON-NLS-1$ } protected VirtualPath(String device, char sepChar, LinkedList<String> segments) { this.device = device; this.sepChar = sepChar; this.segments = segments; } public String getLastSegment() { return segments.getLast(); } public int getSegmentsCount() { return segments.size(); } public String removeFirstSegment() { return segments.removeFirst(); } public String removeLastSegment() { return segments.removeLast(); } public void addLastSegment(String segment) { segments.addLast(segment); } public String[] getSegments() { return segments.toArray(new String[segments.size()]); } public char getSeparatorChar() { return sepChar; } public boolean isPrefixOf(VirtualPath path) { Iterator<String> i1 = segments.iterator(); Iterator<String> i2 = path.segments.iterator(); while (i1.hasNext() && i2.hasNext()) { if (!i1.next().equals(i2.next())) { return false; } } return !i1.hasNext(); } public String toString() { StringBuilder buf = new StringBuilder(device); Iterator<String> i = segments.iterator(); while (i.hasNext()) { buf.append(i.next()); if (i.hasNext()) { buf.append(sepChar); } } return buf.toString(); } public VirtualPath clone() { LinkedList<String> segments = new LinkedList<String>(); Iterator<String> i = this.segments.iterator(); while (i.hasNext()) { segments.add(i.next()); } VirtualPath path = new VirtualPath(device, sepChar, segments); return path; } public int hashCode() { return device.hashCode() + 13 * segments.hashCode() + 31 * sepChar; } public boolean equals(Object obj) { if (!(obj instanceof VirtualPath)) { return false; } VirtualPath other = (VirtualPath) obj; boolean segmentsEqual = other.segments.size() == segments.size(); if (segmentsEqual) { Iterator<String> i = segments.iterator(); Iterator<String> j = other.segments.iterator(); while (segmentsEqual && i.hasNext() && j.hasNext()) { segmentsEqual &= i.next().equalsIgnoreCase(j.next()); } } return other.device.equalsIgnoreCase(device) && segmentsEqual && other.sepChar == sepChar; } }