Java tutorial
/******************************************************************************* * Copyright (c) 2012, 2013 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.URI; 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 javax.xml.namespace.QName; import org.w3c.dom.Element; 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.HttpHeaders; 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 org.eclipse.lyo.client.oslc.resources.Requirement; import org.eclipse.lyo.client.oslc.resources.RmConstants; import org.eclipse.lyo.client.oslc.resources.RmUtil; import org.eclipse.lyo.oslc4j.core.model.CreationFactory; import org.eclipse.lyo.oslc4j.core.model.Link; import org.eclipse.lyo.oslc4j.core.model.OslcMediaType; import org.eclipse.lyo.oslc4j.core.model.ResourceShape; import org.eclipse.lyo.oslc4j.core.model.Service; import org.eclipse.lyo.oslc4j.core.model.ServiceProvider; 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"); 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 \"JKE Banking (Requirements Management)\""); 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"); 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"); // 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); //STEP 7: Get the Creation Factory URL for default Requirements so that we can create one Requirement requirement = new Requirement(); String requirementFactory = client.lookupCreationFactory(serviceProviderUrl, OSLCConstants.OSLC_RM_V2, requirement.getRdfTypes()[0].toString()); //STEP 8 Get the default Requirement Type URL ResourceShape reqInstanceShape = RmUtil.lookupRequirementsInstanceShapes(serviceProviderUrl, OSLCConstants.OSLC_RM_V2, requirement.getRdfTypes()[0].toString(), client, "Resource shape for a requirement in the " + projectArea); if ((reqInstanceShape != null) && (requirementFactory != null)) { //STEP 9: Create a Requirement requirement.setInstanceShape(reqInstanceShape.getAbout()); // Add a link requirement.addImplementedBy( new Link(new URI("http://google.com"), "Link created by an Eclipse Lyo user")); requirement.setDescription("Created By EclipseLyo"); // Add the PrimaryText String primaryText = "My Eclipse Lyo CREATED Primary Text"; Element obj = RmUtil.convertStringToHTML(primaryText); requirement.getExtendedProperties().put(RmConstants.PROPERTY_PRIMARY_TEXT, obj); //Create the Requirement ClientResponse creationResponse = client.createResource(requirementFactory, requirement, OslcMediaType.APPLICATION_RDF_XML, OslcMediaType.APPLICATION_RDF_XML); String req01URL = creationResponse.getHeaders().getFirst(HttpHeaders.LOCATION); creationResponse.consumeContent(); } //STEP 10: Query of changed values OslcQueryParameters queryParams = new OslcQueryParameters(); queryParams.setPrefix("oslc_rm=<http://open-services.net/ns/rm#>"); queryParams.setWhere("oslc_rm:implementedBy=<http://google.com>"); OslcQuery query = new OslcQuery(client, queryCapability, 10, queryParams); OslcQueryResult result = query.submit(); boolean processAsJavaObjects = false; int resultsSize = result.getMembersUrls().length; processPagedQueryResults(result, client, processAsJavaObjects); System.out.println("\n------------------------------\n"); System.out.println("Number of Results for query 1 = " + resultsSize + "\n"); //STEP 11: Now get the artifact with identifier = 9 queryParams = new OslcQueryParameters(); queryParams.setPrefix("dcterms=<http://purl.org/dc/terms/>"); queryParams.setWhere("dcterms:identifier=9"); query = new OslcQuery(client, queryCapability, 10, queryParams); result = query.submit(); String requirementURL = null; // Get the URL of returned requirement if (result != null) { String[] returnedURLS = result.getMembersUrls(); if ((returnedURLS != null) && (returnedURLS.length > 0)) { requirementURL = returnedURLS[0]; } } // STEP 12 If requirement found, lets get it an modify if (requirementURL != null) { // Get the requirement ClientResponse getResponse = client.getResource(requirementURL, OslcMediaType.APPLICATION_RDF_XML); requirement = getResponse.getEntity(Requirement.class); // Get the eTAG, we need it to update String etag = getResponse.getHeaders().getFirst(OSLCConstants.ETAG); getResponse.consumeContent(); // Following code is needed to workaround an issue in DWA that exposes the Heading inf as encoded XML { // Get the type for "Object Heading" org.eclipse.lyo.oslc4j.core.model.Property[] properties = reqInstanceShape.getProperties(); String attrDef = null; for (org.eclipse.lyo.oslc4j.core.model.Property property : properties) { if (property.getTitle().equalsIgnoreCase("Object Heading")) { attrDef = property.getPropertyDefinition().toString(); } } if (attrDef != null) { String url = attrDef.substring(0, attrDef.lastIndexOf("/") + 1); String name = attrDef.substring(attrDef.lastIndexOf("/") + 1); // QName attr12Name = new QName("https://slot12.gdl.mex.ibm.com:8443/dwa/rm/urn:rational::1-514b30b9627b2a31-M-00000062/types/", "attrDef-12"); QName attr12Name = new QName(url, name); String attr12 = (String) requirement.getExtendedProperties().get(attr12Name); attr12 = removeXMLEscape(attr12); Element objattr12 = RmUtil.convertStringToHTML(attr12); requirement.getExtendedProperties().put(attr12Name, objattr12); } } // Change the Primary text String primaryText = "My Eclipse Lyo CHANGED Primary Text"; // Put in the proper object ( Element for XML Strings ) Element obj = RmUtil.convertStringToHTML(primaryText); requirement.getExtendedProperties().put(RmConstants.PROPERTY_PRIMARY_TEXT, obj); // Add a couple of links requirement.addImplementedBy(new Link(new URI("http://google.com"), "ImplementedBy example")); requirement.addElaboratedBy(new Link(new URI("http://terra.com.mx"), "ElaboratedBy example")); // Update the requirement with the proper etag ClientResponse updateResponse = client.updateResource(requirementURL, requirement, OslcMediaType.APPLICATION_RDF_XML, OslcMediaType.APPLICATION_RDF_XML, etag); updateResponse.consumeContent(); } } } 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("Project 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; } /** * Find the OSLC Instance Shape URL for a given OSLC resource type. * * @param serviceProviderUrl * @param oslcDomain * @param oslcResourceType - the resource type of the desired query capability. This may differ from the OSLC artifact type. * @return URL of requested Creation Factory or null if not found. * @throws IOException * @throws OAuthException * @throws URISyntaxException * @throws ResourceNotFoundException */ public static ResourceShape lookupRequirementsInstanceShapesOLD(final String serviceProviderUrl, final String oslcDomain, final String oslcResourceType, OslcOAuthClient client, String requiredInstanceShape) throws IOException, OAuthException, URISyntaxException, ResourceNotFoundException { ClientResponse response = client.getResource(serviceProviderUrl, OSLCConstants.CT_RDF); ServiceProvider serviceProvider = response.getEntity(ServiceProvider.class); if (serviceProvider != null) { for (Service service : serviceProvider.getServices()) { URI domain = service.getDomain(); if (domain != null && domain.toString().equals(oslcDomain)) { CreationFactory[] creationFactories = service.getCreationFactories(); if (creationFactories != null && creationFactories.length > 0) { for (CreationFactory creationFactory : creationFactories) { for (URI resourceType : creationFactory.getResourceTypes()) { //return as soon as domain + resource type are matched if (resourceType.toString() != null && resourceType.toString().equals(oslcResourceType)) { URI[] instanceShapes = creationFactory.getResourceShapes(); if (instanceShapes != null) { for (URI typeURI : instanceShapes) { response = client.getResource(typeURI.toString(), OSLCConstants.CT_RDF); ResourceShape resourceShape = response.getEntity(ResourceShape.class); String typeTitle = resourceShape.getTitle(); if ((typeTitle != null) && (typeTitle.equalsIgnoreCase(requiredInstanceShape))) { return resourceShape; } } } } } } } } } } throw new ResourceNotFoundException(serviceProviderUrl, "InstanceShapes"); } /** * Remove XML Escape indicators * * @param content * @return String */ public static String removeXMLEscape(String content) { content = content.replaceAll("<", "<"); //$NON-NLS-1$ //$NON-NLS-2$ content = content.replaceAll(">", ">"); //$NON-NLS-1$ //$NON-NLS-2$ content = content.replaceAll(""", "\""); //$NON-NLS-1$ //$NON-NLS-2$ content = content.replaceAll("'", "\'"); //$NON-NLS-1$ //$NON-NLS-2$ content = content.replaceAll("&", "&"); //$NON-NLS-1$ //$NON-NLS-2$ content = content.trim(); return content; } }