1 19 20 package org.netbeans.modules.subversion.util; 21 22 import org.netbeans.modules.subversion.client.SvnClient; 23 import org.openide.*; 24 import org.openide.cookies.EditorCookie; 25 import org.openide.nodes.Node; 26 import org.openide.windows.TopComponent; 27 import org.openide.util.Lookup; 28 import org.openide.filesystems.FileUtil; 29 import org.openide.filesystems.FileObject; 30 import org.openide.loaders.DataObject; 31 import org.openide.loaders.DataShadow; 32 import org.openide.loaders.DataObjectNotFoundException; 33 import org.netbeans.api.project.*; 34 import org.netbeans.api.fileinfo.NonRecursiveFolder; 35 import org.netbeans.modules.subversion.FileStatusCache; 36 import org.netbeans.modules.subversion.Subversion; 37 import org.netbeans.modules.subversion.FileInformation; 38 import org.netbeans.modules.subversion.SvnFileNode; 39 40 import java.io.*; 41 import java.lang.Character ; 42 import java.util.*; 43 import java.text.ParseException ; 44 import java.util.regex.Matcher ; 45 import java.util.regex.Pattern ; 46 import java.util.regex.PatternSyntaxException ; 47 import org.netbeans.modules.subversion.SvnModuleConfig; 48 import org.netbeans.modules.subversion.client.ExceptionHandler; 49 import org.netbeans.modules.subversion.options.AnnotationExpression; 50 import org.netbeans.modules.versioning.util.FlatFolder; 51 import org.tigris.subversion.svnclientadapter.*; 52 import org.tigris.subversion.svnclientadapter.utils.SVNUrlUtils; 53 54 60 public class SvnUtils { 61 62 private static final Pattern metadataPattern = Pattern.compile(".*\\" + File.separatorChar + "(\\.|_)svn(\\" + File.separatorChar + ".*|$)"); 63 64 private static Node [] contextNodesCached; 65 private static Context contextCached; 66 67 76 public static Context getCurrentContext(Node[] nodes) { 77 if (nodes == null) { 78 nodes = TopComponent.getRegistry().getActivatedNodes(); 79 } 80 if (Arrays.equals(contextNodesCached, nodes)) return contextCached; 81 List<File> files = new ArrayList<File>(nodes.length); 82 List<File> rootFiles = new ArrayList<File>(nodes.length); 83 List<File> rootFileExclusions = new ArrayList<File>(5); 84 for (int i = 0; i < nodes.length; i++) { 85 Node node = nodes[i]; 86 SvnFileNode svnNode = (SvnFileNode) node.getLookup().lookup(SvnFileNode.class); 87 if (svnNode != null) { 88 files.add(svnNode.getFile()); 89 rootFiles.add(svnNode.getFile()); 90 continue; 91 } 92 Project project = (Project) node.getLookup().lookup(Project.class); 93 if (project != null) { 94 addProjectFiles(files, rootFiles, rootFileExclusions, project); 95 continue; 96 } 97 addFileObjects(node, files, rootFiles); 98 } 99 100 contextCached = new Context(files, rootFiles, rootFileExclusions); 101 contextNodesCached = nodes; 102 return contextCached; 103 } 104 105 106 117 public static Context getCurrentContext(Node[] nodes, int includingFileStatus, int includingFolderStatus) { 118 Context context = getCurrentContext(nodes); 119 FileStatusCache cache = Subversion.getInstance().getStatusCache(); 120 File [] files = context.getRootFiles(); 121 for (int i = 0; i < files.length; i++) { 122 File file = files[i]; 123 FileInformation fi = cache.getStatus(file); 124 if (file.isDirectory()) { 125 if ((fi.getStatus() & includingFolderStatus) == 0) return Context.Empty; 126 } else { 127 if ((fi.getStatus() & includingFileStatus) == 0) return Context.Empty; 128 } 129 } 130 return context; 131 } 132 133 141 public static boolean isVersionedProject(Node node) { 142 Lookup lookup = node.getLookup(); 143 Project project = (Project) lookup.lookup(Project.class); 144 return isVersionedProject(project); 145 } 146 147 155 public static boolean isVersionedProject(Project project) { 156 if (project != null) { 157 FileStatusCache cache = Subversion.getInstance().getStatusCache(); 158 Sources sources = ProjectUtils.getSources(project); 159 SourceGroup [] sourceGroups = sources.getSourceGroups(Sources.TYPE_GENERIC); 160 for (int j = 0; j < sourceGroups.length; j++) { 161 SourceGroup sourceGroup = sourceGroups[j]; 162 File f = FileUtil.toFile(sourceGroup.getRootFolder()); 163 if ((cache.getStatus(f).getStatus() & FileInformation.STATUS_MANAGED) != 0) return true; } 172 } 173 return false; 174 } 175 176 private static void addFileObjects(Node node, List<File> files, List<File> rootFiles) { 177 Collection<? extends NonRecursiveFolder> folders = node.getLookup().lookup(new Lookup.Template<NonRecursiveFolder>(NonRecursiveFolder.class)).allInstances(); 178 List<File> nodeFiles = new ArrayList<File>(); 179 if (folders.size() > 0) { 180 for (NonRecursiveFolder j : folders) { 181 nodeFiles.add(new FlatFolder(FileUtil.toFile(j.getFolder()).getAbsolutePath())); 182 } 183 } else { 184 Collection<? extends FileObject> fileObjects = node.getLookup().lookup(new Lookup.Template<FileObject>(FileObject.class)).allInstances(); 185 if (fileObjects.size() > 0) { 186 nodeFiles.addAll(toFileCollection(fileObjects)); 187 } else { 188 DataObject dataObject = node.getCookie(DataObject.class); 189 if (dataObject instanceof DataShadow) { 190 dataObject = ((DataShadow) dataObject).getOriginal(); 191 } 192 if (dataObject != null) { 193 Collection<File> doFiles = toFileCollection(dataObject.files()); 194 nodeFiles.addAll(doFiles); 195 } 196 } 197 } 198 files.addAll(nodeFiles); 199 rootFiles.addAll(nodeFiles); 200 } 201 202 208 public static void addProjectFiles(Collection<File> filteredFiles, Collection<File> rootFiles, Collection<File> rootFilesExclusions, Project project) { 209 FileStatusCache cache = Subversion.getInstance().getStatusCache(); 210 Sources sources = ProjectUtils.getSources(project); 211 SourceGroup [] sourceGroups = sources.getSourceGroups(Sources.TYPE_GENERIC); 212 for (int j = 0; j < sourceGroups.length; j++) { 213 SourceGroup sourceGroup = sourceGroups[j]; 214 FileObject srcRootFo = sourceGroup.getRootFolder(); 215 File rootFile = FileUtil.toFile(srcRootFo); 216 if ((cache.getStatus(rootFile).getStatus() & FileInformation.STATUS_MANAGED) == 0) continue; 217 rootFiles.add(rootFile); 218 boolean containsSubprojects = false; 219 FileObject [] rootChildren = srcRootFo.getChildren(); 220 Set<File> projectFiles = new HashSet<File>(rootChildren.length); 221 for (int i = 0; i < rootChildren.length; i++) { 222 FileObject rootChildFo = rootChildren[i]; 223 if (Subversion.getInstance().isAdministrative(rootChildFo.getNameExt())) continue; 224 File child = FileUtil.toFile(rootChildFo); 225 if (sourceGroup.contains(rootChildFo)) { 226 projectFiles.add(child); 228 } else { 229 int status = cache.getStatus(child).getStatus(); 230 if (status != FileInformation.STATUS_NOTVERSIONED_EXCLUDED) { 231 rootFilesExclusions.add(child); 232 containsSubprojects = true; 233 } 234 } 235 } 236 if (containsSubprojects) { 237 filteredFiles.addAll(projectFiles); 238 } else { 239 filteredFiles.add(rootFile); 240 } 241 } 242 } 243 244 250 public static Context getProjectsContext(Project [] projects) { 251 List<File> filtered = new ArrayList<File>(); 252 List<File> roots = new ArrayList<File>(); 253 List<File> exclusions = new ArrayList<File>(); 254 for (int i = 0; i < projects.length; i++) { 255 addProjectFiles(filtered, roots, exclusions, projects[i]); 256 } 257 return new Context(filtered, roots, exclusions); 258 } 259 260 private static Collection<File> toFileCollection(Collection<? extends FileObject> fileObjects) { 261 Set<File> files = new HashSet<File>(fileObjects.size()*4/3+1); 262 for (FileObject f: fileObjects) { 263 files.add(FileUtil.toFile(f)); 264 } 265 files.remove(null); 266 return files; 267 } 268 269 public static File [] toFileArray(Collection<FileObject> fileObjects) { 270 Set<File> files = new HashSet<File>(fileObjects.size()*4/3+1); 271 for (Iterator<FileObject> i = fileObjects.iterator(); i.hasNext();) { 272 files.add(FileUtil.toFile(i.next())); 273 } 274 files.remove(null); 275 return files.toArray(new File[files.size()]); 276 } 277 278 285 public static boolean isParentOrEqual(File parent, File file) { 286 for (; file != null; file = file.getParentFile()) { 287 if (file.equals(parent)) return true; 288 } 289 return false; 290 } 291 292 298 public static String previousRevision(String revision) { 299 return revision == null ? null : Long.toString(Long.parseLong(revision) - 1); 300 } 301 302 311 public static String getRelativePath(File file) { 312 String repositoryPath = null; 313 SvnClient client = Subversion.getInstance().getClient(false); 314 315 List<String > path = new ArrayList<String >(); 316 SVNUrl repositoryURL = null; 317 while (Subversion.getInstance().isManaged(file)) { 318 319 ISVNInfo info = null; 320 try { 321 info = client.getInfoFromWorkingCopy(file); 322 } catch (SVNClientException ex) { 323 if (ExceptionHandler.isUnversionedResource(ex.getMessage()) == false) { 324 ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ex); 325 } 326 } 327 328 if (info != null && info.getUrl() != null) { 329 SVNUrl fileURL = decode(info.getUrl()); 330 repositoryURL = info.getRepository(); 331 332 if (fileURL != null && repositoryURL != null) { 333 String fileLink = fileURL.toString(); 334 String repositoryLink = repositoryURL.toString(); 335 repositoryPath = fileLink.substring(repositoryLink.length()); 336 337 Iterator it = path.iterator(); 338 StringBuffer sb = new StringBuffer (); 339 while (it.hasNext()) { 340 String segment = (String ) it.next(); 341 sb.append("/"); sb.append(segment); 343 } 344 repositoryPath += sb.toString(); 345 break; 346 } 347 } 348 349 path.add(0, file.getName()); 350 file = file.getParentFile(); 351 352 } 353 354 return repositoryPath; 355 } 356 357 367 public static String getRelativePath(SVNUrl repositoryURL, File file) { 368 String repositoryPath = null; 369 SvnClient client = Subversion.getInstance().getClient(false); 370 371 List<String > path = new ArrayList<String >(); 372 while (Subversion.getInstance().isManaged(file)) { 373 374 ISVNStatus status = null; 375 try { 376 status = client.getSingleStatus(file); 377 } catch (SVNClientException ex) { 378 if (ExceptionHandler.isUnversionedResource(ex.getMessage()) == false) { 379 ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ex); 380 } 381 } 382 383 if (status != null && status.getUrl() != null) { 384 SVNUrl fileURL = status.getUrl(); 385 386 if (fileURL != null && repositoryURL != null) { 387 fileURL = decode(fileURL); 388 String fileLink = fileURL.toString(); 389 String repositoryLink = repositoryURL.toString(); 390 repositoryPath = fileLink.substring(repositoryLink.length()); 391 392 Iterator it = path.iterator(); 393 StringBuffer sb = new StringBuffer (); 394 while (it.hasNext()) { 395 String segment = (String ) it.next(); 396 sb.append("/"); sb.append(segment); 398 } 399 repositoryPath += sb.toString(); 400 break; 401 } 402 } 403 404 path.add(0, file.getName()); 405 file = file.getParentFile(); 406 407 } 408 409 return repositoryPath; 410 } 411 412 421 public static SVNUrl getRepositoryRootUrl(File file) { 422 SvnClient client = Subversion.getInstance().getClient(false); 423 424 SVNUrl repositoryURL = null; 425 while (Subversion.getInstance().isManaged(file)) { 426 ISVNInfo info = null; 427 try { 428 info = client.getInfoFromWorkingCopy(file); 429 } catch (SVNClientException ex) { 430 if (ExceptionHandler.isUnversionedResource(ex.getMessage()) == false) { 431 ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ex); 432 } 433 } 434 435 if (info != null && info.getUrl() != null) { 436 repositoryURL = info.getRepository(); 437 if (repositoryURL != null) { 438 break; 439 } 440 } 441 442 file = file.getParentFile(); 444 445 } 446 return repositoryURL; 447 } 448 449 458 public static SVNUrl getRepositoryUrl(File file) { 459 SvnClient client = Subversion.getInstance().getClient(false); 460 461 StringBuffer path = new StringBuffer (); 462 SVNUrl fileURL = null; 463 while (Subversion.getInstance().isManaged(file)) { 464 465 try { 466 ISVNStatus status = getSingleStatus(client, file); 468 if (status != null) { 469 fileURL = decode(status.getUrl()); 470 if (fileURL != null) { 471 break; 472 } 473 } 474 } catch (SVNClientException ex) { 475 if (ExceptionHandler.isUnversionedResource(ex.getMessage()) == false) { 476 ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ex); 477 } 478 } 479 480 482 ISVNInfo info = null; 483 try { 484 info = client.getInfoFromWorkingCopy(file); 485 } catch (SVNClientException ex) { 486 if (ExceptionHandler.isUnversionedResource(ex.getMessage()) == false) { 487 ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ex); 488 } 489 } 490 491 if (info != null) { 492 fileURL = decode(info.getUrl()); 493 494 if (fileURL != null ) { 495 break; 496 } 497 } 498 499 path.insert(0, file.getName()).insert(0, "/"); 500 file = file.getParentFile(); 501 502 } 503 if (path.length() > 0) fileURL = fileURL.appendPath(path.toString()); 504 return fileURL; 505 } 506 507 private static ISVNStatus getSingleStatus(SvnClient client, File file) throws SVNClientException{ 508 return client.getSingleStatus(file); 509 } 510 511 517 private static SVNUrl decode(SVNUrl url) { 518 if (url == null) return null; 519 String s = url.toString(); 520 StringBuffer sb = new StringBuffer (s.length()); 521 522 boolean inQuery = false; 523 for (int i = 0; i < s.length(); i++) { 524 char c = s.charAt(i); 525 if (c == '?') { 526 inQuery = true; 527 } else if (c == '+' && inQuery) { 528 c = ' '; 529 } else if (c == '%' && i + 2 < s.length() && isHexDigit(s.charAt(i + 1)) && isHexDigit(s.charAt(i + 2))) { 530 c = (char) Integer.parseInt(s.substring(i + 1, i + 3), 16); 531 i += 2; 532 } 533 sb.append(c); 534 } 535 try { 536 return new SVNUrl(sb.toString()); 537 } catch (java.net.MalformedURLException e) { 538 throw new RuntimeException (e); 539 } 540 } 541 542 private static boolean isHexDigit(char c) { 543 return c >= '0' && c <= '9' || c >= 'A' && c <= 'F' || c >= 'a' && c <= 'f'; 544 } 545 546 552 public static String getRepositoryPath(File file) { 553 SVNUrl url = getRepositoryUrl(file); 554 SVNUrl rootUrl = getRepositoryRootUrl(file); 555 return SVNUrlUtils.getRelativePath(rootUrl, url, true); 556 } 557 558 564 public static boolean isFileContentBinary(File file) { 565 FileObject fo = FileUtil.toFileObject(file); 566 if (fo == null) return false; 567 try { 568 DataObject dao = DataObject.find(fo); 569 return dao.getCookie(EditorCookie.class) == null; 570 } catch (DataObjectNotFoundException e) { 571 } 573 return false; 574 } 575 576 581 public static boolean isBinary(byte[] buffer) { 582 for (int i = 0; i<buffer.length; i++) { 583 int ch = buffer[i]; 584 if (ch < 32 && ch != '\t' && ch != '\n' && ch != '\r') { 585 return true; 586 } 587 } 588 return false; 589 } 590 591 594 public static class ByImportanceComparator<T> implements Comparator<FileInformation> { 595 public int compare(FileInformation i1, FileInformation i2) { 596 return getComparableStatus(i1.getStatus()) - getComparableStatus(i2.getStatus()); 597 } 598 } 599 600 601 614 public static File[] flatten(File[] files, int status) { 615 LinkedList<File> ret = new LinkedList<File>(); 616 617 FileStatusCache cache = Subversion.getInstance().getStatusCache(); 618 for (int i = 0; i<files.length; i++) { 619 File dir = files[i]; 620 FileInformation info = cache.getStatus(dir); 621 if ((status & info.getStatus()) != 0) { 622 ret.add(dir); 623 } 624 File[] entries = cache.listFiles(dir); for (int e = 0; e<entries.length; e++) { 626 File entry = entries[e]; 627 info = cache.getStatus(entry); 628 if ((status & info.getStatus()) != 0) { 629 ret.add(entry); 630 } 631 } 632 } 633 634 return ret.toArray(new File[ret.size()]); 635 } 636 637 645 public static File [] getModifiedFiles(Context context, int includeStatus) { 646 File[] all = Subversion.getInstance().getStatusCache().listFiles(context, includeStatus); 647 List<File> files = new ArrayList<File>(); 648 for (int i = 0; i < all.length; i++) { 649 File file = all[i]; 650 String path = file.getAbsolutePath(); 651 if (SvnModuleConfig.getDefault().isExcludedFromCommit(path) == false) { 652 files.add(file); 653 } 654 } 655 656 FileStatusCache cache = Subversion.getInstance().getStatusCache(); 658 File [] rootFiles = context.getRootFiles(); 659 for (int i = 0; i < rootFiles.length; i++) { 660 File file = rootFiles[i]; 661 if (file.isFile() && (cache.getStatus(file).getStatus() & includeStatus) != 0 && !files.contains(file)) { 662 files.add(file); 663 } 664 } 665 return files.toArray(new File[files.size()]); 666 } 667 668 669 675 public static boolean isPartOfSubversionMetadata(File file) { 676 return metadataPattern.matcher(file.getAbsolutePath()).matches(); 677 } 678 679 685 public static int getComparableStatus(int status) { 686 if (0 != (status & FileInformation.STATUS_VERSIONED_CONFLICT)) { 687 return 0; 688 } else if (0 != (status & FileInformation.STATUS_VERSIONED_MERGE)) { 689 return 1; 690 } else if (0 != (status & FileInformation.STATUS_VERSIONED_DELETEDLOCALLY)) { 691 return 10; 692 } else if (0 != (status & FileInformation.STATUS_VERSIONED_REMOVEDLOCALLY)) { 693 return 11; 694 } else if (0 != (status & FileInformation.STATUS_NOTVERSIONED_NEWLOCALLY)) { 695 return 12; 696 } else if (0 != (status & FileInformation.STATUS_VERSIONED_ADDEDLOCALLY)) { 697 return 13; 698 } else if (0 != (status & FileInformation.STATUS_VERSIONED_MODIFIEDLOCALLY)) { 699 return 14; 700 } else if (0 != (status & FileInformation.STATUS_VERSIONED_REMOVEDINREPOSITORY)) { 701 return 30; 702 } else if (0 != (status & FileInformation.STATUS_VERSIONED_NEWINREPOSITORY)) { 703 return 31; 704 } else if (0 != (status & FileInformation.STATUS_VERSIONED_MODIFIEDINREPOSITORY)) { 705 return 32; 706 } else if (0 != (status & FileInformation.STATUS_VERSIONED_UPTODATE)) { 707 return 50; 708 } else if (0 != (status & FileInformation.STATUS_NOTVERSIONED_EXCLUDED)) { 709 return 100; 710 } else if (0 != (status & FileInformation.STATUS_NOTVERSIONED_NOTMANAGED)) { 711 return 101; 712 } else if (status == FileInformation.STATUS_UNKNOWN) { 713 return 102; 714 } else { 715 throw new IllegalArgumentException ("Uncomparable status: " + status); } 717 } 718 719 723 public static String getCopy(File file) { 724 return getCopy(file, SvnModuleConfig.getDefault().getAnnotationExpresions()); 725 } 726 727 733 public static String getCopy(File file, List<AnnotationExpression> annotationExpressions) { 734 SVNUrl url = getRepositoryUrl(file); 735 return getCopy(url, annotationExpressions); 736 } 737 738 public static String getCopy(SVNUrl url) { 739 return getCopy(url, SvnModuleConfig.getDefault().getAnnotationExpresions()); 740 } 741 742 public static String getCopy(SVNUrl url, List<AnnotationExpression> annotationExpressions) { 743 if (url != null) { 744 for (Iterator<AnnotationExpression> it = annotationExpressions.iterator(); it.hasNext();) { 745 AnnotationExpression annotationExpression = it.next(); 746 747 Matcher m = annotationExpression.getUrlPatern().matcher(url.toString()); 748 if (m.matches()) { 749 String ae = annotationExpression.getAnnotationExp(); 750 751 StringBuffer copyName = new StringBuffer (); 752 StringBuffer groupStr = new StringBuffer (); 753 boolean inGroup = false; 754 755 for (int i = 0; i < ae.length(); i++) { 756 char c = ae.charAt(i); 757 if(c == '\\') { 758 inGroup = true; 759 continue; 760 } else if(inGroup) { 761 if(Character.isDigit(c)) { 762 groupStr.append(c); 763 } else { 764 if(groupStr.length() > 0) { 765 int group = Integer.valueOf(groupStr.toString()).intValue(); 766 copyName.append(m.group(group)); 767 groupStr = new StringBuffer (); 768 } else { 769 copyName.append('\\'); 770 copyName.append(c); 771 } 772 inGroup = false; 773 } 774 continue; 775 } 776 copyName.append(c); 777 } 778 if(groupStr.length() > 0) { 779 int group = Integer.valueOf(groupStr.toString()).intValue(); 780 copyName.append(m.group(group)); 781 } 782 return copyName.toString(); 783 } 784 } 785 } 786 return null; 787 } 788 789 805 821 826 public static void refreshRecursively(File folder) { 827 if (folder == null) return; 828 refreshRecursively(folder.getParentFile()); 829 Subversion.getInstance().getStatusCache().refresh(folder, FileStatusCache.REPOSITORY_STATUS_UNKNOWN); 830 } 831 832 public static String ripUserFromHost(String host) { 833 int idx = host.indexOf('@'); 834 if(idx < 0) { 835 return host; 836 } else { 837 return host.substring(idx + 1); 838 } 839 } 840 841 public static SVNRevision getSVNRevision(String revisionString) { 842 try { 843 return SVNRevision.getRevision(revisionString); 845 } catch (ParseException ex) { 846 return new SVNRevision.Number(Long.parseLong(revisionString)); 847 } 848 } 849 850 858 public static List<String > getMatchinIgnoreParterns(List<String > patterns, String value, boolean onlyFirstMatch) { 859 List<String > ret = new ArrayList<String >(); 860 for (Iterator<String > i = patterns.iterator(); i.hasNext();) { 861 try { 862 String patternString = i.next(); 864 String shellPatternString = regExpToFilePatterns(patternString); 865 Pattern pattern = Pattern.compile(shellPatternString); 866 if (pattern.matcher(value).matches()) { 867 ret.add(patternString); 868 if(onlyFirstMatch) { 869 return ret; 870 } 871 } 872 } catch (PatternSyntaxException e) { 873 ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e); 876 } 877 } 878 return ret; 879 } 880 881 private static String regExpToFilePatterns(String exp) { 882 exp = exp.replaceAll("\\.", "\\\\."); exp = exp.replaceAll("\\*", ".*"); exp = exp.replaceAll("\\?", "."); 886 exp = exp.replaceAll("\\$", "\\\\\\$"); exp = exp.replaceAll("\\^", "\\\\^"); exp = exp.replaceAll("\\<", "\\\\<"); exp = exp.replaceAll("\\>", "\\\\>"); exp = exp.replaceAll("\\[", "\\\\["); exp = exp.replaceAll("\\]", "\\\\]"); exp = exp.replaceAll("\\{", "\\\\{"); exp = exp.replaceAll("\\}", "\\\\}"); exp = exp.replaceAll("\\(", "\\\\("); exp = exp.replaceAll("\\)", "\\\\)"); exp = exp.replaceAll("\\+", "\\\\+"); exp = exp.replaceAll("\\|", "\\\\|"); 899 return exp; 900 } 901 } 902 | Popular Tags |