* @return array of versions migrated
* @throws ServerException
*/
public Date[] modifyDatastreamControlGroup(Context context, String pid, String dsID, String controlGroup, boolean addXMLHeader, boolean reformat, boolean setMIMETypeCharset) throws ServerException {
DOWriter w = null;
try {
logger.debug("Entered modifyDatastreamControlGroup");
// FIXME: see FCREPO-765 - add proper auth when migrating this to an Admin module, for now use same permissions as reloading policies
m_authz.enforceReloadPolicies(context);
if (!controlGroup.equals("M"))
throw new GeneralException("Invalid target controlGroup " + controlGroup + ". Only \"M\" is currently supported");
try {
w = m_manager.getWriter(false, context, pid);
} catch (ObjectNotInLowlevelStorageException e ){
throw new ObjectNotFoundException("Object " + pid + " does not exist.");
}
Datastream currentDS = w.GetDatastream(dsID, null);
if (currentDS == null) {
throw new DatastreamNotFoundException("Datastream " + dsID + " not found");
}
if (currentDS.DSControlGrp.equals("X")) {
// take a copy of the existing datastream versions
Date[] versions = w.getDatastreamVersions(dsID);
Map<Date, Datastream> copyDS = new HashMap<Date, Datastream>();
for (Date version: versions) {
Datastream d = w.GetDatastream(dsID, version);
copyDS.put(version, d.copy());
}
// purge the existing datastream (all versions)
w.removeDatastream(dsID, null, null);
// add back each datastream version in reverse order as managed content
// (order might not strictly be necessary)
Arrays.sort(versions);
for (int i = versions.length - 1; i >= 0; i--) {
// get a managed content copy of this datastream version
DatastreamXMLMetadata existing = (DatastreamXMLMetadata)copyDS.get(versions[i]);
DatastreamManagedContent newDS = new DatastreamManagedContent();
existing.copy(newDS);
// X control group will have been copied over by above, reset it
newDS.DSControlGrp = controlGroup;
// probably not necessary, but just in case...
newDS.DSLocation = null;
newDS.DSLocationType = null;
// add character encoding to mime type (will always be UTF-8 as it has come from X datastream in FOXML)
if (setMIMETypeCharset) {
if (newDS.DSMIME != null && !newDS.DSMIME.equals("") & !newDS.DSMIME.contains("charset=")) {
newDS.DSMIME = newDS.DSMIME + "; charset=UTF-8";
} else {
newDS.DSMIME = "text/xml; charset=UTF-8";
}
}
byte[] byteContent;
// Note: use getContentStream() rather than getting bytes directly, as this is how
// X datastreams are disseminated (we want the M content to be identical on
// dissemination)
if (reformat) {
byteContent = this.getXML(existing.getContentStream(), addXMLHeader);
} else {
// add just the XML header declaring encoding, if requested
if (addXMLHeader) {
byte[] header;
try {
header = xmlHeader.getBytes("UTF-8");
} catch (UnsupportedEncodingException e) {
// should never happen
throw new RuntimeException(e);
}
byte[] existingContent;
try {
existingContent = IOUtils.toByteArray(existing.getContentStream());
} catch (IOException e) {
throw new GeneralException("Error reading existing content from X datastream", e);
}
byteContent = Arrays.copyOf(header, header.length + existingContent.length);
System.arraycopy(existing.xmlContent, 0, byteContent, header.length, existingContent.length);
} else {
try {
byteContent = IOUtils.toByteArray(existing.getContentStream());
} catch (IOException e) {
throw new GeneralException("Error reading existing content from X datastream", e);
}
}
}
// add the content stream
MIMETypedStream content = new MIMETypedStream(null, new ByteArrayInputStream(byteContent), null, byteContent.length);
newDS.putContentStream(content);
// checksum only needs recalc if we added a header
// note getChecksum() caters for checksum type set to disabled
if (addXMLHeader) {
logger.debug("Recalculating checksum. Type=" + newDS.DSChecksumType + " Existing checksum: " + newDS.DSChecksum != null ? newDS.DSChecksum : "none");
// forces computation rather than return existing
newDS.DSChecksum = Datastream.CHECKSUM_NONE;
newDS.DSChecksum = newDS.getChecksum();
logger.debug("New checksum: " + newDS.DSChecksum);
logger.debug("Testing new checksum, response is {}", newDS.compareChecksum());
}
w.addDatastream(newDS, true);
}
Date nowUTC = Server.getCurrentDate(context);
String logMessage = "Modified datastream control group for " + pid + " " + dsID + " from " + currentDS.DSControlGrp + " to " + controlGroup;
addAuditRecord(context,
w,
"modifyDatastreamControlGroup",
dsID,
logMessage,
nowUTC);
w.commit(logMessage);
return versions;
} else { // existing control group is not X
if (currentDS.DSControlGrp.equals("M")) {
// nothing modified