001: /**
002: * JOnAS: Java(TM) Open Application Server
003: * Copyright (C) 1999 Bull S.A.
004: * Contact: jonas-team@objectweb.org
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation; either
009: * version 2.1 of the License, or any later version.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: * You should have received a copy of the GNU Lesser General Public
017: * License along with this library; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
019: * USA
020: *
021: * Initial Developer : Sauthier Guillaume
022: * --------------------------------------------------------------------------
023: * $Id: RegistryWSDLHandler.java 5631 2004-10-15 12:24:56Z sauthieg $
024: * --------------------------------------------------------------------------
025: */package org.objectweb.jonas.ws.handler;
026:
027: import java.net.MalformedURLException;
028: import java.net.PasswordAuthentication;
029: import java.net.URL;
030: import java.util.ArrayList;
031: import java.util.Collection;
032: import java.util.HashSet;
033: import java.util.Iterator;
034: import java.util.List;
035: import java.util.Properties;
036: import java.util.Set;
037:
038: import javax.wsdl.extensions.ExtensibilityElement;
039: import javax.wsdl.extensions.soap.SOAPAddress;
040: import javax.xml.registry.BulkResponse;
041: import javax.xml.registry.BusinessLifeCycleManager;
042: import javax.xml.registry.BusinessQueryManager;
043: import javax.xml.registry.Connection;
044: import javax.xml.registry.ConnectionFactory;
045: import javax.xml.registry.JAXRException;
046: import javax.xml.registry.LifeCycleManager;
047: import javax.xml.registry.RegistryException;
048: import javax.xml.registry.RegistryService;
049: import javax.xml.registry.infomodel.Classification;
050: import javax.xml.registry.infomodel.ClassificationScheme;
051: import javax.xml.registry.infomodel.Concept;
052: import javax.xml.registry.infomodel.ExternalLink;
053: import javax.xml.registry.infomodel.InternationalString;
054: import javax.xml.registry.infomodel.Key;
055: import javax.xml.registry.infomodel.Organization;
056: import javax.xml.registry.infomodel.PersonName;
057: import javax.xml.registry.infomodel.Service;
058: import javax.xml.registry.infomodel.ServiceBinding;
059: import javax.xml.registry.infomodel.SpecificationLink;
060: import javax.xml.registry.infomodel.User;
061:
062: import org.w3c.dom.Element;
063:
064: import org.objectweb.jonas_lib.I18n;
065:
066: import org.objectweb.jonas_ws.deployment.api.ServiceDesc;
067:
068: import org.objectweb.jonas.common.Log;
069: import org.objectweb.jonas.ws.WSServiceException;
070:
071: import org.objectweb.util.monolog.api.BasicLevel;
072: import org.objectweb.util.monolog.api.Logger;
073:
074: /**
075: * Publish a given WSDL Definition into a specified WebServices registry (UDDI/ebXML).
076: * Use JAXR (only UDDI At this time).
077: * properties :<br/>
078: * - <code>jonas.service.publish.uddi.username</code> : publisher username<br/>
079: * - <code>jonas.service.publish.uddi.password</code> : publisher password<br/>
080: * - <code>javax.xml.registry.lifeCycleManagerURL</code> : url of the Publish API for a registry<br/>
081: * - <code>javax.xml.registry.queryManagerURL</code> : url of the Query API for a registry<br/>
082: * - <code>jonas.service.publish.uddi.organization.name</code> : The organisation name<br/>
083: * - <code>jonas.service.publish.uddi.organization.desc</code> : The organization description (optionnal)<br/>
084: * - <code>jonas.service.publish.uddi.organization.person_name</code> : Primary Contact for the organization<br/>
085: * The property file is given 'as is' to the ConnectionFactory, If you want to add some JAXR specific
086: * properties, add them in this property file.
087: *
088: * @author Guillaume Sauthier
089: */
090: public class RegistryWSDLHandler implements WSDLHandler {
091:
092: /**
093: * Standard Publish URL
094: */
095: private static final String PUBLISH_URL_PROP = "javax.xml.registry.lifeCycleManagerURL";
096:
097: /**
098: * Standard Inquiry URL
099: */
100: private static final String INQUIRY_URL_PROP = "javax.xml.registry.queryManagerURL";
101:
102: /**
103: * JOnAS Username
104: */
105: private static final String USERNAME = "jonas.service.publish.uddi.username";
106:
107: /**
108: * JOnAS Password
109: */
110: private static final String PASSWORD = "jonas.service.publish.uddi.password";
111:
112: /**
113: * JOnAS Organization name
114: */
115: private static final String ORGANIZATION_NAME = "jonas.service.publish.uddi.organization.name";
116:
117: /**
118: * JOnAS Organization description
119: */
120: private static final String ORGANIZATION_DESC = "jonas.service.publish.uddi.organization.desc";
121:
122: /**
123: * JOnAS Person under wich WSDL will be published
124: */
125: private static final String PERSON_NAME = "jonas.service.publish.uddi.organization.person_name";
126:
127: /** JAXR ConnectionFactory to use */
128: private ConnectionFactory connFactory;
129:
130: /** username/password pair */
131: private PasswordAuthentication passAuth;
132:
133: /** list of properties */
134: private Properties props;
135:
136: /** Publication Logger (special file storing keys) */
137: private static Logger logger = Log
138: .getLogger(Log.JONAS_PUBLISH_PREFIX);
139:
140: /** Internationalisation tool */
141: private static I18n i18n = I18n
142: .getInstance(RegistryWSDLHandler.class);
143:
144: /**
145: * Constructor : creates a RegistryWSDLHandler object.
146: *
147: * @param props uddi.properties file
148: *
149: * @throws WSServiceException When some properties are missing
150: */
151: public RegistryWSDLHandler(Properties props)
152: throws WSServiceException {
153:
154: this .props = props;
155:
156: //Check minimal properties
157: String publishURL = props.getProperty(PUBLISH_URL_PROP);
158: String queryURL = props.getProperty(INQUIRY_URL_PROP);
159: String username = props.getProperty(USERNAME);
160: String password = props.getProperty(PASSWORD);
161:
162: // Check if publishURL is an URL
163: try {
164: new URL(publishURL);
165: } catch (MalformedURLException mue) {
166: String err = i18n.getMessage(
167: "RegistryWSDLHandler.constr.mue", publishURL);
168: logger.log(BasicLevel.ERROR, err);
169: throw new WSServiceException(err, mue);
170: }
171:
172: try {
173: new URL(queryURL);
174: } catch (MalformedURLException mue) {
175: String err = i18n.getMessage(
176: "RegistryWSDLHandler.constr.mue", queryURL);
177: logger.log(BasicLevel.ERROR, err);
178: throw new WSServiceException(err, mue);
179: }
180:
181: try {
182: // Create the ConnectionFactory
183: connFactory = ConnectionFactory.newInstance();
184: connFactory.setProperties(props);
185: } catch (JAXRException jaxre) {
186: String err = i18n
187: .getMessage("RegistryWSDLHandler.constr.jaxrException");
188: logger.log(BasicLevel.ERROR, err);
189: throw new WSServiceException(err, jaxre);
190: }
191:
192: // Create the Authentication
193: if (username != null && password != null) {
194: passAuth = new PasswordAuthentication(username, password
195: .toCharArray());
196: } else {
197: String err = i18n
198: .getMessage("RegistryWSDLHandler.constr.noCreds");
199: logger.log(BasicLevel.ERROR, err);
200: throw new WSServiceException(err);
201: }
202:
203: // Check organization props
204: String name = props.getProperty(ORGANIZATION_NAME);
205: String person = props.getProperty(PERSON_NAME);
206: if ((name == null) || (person == null)) {
207: String err = i18n
208: .getMessage("RegistryWSDLHandler.constr.missingProp");
209: logger.log(BasicLevel.ERROR, err);
210: throw new WSServiceException(err);
211: }
212: }
213:
214: /**
215: * Publish the WSDL into a Registry.
216: * @param sd the Service containing the WSDL file to publish.
217: * @throws WSServiceException When cannot access to publish API
218: */
219: public void publish(ServiceDesc sd) throws WSServiceException {
220:
221: try {
222: javax.wsdl.Definition def = sd.getWSDL().getDefinition();
223:
224: // Create the connection
225: Connection connection = connFactory.createConnection();
226:
227: // Add Credentials
228: Set creds = new HashSet();
229: creds.add(passAuth);
230: connection.setCredentials(creds);
231:
232: // Get the registry Service
233: RegistryService rs = connection.getRegistryService();
234:
235: // get the Query API Manager
236: BusinessQueryManager bqm = rs.getBusinessQueryManager();
237:
238: // get the Publish API Manager
239: BusinessLifeCycleManager blcm = rs
240: .getBusinessLifeCycleManager();
241:
242: // Reference a unique InternationalString
243: InternationalString is = null;
244:
245: // Create the Organization with properties
246: Organization org = blcm.createOrganization(props
247: .getProperty(ORGANIZATION_NAME));
248: String orgDesc = props.getProperty(ORGANIZATION_DESC);
249: if (orgDesc != null) {
250: is = blcm.createInternationalString(orgDesc);
251: org.setDescription(is);
252: }
253: User contact = blcm.createUser();
254: PersonName pName = blcm.createPersonName(props
255: .getProperty(PERSON_NAME));
256: contact.setPersonName(pName);
257: org.setPrimaryContact(contact);
258:
259: Collection services = new ArrayList();
260: // Create n Service (1 for each service)
261: for (Iterator servicesIter = def.getServices().values()
262: .iterator(); servicesIter.hasNext();) {
263:
264: javax.wsdl.Service s = (javax.wsdl.Service) servicesIter
265: .next();
266: Service service = blcm.createService(s.getQName()
267: .getLocalPart());
268:
269: Element desc = s.getDocumentationElement();
270: if (desc != null) {
271: String description = getDescription(desc);
272: is = blcm.createInternationalString(description);
273: service.setDescription(is);
274: }
275:
276: // Create n ServiceBinding (1 for each port)
277: Collection serviceBindings = new ArrayList();
278: for (Iterator portsIter = s.getPorts().values()
279: .iterator(); portsIter.hasNext();) {
280:
281: javax.wsdl.Port port = (javax.wsdl.Port) portsIter
282: .next();
283:
284: ServiceBinding binding = blcm
285: .createServiceBinding();
286:
287: Element pDesc = port.getDocumentationElement();
288: String pDescription = port.getName();
289: if (pDesc != null) {
290: pDescription += " " + getDescription(pDesc);
291: }
292: is = blcm.createInternationalString(pDescription);
293: binding.setDescription(is);
294:
295: // we do not check URL validity because webapps
296: // are not deployed at this point.
297: binding.setValidateURI(false);
298: String url = getEndpoint(port);
299: binding.setAccessURI(url);
300:
301: // Create the Concep for WSDL
302: Concept concept = blcm.createConcept(null, port
303: .getName()
304: + " Concept", "");
305: is = blcm.createInternationalString(pDescription
306: + " Concept");
307: concept.setDescription(is);
308:
309: ExternalLink extlink = blcm.createExternalLink(
310: "file://", "WSDL");
311: extlink.setValidateURI(false);
312: // !!! Axis specific !!!
313: extlink.setExternalURI(url + "?JWSDL");
314:
315: concept.addExternalLink(extlink);
316:
317: // The Concept is a WSDL Document
318: ClassificationScheme uddiOrgTypes = bqm
319: .findClassificationSchemeByName(null,
320: "uddi-org:types");
321: Classification wsdlSpecClass = blcm
322: .createClassification(uddiOrgTypes,
323: "wsdlSpec", "wsdlSpec");
324: concept.addClassification(wsdlSpecClass);
325:
326: // save into registry and get key
327: Collection concepts = new ArrayList();
328: concepts.add(concept);
329: BulkResponse br = blcm.saveConcepts(concepts);
330: String key = getKey(br);
331:
332: // i18n RegistryWSDLHandler.publish.conceptKey
333: String msg = i18n.getMessage(
334: "RegistryWSDLHandler.publish.conceptKey",
335: port.getName(), key);
336: logger.log(BasicLevel.INFO, msg);
337:
338: // get the concept from registry
339: Concept c = (Concept) bqm.getRegistryObject(key,
340: LifeCycleManager.CONCEPT);
341:
342: SpecificationLink specLink = blcm
343: .createSpecificationLink();
344: specLink.setSpecificationObject(c);
345: binding.addSpecificationLink(specLink);
346:
347: serviceBindings.add(binding);
348: }
349: service.addServiceBindings(serviceBindings);
350: services.add(service);
351: }
352: // Save into the Organisation
353: org.addServices(services);
354:
355: Collection orgs = new ArrayList();
356: orgs.add(org);
357:
358: BulkResponse br = blcm.saveOrganizations(orgs);
359: String key = getKey(br);
360:
361: // i18n RegistryWSDLHandler.publish.organisationKey
362: String msg = i18n.getMessage(
363: "RegistryWSDLHandler.publish.organisationKey", org,
364: key);
365: logger.log(BasicLevel.INFO, msg);
366:
367: } catch (JAXRException jaxre) {
368: String err = i18n
369: .getMessage("RegistryWSDLHandler.publish.jaxrException");
370: logger.log(BasicLevel.ERROR, err);
371: throw new WSServiceException(err, jaxre);
372: }
373: }
374:
375: /**
376: * Return the <code>soap:location</code> of the Port.
377: *
378: * @param port the <code>wsdl:port</code> we want the endpoint URL.
379: *
380: * @return the endpoint URL.
381: */
382: private String getEndpoint(javax.wsdl.Port port) {
383: String url = null;
384: List ee = port.getExtensibilityElements();
385: for (Iterator ext = ee.iterator(); ext.hasNext();) {
386: ExtensibilityElement elem = (ExtensibilityElement) ext
387: .next();
388: if (elem instanceof SOAPAddress) {
389: SOAPAddress soap = (SOAPAddress) elem;
390: url = soap.getLocationURI();
391: }
392: }
393: return url;
394: }
395:
396: /**
397: * @param e Element containing Description
398: * @return Returns the desciption of the given Element
399: */
400: private String getDescription(Element e) {
401: return e.getFirstChild().getNodeValue();
402: }
403:
404: /**
405: * Return the Key contained in the Registry response.
406: *
407: * @param br the Registry response
408: *
409: * @return the key contained in the response
410: *
411: * @throws WSServiceException when no key returned or response
412: * wraps server side exceptions.
413: * @throws JAXRException If no Key was returned by the server
414: */
415: private String getKey(BulkResponse br) throws WSServiceException,
416: JAXRException {
417: String keyStr = null;
418: Collection exceptions = br.getExceptions();
419: Key key = null;
420: if (exceptions == null) {
421: // save OK
422: Collection keys = br.getCollection();
423: Iterator keyIter = keys.iterator();
424: if (keyIter.hasNext()) {
425: // we have 1 key
426: key = (Key) keyIter.next();
427: keyStr = key.getId();
428: } else {
429: // no key
430: // i18n RegistryWSDLHandler.getKey.noKeyReturned
431: String err = i18n
432: .getMessage("RegistryWSDLHandler.getKey.noKeyReturned");
433: logger.log(BasicLevel.ERROR, err);
434: throw new WSServiceException(err);
435: }
436: } else {
437:
438: // Exceptions in Server Side
439:
440: // i18n RegistryWSDLHandler.getKey.serverSideExceptions
441: String err = i18n
442: .getMessage("RegistryWSDLHandler.getKey.serverSideExceptions");
443:
444: // Get Server Side Cause
445: Iterator exIter = exceptions.iterator();
446: Exception cause = null;
447: if (exIter.hasNext()) {
448: // we have 1 Exception
449: cause = (RegistryException) exIter.next();
450: }
451: logger.log(BasicLevel.ERROR, err);
452: if (cause == null) {
453: throw new WSServiceException(err);
454: } else {
455: throw new WSServiceException(err, cause);
456: }
457: }
458:
459: return keyStr;
460: }
461: }
|