Skip to content

Commit

Permalink
ARTIF-678 allow "forced" deletion of artifacts with no constraint checks
Browse files Browse the repository at this point in the history
  • Loading branch information
brmeyer committed Apr 20, 2015
1 parent 1b4ae37 commit e65fbcc
Show file tree
Hide file tree
Showing 10 changed files with 139 additions and 62 deletions.
Expand Up @@ -654,34 +654,51 @@ public BaseArtifactType addComment(String uuid, ArtifactType type, String text)
}
}

/**
* Delets an artifact from the s-ramp repository.
* @param uuid
* @param type
* @throws ArtificerClientException
* @throws ArtificerServerException
*/
public void deleteArtifact(String uuid, ArtifactType type) throws ArtificerClientException, ArtificerServerException {
assertFeatureEnabled(type);
/**
* Delets an artifact from the s-ramp repository.
* @param uuid
* @param type
* @throws ArtificerClientException
* @throws ArtificerServerException
*/
public void deleteArtifact(String uuid, ArtifactType type) throws ArtificerClientException, ArtificerServerException {
deleteArtifact(uuid, type, false);
}

/**
* Delets an artifact from the s-ramp repository.
* @param uuid
* @param type
* @param force
* @throws ArtificerClientException
* @throws ArtificerServerException
*/
public void deleteArtifact(String uuid, ArtifactType type, boolean force) throws ArtificerClientException, ArtificerServerException {
assertFeatureEnabled(type);
ClientResponse<?> response = null;
try {
String artifactModel = type.getArtifactType().getModel();
String artifactType = type.getArtifactType().getType();
if ("ext".equals(type.getArtifactType().getModel()) && type.getExtendedType()!=null) {
artifactType = type.getExtendedType();
}
String artifactUuid = uuid;
String atomUrl = String.format("%1$s/%2$s/%3$s/%4$s", srampEndpoint, artifactModel, artifactType, artifactUuid);
ClientRequest request = createClientRequest(atomUrl);
response = request.delete();
} catch (ArtificerServerException e) {
throw e;
} catch (Throwable e) {
throw new ArtificerClientException(e);
try {
String artifactModel = type.getArtifactType().getModel();
String artifactType = type.getArtifactType().getType();
if ("ext".equals(type.getArtifactType().getModel()) && type.getExtendedType()!=null) {
artifactType = type.getExtendedType();
}
String artifactUuid = uuid;
String atomUrl;
if (force) {
atomUrl = String.format("%1$s/%2$s/%3$s/%4$s/force", srampEndpoint, artifactModel, artifactType, artifactUuid);
} else {
atomUrl = String.format("%1$s/%2$s/%3$s/%4$s", srampEndpoint, artifactModel, artifactType, artifactUuid);
}
ClientRequest request = createClientRequest(atomUrl);
response = request.delete();
} catch (ArtificerServerException e) {
throw e;
} catch (Throwable e) {
throw new ArtificerClientException(e);
} finally {
closeQuietly(response);
}
}
}
}

