alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

/*
 *                 Sun Public License Notice
 * 
 * The contents of this file are subject to the Sun Public License
 * Version 1.0 (the "License"). You may not use this file except in
 * compliance with the License. A copy of the License is available at
 * http://www.sun.com/
 * 
 * The Original Code is NetBeans. The Initial Developer of the Original
 * Code is Sun Microsystems, Inc. Portions Copyright 1997-2003 Sun
 * Microsystems, Inc. All Rights Reserved.
 */

package org.netbeans.modules.vcscore;

import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;

import org.openide.ErrorManager;

import org.netbeans.modules.vcscore.util.*;
//import org.netbeans.modules.vcscore.*;

/**
 * This class contains static methods for variable expansion.
 * 

* Expand Bash style variables, e.g. ${USER}, with some additional gramatic. * * @author Michal Fadljevic, Pavel Buzek, Martin Entlicher */ //------------------------------------------- public class Variables { /** * Automatically set context-specific variables. */ /** The name of a variable, whose value is set to the selected file name. * When more than one file is selected, the first one is taken. */ public static final String FILE = "FILE"; /** The name of a variable, whose value is set to the selected file name quoted * by the value of the QUOTING variable. * When more than one file is selected, the first one is taken. */ public static final String QFILE = "QFILE"; /** The name of a variable, whose value is set to the selected file names. * They are delimeted by the path separator. */ public static final String FILES = "FILES"; /** The name of a variable, whose value is set to the selected file names each * quoted by the value of the QUOTING variable and delimeted by spaces. */ public static final String QFILES = "QFILES"; public static final String DIR = "DIR"; public static final String PATH = "PATH"; public static final String QPATH = "QPATH"; public static final String PATHS = "PATHS"; public static final String QPATHS = "QPATHS"; public static final String MPATHS = "MPATHS"; public static final String QMPATHS = "QMPATHS"; public static final String MIMETYPE = "MIMETYPE"; public static final String NUM_FILES = "NUM_FILES"; public static final String NUM_IMPORTANT_FILES = "NUM_IMPORTANT_FILES"; public static final String FILE_IS_FOLDER = "FILE_IS_FOLDER"; public static final String FILES_IS_FOLDER = "FILES_IS_FOLDER"; public static final String MULTIPLE_FILES = "MULTIPLE_FILES"; /** * Variables with special functionality. */ /** * This variable is defined only when used in the execution string * and is filled with the full path to a temporary file, that is created * and exists ONLY while the command is running. The file is deleted * automatically as soon as the command finish. */ public static final String TEMPORARY_FILE = "TEMPORARY_FILE"; // NOI18N /** * When non-empty, the directory reader should read also files, which were deleted * from the version control system, but their old revisions exist. */ public static final String SHOW_DEAD_FILES = "SHOW_DEAD_FILES"; /** * The content of this variable is taken as a message, * that is used to ask whether the EDIT command should be executed. * This message is used only when the execution is caused by typing * to a read-oly file. */ public static final String MSG_PROMPT_FOR_AUTO_EDIT = "MSG_PROMPT_FOR_AUTO_EDIT"; /** * The content of this variable is taken as a message, * that is used to ask whether the LOCK command should be executed. * This message is used only when the execution is caused by typing * to a file, that is not locked by the user. */ public static final String MSG_PROMPT_FOR_AUTO_LOCK = "MSG_PROMPT_FOR_AUTO_LOCK"; /** * If this variable is defined, than it's value (should be integer) is supposed * to be the maximum length of a command in the system. * If the length of the execution string exceeds this value and it's possible * to split it (the command takes more than one file as an argument), * the execution string is split into two or more execution strings. * These are then executed synchronously in the OS. */ public static final String MAX_CMD_LENGTH = "MAX_CMD_LENGTH"; // NOI18N //private boolean warnUndefVars = true; private static final String SUBSTRACT = "-"; // NOI18N private static final String REPLACE = "_"; // NOI18N private static final String[] VARS_SYS_PROP = { "netbeans.user", "java.home", "file.separator", // NOI18N "os.name", "os.arch", "os.version", "user.name", "user.home", // NOI18N }; private static Collection contextVariablesNames = null; private static Map defaultVariablesMap = null; private Variables() { } public static synchronized Collection getContextVariablesNames() { if (contextVariablesNames == null) { contextVariablesNames = createContextVariablesNames(); } return contextVariablesNames; } private static Collection createContextVariablesNames() { HashSet varNames = new HashSet(); varNames.addAll(Arrays.asList(new String[] { FILE, QFILE, FILES, QFILES, DIR, PATH, QPATH, PATHS, QPATHS, MPATHS, QMPATHS, MIMETYPE, NUM_FILES, NUM_IMPORTANT_FILES, FILE_IS_FOLDER, FILES_IS_FOLDER, MULTIPLE_FILES })); return Collections.unmodifiableSet(varNames); } public static synchronized Map getDefaultVariablesMap() { if (defaultVariablesMap == null) { defaultVariablesMap = createDefaultVariablesMap(); } return defaultVariablesMap; } private static Map createDefaultVariablesMap() { Map vars = new HashMap(); for (int i = 0; i < VARS_SYS_PROP.length; i++) { vars.put(VARS_SYS_PROP[i], System.getProperty(VARS_SYS_PROP[i])); } vars.put("classpath.separator", java.io.File.pathSeparator); // NOI18N vars.put("path.separator", java.io.File.separator); // NOI18N return Collections.unmodifiableMap(vars); } /** Expand all occurences of ${VARIABLE_NAME} repeatetively. * It uses {@link #needFurtherExpansion} function to see * when to stop scanning (via {@link #expandOnce}). * @param tab Hashtable holding (String)VARIABLE, (String)VALUE pairs * @param cmd Command with ${VAR} sequences * @return String with all variables expanded * public static String expand_OLD(Hashtable tab, String cmd, boolean warnUndefVars) { String cmd_cond = ""; // NOI18N //this.warnUndefVars = warnUndefVars; boolean expanded = false; do { while (true) { cmd_cond = expandConditional (tab, cmd, warnUndefVars); if (cmd.equals(cmd_cond)) break; cmd = cmd_cond; } expanded = true; while(needFurtherExpansion(cmd) == true) { cmd = expandOnce(tab, cmd, warnUndefVars); expanded = false; } } while(!expanded); cmd = org.openide.util.Utilities.replaceString(cmd, "\\${", "${"); cmd = org.openide.util.Utilities.replaceString(cmd, "\\$[", "$["); return cmd; //return VcsUtilities.replaceBackslashDollars( cmd ); } */ /** Expand all occurences of ${} repeatetively. * Expand also conditionals like $[? ] [] * []. * @param tab a map holding (String)VARIABLE, (String)VALUE pairs * @param cmd Command with ${VAR} sequences * @return String with all variables expanded */ public static String expand(Map tab, String cmd, boolean warnUndefVars) { StringBuffer result = new StringBuffer(); int begin = 0; int end; do { end = cmd.indexOf("$", begin); if (end < 0) { result.append(cmd.substring(begin, cmd.length())); break; } boolean var = false; boolean cond = false; boolean escape = false; if (end > 0 && (escape = (cmd.charAt(end - 1) == '\\')) || end == (cmd.length() - 1) || (!(var = (cmd.charAt(end + 1) == '{')) && (!(cond = (cmd.charAt(end + 1) == '['))))) { if (escape && (end < (cmd.length() - 1)) && ((cmd.charAt(end + 1) == '{') || (cmd.charAt(end + 1) == '['))) { result.append(cmd.substring(begin, end - 1)); result.append('$'); } else { result.append(cmd.substring(begin, end + 1)); } begin = end + 1; } else { result.append(cmd.substring(begin, end)); begin = end + 2; if (var) { end = VcsUtilities.getPairIndex(cmd, begin, '{', '}'); // cmd.indexOf("}",begin); // NOI18N if (end < 0) { ErrorManager.getDefault().notify(ErrorManager.WARNING, new IOException("Missing closing bracket '}'. Corresponding opening bracket '{' is at pos = "+(begin - 1))); result.append("${"); } else { String expansion = expandVariable(tab, cmd.substring(begin, end), warnUndefVars); if (expansion == null) { if (warnUndefVars) { ErrorManager.getDefault().notify(ErrorManager.WARNING, new IOException("Variable undefined '"+cmd.substring(begin, end)+ "'. Expanding it to an empty string.")); // NOI18N } } else { result.append(expansion); } begin = end + 1; } } else if (cond) { int[] expandEnd = new int[1]; String expansion = expandConditional(tab, cmd.substring(begin - 2), warnUndefVars, expandEnd); if (expandEnd[0] < 0) { result.append("$["); } else { result.append(expansion); begin += expandEnd[0] - 1; } } } } while (begin < cmd.length()); return result.toString(); } public static String expandVariable(Map tab, String name, boolean warnUndefVars) { String value = (String) tab.get(name); char replC1 = (char) -1; char replC2 = (char) -1; if (value == null) { int r = name.lastIndexOf(REPLACE); if (r > 0 && name.length() == (r + 3)) { value = (String) tab.get(name.substring(0, r)); if (value != null) { replC1 = name.charAt(r+1); replC2 = name.charAt(r+2); //value = value.replace(c1, c2); } } } if (value == null) { int substr; int begin = 0; while((substr = name.indexOf(SUBSTRACT, begin)) > 0) { String var = name.substring(begin, substr); if (var != null) var = var.trim(); String svalue = expandVariable(tab, var, warnUndefVars); if (svalue == null) { if (warnUndefVars) { ErrorManager.getDefault().log("Variable undefined '"+var+"'."); } return null; } if (begin == 0) value = svalue; else value = substractVariables(value, svalue);//VcsFileSystem.substractRootDir(value, svalue); begin = substr + SUBSTRACT.length(); } if (begin == 0) value = (String) tab.get(name); else { String svalue = expandVariable(tab, name.substring(begin).trim(), warnUndefVars); if (svalue == null) { return null; } value = substractVariables(value, svalue); //VcsFileSystem.substractRootDir(value, svalue); } } else { value = expand(tab, value, warnUndefVars); } if (replC1 != ((char) -1)) { if (value != null) value = value.replace(replC1, replC2); } return value; } private static String substractVariables(String value1, String value2) { if (value2 == null || value2.length() == 0) return value1; int index = value1.lastIndexOf(value2); if (index < 0) return value1; else return value1.substring(0, index); } private static String expandConditional(Map tab, String cmd, boolean warnUndefVars, int[] expandEnd) { expandEnd[0] = -1; if (!cmd.startsWith("$[?")) return null; int begin = 3; int end = VcsUtilities.getPairIndex(cmd, begin, '[', ']'); if (end < 0) { ErrorManager.getDefault().notify(ErrorManager.WARNING, new IOException("Missing closing bracket ']'."+ " Corresponding opening bracket '[' is at pos = "+(begin - 1))); return null; } String var = cmd.substring(begin, end).trim(); String value = expandVariable(tab, var, warnUndefVars); if (value == null) { if (warnUndefVars) { ErrorManager.getDefault().notify(ErrorManager.WARNING, new IOException("Variable undefined '"+var+ "'. Expanding it to an empty string.")); // NOI18N } } // find first and second option and choose // first int firstBegin = cmd.indexOf("[", end + 1); // NOI18N if (firstBegin < 0) { return null; } int firstEnd = VcsUtilities.getPairIndex(cmd, firstBegin + 1, '[', ']'); if (firstEnd < 0) { return null; } String first = cmd.substring(firstBegin + 1, firstEnd); //index = firstEnd; // second int secondBegin=cmd.indexOf("[", firstEnd); // NOI18N if (secondBegin < 0) { return null; } //result.append(cmd.substring(index,secondBegin)); int secondEnd = VcsUtilities.getPairIndex(cmd, secondBegin + 1, '[', ']'); if (secondEnd < 0) { return null; } String second = cmd.substring(secondBegin+1, secondEnd); expandEnd[0] = secondEnd; String result; if (value == null || value.length() == 0) { result = second; } else { result = first; } return expand(tab, result, warnUndefVars); } /** Expand all occurences of ${VARIABLE_NAME}. * It makes only one expansion cycle, no variables inside other variables are expanded. * @param tab Hashtable holding (String)VARIABLE, (String)VALUE pairs * @param cmd Command with ${VAR} sequences * @return String with variables expanded */ public static String expandFast(Map tab, String cmd, boolean warnUndefVars) { String cmd_cond = ""; // NOI18N //this.warnUndefVars = warnUndefVars; boolean expanded = false; cmd_cond = expandConditional (tab, cmd, warnUndefVars); cmd = expandOnce(tab, cmd_cond, warnUndefVars); return VcsUtilities.replaceBackslashDollars( cmd ); } public static String expandConditional (Map tab, String cmd, boolean warnUndefVars) { int index = 0; int size = cmd.length(); int begin = 0; int end = 0; int nextBegin = 0; StringBuffer result = new StringBuffer(size+20); while(true) { begin = cmd.indexOf("$[?", index); // NOI18N if (begin < 0) { result.append(cmd.substring(index)); break; } result.append(cmd.substring(index,begin)); int fake = cmd.indexOf("\\$[?", index); // NOI18N if (fake >= 0 && fake + 1 == begin) { index = begin + 1; result.append('$'); continue; } //end=cmd.indexOf("]",begin); // NOI18N end = VcsUtilities.getPairIndex(cmd, begin + 3, '[', ']'); if (end < 0) { index = begin + 1; continue; } String var = cmd.substring(begin+3, end).trim(); String value = getVarValue(tab, var); //(String)tab.get(var); if (value == null) { if (warnUndefVars) { ErrorManager.getDefault().log(ErrorManager.INFORMATIONAL, "Variable undefined '"+var+"'. Expanding it to an empty string."); } if (var.indexOf("$[?") >= 0) { // NOI18N ErrorManager.getDefault().log(ErrorManager.INFORMATIONAL, "Missing closing bracket ']' ?"); } } index = end + 1; // find first and second option and choose // first int firstBegin = cmd.indexOf("[", index); // NOI18N if (firstBegin < 0) { result.append(cmd.substring(index)); break; } //result.append(cmd.substring(index,firstBegin)); fake = cmd.indexOf("\\[", index); // NOI18N if (fake >= 0 && fake + 1 == firstBegin) { index = firstBegin + 1; result.append('['); continue; } //int firstEnd=cmd.indexOf("]",firstBegin); // NOI18N int firstEnd = VcsUtilities.getPairIndex(cmd, firstBegin + 1, '[', ']'); if (firstEnd < 0) { index = firstBegin+1; continue; } String first = cmd.substring(firstBegin + 1, firstEnd); index = firstEnd; // second int secondBegin=cmd.indexOf("[", index); // NOI18N if (secondBegin < 0) { result.append(cmd.substring(index)); break; } //result.append(cmd.substring(index,secondBegin)); fake = cmd.indexOf("\\[", index); // NOI18N if (fake >= 0 && fake + 1 == secondBegin) { index = secondBegin + 1; result.append('['); continue; } //int secondEnd=cmd.indexOf("]",secondBegin); // NOI18N int secondEnd = VcsUtilities.getPairIndex(cmd, secondBegin + 1, '[', ']'); if (secondEnd < 0) { index = secondBegin + 1; continue; } String second = cmd.substring(secondBegin+1, secondEnd); index = secondEnd + 1; if (value == null || value.equals ("")) { // NOI18N result.append (/*"["+*/second); // NOI18N } else { result.append (/*"["+*/first); // NOI18N } } return new String(result); } //------------------------------------------- public static boolean needFurtherExpansion(String cmd) { int begin = cmd.indexOf("${"); // NOI18N int fake = cmd.indexOf("\\${"); // NOI18N if (begin < 0) { return false ; } if (fake >= 0 && fake + 1 == begin) { return needFurtherExpansion(cmd.substring(begin + 1)); } return true ; } //------------------------------------------- /** Expand (once) ${VARIABLE} variables in command. * It scans 'cmd' string and replaces all occurences of ${VARIABLE} * to VALUE=tab.get(VARIABLE). Both VARIABLE and VALUE must be Strings. *

