Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [lyo-dev] DoorsOauthSample

Hi Peter, Steve,

// dependent on version of DOORS
I got the sample working fine with DOORS 9.5.  It just worked.  I think we should update the doc to say 'use DOORS/DWA 9.5'.

With 9.4/DWA 1.5.0.0 I did have problems.  I got it working eventually with some help from Gabriel, attached.

Maeve





From: Steve Speicher <sspeiche@xxxxxxxxx>
To: Lyo project developer discussions <lyo-dev@xxxxxxxxxxx>
Sent: Thursday, 27 June 2013, 12:37
Subject: Re: [lyo-dev] DoorsOauthSample


On Wed, Jun 26, 2013 at 12:10 PM, Peter Raymond <praymond@xxxxxxxxxx> wrote:
Hi,
 
I have been struggling to get the sample OSLC client for DOORS to work for some time.  I think I have found several defects in the code and believe I have fixes for them.  Just wondering if anyone else got this sample to run or if maybe it is dependent on version of DOORS or some other environment or configuration difference or if this sample has not been tested.
 
The code I am trying to get running is the DoorsOauthSample.java in the package org.eclipse.lyo.client.oslc.samples.
I am using IBM DOORS 9.4 with Doors Web Access 1.5.
I am working with the latest code for the org.eclipse.lyo.client (cloned from the master branch at git://git.eclipse.org/gitroot/lyo/org.eclipse.lyo.client.git)
 
So far the problems I have found and fixed locally are:
 
1)      On line 419 in the validateTokens method the code tries to get the oauth_token and oauth_verifier query params from a URL.  But it is looking at the wrong URL, it tries to get the parameters from the URL that it sent the third GET request to…it should be looking at the URL that the third GET returned (the location sent in the 302 response to the third GET).
 
2)      There is a method called getQueryMap which tries to build a Map of name/value pairs based on the query parameters from a URL that is passed into the method.  But it will never pick up the very first query parameter correctly from the URL because it splits using ‘&’ character.  Let’s say the method is passed http://myhost/something?a=1&b=2  the map returned will contain key “http://myhost/something?a” with value “1” and another entry in the map where key is “b” and value is “2”.  
 
3)      On line 424 in the validateTokens method the POST request is being sent to the wrong URL.  It uses the variable authUrl which is still pointing to the login form.  It should instead use the URL that was returned from the third GET.
 
4)      On line 425 the code tries to set some parameters into the body of the POST request but it is doing this BEFORE setting the content type so those parameters never get set.
 
Having made those changes the sample successfully logs in to DOORS and obtains the OSLC catalogue.  But now I am running into troubles navigating the catalogues and providers to find the provider for my DOORS project.  So I suspect there are further fixes needed to the code but before I spend much more time on it was wondering if anyone has hit the same problems with the sample?
 
I have attached a patch of my modifications so far.  Should I raise a bugzilla ticket for this and get my patch submitted?
 
Hi Peter,

I think it would be best if you did that, there are instructions here to help guide you: http://wiki.eclipse.org/Lyo/ContributorsGettingStarted#Lyo_contribution_process

Let us know you get stuck and thanks for sharing this.

 - Steve Speicher

Regards,
--
Peter Raymond
Principal Software Architect
Serena Software
 

_______________________________________________
lyo-dev mailing list
lyo-dev@xxxxxxxxxxx
http://dev.eclipse.org/mailman/listinfo/lyo-dev



_______________________________________________
lyo-dev mailing list
lyo-dev@xxxxxxxxxxx
http://dev.eclipse.org/mailman/listinfo/lyo-dev


/*******************************************************************************
 * Copyright (c) 2012 IBM Corporation.
 *
 *  All rights reserved. This program and the accompanying materials
 *  are made available under the terms of the Eclipse Public License v1.0
 *  and Eclipse Distribution License v. 1.0 which accompanies this distribution.
 *  
 *  The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
 *  and the Eclipse Distribution License is available at
 *  http://www.eclipse.org/org/documents/edl-v10.php.
 *  
 *  Contributors:
 *  
 *     Gabriel Ruelas     - initial API and implementation
 *******************************************************************************/