/**
* Deletes an artifact's content from the s-ramp repository.
Expand Down
Expand Up @@ -345,7 +345,7 @@ public BaseArtifactType addComment(String uuid, ArtifactType type, String text)
}

@Override
public BaseArtifactType deleteArtifact(String uuid, ArtifactType type) throws ArtificerException {
public BaseArtifactType deleteArtifact(String uuid, ArtifactType type, boolean force) throws ArtificerException {
Session session = null;
try {
session = JCRRepositoryFactory.getSession();
Expand All @@ -355,8 +355,11 @@ public BaseArtifactType deleteArtifact(String uuid, ArtifactType type) throws Ar
throw ArtificerNotFoundException.artifactNotFound(uuid);
}

JCRUtils.relationshipConstraints(uuid, artifactNode, session);
JCRUtils.deleteDerivedRelationships(artifactNode, session);
if (force) {
JCRUtils.deleteReverseRelationships(artifactNode, session);
} else {
JCRUtils.relationshipConstraints(uuid, artifactNode, session);
}

// Move the node to the trash.
String srcPath = artifactNode.getPath();
Expand Down
Expand Up @@ -550,22 +550,54 @@ public static void customMetadataConstraintsOnDerived(String uuid, Node primaryN
}
}

// /**
// * Deletes all derived relationship nodes that point *to* the given artifact or its derived artifacts
// *
// * @param primaryNode
// * @param session
// * @throws Exception
// */
// public static void deleteDerivedReverseRelationships(Node primaryNode, Session session) throws Exception {
// String query = String.format("SELECT r.* FROM [sramp:relationship] AS r " +
// "JOIN [sramp:target] AS t ON ISCHILDNODE(t, r) " +
// // root path, *not* in the trash
// "WHERE ISDESCENDANTNODE(r, '" + JCRConstants.ROOT_PATH + "') " +
// // relationship is not from one of the given artifact's children
// "AND NOT(ISDESCENDANTNODE(r, '%2$s')) " +
// // derived relationships only
// "AND r.[sramp:derived] = true " +
// // targets the primary artifact or any of its derived artifacts
// "AND (REFERENCE(t) = '%1$s' OR REFERENCE(t) IN (SELECT referenced.[jcr:uuid] FROM [sramp:baseArtifactType] AS referenced WHERE ISDESCENDANTNODE(referenced, '%2$s')))",
// primaryNode.getIdentifier(), primaryNode.getPath());
// javax.jcr.query.QueryManager jcrQueryManager = session.getWorkspace().getQueryManager();
// javax.jcr.query.Query jcrQuery = jcrQueryManager.createQuery(query, JCRConstants.JCR_SQL2);
// QueryResult jcrQueryResult = jcrQuery.execute();
// NodeIterator jcrNodes = jcrQueryResult.getNodes();
//
// while (jcrNodes.hasNext()) {
// Node node = jcrNodes.nextNode();
// // delete it
// node.remove();
// }
//
// session.save();
// }

