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: package org.apache.cocoon.components.treeprocessor.variables;
018:
019: import org.apache.avalon.framework.component.ComponentManager;
020: import org.apache.avalon.framework.service.ServiceManager;
021: import org.apache.avalon.framework.service.WrapperServiceManager;
022:
023: import org.apache.cocoon.sitemap.PatternException;
024:
025: import java.util.List;
026:
027: /**
028: *
029: * @version CVS $Id: VariableResolverFactory.java 433543 2006-08-22 06:22:54Z crossley $
030: */
031: public class VariableResolverFactory {
032:
033: private static ThreadLocal disposableCollector = new ThreadLocal();
034:
035: /**
036: * Set the thread-local list where all created resolvers that need to be
037: * disposed will be collected.
038: * <p>
039: * The purpose of collecting resolvers is to avoid manual release (or lack thereof)
040: * that requires most <code>ProcessingNodes</code> to implement <code>Disposable</code>.
041: */
042: public static void setDisposableCollector(List collector) {
043: disposableCollector.set(collector);
044: }
045:
046: /**
047: * Does an expression need resolving (i.e. contain {...} patterns) ?
048: */
049: public static boolean needsResolve(String expression) {
050: if (expression == null || expression.length() == 0) {
051: return false;
052: }
053:
054: // Is the first char a '{' ?
055: if (expression.charAt(0) == '{') {
056: return true;
057: }
058:
059: if (expression.length() < 2) {
060: return false;
061: }
062:
063: // Is there any unescaped '{' ?
064: int pos = 1;
065: while ((pos = expression.indexOf('{', pos)) != -1) {
066: // Found a '{' : is it escaped ?
067: if (expression.charAt(pos - 1) != '\\') {
068: // No : need to resolve
069: return true;
070: }
071: pos++;
072: }
073: // Nothing found...
074: return false;
075: }
076:
077: /**
078: * Unescape an expression that doesn't need to be resolved, but may contain
079: * escaped '{' characters.
080: *
081: * @param expression the expression to unescape.
082: * @return the unescaped result, or <code>expression</code> if unescaping isn't necessary.
083: */
084: public static String unescape(String expression) {
085: // Does it need escaping ?
086: if (expression == null || expression.indexOf("\\{") == -1) {
087: return expression;
088: }
089:
090: StringBuffer buf = new StringBuffer();
091: for (int i = 0; i < expression.length(); i++) {
092: char ch = expression.charAt(i);
093: if (ch != '\\' || i >= (expression.length() - 1)
094: || expression.charAt(i + 1) != '{') {
095: buf.append(ch);
096: }
097: }
098:
099: return buf.toString();
100: }
101:
102: /**
103: * Get a resolver for a given expression. Chooses the most efficient implementation
104: * depending on <code>expression</code>.
105: *
106: * @deprecated use the version with <code>ServiceManager</service>
107: */
108: public static VariableResolver getResolver(String expression,
109: ComponentManager manager) throws PatternException {
110: return getResolver(expression, new WrapperServiceManager(
111: manager));
112: }
113:
114: /**
115: * Get a resolver for a given expression. Chooses the most efficient implementation
116: * depending on <code>expression</code>.
117: */
118: public static VariableResolver getResolver(String expression,
119: ServiceManager manager) throws PatternException {
120: if (needsResolve(expression)) {
121: VariableResolver resolver = new PreparedVariableResolver(
122: expression, manager);
123: List collector = (List) disposableCollector.get();
124: if (collector != null)
125: collector.add(resolver);
126:
127: return resolver;
128:
129: } else {
130: return new NOPVariableResolver(expression);
131: }
132: }
133: }
|