package org.eclipse.lyo.client.oslc.samples;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import net.oauth.OAuthException;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.GnuParser;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.auth.InvalidCredentialsException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.params.HttpClientParams;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.apache.wink.client.ClientResponse;
import org.eclipse.lyo.client.exception.ResourceNotFoundException;
import org.eclipse.lyo.client.exception.RootServicesException;
import org.eclipse.lyo.client.oslc.OAuthRedirectException;
import org.eclipse.lyo.client.oslc.OSLCConstants;
import org.eclipse.lyo.client.oslc.OslcClient;
import org.eclipse.lyo.client.oslc.OslcOAuthClient;
import org.eclipse.lyo.client.oslc.jazz.JazzRootServicesHelper;
import org.eclipse.lyo.client.oslc.resources.OslcQuery;
import org.eclipse.lyo.client.oslc.resources.OslcQueryParameters;
import org.eclipse.lyo.client.oslc.resources.OslcQueryResult;

import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.rdf.model.Property;
import com.hp.hpl.jena.rdf.model.RDFNode;
import com.hp.hpl.jena.rdf.model.ResIterator;
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.rdf.model.Selector;
import com.hp.hpl.jena.rdf.model.SimpleSelector;
import com.hp.hpl.jena.rdf.model.Statement;
import com.hp.hpl.jena.rdf.model.StmtIterator;
import com.hp.hpl.jena.vocabulary.RDF;

/**
 * Samples of logging in to Doors Web Access and running OSLC operations
 * 
 * 
 * - run an OLSC Requirement query and retrieve OSLC Requirements and de-serialize them as Java objects
 * - TODO:  Add more requirement sample scenarios
 *
 */
public class DoorsOauthSample {

	private static final Logger logger = Logger.getLogger(DoorsOauthSample.class.getName());