* Note that 'cmd' string is scanned only once. * Use {@link #needFurtherExpansion} function to see if it should * be called again. * @param tab Hashtable holding (String)VARIABLE=(String)VALUE pairs * @param cmd Command in which ${VAR} sequences * @return String with all variables expanded */ public static String expandOnce(Map tab, String cmd, boolean warnUndefVars) { int index=0; int size=cmd.length(); int begin=0,end=0,nextBegin=0; StringBuffer result=new StringBuffer(size+20); while(true){ begin=cmd.indexOf("${",index); // NOI18N if( begin<0 ){ result.append(cmd.substring(index)); break; } result.append(cmd.substring(index,begin)); int fake = cmd.indexOf("\\${",index); // NOI18N if(fake >= 0 && (fake + 1 == begin)) { index=begin + 1; result.append('$'); continue; } end = VcsUtilities.getPairIndex(cmd, begin + 2, '{', '}'); // cmd.indexOf("}",begin); // NOI18N if( end<0 ){ index=begin+1; continue; } String var=cmd.substring(begin+2,end); String value=getVarValue(tab, var); //String value=(String)tab.get(var); if( value != null ){ result.append(value); } else { if (warnUndefVars) { ErrorManager.getDefault().log(ErrorManager.INFORMATIONAL, "Variable undefined '"+var+"'. Expanding it to an empty string."); } if( var.indexOf("${")>=0 ){ // NOI18N ErrorManager.getDefault().log("Missing closing bracket '}' ?"); // cvs commit has enclosed variable ${FILE} => do not warn of this case } } index=end+1; } return new String(result); } /** Expand (once) ${VARIABLE} variables in command only if they are known. * It scans 'cmd' string and replaces all occurences of ${VARIABLE} * to VALUE=tab.get(VARIABLE). Both VARIABLE and VALUE must be Strings. *

* Note that 'cmd' string is scanned only once. * @param tab Hashtable holding (String)VARIABLE=(String)VALUE pairs * @param cmd Command in which ${VAR} sequences * @return String with all known variables expanded */ public static String expandKnownOnly(Map tab, String cmd) { int index=0; int size=cmd.length(); int begin=0,end=0,nextBegin=0; StringBuffer result=new StringBuffer(size+20); while(true){ begin=cmd.indexOf("${",index); // NOI18N if( begin<0 ){ result.append(cmd.substring(index)); break; } result.append(cmd.substring(index,begin)); int fake=cmd.indexOf("\\${",index); // NOI18N if( fake<0 ){ fake=-5; } if(fake+1==begin){ index=begin+1; result.append('$'); continue; } end = VcsUtilities.getPairIndex(cmd, begin + 2, '{', '}'); // cmd.indexOf("}",begin); // NOI18N if( end<0 ){ index=begin+1; continue; } String var=cmd.substring(begin+2,end); String value=getVarValue(tab, var); //String value=(String)tab.get(var); if( value != null ){ result.append(value); } else { result.append(cmd.substring(begin, end+1)); } index=end+1; } return new String(result); } /** * Get the value of a variable. If the variable name is not known, * this method search for the last occurence of character '_' and if it * is followed by two more chracters it replaces the first by the second * in the value of that variable. * @param tab The table holding (String)VARIABLE=(String)VALUE pairs * @param name The variable name or expression to evaluate */ private static String getReplaceVarValue(Map tab, String name) { if (name == null) return null; String value = (String) tab.get(name); if (value == null) { int r = name.lastIndexOf(REPLACE); if (r > 0) { value = (String) tab.get(name.substring(0, r)); if (value != null && name.length() >= r+3) { char c1 = name.charAt(r+1); char c2 = name.charAt(r+2); value = value.replace(c1, c2); } } } return value; } /** * Get the value of a variable or an expression. * @param tab The table holding (String)VARIABLE=(String)VALUE pairs * @param name The variable name or expression to evaluate */ private static String getVarValue(Map tab, String name) { int substr; int begin = 0; String value = getReplaceVarValue(tab, name); if (value == null) { while((substr = name.indexOf(SUBSTRACT, begin)) > 0) { String var = name.substring(begin, substr); if (var != null) var = var.trim(); String svalue = getReplaceVarValue(tab, var); if (svalue == null) { return null; } if (begin == 0) value = svalue; else value = VcsFileSystem.substractRootDir(value, svalue); begin = substr + SUBSTRACT.length(); } if (begin == 0) value = (String) tab.get(name); else value = VcsFileSystem.substractRootDir(value, getReplaceVarValue(tab, name.substring(begin).trim())); } return value; } /* //------------------------------------------- public static void main(String[] args){ Hashtable vars=new Hashtable(); vars.put("A","a"); // NOI18N vars.put("B","${A}b"); // NOI18N vars.put("BB","\\${A}b"); // NOI18N vars.put("C","${B}c"); // NOI18N vars.put("CC","\\${A}\\${B}c"); // NOI18N vars.put("DIR","src"); // NOI18N vars.put("STCMD","stcmd30"); // NOI18N Variables v=new Variables(); System.out.println("vars="+vars); // NOI18N System.out.println("orig='"+args[0]+"'"); // NOI18N System.out.println("new ='"+v.expand(vars,args[0], true)+"'"); // NOI18N } */ }

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.