001: /*
002: * Copyright 2004,2004 The Apache Software Foundation.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.apache.bsf.util;
018:
019: import java.beans.Introspector;
020: import java.io.BufferedReader;
021: import java.io.File;
022: import java.io.FileNotFoundException;
023: import java.io.IOException;
024: import java.io.InputStream;
025: import java.io.InputStreamReader;
026: import java.io.Reader;
027: import java.io.StringReader;
028: import java.net.MalformedURLException;
029: import java.net.URL;
030: import java.util.StringTokenizer;
031: import java.util.Vector;
032:
033: /**
034: * Deals with strings (probably need to elaborate some more).
035: *
036: * @author Matthew J. Duftler
037: */
038: public class StringUtils {
039: public static final String lineSeparator = System.getProperty(
040: "line.separator", "\n");
041: public static final String lineSeparatorStr = cleanString(lineSeparator);
042:
043: public static String classNameToVarName(String className) {
044: // Might represent an array.
045: int arrayDim = 0;
046:
047: while (className.endsWith("[]")) {
048: className = className.substring(0, className.length() - 2);
049: arrayDim++;
050: }
051:
052: int iLastPeriod = className.lastIndexOf('.');
053: String varName = Introspector
054: .decapitalize(iLastPeriod != -1 ? className
055: .substring(iLastPeriod + 1) : className);
056:
057: if (arrayDim > 0) {
058: varName += "_" + arrayDim + "D";
059: }
060:
061: return getValidIdentifierName(varName);
062: }
063:
064: // Ensure that escape sequences are passed through properly.
065: public static String cleanString(String str) {
066: if (str == null)
067: return null;
068: else {
069: char[] charArray = str.toCharArray();
070: StringBuffer sBuf = new StringBuffer();
071:
072: for (int i = 0; i < charArray.length; i++)
073: switch (charArray[i]) {
074: case '\"':
075: sBuf.append("\\\"");
076: break;
077: case '\\':
078: sBuf.append("\\\\");
079: break;
080: case '\n':
081: sBuf.append("\\n");
082: break;
083: case '\r':
084: sBuf.append("\\r");
085: break;
086: default:
087: sBuf.append(charArray[i]);
088: break;
089: }
090:
091: return sBuf.toString();
092: }
093: }
094:
095: /**
096: * Get a string consisting of <code>numberOfChars</code> theChars.
097: *
098: * @return a string consisting of <code>numberOfChars</code> theChars.
099: */
100: public static String getChars(int numberOfChars, char theChar) {
101: if (numberOfChars <= 0)
102: return "";
103:
104: StringBuffer sRet = new StringBuffer(numberOfChars);
105:
106: for (int i = 0; i < numberOfChars; i++)
107: sRet.append(theChar);
108:
109: return sRet.toString();
110: }
111:
112: /*
113: This method will return the correct name for a class object representing
114: a primitive, a single instance of a class, as well as n-dimensional arrays
115: of primitives or instances. This logic is needed to handle the string returned
116: from Class.getName(). If the class object represents a single instance (or
117: a primitive), Class.getName() returns the fully-qualified name of the class
118: and no further work is needed. However, if the class object represents an
119: array (of n dimensions), Class.getName() returns a Descriptor (the Descriptor
120: grammar is defined in section 4.3 of the Java VM Spec). This method will
121: parse the Descriptor if necessary.
122: */
123: public static String getClassName(Class targetClass) {
124: String className = targetClass.getName();
125:
126: return targetClass.isArray() ? parseDescriptor(className)
127: : className;
128: }
129:
130: public static String getCommaListFromVector(Vector sourceVector) {
131: StringBuffer strBuf = new StringBuffer();
132:
133: for (int i = 0; i < sourceVector.size(); i++) {
134: strBuf.append((i > 0 ? ", " : "")
135: + sourceVector.elementAt(i));
136: }
137:
138: return strBuf.toString();
139: }
140:
141: /*
142: Returns a Reader for reading from the specified resource, if the resource
143: points to a stream.
144: */
145: public static Reader getContentAsReader(URL url)
146: throws SecurityException, IllegalArgumentException,
147: IOException {
148: if (url == null) {
149: throw new IllegalArgumentException("URL cannot be null.");
150: }
151:
152: try {
153: Object content = url.getContent();
154:
155: if (content == null) {
156: throw new IllegalArgumentException("No content.");
157: }
158:
159: if (content instanceof InputStream) {
160: Reader in = new InputStreamReader((InputStream) content);
161:
162: if (in.ready()) {
163: return in;
164: } else {
165: throw new FileNotFoundException();
166: }
167: } else {
168: throw new IllegalArgumentException(
169: (content instanceof String) ? (String) content
170: : "This URL points to a: "
171: + StringUtils
172: .getClassName(content
173: .getClass()));
174: }
175: } catch (SecurityException e) {
176: throw new SecurityException(
177: "Your JVM's SecurityManager has disallowed this.");
178: } catch (FileNotFoundException e) {
179: throw new FileNotFoundException("This file was not found: "
180: + url);
181: }
182: }
183:
184: /*
185: Shorthand for: IOUtils.getStringFromReader(getContentAsReader(url)).
186: */
187: public static String getContentAsString(URL url)
188: throws SecurityException, IllegalArgumentException,
189: IOException {
190: return IOUtils.getStringFromReader(getContentAsReader(url));
191: }
192:
193: // Handles multi-line strings.
194: public static String getSafeString(String scriptStr) {
195: BufferedReader in = new BufferedReader(new StringReader(
196: scriptStr));
197: StringBuffer strBuf = new StringBuffer();
198: String tempLine, previousLine = null;
199:
200: try {
201: while ((tempLine = in.readLine()) != null) {
202: if (previousLine != null) {
203: strBuf
204: .append("\"" + previousLine
205: + lineSeparatorStr + "\" +"
206: + lineSeparator);
207: }
208:
209: previousLine = cleanString(tempLine);
210: }
211: } catch (IOException e) {
212: }
213:
214: strBuf.append("\"" + (previousLine != null ? previousLine : "")
215: + "\"" + lineSeparator);
216:
217: return strBuf.toString();
218: }
219:
220: /*
221: */
222: public static URL getURL(URL contextURL, String spec)
223: throws MalformedURLException {
224: return getURL(contextURL, spec, 1);
225: }
226:
227: /*
228: The recursiveDepth argument is used to insure that the algorithm gives up
229: after hunting 2 levels up in the contextURL's path.
230: */
231: private static URL getURL(URL contextURL, String spec,
232: int recursiveDepth) throws MalformedURLException {
233: URL url = null;
234:
235: try {
236: url = new URL(contextURL, spec);
237:
238: try {
239: url.openStream();
240: } catch (IOException ioe1) {
241: throw new MalformedURLException(
242: "This file was not found: " + url);
243: }
244: } catch (MalformedURLException e1) {
245: url = new URL("file", "", spec);
246:
247: try {
248: url.openStream();
249: } catch (IOException ioe2) {
250: if (contextURL != null) {
251: String contextFileName = contextURL.getFile();
252: String parentName = new File(contextFileName)
253: .getParent();
254:
255: if (parentName != null && recursiveDepth < 3) {
256: return getURL(new URL("file", "",
257: parentName + '/'), spec,
258: recursiveDepth + 1);
259: }
260: }
261:
262: throw new MalformedURLException(
263: "This file was not found: " + url);
264: }
265: }
266:
267: return url;
268: }
269:
270: public static String getValidIdentifierName(String identifierName) {
271: if (identifierName == null || identifierName.length() == 0)
272: return null;
273:
274: StringBuffer strBuf = new StringBuffer();
275:
276: char[] chars = identifierName.toCharArray();
277:
278: strBuf
279: .append(Character.isJavaIdentifierStart(chars[0]) ? chars[0]
280: : '_');
281:
282: for (int i = 1; i < chars.length; i++) {
283: strBuf
284: .append(Character.isJavaIdentifierPart(chars[i]) ? chars[i]
285: : '_');
286: }
287:
288: return strBuf.toString();
289: }
290:
291: public static boolean isValidIdentifierName(String identifierName) {
292: if (identifierName == null || identifierName.length() == 0)
293: return false;
294:
295: char[] chars = identifierName.toCharArray();
296:
297: if (!Character.isJavaIdentifierStart(chars[0]))
298: return false;
299:
300: for (int i = 1; i < chars.length; i++)
301: if (!Character.isJavaIdentifierPart(chars[i]))
302: return false;
303:
304: return true;
305: }
306:
307: public static boolean isValidPackageName(String packageName) {
308: if (packageName == null)
309: return false;
310: else if (packageName.length() == 0)
311: // Empty is ok.
312: return true;
313:
314: StringTokenizer strTok = new StringTokenizer(packageName, ".",
315: true);
316:
317: // Should have an odd number of tokens (including '.' delimiters).
318: if (strTok.countTokens() % 2 != 1)
319: return false;
320:
321: // Must start with a valid identifier name.
322: if (!isValidIdentifierName(strTok.nextToken()))
323: return false;
324:
325: // ... followed by 0 or more of ".ValidIdentifier".
326: while (strTok.hasMoreTokens()) {
327: // Must be a '.'.
328: if (!strTok.nextToken().equals("."))
329: return false;
330:
331: // Must be a valid identifier name.
332: if (strTok.hasMoreTokens()) {
333: if (!isValidIdentifierName(strTok.nextToken()))
334: return false;
335: } else
336: return false;
337: }
338:
339: return true;
340: }
341:
342: /*
343: See the comment above for getClassName(targetClass)...
344: */
345: private static String parseDescriptor(String className) {
346: char[] classNameChars = className.toCharArray();
347: int arrayDim = 0;
348: int i = 0;
349:
350: while (classNameChars[i] == '[') {
351: arrayDim++;
352: i++;
353: }
354:
355: StringBuffer classNameBuf = new StringBuffer();
356:
357: switch (classNameChars[i++]) {
358: case 'B':
359: classNameBuf.append("byte");
360: break;
361: case 'C':
362: classNameBuf.append("char");
363: break;
364: case 'D':
365: classNameBuf.append("double");
366: break;
367: case 'F':
368: classNameBuf.append("float");
369: break;
370: case 'I':
371: classNameBuf.append("int");
372: break;
373: case 'J':
374: classNameBuf.append("long");
375: break;
376: case 'S':
377: classNameBuf.append("short");
378: break;
379: case 'Z':
380: classNameBuf.append("boolean");
381: break;
382: case 'L':
383: classNameBuf.append(classNameChars, i,
384: classNameChars.length - i - 1);
385: break;
386: }
387:
388: for (i = 0; i < arrayDim; i++)
389: classNameBuf.append("[]");
390:
391: return classNameBuf.toString();
392: }
393: }
|