	/**
	 * Login to the DWA server and perform some OSLC actions
	 * @param args
	 * @throws ParseException 
	 */
	public static void main(String[] args) throws ParseException {

		Options options=new Options();
		
		options.addOption("url", true, "url");
		options.addOption("user", true, "user ID");
		options.addOption("password", true, "password");
		options.addOption("project",true,"project area");
		
		/*options.addOption("url", true, "http://clm:8080/dwa";);
		options.addOption("user", true, "Administrator");
		options.addOption("password", true, "Rat1onal");
		options.addOption("project",true,"myProject");*/

		CommandLineParser cliParser = new GnuParser();			
		
		//Parse the command line
		CommandLine cmd = cliParser.parse(options, args);
		
		if (!validateOptions(cmd)) {		
			logger.severe("Syntax:  java <class_name> -url https://<server>:port/<context>/ -user <user> -password <password> -project \"<project_area>\"");
			logger.severe("Example: java DoorsOauthSample -url https://exmple.com:9443/dwa -user ADMIN -password ADMIN -project \"myModule\"");
			return;
		}
			
		String webContextUrl = cmd.getOptionValue("url");
		String user = cmd.getOptionValue("user");
		String passwd = cmd.getOptionValue("password");
		String projectArea = cmd.getOptionValue("project");
		
		try {
			
			//STEP 1: Initialize a Jazz rootservices helper and indicate we're looking for the RequirementManagement catalog
			// The root services for DOORs is found at /public level
			JazzRootServicesHelper helper = new JazzRootServicesHelper(webContextUrl + "/public",OSLCConstants.OSLC_RM_V2);
			
			//STEP 2: Create a new OSLC OAuth capable client, the parameter of following call should be provided
			// by the system administrator of the DOORs Web Access server
			//OslcOAuthClient client = helper.initOAuthClient("1234567890", "123");
			//From local keys - create this
			OslcOAuthClient client = helper.initOAuthClient("lyo", "lyo");
			
			if ( client != null ) {
				
				//STEP 3: Try to access the context URL to trigger the OAuth dance and login
				try {
					client.getResource(webContextUrl,OSLCConstants.CT_RDF);
				} catch (OAuthRedirectException oauthE) {
			//		validateTokens(client,  oauthE.getRedirectURL() + "?oauth_token=" + oauthE.getAccessor().requestToken, user, passwd, webContextUrl + "/j_acegi_security_check" );
			//DOORS 9.5 oAuth 1.0a
				//	validateTokens(client,  oauthE.getRedirectURL() + "?oauth_token=" + oauthE.getAccessor().requestToken, user, passwd, webContextUrl + "/j_acegi_security_check" );
					//DOORS 9.4 oAuth 1.0
					validateTokens(client,  oauthE.getRedirectURL() + "?oauth_token=" + oauthE.getAccessor().requestToken, user, passwd, webContextUrl + "/oauth/j_acegi_security_check" );
					// Try to access again
					ClientResponse response = client.getResource(webContextUrl,OSLCConstants.CT_RDF);
					response.getEntity(InputStream.class).close();
				}
								
				//STEP 4: Get the URL of the OSLC catalog
				String catalogUrl = helper.getCatalogUrl();
				
				//STEP 5: Find the OSLC Service Provider for the project area we want to work with
				String serviceProviderUrl = lookupServiceProviderUrl(catalogUrl, "Services for " + projectArea, client);

				//STEP 6: Get the Query Capabilities URL so that we can run some OSLC queries
				String queryCapability = client.lookupQueryCapability(serviceProviderUrl,
																	  OSLCConstants.OSLC_RM_V2,
																	  OSLCConstants.RM_REQUIREMENT_TYPE);
				
				//SCENARIO A: Run a query for all Requirements modified since 08/02/2010 with OSLC paging of 10 items per
				//page turned on and list the members of the result

		//		OslcQueryParameters queryParams = new OslcQueryParameters("dcterms:modified>=\"2010-08-01T21:51:40.979Z\"^^xsd:dateTime",null,null, null,"dcterms=<http://purl.org/dc/terms/>");
				OslcQueryParameters queryParams = new OslcQueryParameters("dcterms:modified>=\"2010-08-01T21:51:40.979Z\"xsd:dateTime",null,null, null,"dcterms=<http://purl.org/dc/terms/>");

				OslcQuery query = new OslcQuery(client, queryCapability, 10, queryParams);
				
				OslcQueryResult result = query.submit();
				
				boolean processAsJavaObjects = false;
				processPagedQueryResults(result,client, processAsJavaObjects);
				
				System.out.println("\n------------------------------\n");
				
				//TODO:  Add more RRC/Requirement scenarios
			}
		} catch (RootServicesException re) {
			logger.log(Level.SEVERE,"Unable to access the Jazz rootservices document at: " + webContextUrl + "/public/rootservices", re);
		} catch (Exception e) {
			logger.log(Level.SEVERE,e.getMessage(),e);
		}
		
		


	}
	
	private static void processPagedQueryResults(OslcQueryResult result, OslcClient client, boolean asJavaObjects) {
		int page = 1;
		//For now, just show first 5 pages
		do {
			System.out.println("\nPage " + page + ":\n");
			result = processCurrentPage(result,client,asJavaObjects);
			if (result.hasNext() && page < 5) {
				result = result.next();
				page++;
			} else {
				break;
			}
		} while(true);
	}
	
	private static OslcQueryResult processCurrentPage(OslcQueryResult result, OslcClient client, boolean asJavaObjects) {
		
		for (String resultsUrl : result.getMembersUrls()) {
			System.out.println(resultsUrl);
			
			ClientResponse response = null;
			try {
				
				//Get a single artifact by its URL 
				response = client.getResource(resultsUrl, OSLCConstants.CT_RDF);
		
				if (response != null) {
					//De-serialize it as a Java object 
					if (asJavaObjects) {
						   //Requirement req = response.getEntity(Requirement.class);
						   //printRequirementInfo(req);   //print a few attributes
					} else {
						
						//Just print the raw RDF/XML (or process the XML as desired)
						processRawResponse(response);
						
					}
				}
			} catch (Exception e) {
				logger.log(Level.SEVERE, "Unable to process artfiact at url: " + resultsUrl, e);
			}
			
		}
		return result;
		
	}
	
