View Javadoc
1   /*
2    * Copyright 2013 The Apache Software Foundation.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.apache.juddi.v3.client.mapping.wadl;
17  
18  import java.io.File;
19  import java.io.FileNotFoundException;
20  import java.io.IOException;
21  import java.io.InputStream;
22  import java.io.StringReader;
23  import java.net.MalformedURLException;
24  import java.net.URL;
25  import java.util.ArrayList;
26  import java.util.HashSet;
27  import java.util.List;
28  import java.util.Properties;
29  import java.util.Set;
30  
31  import javax.xml.bind.JAXB;
32  import javax.xml.namespace.QName;
33  
34  import org.apache.commons.configuration.ConfigurationException;
35  import org.apache.commons.logging.Log;
36  import org.apache.commons.logging.LogFactory;
37  import org.apache.http.HttpResponse;
38  import org.apache.http.auth.AuthScope;
39  import org.apache.http.auth.UsernamePasswordCredentials;
40  import org.apache.http.client.ResponseHandler;
41  import org.apache.http.client.methods.HttpGet;
42  import org.apache.http.conn.ClientConnectionManager;
43  import org.apache.http.conn.scheme.Scheme;
44  import org.apache.http.conn.scheme.SchemeRegistry;
45  import org.apache.http.impl.client.BasicResponseHandler;
46  import org.apache.http.impl.client.DefaultHttpClient;
47  import org.apache.http.impl.conn.BasicClientConnectionManager;
48  import org.apache.juddi.api_v3.AccessPointType;
49  import org.apache.juddi.v3.client.UDDIConstants;
50  import org.apache.juddi.v3.client.config.Property;
51  import org.apache.juddi.v3.client.config.UDDIClerk;
52  import org.apache.juddi.v3.client.config.UDDIKeyConvention;
53  import org.apache.juddi.v3.client.cryptor.XmlUtils;
54  import org.apache.juddi.v3.client.mapping.Common2UDDI;
55  import org.apache.juddi.v3.client.mapping.MockSSLSocketFactory;
56  import org.apache.juddi.v3.client.mapping.URLLocalizer;
57  import org.uddi.api_v3.AccessPoint;
58  import org.uddi.api_v3.BindingTemplate;
59  import org.uddi.api_v3.BindingTemplates;
60  import org.uddi.api_v3.BusinessService;
61  import org.uddi.api_v3.CategoryBag;
62  import org.uddi.api_v3.Description;
63  import org.uddi.api_v3.InstanceDetails;
64  import org.uddi.api_v3.KeyedReference;
65  import org.uddi.api_v3.Name;
66  import org.uddi.api_v3.TModel;
67  import org.uddi.api_v3.TModelInstanceDetails;
68  import org.uddi.api_v3.TModelInstanceInfo;
69  
70  /**
71   * This class converts a WADL document, web application description language into a
72   * structure that more or less works within the UDDI data structures.<br><br>
73   * <h1>Example Usage Scenario</h1>
74   * <pre>
75          Application app = WADL2UDDI.parseWadl(new File("A path to your file.wadl"));
76          List<URL> urls = WADL2UDDI.getBaseAddresses(app);
77          URL url = urls.get(0);
78          String domain = url.getHost();
79          TModel keygen = UDDIClerk.createKeyGenator("uddi:" + domain + ":keygenerator", domain, "en");
80          //save the keygen
81          SaveTModel stm = new SaveTModel();
82          stm.setAuthInfo(rootAuthToken.getAuthInfo());
83          stm.getTModel().add(keygen);
84          
85          properties.put("keyDomain", domain);
86          properties.put("businessName", domain);
87          properties.put("serverName", url.getHost());
88          properties.put("serverPort", url.getPort());
89          WADL2UDDI wadl2UDDI = new WADL2UDDI(null, new URLLocalizerDefaultImpl(), properties);
90         
91          BusinessService businessServices = wadl2UDDI.createBusinessService(new QName("MyWasdl.namespace", "Servicename"), app);
92          Set<TModel> portTypeTModels = wadl2UDDI.createWADLPortTypeTModels(wsdlURL, app);
93          
94          //Since the service depends on the tModel, we have to save the tModels first
95          SaveTModel tms = new SaveTModel();
96  
97          TModel[] tmodels = portTypeTModels.toArray(new TModel[0]);
98          for (int i = 0; i < tmodels.length; i++) {
99              System.out.println(tmodelPrinter.print(tmodels[i]));
100             tms.getTModel().add(tmodels[i]);
101         }
102 
103 
104         //important, you'll need to save your new tModels, or else saving the business/service may fail
105         publish.saveTModel(stm);
106 
107         //finaly, we're ready to save all of the services defined in the WSDL
108         //again, we're creating a new business, if you have one already, look it up using the Inquiry getBusinessDetails
109 
110         PrintUDDI<BusinessService> servicePrinter = new PrintUDDI<BusinessService>();
111         System.out.println(servicePrinter.print(businessServices));
112         
113         SaveBusiness sb = new SaveBusiness();
114         sb.setAuthInfo(rootAuthToken.getAuthInfo());
115         BusinessEntity be = new BusinessEntity();
116         be.setBusinessKey(businessServices.getBusinessKey());
117         be.getName().add(new Name());
118         //TODO, use some relevant here
119         be.getName().get(0).setValue(domain);
120         be.getName().get(0).setLang("en");
121         be.setBusinessServices(new BusinessServices());
122         be.getBusinessServices().getBusinessService().add(businessServices);
123         sb.getBusinessEntity().add(be);
124         PrintUDDI<SaveBusiness> sbp = new PrintUDDI<SaveBusiness>();
125         System.out.println("Request " + sbp.print(sb));
126         publish.saveBusiness(sb);
127 
128         //and we're done
129         //Be sure to report any problems to the jUDDI JIRA bug tracker at 
130         //https://issues.apache.org/jira/browse/JUDDI
131 </pre>
132  *
133  * @author <a href="mailto:alexoree@apache.org">Alex O'Ree</a>
134  */
135 public class WADL2UDDI {
136 
137     private static Log log = LogFactory.getLog(WADL2UDDI.class);
138     private String keyDomainURI;
139     private String businessKey;
140     private String lang;
141     private UDDIClerk clerk = null;
142     private Properties properties = null;
143     private URLLocalizer urlLocalizer;
144 
145     public WADL2UDDI(UDDIClerk clerk, URLLocalizer urlLocalizer, Properties properties) throws ConfigurationException {
146         super();
147         this.clerk = clerk;
148         this.urlLocalizer = urlLocalizer;
149         this.properties = properties;
150 
151         if (clerk != null) {
152             if (!properties.containsKey("keyDomain")) {
153                 throw new ConfigurationException("Property keyDomain is a required property when using WADL2UDDI.");
154             }
155             if (!properties.containsKey("businessKey") && !properties.containsKey("businessName")) {
156                 throw new ConfigurationException("Either property businessKey, or businessName, is a required property when using WADL2UDDI.");
157             }
158             if (!properties.containsKey("nodeName")) {
159                 if (properties.containsKey("serverName") && properties.containsKey("serverPort")) {
160                     String nodeName = properties.getProperty("serverName") + "_" + properties.getProperty("serverPort");
161                     properties.setProperty("nodeName", nodeName);
162                 } else {
163                     throw new ConfigurationException("Property nodeName is not defined and is a required property when using WADL2UDDI.");
164                 }
165             }
166         }
167 
168         //Obtaining values from the properties
169         this.keyDomainURI = "uddi:" + properties.getProperty("keyDomain") + ":";
170         if (properties.contains(Property.BUSINESS_KEY)) {
171             this.businessKey = properties.getProperty(Property.BUSINESS_KEY);
172         } else {
173             //using the BusinessKey Template, and the businessName to construct the key 
174             this.businessKey = UDDIKeyConvention.getBusinessKey(properties);
175         }
176         this.lang = properties.getProperty(Property.LANG, Property.DEFAULT_LANG);
177     }
178 
179     public Set<TModel> createWADLTModels(String wadlURL, Application app) throws Exception {
180         Set<TModel> tModels = new HashSet<TModel>();
181         TModel binding = new TModel();
182         binding.setTModelKey(keyDomainURI + "binding");
183         
184         Name sName = new Name();
185         sName.setLang(lang);
186         if (!app.getDoc().isEmpty()) {
187             sName.setValue(app.getDoc().get(0).getTitle());
188         }
189         if (sName.getValue() == null) {
190             sName.setValue(keyDomainURI + " Binding tModel");
191         }
192         binding.setName(sName);
193         tModels.add(binding);
194         
195         
196          binding = new TModel();
197         binding.setTModelKey(keyDomainURI + "rest");
198         
199         sName = new Name();
200         sName.setLang(lang);
201         if (!app.getDoc().isEmpty()) {
202             sName.setValue(app.getDoc().get(0).getTitle());
203         }
204         if (sName.getValue() == null) {
205             sName.setValue(keyDomainURI + " Rest tModel");
206         }
207         binding.setName(sName);
208         tModels.add(binding);
209         
210 
211         //keyDomainURI + "binding"
212         return tModels;
213     }
214 
215     public Set<TModel> createWADLPortTypeTModels(String wadlURL, Application app) throws Exception {
216         Set<TModel> tModels = new HashSet<TModel>();
217         // Create a tModel for each portType
218 
219         return tModels;
220     }
221 
222     public String getKeyDomainURI() {
223         return keyDomainURI;
224     }
225 
226     public void setKeyDomain(String keyDomainURI) {
227         this.keyDomainURI = keyDomainURI;
228     }
229 
230     public String getLang() {
231         return lang;
232     }
233 
234     public void setLang(String lang) {
235         this.lang = lang;
236     }
237 
238     private static String ContentToString(List<Object> content) {
239         StringBuilder sb = new StringBuilder();
240         for (int i = 0; i < content.size(); i++) {
241             sb.append(content.get(i).toString()).append(" ");
242         }
243         return sb.toString().trim();
244     }
245 
246     /**
247      * Creates a UDDI Business Service.
248      *
249      * @param serviceQName This must be specified to identify the namespace of
250      * the service, which is used to set the service uddi key
251      * @param wadlDefinition
252      * @return BusinessService
253      * @throws MalformedURLException
254      */
255     public BusinessService createBusinessService(QName serviceQName, Application wadlDefinition) throws MalformedURLException {
256 
257         log.debug("Constructing Service UDDI Information for " + serviceQName);
258         BusinessService service = new BusinessService();
259         // BusinessKey
260         service.setBusinessKey(businessKey);
261         // ServiceKey
262         service.setServiceKey(UDDIKeyConvention.getServiceKey(properties, serviceQName.getLocalPart()));
263         // Description
264         String serviceDescription = properties.getProperty(Property.SERVICE_DESCRIPTION, Property.DEFAULT_SERVICE_DESCRIPTION);
265         // Override with the service description from the WADL if present
266         boolean lengthwarn = false;
267         if (!wadlDefinition.getDoc().isEmpty()) {
268 
269             for (int i = 0; i < wadlDefinition.getDoc().size(); i++) {
270                 String locallang=lang;
271                 if (wadlDefinition.getDoc().get(i).getLang() != null) {
272                    locallang=(wadlDefinition.getDoc().get(i).getLang());
273                 } 
274                 if (locallang.length() > UDDIConstants.MAX_xml_lang_length) {
275                     lengthwarn = true;
276                     locallang=(locallang.substring(0, UDDIConstants.MAX_xml_lang_length - 1));
277                 }
278 
279                 StringBuilder sb = new StringBuilder();
280                 sb.append(wadlDefinition.getDoc().get(i).getTitle()).append(" ");
281                 sb.append(ContentToString(wadlDefinition.getDoc().get(i).getContent()));
282 
283                 service.getDescription().addAll(Common2UDDI.mapDescription(sb.toString(), locallang));
284 
285             }
286         } else {
287                 service.getDescription().addAll(Common2UDDI.mapDescription(serviceDescription, lang));
288         }
289 
290 
291 
292         // Service name
293         Name sName = new Name();
294         sName.setLang(lang);
295         if (!wadlDefinition.getDoc().isEmpty()) {
296             sName.setValue(wadlDefinition.getDoc().get(0).getTitle());
297         }
298         if (sName.getValue() == null) {
299             sName.setValue(serviceQName.getLocalPart());
300         }
301         service.getName().add(sName);
302 
303         CategoryBag categoryBag = new CategoryBag();
304 
305         String namespace = serviceQName.getNamespaceURI();
306         if (namespace != null && namespace.length()!=0) {
307             KeyedReference namespaceReference = newKeyedReference(
308                     "uddi:uddi.org:xml:namespace", "uddi-org:xml:namespace", namespace);
309             categoryBag.getKeyedReference().add(namespaceReference);
310         }
311 
312         KeyedReference serviceReference = newKeyedReference(
313                 "uddi:uddi.org:wadl:types", "uddi-org:wadl:types", "service");
314         categoryBag.getKeyedReference().add(serviceReference);
315 
316         KeyedReference localNameReference = newKeyedReference(
317                 "uddi:uddi.org:xml:localname", "uddi-org:xml:localName", serviceQName.getLocalPart());
318         categoryBag.getKeyedReference().add(localNameReference);
319 
320         service.setCategoryBag(categoryBag);
321 
322         for (int i = 0; i < wadlDefinition.getResources().size(); i++) {
323             BindingTemplate bindingTemplate = createWADLBinding(serviceQName, getDocTitle(wadlDefinition.getResources().get(i).getDoc()), new URL(wadlDefinition.getResources().get(i).getBase()), wadlDefinition.getResources().get(i));
324             service.setBindingTemplates(new BindingTemplates());
325             service.getBindingTemplates().getBindingTemplate().add(bindingTemplate);
326         }
327 
328 
329         if (lengthwarn) {
330             log.warn("Some object descriptions are longer than the maximum allowed by UDDI and have been truncated.");
331         }
332         return service;
333     }
334     
335     public static List<URL> getBaseAddresses(Application app)
336     {
337         List<URL> urls = new ArrayList<URL>();
338         if (app==null) return urls;
339         for (int i=0; i < app.getResources().size(); i++){
340             try {
341                 urls.add(new URL(app.getResources().get(i).getBase()));
342             } catch (MalformedURLException ex) {
343                 log.warn("The base URL " + app.getResources().get(i).getBase() + " is invalid or could not be parsed", ex);
344             }
345         }
346         return urls;
347     }
348 
349     protected static KeyedReference newKeyedReference(String tModelKey, String keyName, String value) {
350         KeyedReference typesReference = new KeyedReference();
351         typesReference.setTModelKey(tModelKey);
352         typesReference.setKeyName(keyName);
353         typesReference.setKeyValue(value);
354         return typesReference;
355     }
356 
357     protected BindingTemplate createWADLBinding(QName serviceQName, String portName, URL serviceUrl, Resources res) {
358 
359         BindingTemplate bindingTemplate = new BindingTemplate();
360         // Set BusinessService Key
361         bindingTemplate.setServiceKey(UDDIKeyConvention.getServiceKey(properties, serviceQName.getLocalPart()));
362 
363         if (serviceUrl != null) {
364             // Set AccessPoint
365             AccessPoint accessPoint = new AccessPoint();
366             accessPoint.setUseType(AccessPointType.END_POINT.toString());
367             accessPoint.setValue(urlLocalizer.rewrite(serviceUrl));
368             bindingTemplate.setAccessPoint(accessPoint);
369             // Set Binding Key
370             String bindingKey = UDDIKeyConvention.getBindingKey(properties, serviceQName, portName, serviceUrl);
371             bindingTemplate.setBindingKey(bindingKey);
372 
373             
374             bindingTemplate.getDescription().addAll(Common2UDDI.mapDescription(getDescription(res.getDoc()), lang));
375 
376             // reference wsdl:binding tModel
377             TModelInstanceInfo tModelInstanceInfoBinding = new TModelInstanceInfo();
378             tModelInstanceInfoBinding.setTModelKey(keyDomainURI + "binding");
379             InstanceDetails instanceDetails = new InstanceDetails();
380             instanceDetails.setInstanceParms(portName);
381             tModelInstanceInfoBinding.setInstanceDetails(instanceDetails);
382            
383             tModelInstanceInfoBinding.getDescription().addAll(Common2UDDI.mapDescription("The binding that this endpoint implements. " + bindingTemplate.getDescription().get(0).getValue()
384                     + " The instanceParms specifies the \" port local name.", lang));
385             TModelInstanceDetails tModelInstanceDetails = new TModelInstanceDetails();
386             tModelInstanceDetails.getTModelInstanceInfo().add(tModelInstanceInfoBinding);
387 
388             // reference wsdl:portType tModel
389 
390             TModelInstanceInfo tModelInstanceInfoPortType = new TModelInstanceInfo();
391             tModelInstanceInfoPortType.setTModelKey(keyDomainURI + "rest");
392             //String portTypeDescription = "";
393            
394             Description descriptionPT = new Description();
395             descriptionPT.setLang(lang);
396             descriptionPT.setValue("The wadl:Resource:base implements." );
397             tModelInstanceInfoPortType.getDescription().add(descriptionPT);
398             tModelInstanceDetails.getTModelInstanceInfo().add(tModelInstanceInfoPortType);
399 
400             bindingTemplate.setTModelInstanceDetails(tModelInstanceDetails);
401 
402         }
403         return bindingTemplate;
404     }
405 
406     /**
407      * parses a wadl from stream
408      * @param stream
409      * @return Application instance (WADL FILE)
410      */
411     public static Application parseWadl(InputStream stream) {
412         Application unmarshal = (Application) XmlUtils.unmarshal(stream, Application.class);
413         return unmarshal;
414     }
415     public static final String PACKAGE = "org.apache.juddi.v3.client.mapping.wadl";
416 
417     /**
418      * parses a wadl from a URL or file
419      * @param file
420      * @return  Application instance (WADL FILE)
421      */
422     public static Application parseWadl(URL file) {
423         Application unmarshal = JAXB.unmarshal(file, Application.class);
424         return unmarshal;
425     }
426     
427     /**
428      * Parses a web accessible WADL file
429      * @param weburl
430      * @param username
431      * @param password
432      * @param ignoreSSLErrors if true, SSL errors are ignored
433      * @return a non-null "Application" object, represeting a WADL's application root XML 
434      * Sample code:<br>
435      * <pre>
436      * Application app = WADL2UDDI.parseWadl(new URL("http://server/wsdl.wsdl"), "username", "password", 
437      *      clerkManager.getClientConfig().isX_To_Wsdl_Ignore_SSL_Errors() );
438      * </pre>
439      */
440     public static Application parseWadl(URL weburl, String username, String password, boolean ignoreSSLErrors){
441             DefaultHttpClient httpclient = null;
442             Application unmarshal=null;
443         try {
444             String url = weburl.toString();
445             if (!url.toLowerCase().startsWith("http")) {
446                 return parseWadl(weburl);
447             }
448             
449             boolean usessl = false;
450             int port = 80;
451             if (url.toLowerCase().startsWith("https://")) {
452                 port = 443;
453                 usessl = true;
454             }
455 
456             if (weburl.getPort() > 0) {
457                 port = weburl.getPort();
458             }
459 
460             if (ignoreSSLErrors && usessl) {
461                 SchemeRegistry schemeRegistry = new SchemeRegistry();
462                 schemeRegistry.register(new Scheme("https", port, new MockSSLSocketFactory()));
463                 ClientConnectionManager cm = new BasicClientConnectionManager(schemeRegistry);
464                 httpclient = new DefaultHttpClient(cm);
465             } else {
466                 httpclient = new DefaultHttpClient();
467             }
468 
469             if (username != null && username.length() > 0
470                     && password != null && password.length() > 0) {
471 
472 
473                 httpclient.getCredentialsProvider().setCredentials(
474                         new AuthScope(weburl.getHost(), port),
475                         new UsernamePasswordCredentials(username, password));
476             }
477             HttpGet httpGet = new HttpGet(url);
478             try {
479 
480                 HttpResponse response1 = httpclient.execute(httpGet);
481                 //System.out.println(response1.getStatusLine());
482                 // HttpEntity entity1 = response1.getEntity();
483                 // do something useful with the response body
484                 // and ensure it is fully consumed
485                 ResponseHandler<String> responseHandler = new BasicResponseHandler();
486                 String handleResponse = responseHandler.handleResponse(response1);
487                 StringReader sr = new StringReader(handleResponse);
488                 unmarshal = (Application) XmlUtils.unmarshal(sr, Application.class);
489                 sr.close();
490 
491             } finally {
492                 httpGet.releaseConnection();
493 
494             }
495 
496         } catch (Exception e) {
497             log.error(e.getMessage(), e);
498         } finally {
499             if (httpclient != null) {
500                 httpclient.getConnectionManager().shutdown();
501             }
502         }
503         return unmarshal;
504     }
505 
506     public static Application parseWadl(File file) throws FileNotFoundException, IOException {
507         Application unmarshal = (Application) XmlUtils.unmarshal(file, Application.class);
508         return unmarshal;
509     }
510 
511     
512     private String getDocTitle(List<Doc> doc) {
513         if (doc.isEmpty() || doc.get(0) == null || doc.get(0).getTitle() == null) {
514             return "A resource base URL without a description";
515         }
516         return (doc.get(0).getTitle());
517     }
518 
519     private String getDescription(List<Doc> doc) {
520         StringBuilder sb = new StringBuilder();
521         for (int i = 0; i < doc.size(); i++) {
522             sb.append(doc.get(i).getTitle()).append(" ");
523             sb.append(ContentToString(doc.get(i).getContent()));
524         }
525         String ret= sb.toString().trim();
526         
527         if (ret.length()==0)
528                 return "No Description";
529         return ret;
530     }
531 }