All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.pivotal.gemfirexd.internal.iapi.util.IdUtil Maven / Gradle / Ivy

There is a newer version: 1.6.7
Show newest version
/*

   Derby - Class com.ihost.cs.IdUtil

   Licensed to the Apache Software Foundation (ASF) under one or more
   contributor license agreements.  See the NOTICE file distributed with
   this work for additional information regarding copyright ownership.
   The ASF licenses this file to you under the Apache License, Version 2.0
   (the "License"); you may not use this file except in compliance with
   the License.  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.

 */

/*
 * Changes for GemFireXD distributed data platform (some marked by "GemStone changes")
 *
 * Portions Copyright (c) 2010-2015 Pivotal Software, Inc. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you
 * may not use this file except in compliance with the License. You
 * may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
 * implied. See the License for the specific language governing
 * permissions and limitations under the License. See accompanying
 * LICENSE file.
 */

package com.pivotal.gemfirexd.internal.iapi.util;

import com.pivotal.gemfirexd.internal.iapi.error.StandardException;
import com.pivotal.gemfirexd.internal.iapi.reference.Attribute;
import com.pivotal.gemfirexd.internal.iapi.reference.Property;
import com.pivotal.gemfirexd.internal.iapi.reference.SQLState;

import java.io.IOException;
import java.io.StringReader;
import java.util.Vector;
import java.util.HashSet;
import java.util.Properties;