	private static void processRawResponse(ClientResponse response) throws IOException {
		InputStream is = response.getEntity(InputStream.class);
		BufferedReader in = new BufferedReader(new InputStreamReader(is));
		
		String line = null;
		while((line = in.readLine()) != null) {
		  System.out.println(line);
		}
		System.out.println();
		response.consumeContent();
	}

	
	private static boolean validateOptions(CommandLine cmd) {
		boolean isValid = true;
		
		if (! (cmd.hasOption("url") &&
			   cmd.hasOption("user") &&
			   cmd.hasOption("password") &&
			   cmd.hasOption("project"))) {
			  
			isValid = false;
		}
		return isValid;		
	}
	
	/**
	 * Print out the HTTPResponse headers
	 */
	public static void printResponseHeaders(HttpResponse response) {
		Header[] headers = response.getAllHeaders();
		for (int i = 0; i < headers.length; i++) {
			System.out.println("\t- " + headers[i].getName() + ": " + headers[i].getValue());
		}
	}
	
	public static Map<String, String> getQueryMap(String query) {
		Map<String, String> map = new HashMap<String, String>();
		String[] params = query.split("&"); //$NON-NLS-1$

		for (String param : params) {
		String name = param.split("=")[0]; //$NON-NLS-1$
		String value = param.split("=")[1]; //$NON-NLS-1$
		map.put(name, value);
		}

		return map;
	} 
	
