001: /*
002: ItsNat Java Web Application Framework
003: Copyright (C) 2007 Innowhere Software Services S.L., Spanish Company
004: Author: Jose Maria Arranz Santamaria
005:
006: This program is free software: you can redistribute it and/or modify
007: it under the terms of the GNU Affero General Public License as published by
008: the Free Software Foundation, either version 3 of the License, or
009: (at your option) any later version. See the GNU Affero General Public
010: License for more details. See the copy of the GNU Affero General Public License
011: included in this program. If not, see <http://www.gnu.org/licenses/>.
012: */
013:
014: package org.itsnat.impl.core;
015:
016: import java.beans.BeanInfo;
017: import java.beans.IntrospectionException;
018: import java.beans.Introspector;
019: import java.beans.PropertyDescriptor;
020: import java.lang.reflect.InvocationTargetException;
021: import java.lang.reflect.Method;
022: import org.itsnat.core.ItsNatVariableResolver;
023: import java.util.HashMap;
024: import java.util.Map;
025: import org.itsnat.core.ItsNatException;
026: import org.w3c.dom.Attr;
027: import org.w3c.dom.NamedNodeMap;
028: import org.w3c.dom.Node;
029: import org.w3c.dom.CharacterData;
030:
031: /**
032: *
033: * @author jmarranz
034: */
035: public class ItsNatVariableResolverImpl implements
036: ItsNatVariableResolver {
037: protected ItsNatVariableResolverImpl parent;
038: protected ItsNatServletRequestImpl request;
039: protected ItsNatDocumentImpl document;
040: protected ItsNatSessionImpl session;
041: protected ItsNatServletContextImpl context;
042: protected Map localAttribs = new HashMap();
043:
044: /**
045: * Creates a new instance of ItsNatVariableResolverImpl
046: */
047: public ItsNatVariableResolverImpl(
048: ItsNatVariableResolverImpl parent,
049: ItsNatServletRequestImpl request,
050: ItsNatDocumentImpl document, ItsNatSessionImpl session,
051: ItsNatServletContextImpl context) {
052: // Sólo una de ellas será null
053: this .parent = parent;
054: this .request = request;
055: this .document = document;
056: this .session = session;
057: this .context = context;
058: }
059:
060: public ItsNatVariableResolver createItsNatVariableResolver() {
061: return new ItsNatVariableResolverImpl(this , null, null, null,
062: null);
063: }
064:
065: public Object getLocalVariable(String name) {
066: return localAttribs.get(name);
067: }
068:
069: public Object setLocalVariable(String name, Object value) {
070: return localAttribs.put(name, value);
071: }
072:
073: public Object removeLocalVariable(String name) {
074: return localAttribs.remove(name);
075: }
076:
077: public void introspect(String refName, Object obj) {
078: String prefix = "";
079: if ((refName != null) && !refName.equals(""))
080: prefix = refName + ".";
081:
082: // Podríamos usar la clase Instrospector pero "nos sobra" funcionalidad.
083: // mejor a mano.
084: Class clasz = obj.getClass();
085: BeanInfo beanInfo;
086: try {
087: beanInfo = Introspector.getBeanInfo(clasz);
088: } catch (IntrospectionException ex) {
089: throw new ItsNatException(ex);
090: }
091:
092: PropertyDescriptor[] props = beanInfo.getPropertyDescriptors();
093: try {
094: for (int i = 0; i < props.length; i++) {
095: PropertyDescriptor property = props[i];
096: String propName = property.getName();
097: Method method = property.getReadMethod();
098: Object res = method.invoke(obj, null);
099: setLocalVariable(prefix + propName, res);
100: }
101: } catch (IllegalAccessException ex) {
102: throw new ItsNatException(ex);
103: } catch (InvocationTargetException ex) {
104: throw new ItsNatException(ex);
105: }
106: }
107:
108: public Object getVariable(String name) {
109: Object value = getLocalVariable(name);
110: if (value != null)
111: return value;
112:
113: if (parent != null)
114: return parent.getVariable(name);
115: else if (request != null)
116: return request.getVariable(name);
117: else if (document != null)
118: return document.getVariable(name);
119: else if (session != null)
120: return session.getVariable(name);
121: else
122: return context.getVariable(name);
123: }
124:
125: public String resolve(String str) {
126: // Devolver null si no se ha resuelto ninguna variable (no hay o no se conocen)
127: if (str == null)
128: return null;
129: if (str.length() == 0)
130: return null;
131:
132: boolean resolvedSomeVar = false;
133:
134: StringBuffer res = new StringBuffer();
135: int pos = 0;
136: do {
137: int first = str.indexOf("${", pos);
138: if (first != -1) {
139: int end = str.indexOf('}', first + 2);
140: if (end != -1) {
141: res.append(str.substring(pos, first));
142: String varName = str.substring(first + 2, end);
143: Object value = getVariable(varName);
144: if (value != null) {
145: res.append(value.toString());
146: resolvedSomeVar = true;
147: } else
148: // Es una variable pero no se conoce, la dejamos como estaba, puede ser una marca de nodo cacheado
149: res.append(str.substring(first, end + 1)); // Dejamos la variable como está
150: pos = end + 1;
151: if (pos >= str.length())
152: pos = -1;
153: } else {
154: if (pos == 0)
155: return null; // No hay nada que substituir
156:
157: res.append(str.substring(pos));
158: pos = -1;
159: }
160: } else {
161: if (pos == 0)
162: return null; // No hay nada que substituir
163:
164: res.append(str.substring(pos));
165: pos = -1;
166: }
167: } while (pos != -1);
168:
169: if (!resolvedSomeVar)
170: return null;
171:
172: return res.toString(); // La nueva cadena con las variables (conocidas) resueltas
173: }
174:
175: public boolean resolve(Node node) {
176: boolean resolvedSomeVar = false;
177: if (node.hasAttributes()) {
178: NamedNodeMap attribs = node.getAttributes();
179: for (int i = 0; i < attribs.getLength(); i++) {
180: Attr attr = (Attr) attribs.item(i);
181: String oldValue = attr.getValue();
182: String newValue = resolve(oldValue);
183: if (newValue != null) {
184: attr.setValue(newValue);
185: resolvedSomeVar = true;
186: }
187: }
188: }
189:
190: Node child = node.getFirstChild();
191: while (child != null) {
192: if (child instanceof CharacterData) {
193: CharacterData textNode = (CharacterData) child;
194: String oldValue = textNode.getData();
195: String newValue = resolve(oldValue);
196: if (newValue != null) {
197: textNode.setData(newValue);
198: resolvedSomeVar = true;
199: }
200: } else {
201: if (resolve(child))
202: resolvedSomeVar = true;
203: }
204:
205: child = child.getNextSibling();
206: }
207:
208: return resolvedSomeVar;
209: }
210:
211: }
|