/**
  Utility class for parsing and producing string representations of
  ids. This class supports both delimited and un-delimited ids.

  

The syntax for an id follows.

      id := delim-id | unDelim-id

	  delim-id := "[""|[any char but quote]]+"
	  undelim-id := (a-z|A-Z|anyunicodeletter)[a-z|A-Z|_|0-9|anyunicodeletter|anyunicodedigit]*

	  In the syntax braces show grouping. '*' means repeat 0 or more times.
	  '|' means or. '+' means repeat 1 or more times. 
  

In addition this class provides support for qualified names. A qualified name is a dot (.) separated list of ids.

Limitations:

  1. Unicode escape sequences in ids are not supported.
  2. Escape sequences (\n...) are not supported.
*/ public abstract class IdUtil { /** * Produce a delimited form of a normal value. @return the delimited identifier. */ public static String normalToDelimited(String id) { StringBuilder quotedBuffer = new StringBuilder(); quotedBuffer.append('\"'); for (int ix = 0; ix < id.length(); ix++){ char currentChar = id.charAt(ix); quotedBuffer.append(currentChar); if (currentChar == '\"') quotedBuffer.append('\"'); } quotedBuffer.append('\"'); return quotedBuffer.toString(); } /** Produce a delimited two part qualified name from two un-delimited identifiers. @return the result. */ public static String mkQualifiedName(String id1, String id2) { if( null == id1) return normalToDelimited(id2); return normalToDelimited(id1) + "." + normalToDelimited(id2); } /** Make a string form of a qualified name from the array of ids provided. */ public static String mkQualifiedName(String[] ids) { StringBuilder sb = new StringBuilder(); for (int ix=0; ix < ids.length; ix++) { if (ix!=0) sb.append("."); sb.append(normalToDelimited(ids[ix])); } return sb.toString(); } /** Parse a multi-part (dot separated) SQL identifier form the String provided. Raise an excepion if the string does not contain valid SQL indentifiers. The returned String array contains the normalized form of the identifiers. @param s The string to be parsed @return An array of strings made by breaking the input string at its dots, '.'. @exception StandardException Oops */ public static String[] parseMultiPartSQLIdentifier(String s) throws StandardException { StringReader r = new StringReader(s); String[] qName = parseMultiPartSQLIdentifier(r); verifyEmpty(r); return qName; } /** @param r The multi-part identifier to be parsed @return An array of strings made by breaking the input string at its dots, '.'. @exception StandardException Oops */ private static String[] parseMultiPartSQLIdentifier(StringReader r) throws StandardException { Vector v = new Vector(); while (true) { String thisId = parseId(r,true); v.addElement(thisId); int dot; try { r.mark(0); dot = r.read(); if (dot != '.') { if (dot!=-1) r.reset(); break; } } catch (IOException ioe){ throw StandardException.newException(SQLState.ID_PARSE_ERROR,ioe); } } String[] result = new String[v.size()]; v.copyInto(result); return result; } /** Parse a SQL identifier from the String provided. Raise an excepion if the string does not contain a valid SQL indentifier. The returned String contains the normalized form of the identifier. @exception StandardException Oops */ public static String parseSQLIdentifier(String s) throws StandardException { StringReader r = new StringReader(s); String id = parseId(r,true); verifyEmpty(r); return id; } /** Read an id from the StringReader provided. @param normalize true means return ids in nomral form, false means return them as they were entered.

Raise an exception if the first thing in the StringReader is not a valid id. @exception StandardException Ooops. */ private static String parseId(StringReader r, boolean normalize) throws StandardException { try { r.mark(0); int c = r.read(); if (c == -1) //id can't be 0-length throw StandardException.newException(SQLState.ID_PARSE_ERROR); r.reset(); if (c == '"') return parseQId(r,normalize); else return parseUnQId(r,normalize); } catch (IOException ioe){ throw StandardException.newException(SQLState.ID_PARSE_ERROR,ioe); } } /** * Parse a regular identifier (unquoted) returning returning either * the value of the identifier or a delimited identifier. Ensures * that all characters in the identifer are valid for a regular identifier. * * @param r Regular identifier to parse. * @param normalize If true return the identifer converted to a single case, otherwise return the identifier as entered. * @return the value of the identifer or a delimited identifier * @throws IOException Error accessing value * @throws StandardException Error parsing identifier. */ private static String parseUnQId(StringReader r, boolean normalize) throws IOException,StandardException { StringBuilder b = new StringBuilder(); int c; boolean first; // for(first = true; ; first=false) { r.mark(0); if (idChar(first,c=r.read())) b.append((char)c); else break; } if (c != -1) r.reset(); String id = b.toString(); if (normalize) return StringUtil.SQLToUpperCase(id); else return id; } private static boolean idChar(boolean first,int c) { if (((c>='a' && c<='z') || (c>='A' && c<='Z')) || (!first &&(c>='0' && c<='9')) || (!first &&c =='_') ) return true; else if (Character.isLetter((char) c)) return true; else if (!first && Character.isDigit((char) c)) return true; return false; } /** * Parse a delimited (quoted) identifier returning either * the value of the identifier or a delimited identifier. * @param r Quoted identifier to parse. * @param normalize If true return a delimited identifer, otherwise return the identifier's value. * @return the value of the identifer or a delimited identifier * @throws IOException Error accessing value * @throws StandardException Error parsing identifier. */ private static String parseQId(StringReader r,boolean normalize) throws IOException,StandardException { StringBuilder b = new StringBuilder(); int c = r.read(); if (c != '"') throw StandardException.newException(SQLState.ID_PARSE_ERROR); while (true) { c=r.read(); if (c == '"') { r.mark(0); int c2 = r.read(); if (c2 != '"') { if (c2!=-1)r.reset(); break; } } else if (c == -1) throw StandardException.newException(SQLState.ID_PARSE_ERROR); b.append((char)c); } if (b.length() == 0) //id can't be 0-length throw StandardException.newException(SQLState.ID_PARSE_ERROR); if (normalize) return b.toString(); else return normalToDelimited(b.toString()); //Put the quotes back. } /** * Verify the read is empty (no more characters in its stream). * @param r * @throws StandardException */ private static void verifyEmpty(java.io.Reader r) throws StandardException { try { if (r.read() != -1) throw StandardException.newException(SQLState.ID_PARSE_ERROR); } catch (IOException ioe){ throw StandardException.newException(SQLState.ID_PARSE_ERROR,ioe); } } /**Index of the schema name in a jar name on a db classpath*/ public static final int DBCP_SCHEMA_NAME = 0; /**Index of the sql jar name in a jar name on a db classpath*/ public static final int DBCP_SQL_JAR_NAME = 1; /** Scan a database classpath from the string provided. This returns an array with one qualified name per entry on the classpath. The constants above describe the content of the returned names. This raises an an exception if the string does not contain a valid database class path.

      classpath := item[:item]*
	  item := id.id
	  
	  In the syntax braces ([]) show grouping. '*' means repeat 0 or more times.
	  The syntax for id is defined in IdUtil.
  

Classpath returned is a two part name.
If the class path is empty then this returns an array of zero length. @exception StandardException Oops */ public static String[][] parseDbClassPath(String input) throws StandardException { //As a special case we accept a zero length dbclasspath. if (input.length() == 0) return new String[0][]; Vector v = new Vector(); java.io.StringReader r = new java.io.StringReader(input); // while (true) { try { String[] thisQName = IdUtil.parseMultiPartSQLIdentifier(r); if (thisQName.length != 2) throw StandardException.newException(SQLState.DB_CLASS_PATH_PARSE_ERROR,input); v.addElement(thisQName); int delim = r.read(); if (delim != ':') { if (delim!=-1) throw StandardException.newException(SQLState.DB_CLASS_PATH_PARSE_ERROR,input); break; } } catch (StandardException se){ if (se.getMessageId().equals(SQLState.ID_PARSE_ERROR)) throw StandardException.newException(SQLState.DB_CLASS_PATH_PARSE_ERROR, se,input); else throw se; } catch (IOException ioe){ throw StandardException.newException(SQLState.DB_CLASS_PATH_PARSE_ERROR,ioe,input); } } String[][] result = new String[v.size()][]; v.copyInto(result); return result; } /* ** Methods that operate on lists of identifiers. */ /** Scan a list of comma separated SQL identifiers from the string provided. This returns an array with containing the normalized forms of the identifiers. This raises an an exception if the string does not contain a valid list of names. @exception StandardException Oops */ public static String[] parseIdList(String p) throws StandardException { if (p==null) return null; StringReader r = new StringReader(p); String[] result = parseIdList(r, true); verifyEmpty(r); return result; } /** Parse a list of comma separated SQL identifiers returning them a as elements in an array. @param normalize true means return ids in nomral form, false means return them as they were entered. @exception StandardException Oops */ private static String[] parseIdList(StringReader r, boolean normalize) throws StandardException { Vector v = new Vector(); while (true) { int delim; try { String thisId = IdUtil.parseId(r,normalize); v.addElement(thisId); r.mark(0); delim = r.read(); if (delim != ',') { if (delim!=-1) r.reset(); break; } } catch (StandardException se){ if (se.getMessageId().equals(SQLState.ID_LIST_PARSE_ERROR)) throw StandardException.newException(SQLState.ID_LIST_PARSE_ERROR,se); else throw se; } catch (IOException ioe){ throw StandardException.newException(SQLState.ID_LIST_PARSE_ERROR,ioe); } } if (v.size() == 0) return null; String[] result = new String[v.size()]; v.copyInto(result); return result; } /** Return an IdList with all the ids that in l1 and l2 or null if not ids are on both lists. @param l1 An array of ids in normal form @param l2 An array of ids in nomral form */ public static String intersect(String[] l1, String[] l2) { if (l1 == null || l2 == null) return null; HashSet h = new HashSet(); for(int ix=0;ix




© 2015 - 2024 Weber Informatics LLC | Privacy Policy