	private static void validateTokens(OslcOAuthClient client, String redirect, String user, String password, String authURL) throws Exception {
		
		HttpGet request2 = new HttpGet(redirect);
		HttpClientParams.setRedirecting(request2.getParams(), false);
		HttpResponse response = client.getHttpClient().execute(request2);
		EntityUtils.consume(response.getEntity());
		
		// Get the location
		Header location = response.getFirstHeader("Location");
		HttpGet request3 = new HttpGet(location.getValue());
		HttpClientParams.setRedirecting(request3.getParams(), false);	
		response = client.getHttpClient().execute(request3);
		EntityUtils.consume(response.getEntity());
		
		//POST to login form
		// The server requires an authentication: Create the login form
		// Following line should be like : "https://server:port/dwa/j_acegi_security_check";
		HttpPost formPost = new HttpPost(authURL);
		List<NameValuePair> nvps = new ArrayList<NameValuePair>();
		nvps.add(new BasicNameValuePair("j_username", user));
		nvps.add(new BasicNameValuePair("j_password", password));
		formPost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8));
				
		HttpResponse formResponse = client.getHttpClient().execute(formPost);
		EntityUtils.consume(formResponse.getEntity());
	
		location = formResponse.getFirstHeader("Location");
		//Third GET
		HttpGet request4 = new HttpGet(location.getValue());
		HttpClientParams.setRedirecting(request4.getParams(), false);
		response = client.getHttpClient().execute(request4);
		EntityUtils.consume(response.getEntity());
	    
		Map<String,String> oAuthMap = getQueryMap(location.getValue());
		String oauthToken = oAuthMap.get("oauth_token");
		String oauthverifier = oAuthMap.get("oauth_verifier");
		
		// The server requires an authentication: Create the login form
	/*	HttpPost formPost2 = new HttpPost(authURL);
		formPost2.getParams().setParameter("oauth_token", oauthToken);
		formPost2.getParams().setParameter("oauth_verifier", oauthverifier);
		formPost2.getParams().setParameter("authorize", "true");
		formPost2.addHeader("Content-Type","application/x-www-form-urlencoded;charset=UTF-8");
		
		formResponse = client.getHttpClient().execute(formPost2);
		EntityUtils.consume(formResponse.getEntity());
		
		Header header = formResponse.getFirstHeader("Content-Length");
		if ((header!=null) && (!("0".equals(header.getValue())))) {
			// The login failed
			throw new InvalidCredentialsException("Authentication failed");
		} else {
			// The login succeed
			// Step (3): Request again the protected resource
			EntityUtils.consume(formResponse.getEntity());
		}*/
	}
	
	/**
	 * Lookup the URL of a specific OSLC Service Provider in an OSLC Catalog using the service provider's title
	 * 
	 * @param catalogUrl
	 * @param serviceProviderTitle
	 * @return
	 * @throws IOException
	 * @throws OAuthException
	 * @throws URISyntaxException
	 * @throws ResourceNotFoundException 
	 */
	public static String lookupServiceProviderUrl(final String catalogUrl, final String serviceProviderTitle, final OslcOAuthClient client) 
			throws IOException, OAuthException, URISyntaxException, ResourceNotFoundException
	{
		String retval = null;
		ClientResponse response = client.getResource(catalogUrl,OSLCConstants.CT_RDF);
		Model rdfModel = ModelFactory.createDefaultModel();

		rdfModel.read(response.getEntity(InputStream.class),catalogUrl);
		
		// Step 1 Check if it is the service provider we are looking for by comparing the name		
		ResIterator listResources = rdfModel.listResourcesWithProperty(RDF.type,rdfModel.createResource("http://open-services.net/ns/core#ServiceProvider";));
		Property titleProp = rdfModel.createProperty(OSLCConstants.DC,"title");
		//check each serviceProvider's title and match it to the one passed in
		while (listResources.hasNext()) {
			Resource resource = listResources.next();
			Statement titlestatement = resource.getProperty(titleProp);
			if (titlestatement == null)
				continue;
			String mytitle = titlestatement.getLiteral().getString();
			System.out.println(mytitle);
			if (( mytitle != null) && (mytitle.equalsIgnoreCase(serviceProviderTitle))) {
				System.out.println("Module Found");
				retval =  catalogUrl;
			}
		}

		// Step 2 Check if there are Service providers properties to recursively look in them
		if ( retval == null) {
			Property spPredicate = rdfModel.createProperty(OSLCConstants.OSLC_V2,"serviceProvider");
			Selector select = new SimpleSelector(null, spPredicate, (RDFNode)null); 
			StmtIterator listStatements = rdfModel.listStatements(select);
			
			//check each serviceProvider's title and match it to the one passed in
			while (listStatements.hasNext()) {
				Statement thisSP = listStatements.nextStatement();
				com.hp.hpl.jena.rdf.model.Resource spRes = thisSP.getResource();
				if ( spRes.isResource()) {
					// Recursively look for the project Name
					String newURL = spRes.getURI();
					try {
						return lookupServiceProviderUrl(newURL, serviceProviderTitle, client);
					} catch (ResourceNotFoundException nf){
						
					}
				}
			}
			
		}
		
		// Step 3 Check if there are ServiceProvider catalog and recursively look in them
		if ( retval == null) {
			Property spcPredicate = rdfModel.createProperty(OSLCConstants.OSLC_V2,"serviceProviderCatalog");
			Selector select = new SimpleSelector(null, spcPredicate, (RDFNode)null); 
			StmtIterator listStatements = rdfModel.listStatements(select);
			
			//check each serviceProvider's title and match it to the one passed in
			while (listStatements.hasNext()) {
				Statement thisSP = listStatements.nextStatement();
				com.hp.hpl.jena.rdf.model.Resource spRes = thisSP.getResource();
				if ( spRes.isResource()) {
					// Recursively look for the project Name
					String newURL = spRes.getURI();
					try {
						return lookupServiceProviderUrl(newURL, serviceProviderTitle, client);
					} catch (ResourceNotFoundException nf){
						
					}
				} 
			} 
		}
		
		if (retval == null ) {
			throw new ResourceNotFoundException(catalogUrl, serviceProviderTitle);
		}
		
		return retval; 
	}

}

Back to the top