001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: */
018:
019: package org.apache.tools.ant.util.regexp;
020:
021: import org.apache.tools.ant.Project;
022: import org.apache.tools.ant.MagicNames;
023: import org.apache.tools.ant.BuildException;
024: import org.apache.tools.ant.util.ClasspathUtils;
025: import org.apache.tools.ant.util.JavaEnvUtils;
026:
027: /**
028: * Simple Factory Class that produces an implementation of
029: * RegexpMatcher based on the system property
030: * <code>ant.regexp.regexpimpl</code> and the classes
031: * available.
032: *
033: * <p>In a more general framework this class would be abstract and
034: * have a static newInstance method.</p>
035: *
036: */
037: public class RegexpMatcherFactory {
038:
039: /** Constructor for RegexpMatcherFactory. */
040: public RegexpMatcherFactory() {
041: }
042:
043: /***
044: * Create a new regular expression instance.
045: * @return the matcher
046: * @throws BuildException on error
047: */
048: public RegexpMatcher newRegexpMatcher() throws BuildException {
049: return newRegexpMatcher(null);
050: }
051:
052: /***
053: * Create a new regular expression instance.
054: *
055: * @param p Project whose ant.regexp.regexpimpl property will be used.
056: * @return the matcher
057: * @throws BuildException on error
058: */
059: public RegexpMatcher newRegexpMatcher(Project p)
060: throws BuildException {
061: String systemDefault = null;
062: if (p == null) {
063: systemDefault = System.getProperty(MagicNames.REGEXP_IMPL);
064: } else {
065: systemDefault = p.getProperty(MagicNames.REGEXP_IMPL);
066: }
067:
068: if (systemDefault != null) {
069: return createInstance(systemDefault);
070: // XXX should we silently catch possible exceptions and try to
071: // load a different implementation?
072: }
073:
074: Throwable cause = null;
075:
076: try {
077: testAvailability("java.util.regex.Matcher");
078: return createInstance("org.apache.tools.ant.util.regexp.Jdk14RegexpMatcher");
079: } catch (BuildException be) {
080: cause = orCause(cause, be, JavaEnvUtils
081: .getJavaVersionNumber() < 14);
082: }
083:
084: try {
085: testAvailability("org.apache.oro.text.regex.Pattern");
086: return createInstance("org.apache.tools.ant.util.regexp.JakartaOroMatcher");
087: } catch (BuildException be) {
088: cause = orCause(cause, be, true);
089: }
090:
091: try {
092: testAvailability("org.apache.regexp.RE");
093: return createInstance("org.apache.tools.ant.util.regexp.JakartaRegexpMatcher");
094: } catch (BuildException be) {
095: cause = orCause(cause, be, true);
096: }
097:
098: throw new BuildException(
099: "No supported regular expression matcher found"
100: + (cause != null ? ": " + cause : ""), cause);
101: }
102:
103: static Throwable orCause(Throwable deflt, BuildException be,
104: boolean ignoreCnfe) {
105: if (deflt != null) {
106: return deflt;
107: }
108: Throwable t = be.getException();
109: return ignoreCnfe && t instanceof ClassNotFoundException ? null
110: : t;
111: }
112:
113: /**
114: * Create an instance of a matcher from a classname.
115: *
116: * @param className a <code>String</code> value
117: * @return a <code>RegexpMatcher</code> value
118: * @exception BuildException if an error occurs
119: */
120: protected RegexpMatcher createInstance(String className)
121: throws BuildException {
122: return (RegexpMatcher) ClasspathUtils.newInstance(className,
123: RegexpMatcherFactory.class.getClassLoader(),
124: RegexpMatcher.class);
125: }
126:
127: /**
128: * Test if a particular class is available to be used.
129: *
130: * @param className a <code>String</code> value
131: * @exception BuildException if an error occurs
132: */
133: protected void testAvailability(String className)
134: throws BuildException {
135: try {
136: Class.forName(className);
137: } catch (Throwable t) {
138: throw new BuildException(t);
139: }
140: }
141: }
|