blob: 7499dd2098777064e288fa3d618fedf3b681b36c [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004, 2007 Boeing.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Boeing - initial API and implementation
*******************************************************************************/
package org.eclipse.osee.framework.skynet.core.artifact.search;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.osee.framework.core.client.ClientSessionManager;
import org.eclipse.osee.framework.core.client.server.HttpUrlBuilder;
import org.eclipse.osee.framework.core.data.JoinUtility;
import org.eclipse.osee.framework.core.data.OseeServerContext;
import org.eclipse.osee.framework.db.connection.exception.OseeCoreException;
import org.eclipse.osee.framework.db.connection.exception.OseeDataStoreException;
import org.eclipse.osee.framework.db.connection.exception.OseeWrappedException;
import org.eclipse.osee.framework.jdk.core.type.HashCollection;
import org.eclipse.osee.framework.jdk.core.type.ObjectPair;
import org.eclipse.osee.framework.jdk.core.type.PropertyStore;
import org.eclipse.osee.framework.jdk.core.type.PropertyStoreWriter;
import org.eclipse.osee.framework.jdk.core.util.HttpProcessor;
import org.eclipse.osee.framework.jdk.core.util.Strings;
import org.eclipse.osee.framework.jdk.core.util.HttpProcessor.AcquireResult;
import org.eclipse.osee.framework.jdk.core.util.io.CharBackedInputStream;
import org.eclipse.osee.framework.skynet.core.artifact.Artifact;
import org.eclipse.osee.framework.skynet.core.artifact.ArtifactLoad;
import org.eclipse.osee.framework.skynet.core.artifact.ArtifactLoader;
import org.eclipse.osee.framework.skynet.core.artifact.Branch;
import org.eclipse.osee.framework.skynet.core.artifact.ISearchConfirmer;
import org.eclipse.osee.framework.skynet.core.artifact.search.ArtifactXmlQueryResultParser.MatchLocation;
import org.eclipse.osee.framework.skynet.core.artifact.search.ArtifactXmlQueryResultParser.XmlArtifactSearchResult;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLReaderFactory;
/**
* @author Roberto E. Escobar
*/
final class HttpArtifactQuery {
private final String queryString;
private final boolean matchWordOrder;
private final String[] attributeTypes;
private final boolean includeDeleted;
private final Branch branch;
private final boolean isCaseSensitive;
protected HttpArtifactQuery(Branch branch, String queryString, boolean matchWordOrder, boolean includeDeleted, boolean isCaseSensitive, String... attributeTypes) {
this.branch = branch;
this.matchWordOrder = matchWordOrder;
this.includeDeleted = includeDeleted;
this.attributeTypes = attributeTypes != null ? attributeTypes : new String[0];
this.queryString = queryString;
this.isCaseSensitive = isCaseSensitive;
}
private String getSearchUrl(String sessionId) throws OseeDataStoreException {
Map<String, String> parameters = new HashMap<String, String>();
parameters.put("sessionId", sessionId);
return HttpUrlBuilder.getInstance().getOsgiServletServiceUrl(OseeServerContext.SEARCH_CONTEXT, parameters);
}
private CharBackedInputStream getSearchParameters(String sessionId, boolean withMatches, boolean findAllMatchLocations) throws IOException {
CharBackedInputStream backedInputStream = new CharBackedInputStream();
PropertyStore propertyStore = new PropertyStore(sessionId);
propertyStore.put("branchId", branch.getBranchId());
propertyStore.put("query", queryString);
propertyStore.put("include deleted", includeDeleted);
propertyStore.put("match word order", matchWordOrder);
propertyStore.put("attributeType", attributeTypes);
propertyStore.put("case sensitive", isCaseSensitive);
if (matchWordOrder) {
propertyStore.put("as xml", withMatches);
if (withMatches) {
propertyStore.put("find all locations", findAllMatchLocations);
}
}
PropertyStoreWriter writer = new PropertyStoreWriter();
writer.save(propertyStore, backedInputStream.getWriter());
return backedInputStream;
}
public List<Artifact> getArtifacts(ArtifactLoad loadLevel, ISearchConfirmer confirmer, boolean reload, boolean historical, boolean allowDeleted) throws OseeCoreException {
List<Artifact> toReturn = null;
ObjectPair<String, ByteArrayOutputStream> data = executeSearch(false, false);
if (data != null) {
try {
ObjectPair<Integer, Integer> queryIdAndSize = handleAsDbJoin(data.object2);
if (queryIdAndSize != null && queryIdAndSize.object2 > 0) {
try {
toReturn =
ArtifactLoader.loadArtifactsFromQueryId(queryIdAndSize.object1, loadLevel, confirmer,
queryIdAndSize.object2, reload, historical, allowDeleted);
} finally {
JoinUtility.deleteQuery(JoinUtility.JoinItem.ARTIFACT, queryIdAndSize.object1.intValue());
}
}
} catch (Exception ex) {
throw new OseeWrappedException(ex);
}
}
if (toReturn == null) {
toReturn = java.util.Collections.emptyList();
}
return toReturn;
}
public List<ArtifactMatch> getArtifactsWithMatches(ArtifactLoad loadLevel, ISearchConfirmer confirmer, boolean reload, boolean historical, boolean allowDeleted, boolean findAllMatchLocations) throws OseeCoreException {
List<ArtifactMatch> toReturn = new ArrayList<ArtifactMatch>();
ObjectPair<String, ByteArrayOutputStream> data = executeSearch(true, findAllMatchLocations);
if (data != null) {
try {
if (data.object1.endsWith("xml")) {
List<XmlArtifactSearchResult> results = handleAsXmlResults(data.object2);
for (XmlArtifactSearchResult result : results) {
try {
result.getJoinQuery().store();
List<Artifact> artifacts =
ArtifactLoader.loadArtifactsFromQueryId(result.getJoinQuery().getQueryId(), loadLevel,
confirmer, result.getJoinQuery().size(), reload, historical, allowDeleted);
for (Artifact artifact : artifacts) {
ArtifactMatch artMatch = new ArtifactMatch(artifact, allowDeleted);
HashCollection<Long, MatchLocation> attributeMatches =
result.getAttributeMatches(artifact.getArtId());
if (attributeMatches != null) {
artMatch.addMatches(attributeMatches);
}
toReturn.add(artMatch);
}
} finally {
result.getJoinQuery().delete();
}
}
} else if (data.object1.endsWith("plain")) {
ObjectPair<Integer, Integer> queryIdAndSize = handleAsDbJoin(data.object2);
if (queryIdAndSize != null && queryIdAndSize.object2 > 0) {
try {
List<Artifact> artifactList =
ArtifactLoader.loadArtifactsFromQueryId(queryIdAndSize.object1, loadLevel, confirmer,
queryIdAndSize.object2, reload, historical, allowDeleted);
for (Artifact artifact : artifactList) {
toReturn.add(new ArtifactMatch(artifact, allowDeleted));
}
} finally {
JoinUtility.deleteQuery(JoinUtility.JoinItem.ARTIFACT, queryIdAndSize.object1.intValue());
}
}
}
} catch (Exception ex) {
throw new OseeWrappedException(ex);
}
}
return toReturn;
}
private ObjectPair<String, ByteArrayOutputStream> executeSearch(boolean withMatches, boolean findAllMatchLocations) throws OseeCoreException {
ObjectPair<String, ByteArrayOutputStream> toReturn = null;
String sessionId = ClientSessionManager.getSessionId();
CharBackedInputStream inputStream = null;
try {
inputStream = getSearchParameters(sessionId, withMatches, findAllMatchLocations);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
AcquireResult httpRequestResult =
HttpProcessor.post(new URL(getSearchUrl(sessionId)), inputStream, "application/xml", "UTF-8",
outputStream);
if (httpRequestResult.getCode() == HttpURLConnection.HTTP_ACCEPTED) {
toReturn = new ObjectPair<String, ByteArrayOutputStream>(httpRequestResult.getContentType(), outputStream);
} else if (httpRequestResult.getCode() != HttpURLConnection.HTTP_NO_CONTENT) {
throw new OseeCoreException(String.format("Search error due to bad request: url[%s] status code: [%s]",
inputStream.toString(), httpRequestResult.getCode()));
}
} catch (Exception ex) {
throw new OseeWrappedException(ex);
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (Exception ex) {
throw new OseeWrappedException(ex);
}
}
}
return toReturn;
}
private List<XmlArtifactSearchResult> handleAsXmlResults(ByteArrayOutputStream outputStream) throws SAXException, IOException {
ArtifactXmlQueryResultParser parser = new ArtifactXmlQueryResultParser();
XMLReader xmlReader = XMLReaderFactory.createXMLReader();
xmlReader.setContentHandler(parser);
xmlReader.parse(new InputSource(new ByteArrayInputStream(outputStream.toByteArray())));
return parser.getResults();
}
private ObjectPair<Integer, Integer> handleAsDbJoin(ByteArrayOutputStream outputStream) throws UnsupportedEncodingException {
ObjectPair<Integer, Integer> toReturn = null;
String queryIdString = outputStream.toString("UTF-8");
if (Strings.isValid(queryIdString)) {
String[] entries = queryIdString.split(",\\s*");
if (entries.length >= 2) {
toReturn = new ObjectPair<Integer, Integer>(new Integer(entries[0]), new Integer(entries[1]));
}
}
return toReturn;
}
}