001: /* ====================================================================
002: * The Jcorporate Apache Style Software License, Version 1.2 05-07-2002
003: *
004: * Copyright (c) 1995-2002 Jcorporate Ltd. All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions
008: * are met:
009: *
010: * 1. Redistributions of source code must retain the above copyright
011: * notice, this list of conditions and the following disclaimer.
012: *
013: * 2. Redistributions in binary form must reproduce the above copyright
014: * notice, this list of conditions and the following disclaimer in
015: * the documentation and/or other materials provided with the
016: * distribution.
017: *
018: * 3. The end-user documentation included with the redistribution,
019: * if any, must include the following acknowledgment:
020: * "This product includes software developed by Jcorporate Ltd.
021: * (http://www.jcorporate.com/)."
022: * Alternately, this acknowledgment may appear in the software itself,
023: * if and wherever such third-party acknowledgments normally appear.
024: *
025: * 4. "Jcorporate" and product names such as "Expresso" must
026: * not be used to endorse or promote products derived from this
027: * software without prior written permission. For written permission,
028: * please contact info@jcorporate.com.
029: *
030: * 5. Products derived from this software may not be called "Expresso",
031: * or other Jcorporate product names; nor may "Expresso" or other
032: * Jcorporate product names appear in their name, without prior
033: * written permission of Jcorporate Ltd.
034: *
035: * 6. No product derived from this software may compete in the same
036: * market space, i.e. framework, without prior written permission
037: * of Jcorporate Ltd. For written permission, please contact
038: * partners@jcorporate.com.
039: *
040: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
041: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
042: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
043: * DISCLAIMED. IN NO EVENT SHALL JCORPORATE LTD OR ITS CONTRIBUTORS
044: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
045: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
046: * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
047: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
048: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
049: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
050: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
051: * SUCH DAMAGE.
052: * ====================================================================
053: *
054: * This software consists of voluntary contributions made by many
055: * individuals on behalf of the Jcorporate Ltd. Contributions back
056: * to the project(s) are encouraged when you make modifications.
057: * Please send them to support@jcorporate.com. For more information
058: * on Jcorporate Ltd. and its products, please see
059: * <http://www.jcorporate.com/>.
060: *
061: * Portions of this software are based upon other open source
062: * products and are subject to their respective licenses.
063: */
064:
065: package com.jcorporate.expresso.kernel.util;
066:
067: import com.jcorporate.expresso.kernel.Containable;
068: import com.jcorporate.expresso.kernel.DataContext;
069: import com.jcorporate.expresso.kernel.ExpressoComponent;
070: import com.jcorporate.expresso.kernel.RootContainerInterface;
071: import com.jcorporate.expresso.kernel.digester.ComponentConfig;
072: import com.jcorporate.expresso.kernel.metadata.ComponentMetadata;
073:
074: import java.util.ArrayList;
075: import java.util.ListIterator;
076: import java.util.Map;
077:
078: /**
079: * Locator Utils are to allow walking the component hierarchy tree so you
080: * can reference components by a 'path name' instead of walking it manually
081: * yourself
082: * <p>Beacuse there are potentially more than one Runtime Environment in a Virtual
083: * Machine, you must associate a LocatorUtils object with any component within
084: * a tree. Once it has that figured out, it can locate any other component
085: * in the tree</p>
086: *
087: * @author Michael Rimov
088: * @version $Revision: 1.9 $ on $Date: 2004/11/17 20:48:17 $
089: * @since Expresso 5.1
090: */
091:
092: public class LocatorUtils {
093: ExpressoComponent root = null;
094:
095: /**
096: * Base constructor that locates the root component in the hierarchy as
097: * soon as it is instantiated.
098: *
099: * @param component any component in the Runtime Hierarchy
100: */
101: public LocatorUtils(ExpressoComponent component) {
102: if (component == null) {
103: throw new IllegalArgumentException(
104: "Must have a non-null argument for parameter 'component'");
105: }
106: boolean done = false;
107: Containable parent = null;
108: while (!done) {
109: parent = component.getParent();
110: if (parent == null) {
111: done = true;
112: root = component;
113: } else {
114: component = parent;
115: }
116: }
117: }
118:
119: /**
120: * <p>Allows you to locate the component via a 'bean utils' style string.</p>
121: * <p>Examples:</p>
122: * <p>Locate a component in default context by the name of myComponent:<br />
123: * ExpressoComponent mycomponent = locator.locateComponent("default.myComponent");</p>
124: * <p>Locate the root container:<br />
125: * ExpressoComponent rootContainer = locator.locateComponent("");</p>
126: *
127: * @param pathName The pathname to use to locate the particular component as
128: * described in the above javadocs.
129: * @return ExpressoComponent found
130: * @throws IllegalArgumentException if either the pathName is improper or
131: * if the component doesn't seem to exist in the given traversal
132: */
133: public ExpressoComponent locateComponent(String pathName) {
134: if (pathName == null || pathName.length() == 0) {
135: return root;
136: }
137:
138: String stringLeft = pathName;
139: String singleComponent = null;
140: int splitPoint = 0;
141: ExpressoComponent currentComponent = root;
142: do {
143: splitPoint = stringLeft.indexOf(".");
144: if (splitPoint == 0) {
145: throw new IllegalArgumentException(
146: "Malformed Path Request: " + pathName);
147: }
148: if (splitPoint == -1) {
149: singleComponent = stringLeft;
150: stringLeft = "";
151: } else {
152: singleComponent = stringLeft.substring(0, splitPoint);
153: stringLeft = stringLeft.substring(splitPoint + 1);
154: }
155:
156: if (!(currentComponent instanceof Containable)) {
157: throw new IllegalArgumentException(
158: "Can't navigate below component: "
159: + currentComponent.getMetaData()
160: .getName()
161: + "it is not a component container");
162: }
163:
164: Containable currentContainer = (Containable) currentComponent;
165: Map children = currentContainer
166: .getContainerImplementation().getChildComponents();
167: if (!children.containsKey(singleComponent)) {
168: throw new IllegalArgumentException(
169: "Unable to locate subcomponent "
170: + singleComponent
171: + " as a subcomponent of "
172: + currentComponent.getMetaData()
173: .getName());
174: }
175:
176: currentComponent = (ExpressoComponent) children
177: .get(singleComponent);
178:
179: } while (splitPoint > -1);
180:
181: return currentComponent;
182: }
183:
184: /**
185: * <p>Allows you to locate the component via a 'bean utils' style string.</p>
186: * <p>Examples:</p>
187: * <p>Locate a components configuration in default context by the name of myComponent:<br />
188: * ComponentConfig myconfig = locator.locateComponent("default.myComponent");</p>
189: * <p>Locate the root container:<br />
190: * ComponentConfig rootContainerConfig = locator.locateComponent("");</p>
191: *
192: * @param pathName The pathname to use to locate the particular component as
193: * described in the above javadocs.
194: * @return ComponentConfig found
195: * @throws IllegalArgumentException if either the pathName is improper or
196: * if the component doesn't seem to exist in the given traversal
197: */
198: public ComponentConfig locateConfiguration(String pathName) {
199: if (pathName == null || pathName.length() == 0) {
200: return ((RootContainerInterface) root)
201: .getExpressoServicesConfig().getRootConfig();
202: }
203:
204: String stringLeft = pathName;
205: String singleComponent = null;
206: int splitPoint = 0;
207: ComponentConfig currentComponent = ((RootContainerInterface) root)
208: .getExpressoServicesConfig().getRootConfig();
209: do {
210: splitPoint = stringLeft.indexOf(".");
211: if (splitPoint == 0) {
212: throw new IllegalArgumentException(
213: "Malformed Path Request: " + pathName);
214: }
215: if (splitPoint == -1) {
216: singleComponent = stringLeft;
217: stringLeft = "";
218: } else {
219: singleComponent = stringLeft.substring(0, splitPoint);
220: stringLeft = stringLeft.substring(splitPoint + 1);
221: }
222:
223: ComponentConfig testconfig = currentComponent
224: .getChildComponent(singleComponent);
225: if (testconfig == null) {
226: throw new IllegalArgumentException(
227: "Unable to locate subcomponent configuration "
228: + singleComponent
229: + " as a subcomponent of "
230: + currentComponent.getName());
231:
232: }
233: currentComponent = testconfig;
234:
235: } while (splitPoint > -1);
236:
237: return currentComponent;
238: }
239:
240: /**
241: * <p>Allows you to locate the component metadata via a 'bean utils' style string.</p>
242: * <p>Examples:</p>
243: * <p>Locate a components configuration in default context by the name of myComponent:<br />
244: * ComponentConfig myconfig = locator.locateComponent("default.myComponent");</p>
245: * <p>Locate the root container:<br />
246: * ComponentConfig rootContainerConfig = locator.locateComponent("");</p>
247: *
248: * @param pathName The pathname to use to locate the particular component as
249: * described in the above javadocs.
250: * @return ComponentMetadata found
251: * @throws IllegalArgumentException if either the pathName is improper or
252: * if the component doesn't seem to exist in the given traversal
253: */
254: public ComponentMetadata locateMetadata(String pathName) {
255: ExpressoComponent component = this .locateComponent(pathName);
256: return component.getMetaData();
257: }
258:
259: /**
260: * Return a path that the Locator utils could find later to relocate this
261: * component.
262: *
263: * @param component The component to get the location string.
264: * @return java.lang.String possibly empty string if the component is root.
265: */
266: public String getPath(ExpressoComponent component) {
267: Containable c = component.getParent();
268: if (c == null) {
269: return "";
270: }
271:
272: ExpressoComponent currentComponent = component;
273: ArrayList al = new ArrayList();
274: //Traverse up the tree
275: while (c != null) {
276: al.add(currentComponent.getMetaData().getName());
277: currentComponent = c;
278: c = currentComponent.getParent();
279: }
280:
281: //Now write the info in reverse
282: FastStringBuffer path = FastStringBuffer.getInstance();
283: boolean needPeriod = false;
284: for (ListIterator i = al.listIterator(al.size()); i
285: .hasPrevious();) {
286: String value = (String) i.previous();
287: if (needPeriod) {
288: path.append(".");
289: } else {
290: needPeriod = true;
291: }
292:
293: path.append(value);
294: }
295:
296: String returnValue = path.toString();
297: path.release();
298: return returnValue;
299: }
300:
301: /**
302: * Given the component that we loaded, find the data context name we're a
303: * part of.
304: *
305: * @param component the name of the component to retrieve the context name
306: * @return java.util.String of the data context name or null if the defined
307: * component is not embedded within a data context.
308: */
309: public String getDataContextName(ExpressoComponent component) {
310: return getDataContext(component).getMetaData().getName();
311:
312: }
313:
314: /**
315: * Retrieve the DataContext that the given component is a part of
316: *
317: * @param component the component in the hierarchy that we want to find
318: * what data context it is a part of.
319: * @return DataContext or null if the component is not part of a data context.
320: */
321: public DataContext getDataContext(ExpressoComponent component) {
322: if (component == null) {
323: throw new IllegalArgumentException(
324: "Must have a non-null argument for parameter 'component'");
325: }
326: boolean done = false;
327: Containable parent = null;
328: while (!done) {
329: parent = component.getParent();
330: if (parent instanceof DataContext) {
331: return (DataContext) parent;
332: }
333:
334: if (parent == null) {
335: done = true;
336: }
337: component = parent;
338: }
339:
340: return null;
341: }
342: }
|