001: /*
002: * $Id: DispatchContext.java,v 1.2 2003/08/17 08:42:35 jonesde Exp $
003: *
004: * Copyright (c) 2001, 2002 The Open For Business Project - www.ofbiz.org
005: *
006: * Permission is hereby granted, free of charge, to any person obtaining a
007: * copy of this software and associated documentation files (the "Software"),
008: * to deal in the Software without restriction, including without limitation
009: * the rights to use, copy, modify, merge, publish, distribute, sublicense,
010: * and/or sell copies of the Software, and to permit persons to whom the
011: * Software is furnished to do so, subject to the following conditions:
012: *
013: * The above copyright notice and this permission notice shall be included
014: * in all copies or substantial portions of the Software.
015: *
016: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
017: * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
018: * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
019: * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
020: * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
021: * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
022: * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
023: *
024: */
025: package org.ofbiz.service;
026:
027: import java.io.Serializable;
028: import java.net.URL;
029: import java.util.Collection;
030: import java.util.HashMap;
031: import java.util.Iterator;
032: import java.util.List;
033: import java.util.Map;
034:
035: import org.ofbiz.base.component.ComponentConfig;
036: import org.ofbiz.base.config.GenericConfigException;
037: import org.ofbiz.base.config.MainResourceHandler;
038: import org.ofbiz.base.config.ResourceHandler;
039: import org.ofbiz.entity.GenericDelegator;
040: import org.ofbiz.security.Security;
041: import org.ofbiz.service.config.ServiceConfigUtil;
042: import org.ofbiz.base.util.Debug;
043: import org.ofbiz.base.util.UtilCache;
044: import org.ofbiz.base.util.UtilXml;
045: import org.w3c.dom.Element;
046:
047: /**
048: * Dispatcher Context
049: *
050: * @author <a href="mailto:jaz@ofbiz.org">Andy Zeneski</a>
051: * @author <a href="mailto:jonesde@ofbiz.org">David E. Jones</a>
052: * @version $Revision: 1.2 $
053: * @since 2.0
054: */
055: public class DispatchContext implements Serializable {
056:
057: public static final String module = DispatchContext.class.getName();
058:
059: protected static final String GLOBAL_KEY = "global.services";
060: protected static UtilCache modelService = new UtilCache(
061: "service.ModelServices", 0, 0);
062:
063: protected transient LocalDispatcher dispatcher;
064: protected ClassLoader loader;
065: protected Collection readers;
066: protected Map attributes;
067: protected String name;
068:
069: /**
070: * Creates new DispatchContext
071: * @param readers a collection of reader URLs
072: * @param loader the classloader to use for dispatched services
073: */
074: public DispatchContext(String name, Collection readers,
075: ClassLoader loader, LocalDispatcher dispatcher) {
076: this .name = name;
077: this .readers = readers;
078: this .loader = loader;
079: this .dispatcher = dispatcher;
080: this .attributes = new HashMap();
081: }
082:
083: public void loadReaders() {
084: Map localService = addReaders(readers);
085: if (localService != null) {
086: modelService.put(name, localService);
087: }
088:
089: Map globalService = addGlobal();
090: if (globalService != null) {
091: modelService.put(GLOBAL_KEY, globalService);
092: }
093: }
094:
095: /**
096: * Returns the service attribute for the given name, or null if there is no attribute by that name.
097: * @param name a String specifying the name of the attribute
098: * @return an Object conatining the value of the attribute, or null if there is no attribute by that name.
099: */
100: public Object getAttribute(String name) {
101: if (attributes.containsKey(name))
102: return attributes.get(name);
103: return null;
104: }
105:
106: /**
107: * Binds an object to a given attribute name in this context.
108: * @param name a String specifying the name of the attribute
109: * @param object an Object representing the attribute to be bound.
110: */
111: public void setAttribute(String name, Object object) {
112: attributes.put(name, object);
113: }
114:
115: /**
116: * Gets the classloader of this context
117: * @return ClassLoader of the context
118: */
119: public ClassLoader getClassLoader() {
120: return this .loader;
121: }
122:
123: /**
124: * Gets the collection of readers associated with this context
125: * @return Collection of reader URLs
126: */
127: public Collection getReaders() {
128: return readers;
129: }
130:
131: /**
132: * Gets the name of the local dispatcher
133: * @return String name of the LocalDispatcher object
134: */
135: public String getName() {
136: return name;
137: }
138:
139: /**
140: * Uses an existing map of name value pairs and extracts the keys which are used in serviceName
141: * Note: This goes not guarantee the context will be 100% valid, there may be missing fields
142: * @param serviceName The name of the service to obtain parameters for
143: * @param mode The mode to use for building the new map (i.e. can be IN or OUT)
144: * @param context The initial set of values to pull from
145: * @return Map contains any valid values
146: * @throws GenericServiceException
147: */
148: public Map makeValidContext(String serviceName, String mode,
149: Map context) throws GenericServiceException {
150: ModelService model = this .getModelService(serviceName);
151: return makeValidContext(model, mode, context);
152:
153: }
154:
155: /**
156: * Uses an existing map of name value pairs and extracts the keys which are used in serviceName
157: * Note: This goes not guarantee the context will be 100% valid, there may be missing fields
158: * @param model The ModelService object of the service to obtain parameters for
159: * @param mode The mode to use for building the new map (i.e. can be IN or OUT)
160: * @param context The initial set of values to pull from
161: * @return Map contains any valid values
162: * @throws GenericServiceException
163: */
164: public Map makeValidContext(ModelService model, String mode,
165: Map context) throws GenericServiceException {
166: Map newContext = null;
167:
168: int modeInt = 0;
169: if (mode.equalsIgnoreCase("in")) {
170: modeInt = 1;
171: } else if (mode.equalsIgnoreCase("out")) {
172: modeInt = 2;
173: }
174:
175: if (model == null) {
176: throw new GenericServiceException(
177: "Model service is null! Should never happen.");
178: } else {
179: switch (modeInt) {
180: case 2:
181: newContext = model.makeValid(context,
182: ModelService.OUT_PARAM, true);
183: break;
184: case 1:
185: newContext = model.makeValid(context,
186: ModelService.IN_PARAM, true);
187: break;
188: default:
189: throw new GenericServiceException(
190: "Invalid mode, should be either IN or OUT");
191: }
192: return newContext;
193: }
194: }
195:
196: /**
197: * Gets the ModelService instance that corresponds to given the name
198: * @param serviceName Name of the service
199: * @return GenericServiceModel that corresponds to the serviceName
200: */
201: public ModelService getModelService(String serviceName)
202: throws GenericServiceException {
203: ModelService retVal = getLocalModelService(serviceName);
204: if (retVal == null) {
205: retVal = getGlobalModelService(serviceName);
206: }
207:
208: if (retVal == null) {
209: throw new GenericServiceException(
210: "Cannot locate service by name (" + serviceName
211: + ")");
212: }
213:
214: return retVal;
215: }
216:
217: private ModelService getLocalModelService(String serviceName)
218: throws GenericServiceException {
219: Map serviceMap = (Map) modelService.get(name);
220: if (serviceMap == null) {
221: synchronized (this ) {
222: serviceMap = (Map) modelService.get(name);
223: if (serviceMap == null) {
224: serviceMap = addReaders(readers);
225: if (serviceMap != null)
226: modelService.put(name, serviceMap);
227: }
228: }
229: }
230:
231: ModelService retVal = null;
232: if (serviceMap != null) {
233: retVal = (ModelService) serviceMap.get(serviceName);
234: if (retVal != null && !retVal.inheritedParameters()) {
235: retVal.interfaceUpdate(this );
236: }
237: }
238:
239: return retVal;
240: }
241:
242: private ModelService getGlobalModelService(String serviceName)
243: throws GenericServiceException {
244: Map serviceMap = (Map) modelService.get(GLOBAL_KEY);
245: if (serviceMap == null) {
246: synchronized (this ) {
247: serviceMap = (Map) modelService.get(GLOBAL_KEY);
248: if (serviceMap == null) {
249: serviceMap = addGlobal();
250: if (serviceMap != null)
251: modelService.put(GLOBAL_KEY, serviceMap);
252: }
253: }
254: }
255:
256: ModelService retVal = null;
257: if (serviceMap != null) {
258: retVal = (ModelService) serviceMap.get(serviceName);
259: if (retVal != null && !retVal.inheritedParameters()) {
260: retVal.interfaceUpdate(this );
261: }
262: }
263:
264: return retVal;
265: }
266:
267: /**
268: * Gets the LocalDispatcher used with this context
269: * @return LocalDispatcher that was used to create this context
270: */
271: public LocalDispatcher getDispatcher() {
272: return this .dispatcher;
273: }
274:
275: /**
276: * Sets the LocalDispatcher used with this context
277: * @param dispatcher The LocalDispatcher to re-assign to this context
278: */
279: public void setDispatcher(LocalDispatcher dispatcher) {
280: this .dispatcher = dispatcher;
281: }
282:
283: /**
284: * Gets the GenericDelegator associated with this context/dispatcher
285: * @return GenericDelegator associated with this context
286: */
287: public GenericDelegator getDelegator() {
288: return dispatcher.getDelegator();
289: }
290:
291: /**
292: * Gets the Security object associated with this dispatcher
293: * @return Security object associated with this dispatcher
294: */
295: public Security getSecurity() {
296: return dispatcher.getSecurity();
297: }
298:
299: private Map addReaders(Collection readerURLs) {
300: Map serviceMap = new HashMap();
301:
302: if (readerURLs == null)
303: return null;
304: Iterator urlIter = readerURLs.iterator();
305:
306: while (urlIter.hasNext()) {
307: URL readerURL = (URL) urlIter.next();
308:
309: serviceMap.putAll(addReader(readerURL));
310: }
311: return serviceMap;
312: }
313:
314: private Map addReader(URL readerURL) {
315: if (readerURL == null) {
316: Debug.logError("Cannot add reader with a null reader URL",
317: module);
318: return null;
319: }
320:
321: ModelServiceReader reader = ModelServiceReader
322: .getModelServiceReader(readerURL, this );
323:
324: if (reader == null) {
325: Debug.logError(
326: "Could not load the reader for the reader URL "
327: + readerURL, module);
328: return null;
329: }
330:
331: Map serviceMap = reader.getModelServices();
332:
333: return serviceMap;
334: }
335:
336: private Map addReader(ResourceHandler handler) {
337: ModelServiceReader reader = ModelServiceReader
338: .getModelServiceReader(handler, this );
339:
340: if (reader == null) {
341: Debug.logError("Could not load the reader for " + handler,
342: module);
343: return null;
344: }
345:
346: Map serviceMap = reader.getModelServices();
347:
348: return serviceMap;
349: }
350:
351: private Map addGlobal() {
352: Map globalMap = new HashMap();
353:
354: Element rootElement = null;
355:
356: try {
357: rootElement = ServiceConfigUtil.getXmlRootElement();
358: } catch (GenericConfigException e) {
359: Debug.logError(e,
360: "Error getting Service Engine XML root element",
361: module);
362: return null;
363: }
364:
365: List globalServicesElements = UtilXml.childElementList(
366: rootElement, "global-services");
367: Iterator gseIter = globalServicesElements.iterator();
368: while (gseIter.hasNext()) {
369: Element globalServicesElement = (Element) gseIter.next();
370: ResourceHandler handler = new MainResourceHandler(
371: ServiceConfigUtil.SERVICE_ENGINE_XML_FILENAME,
372: globalServicesElement);
373:
374: Map servicesMap = addReader(handler);
375: if (servicesMap != null) {
376: globalMap.putAll(servicesMap);
377: }
378: }
379:
380: // get all of the component resource model stuff, ie specified in each ofbiz-component.xml file
381: List componentResourceInfos = ComponentConfig
382: .getAllServiceResourceInfos("model");
383: Iterator componentResourceInfoIter = componentResourceInfos
384: .iterator();
385: while (componentResourceInfoIter.hasNext()) {
386: ComponentConfig.ServiceResourceInfo componentResourceInfo = (ComponentConfig.ServiceResourceInfo) componentResourceInfoIter
387: .next();
388: Map servicesMap = addReader(componentResourceInfo
389: .createResourceHandler());
390: if (servicesMap != null) {
391: globalMap.putAll(servicesMap);
392: }
393: }
394:
395: return globalMap;
396: }
397: }
|