001: /*******************************************************************************
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing,
013: * software distributed under the License is distributed on an
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: *******************************************************************************/package org.ofbiz.service;
019:
020: import java.io.Serializable;
021: import java.net.URL;
022: import java.util.Collection;
023: import java.util.Iterator;
024: import java.util.List;
025: import java.util.Map;
026: import java.util.Set;
027: import java.util.TreeSet;
028: import javax.wsdl.WSDLException;
029:
030: import javolution.util.FastMap;
031:
032: import org.ofbiz.base.component.ComponentConfig;
033: import org.ofbiz.base.config.GenericConfigException;
034: import org.ofbiz.base.config.MainResourceHandler;
035: import org.ofbiz.base.config.ResourceHandler;
036: import org.ofbiz.base.util.Debug;
037: import org.ofbiz.base.util.UtilXml;
038: import org.ofbiz.base.util.cache.UtilCache;
039: import org.ofbiz.entity.GenericDelegator;
040: import org.ofbiz.security.Security;
041: import org.ofbiz.service.config.ServiceConfigUtil;
042: import org.ofbiz.service.eca.ServiceEcaUtil;
043:
044: import org.w3c.dom.Document;
045: import org.w3c.dom.Element;
046:
047: /**
048: * Dispatcher Context
049: */
050: public class DispatchContext implements Serializable {
051:
052: public static final String module = DispatchContext.class.getName();
053:
054: protected static final String GLOBAL_KEY = "global.services";
055: protected static UtilCache modelServiceMapByDispatcher = new UtilCache(
056: "service.ModelServiceMapByDispatcher", 0, 0, false);
057:
058: protected transient LocalDispatcher dispatcher;
059: protected transient ClassLoader loader;
060: protected Collection localReaders;
061: protected Map attributes;
062: protected String name;
063:
064: /**
065: * Creates new DispatchContext
066: * @param localReaders a collection of reader URLs
067: * @param loader the classloader to use for dispatched services
068: */
069: public DispatchContext(String name, Collection localReaders,
070: ClassLoader loader, LocalDispatcher dispatcher) {
071: this .name = name;
072: this .localReaders = localReaders;
073: this .loader = loader;
074: this .dispatcher = dispatcher;
075: this .attributes = FastMap.newInstance();
076: }
077:
078: public void loadReaders() {
079: this .getLocalServiceMap();
080: this .getGlobalServiceMap();
081: }
082:
083: /**
084: * Returns the service attribute for the given name, or null if there is no attribute by that name.
085: * @param name a String specifying the name of the attribute
086: * @return an Object conatining the value of the attribute, or null if there is no attribute by that name.
087: */
088: public Object getAttribute(String name) {
089: if (attributes.containsKey(name))
090: return attributes.get(name);
091: return null;
092: }
093:
094: /**
095: * Binds an object to a given attribute name in this context.
096: * @param name a String specifying the name of the attribute
097: * @param object an Object representing the attribute to be bound.
098: */
099: public void setAttribute(String name, Object object) {
100: attributes.put(name, object);
101: }
102:
103: /**
104: * Gets the classloader of this context
105: * @return ClassLoader of the context
106: */
107: public ClassLoader getClassLoader() {
108: return this .loader;
109: }
110:
111: /**
112: * Gets the collection of readers associated with this context
113: * @return Collection of reader URLs
114: */
115: public Collection getReaders() {
116: return localReaders;
117: }
118:
119: /**
120: * Gets the name of the local dispatcher
121: * @return String name of the LocalDispatcher object
122: */
123: public String getName() {
124: return name;
125: }
126:
127: /**
128: * Uses an existing map of name value pairs and extracts the keys which are used in serviceName
129: * Note: This goes not guarantee the context will be 100% valid, there may be missing fields
130: * @param serviceName The name of the service to obtain parameters for
131: * @param mode The mode to use for building the new map (i.e. can be IN or OUT)
132: * @param context The initial set of values to pull from
133: * @return Map contains any valid values
134: * @throws GenericServiceException
135: */
136: public Map makeValidContext(String serviceName, String mode,
137: Map context) throws GenericServiceException {
138: ModelService model = this .getModelService(serviceName);
139: return makeValidContext(model, mode, context);
140:
141: }
142:
143: /**
144: * Uses an existing map of name value pairs and extracts the keys which are used in serviceName
145: * Note: This goes not guarantee the context will be 100% valid, there may be missing fields
146: * @param model The ModelService object of the service to obtain parameters for
147: * @param mode The mode to use for building the new map (i.e. can be IN or OUT)
148: * @param context The initial set of values to pull from
149: * @return Map contains any valid values
150: * @throws GenericServiceException
151: */
152: public Map makeValidContext(ModelService model, String mode,
153: Map context) throws GenericServiceException {
154: Map newContext;
155:
156: int modeInt = 0;
157: if (mode.equalsIgnoreCase("in")) {
158: modeInt = 1;
159: } else if (mode.equalsIgnoreCase("out")) {
160: modeInt = 2;
161: }
162:
163: if (model == null) {
164: throw new GenericServiceException(
165: "Model service is null! Should never happen.");
166: } else {
167: switch (modeInt) {
168: case 2:
169: newContext = model.makeValid(context,
170: ModelService.OUT_PARAM, true, null);
171: break;
172: case 1:
173: newContext = model.makeValid(context,
174: ModelService.IN_PARAM, true, null);
175: break;
176: default:
177: throw new GenericServiceException(
178: "Invalid mode, should be either IN or OUT");
179: }
180: return newContext;
181: }
182: }
183:
184: /**
185: * Gets the ModelService instance that corresponds to given the name
186: * @param serviceName Name of the service
187: * @return GenericServiceModel that corresponds to the serviceName
188: */
189: public ModelService getModelService(String serviceName)
190: throws GenericServiceException {
191: //long timeStart = System.currentTimeMillis();
192: ModelService retVal = getLocalModelService(serviceName);
193: if (retVal == null) {
194: retVal = getGlobalModelService(serviceName);
195: }
196:
197: if (retVal == null) {
198: throw new GenericServiceException(
199: "Cannot locate service by name (" + serviceName
200: + ")");
201: }
202:
203: //Debug.logTiming("Got ModelService for name [" + serviceName + "] in [" + (System.currentTimeMillis() - timeStart) + "] milliseconds", module);
204: return retVal;
205: }
206:
207: private ModelService getLocalModelService(String serviceName)
208: throws GenericServiceException {
209: Map serviceMap = this .getLocalServiceMap();
210:
211: ModelService retVal = null;
212: if (serviceMap != null) {
213: retVal = (ModelService) serviceMap.get(serviceName);
214: if (retVal != null && !retVal.inheritedParameters()) {
215: retVal.interfaceUpdate(this );
216: }
217: }
218:
219: return retVal;
220: }
221:
222: private ModelService getGlobalModelService(String serviceName)
223: throws GenericServiceException {
224: Map serviceMap = this .getGlobalServiceMap();
225:
226: ModelService retVal = null;
227: if (serviceMap != null) {
228: retVal = (ModelService) serviceMap.get(serviceName);
229: if (retVal != null && !retVal.inheritedParameters()) {
230: retVal.interfaceUpdate(this );
231: }
232: }
233:
234: return retVal;
235: }
236:
237: /**
238: * Gets the LocalDispatcher used with this context
239: * @return LocalDispatcher that was used to create this context
240: */
241: public LocalDispatcher getDispatcher() {
242: return this .dispatcher;
243: }
244:
245: /**
246: * Sets the LocalDispatcher used with this context
247: * @param dispatcher The LocalDispatcher to re-assign to this context
248: */
249: public void setDispatcher(LocalDispatcher dispatcher) {
250: this .dispatcher = dispatcher;
251: }
252:
253: /**
254: * Gets the GenericDelegator associated with this context/dispatcher
255: * @return GenericDelegator associated with this context
256: */
257: public GenericDelegator getDelegator() {
258: return dispatcher.getDelegator();
259: }
260:
261: /**
262: * Gets the Security object associated with this dispatcher
263: * @return Security object associated with this dispatcher
264: */
265: public Security getSecurity() {
266: return dispatcher.getSecurity();
267: }
268:
269: private Map getLocalServiceMap() {
270: Map serviceMap = (Map) modelServiceMapByDispatcher.get(name);
271: if (serviceMap == null) {
272: synchronized (this ) {
273: serviceMap = (Map) modelServiceMapByDispatcher
274: .get(name);
275: if (serviceMap == null) {
276: if (this .localReaders != null) {
277: serviceMap = FastMap.newInstance();
278: Iterator urlIter = this .localReaders.iterator();
279: while (urlIter.hasNext()) {
280: URL readerURL = (URL) urlIter.next();
281: Map readerServiceMap = ModelServiceReader
282: .getModelServiceMap(readerURL, this );
283: if (readerServiceMap != null) {
284: serviceMap.putAll(readerServiceMap);
285: }
286: }
287: }
288: if (serviceMap != null) {
289: modelServiceMapByDispatcher.put(name,
290: serviceMap);
291: // NOTE: the current ECA per dispatcher for local services stuff is a bit broken, so now just doing this on the global def load: ServiceEcaUtil.reloadConfig();
292: }
293: }
294: }
295: }
296:
297: return serviceMap;
298: }
299:
300: private Map getGlobalServiceMap() {
301: Map serviceMap = (Map) modelServiceMapByDispatcher
302: .get(GLOBAL_KEY);
303: if (serviceMap == null) {
304: synchronized (this ) {
305: serviceMap = (Map) modelServiceMapByDispatcher
306: .get(GLOBAL_KEY);
307: if (serviceMap == null) {
308: serviceMap = FastMap.newInstance();
309:
310: Element rootElement;
311:
312: try {
313: rootElement = ServiceConfigUtil
314: .getXmlRootElement();
315: } catch (GenericConfigException e) {
316: Debug
317: .logError(
318: e,
319: "Error getting Service Engine XML root element",
320: module);
321: return null;
322: }
323:
324: List globalServicesElements = UtilXml
325: .childElementList(rootElement,
326: "global-services");
327: Iterator gseIter = globalServicesElements
328: .iterator();
329: while (gseIter.hasNext()) {
330: Element globalServicesElement = (Element) gseIter
331: .next();
332: ResourceHandler handler = new MainResourceHandler(
333: ServiceConfigUtil.SERVICE_ENGINE_XML_FILENAME,
334: globalServicesElement);
335:
336: Map servicesMap = ModelServiceReader
337: .getModelServiceMap(handler, this );
338: if (servicesMap != null) {
339: serviceMap.putAll(servicesMap);
340: }
341: }
342:
343: // get all of the component resource model stuff, ie specified in each ofbiz-component.xml file
344: List componentResourceInfos = ComponentConfig
345: .getAllServiceResourceInfos("model");
346: Iterator componentResourceInfoIter = componentResourceInfos
347: .iterator();
348: while (componentResourceInfoIter.hasNext()) {
349: ComponentConfig.ServiceResourceInfo componentResourceInfo = (ComponentConfig.ServiceResourceInfo) componentResourceInfoIter
350: .next();
351: Map servicesMap = ModelServiceReader
352: .getModelServiceMap(
353: componentResourceInfo
354: .createResourceHandler(),
355: this );
356: if (servicesMap != null) {
357: serviceMap.putAll(servicesMap);
358: }
359: }
360:
361: if (serviceMap != null) {
362: modelServiceMapByDispatcher.put(GLOBAL_KEY,
363: serviceMap);
364: ServiceEcaUtil.reloadConfig();
365: }
366: }
367: }
368: }
369:
370: return serviceMap;
371: }
372:
373: public Set getAllServiceNames() {
374: Set serviceNames = new TreeSet();
375:
376: Map globalServices = (Map) modelServiceMapByDispatcher
377: .get(GLOBAL_KEY);
378: Map localServices = (Map) modelServiceMapByDispatcher.get(name);
379: if (globalServices != null) {
380: serviceNames.addAll(globalServices.keySet());
381: }
382: if (localServices != null) {
383: serviceNames.addAll(localServices.keySet());
384: }
385: return serviceNames;
386: }
387:
388: public Document getWSDL(String serviceName, String locationURI)
389: throws GenericServiceException, WSDLException {
390: ModelService model = this.getModelService(serviceName);
391: return model.toWSDL(locationURI);
392: }
393: }
|