/**
* Deletes all derived relationship nodes that point *to* the given artifact or its derived artifacts
* Deletes *all* relationship nodes that point *to* the given artifact or its derived artifacts. Primarily used
* for force deletes.
*
* @param primaryNode
* @param session
* @throws Exception
*/
public static void deleteDerivedRelationships(Node primaryNode, Session session) throws Exception {
public static void deleteReverseRelationships(Node primaryNode, Session session) throws Exception {
String query = String.format("SELECT r.* FROM [sramp:relationship] AS r " +
"JOIN [sramp:target] AS t ON ISCHILDNODE(t, r) " +
// root path, *not* in the trash
"WHERE ISDESCENDANTNODE(r, '" + JCRConstants.ROOT_PATH + "') " +
// relationship is not from one of the given artifact's children
"AND NOT(ISDESCENDANTNODE(r, '%2$s')) " +
// derived relationships only
"AND r.[sramp:derived] = true " +
// targets the primary artifact or any of its derived artifacts
"AND (REFERENCE(t) = '%1$s' OR REFERENCE(t) IN (SELECT referenced.[jcr:uuid] FROM [sramp:baseArtifactType] AS referenced WHERE ISDESCENDANTNODE(referenced, '%2$s')))",
primaryNode.getIdentifier(), primaryNode.getPath());
Expand Down
Expand Up @@ -61,7 +61,7 @@ public void testDelete() throws Exception {
// Verify deleting the original fails
boolean caught = false;
try {
persistenceManager.deleteArtifact(task.getUuid(), ArtifactType.valueOf(task));
persistenceManager.deleteArtifact(task.getUuid(), ArtifactType.valueOf(task), false);
} catch (ArtificerConflictException e) {
caught = true;
}
Expand All @@ -78,7 +78,7 @@ public void testDelete() throws Exception {
// Verify deleting the original fails
caught = false;
try {
persistenceManager.deleteArtifact(task.getUuid(), ArtifactType.valueOf(task));
persistenceManager.deleteArtifact(task.getUuid(), ArtifactType.valueOf(task), false);
} catch (ArtificerConflictException e) {
caught = true;
}
Expand All @@ -89,7 +89,7 @@ public void testDelete() throws Exception {
persistenceManager.updateArtifact(actor, ArtifactType.valueOf(task));

// Deleting the original should now work
persistenceManager.deleteArtifact(task.getUuid(), ArtifactType.valueOf(task));
persistenceManager.deleteArtifact(task.getUuid(), ArtifactType.valueOf(task), false);
}

@Test
Expand Down Expand Up @@ -118,29 +118,29 @@ public void testDeleteWithDerived() throws Exception {
// Verify the XSD cannot be deleted
boolean caught = false;
try {
persistenceManager.deleteArtifact(xsd.getUuid(), ArtifactType.valueOf(xsd));
persistenceManager.deleteArtifact(xsd.getUuid(), ArtifactType.valueOf(xsd), false);
} catch (ArtificerConflictException e) {
caught = true;
}
assertTrue(caught);

// Clear the generic relationship
persistenceManager.deleteArtifact(fooArtifact.getUuid(), ArtifactType.valueOf(fooArtifact));
persistenceManager.deleteArtifact(fooArtifact.getUuid(), ArtifactType.valueOf(fooArtifact), false);

// Verify the XSD still cannot be deleted (the WSDL still imports it)
caught = false;
try {
persistenceManager.deleteArtifact(xsd.getUuid(), ArtifactType.valueOf(xsd));
persistenceManager.deleteArtifact(xsd.getUuid(), ArtifactType.valueOf(xsd), false);
} catch (ArtificerConflictException e) {
caught = true;
}
assertTrue(caught);

// Delete the WSDL
persistenceManager.deleteArtifact(wsdl.getUuid(), ArtifactType.valueOf(wsdl));
persistenceManager.deleteArtifact(wsdl.getUuid(), ArtifactType.valueOf(wsdl), false);

// Delete the XSD
persistenceManager.deleteArtifact(xsd.getUuid(), ArtifactType.valueOf(xsd));
persistenceManager.deleteArtifact(xsd.getUuid(), ArtifactType.valueOf(xsd), false);
}

@Test
Expand Down Expand Up @@ -176,7 +176,7 @@ public void testUpdateContent() throws Exception {
assertTrue(caught);

// Clear the generic relationship
persistenceManager.deleteArtifact(fooArtifact.getUuid(), ArtifactType.valueOf(fooArtifact));
persistenceManager.deleteArtifact(fooArtifact.getUuid(), ArtifactType.valueOf(fooArtifact), false);

// Add a custom property to one of the XSD's derived artifacts
Property property = new Property();
Expand Down Expand Up @@ -267,7 +267,7 @@ public void testDeleteContent() throws Exception {
assertTrue(caught);

// Clear the generic relationship
persistenceManager.deleteArtifact(fooArtifact.getUuid(), ArtifactType.valueOf(fooArtifact));
persistenceManager.deleteArtifact(fooArtifact.getUuid(), ArtifactType.valueOf(fooArtifact), false);

// Now delete the content, for reals
persistenceManager.deleteArtifactContent(xsd.getUuid(), ArtifactType.valueOf(xsd));
Expand Down
Expand Up @@ -541,7 +541,7 @@ public void testDeleteArtifact() throws Exception {

// Now delete that artifact
ArtifactType at = ArtifactType.valueOf(artifact);
persistenceManager.deleteArtifact(document.getUuid(), at);
persistenceManager.deleteArtifact(document.getUuid(), at, false);

// Now make sure we can't load it back up
BaseArtifactType deleted = persistenceManager.getArtifact(document.getUuid(), at);
Expand All @@ -557,7 +557,7 @@ public void testDeleteArtifact() throws Exception {
pdf = this.getClass().getResourceAsStream("/sample-files/core/" + artifactFileName);
BaseArtifactType artifact2 = persistenceManager.persistArtifact(document, new ArtifactContent(artifactFileName, pdf));
Assert.assertEquals(artifact.getUuid(), artifact2.getUuid());
persistenceManager.deleteArtifact(document.getUuid(), at);
persistenceManager.deleteArtifact(document.getUuid(), at, false);
deleted = persistenceManager.getArtifact(document.getUuid(), at);
Assert.assertNull(deleted);
}
Expand Down
Expand Up @@ -102,9 +102,10 @@ public interface PersistenceManager extends AbstractManager {
* Deletes a previously persisted artifact from the S-RAMP repository.
* @param uuid
* @param artifactType
* @param force
* @throws org.artificer.common.ArtificerException
*/
public BaseArtifactType deleteArtifact(String uuid, ArtifactType artifactType) throws ArtificerException;
public BaseArtifactType deleteArtifact(String uuid, ArtifactType artifactType, boolean force) throws ArtificerException;

/**
* Deletes a previously persisted artifact's content from the S-RAMP repository.
Expand Down
Expand Up @@ -166,8 +166,12 @@ public void updateContent(ArtifactType artifactType, String uuid,

public void delete(String model, String type, String uuid) throws Exception;

public void delete(String model, String type, String uuid, boolean force) throws Exception;

public void delete(ArtifactType artifactType, String uuid) throws Exception;

public void delete(ArtifactType artifactType, String uuid, boolean force) throws Exception;

public void deleteContent(String model, String type, String uuid) throws Exception;

public void deleteContent(ArtifactType artifactType, String uuid) throws Exception;
Expand Down
14 changes: 12 additions & 2 deletions server/src/main/java/org/artificer/server/ArtifactServiceImpl.java
Expand Up @@ -395,19 +395,29 @@ public byte[] getContentBytes(ArtifactType artifactType, BaseArtifactType artifa

@Override
public void delete(String model, String type, String uuid) throws Exception {
delete(model, type, uuid, false);
}

@Override
public void delete(String model, String type, String uuid, boolean force) throws Exception {
ArtifactType artifactType = ArtifactType.valueOf(model, type, null);
delete(artifactType, uuid);
delete(artifactType, uuid, force);
}

@Override
public void delete(ArtifactType artifactType, String uuid) throws Exception {
delete(artifactType, uuid, false);
}

@Override
public void delete(ArtifactType artifactType, String uuid, boolean force) throws Exception {
if (artifactType.isDerived()) {
throw ArtificerUserException.derivedArtifactDelete(artifactType.getArtifactType());
}

PersistenceManager persistenceManager = persistenceManager();
// Delete the artifact by UUID
BaseArtifactType artifact = persistenceManager.deleteArtifact(uuid, artifactType);
BaseArtifactType artifact = persistenceManager.deleteArtifact(uuid, artifactType, force);

Set<EventProducer> eventProducers = EventProducerFactory.getEventProducers();
for (EventProducer eventProducer : eventProducers) {
Expand Down
Expand Up @@ -438,6 +438,30 @@ public void delete(@PathParam("model") String model, @PathParam("type") String t
}
}

/**
* Called to forcefully delete an s-ramp artifact from the repository, ignoring all constraints.
*
* @param model
* @param type
* @param uuid
* @throws org.artificer.atom.err.ArtificerAtomException
*/
@DELETE
@Path("{model}/{type}/{uuid}/force")
public void forceDelete(@PathParam("model") String model, @PathParam("type") String type,
@PathParam("uuid") String uuid) throws ArtificerServerException {
try {
artifactService.delete(model, type, uuid, true);
} catch (ArtificerServerException e) {
// Simply re-throw. Don't allow the following catch it -- ArtificerServerException is mapped to a unique
// HTTP response type.
throw e;
} catch (Throwable e) {
logError(logger, Messages.i18n.format("ERROR_DELETING_ARTY", uuid), e); //$NON-NLS-1$
throw new ArtificerAtomException(e);
}
}

/**
* S-RAMP atom DELETE to delete the artifact's content from the repository.
*
Expand Down
Expand Up @@ -35,7 +35,6 @@
import org.jboss.resteasy.client.core.executors.ApacheHttpClient4Executor;
import org.junit.After;
import org.junit.runner.RunWith;
import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.BaseArtifactType;
import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.StoredQuery;

import java.util.List;
Expand Down Expand Up @@ -68,23 +67,10 @@ public void cleanup() {
ArtificerAtomApiClient client = client();
// Rather than mess with pagination, just set the count to something sufficiently large.
QueryResultSet results = client.query("/s-ramp", 0, 10000, "name", true); //$NON-NLS-1$ //$NON-NLS-2$
for (ArtifactSummary summary : results) {
String uuid = summary.getUuid().replace("urn:uuid:", "");
// First, need to clear the relationships, custom properties, and classifiers to prevent
// constraint Exceptions. Note that modeled relationships must be manually cleared by tests!
BaseArtifactType artifact = client.getArtifactMetaData(uuid);
// This is expensive, so prevent it if possible.
if (artifact.getRelationship().size() > 0 || artifact.getProperty().size() > 0 || artifact.getClassifiedBy().size() > 0) {
artifact.getRelationship().clear();
artifact.getProperty().clear();
artifact.getClassifiedBy().clear();
client.updateArtifactMetaData(artifact);
}
}
for (ArtifactSummary summary : results) {
String uuid = summary.getUuid().replace("urn:uuid:", "");
if (!summary.isDerived()) {
client.deleteArtifact(uuid, summary.getType());
client.deleteArtifact(uuid, summary.getType(), true);
}
}
} catch (Exception e) {
Expand Down

0 comments on commit e65fbcc

Please sign in to comment.