23 |
23 |
|
24 |
24 |
package edu.ucsb.nceas.metacat.dataone;
|
25 |
25 |
|
|
26 |
import java.io.IOException;
|
26 |
27 |
import java.io.InputStream;
|
|
28 |
import java.io.PipedInputStream;
|
|
29 |
import java.io.PipedOutputStream;
|
|
30 |
import java.lang.reflect.InvocationTargetException;
|
27 |
31 |
import java.math.BigInteger;
|
28 |
32 |
import java.sql.SQLException;
|
29 |
33 |
import java.util.ArrayList;
|
... | ... | |
34 |
38 |
|
35 |
39 |
import javax.servlet.http.HttpServletRequest;
|
36 |
40 |
|
|
41 |
import org.apache.commons.beanutils.BeanUtils;
|
37 |
42 |
import org.apache.log4j.Logger;
|
38 |
43 |
import org.dataone.client.v2.CNode;
|
|
44 |
import org.dataone.client.v2.MNode;
|
39 |
45 |
import org.dataone.client.v2.itk.D1Client;
|
40 |
|
import org.dataone.client.v2.MNode;
|
41 |
46 |
import org.dataone.service.cn.v2.CNAuthorization;
|
42 |
47 |
import org.dataone.service.cn.v2.CNCore;
|
43 |
48 |
import org.dataone.service.cn.v2.CNRead;
|
... | ... | |
58 |
63 |
import org.dataone.service.types.v1.AccessPolicy;
|
59 |
64 |
import org.dataone.service.types.v1.Checksum;
|
60 |
65 |
import org.dataone.service.types.v1.ChecksumAlgorithmList;
|
61 |
|
import org.dataone.service.types.v1.DescribeResponse;
|
62 |
66 |
import org.dataone.service.types.v1.Event;
|
63 |
67 |
import org.dataone.service.types.v1.Identifier;
|
64 |
|
import org.dataone.service.types.v2.Log;
|
65 |
|
import org.dataone.service.types.v2.Node;
|
66 |
|
import org.dataone.service.types.v2.NodeList;
|
67 |
68 |
import org.dataone.service.types.v1.NodeReference;
|
68 |
69 |
import org.dataone.service.types.v1.NodeType;
|
69 |
|
import org.dataone.service.types.v2.ObjectFormat;
|
70 |
70 |
import org.dataone.service.types.v1.ObjectFormatIdentifier;
|
71 |
|
import org.dataone.service.types.v2.ObjectFormatList;
|
72 |
71 |
import org.dataone.service.types.v1.ObjectList;
|
73 |
72 |
import org.dataone.service.types.v1.ObjectLocationList;
|
74 |
73 |
import org.dataone.service.types.v1.Permission;
|
... | ... | |
77 |
76 |
import org.dataone.service.types.v1.ReplicationStatus;
|
78 |
77 |
import org.dataone.service.types.v1.Session;
|
79 |
78 |
import org.dataone.service.types.v1.Subject;
|
|
79 |
import org.dataone.service.types.v1_1.QueryEngineDescription;
|
|
80 |
import org.dataone.service.types.v1_1.QueryEngineList;
|
|
81 |
import org.dataone.service.types.v2.Node;
|
|
82 |
import org.dataone.service.types.v2.NodeList;
|
|
83 |
import org.dataone.service.types.v2.ObjectFormat;
|
|
84 |
import org.dataone.service.types.v2.ObjectFormatList;
|
80 |
85 |
import org.dataone.service.types.v2.SystemMetadata;
|
81 |
86 |
import org.dataone.service.types.v2.util.ServiceMethodRestrictionUtil;
|
82 |
|
import org.dataone.service.types.v1_1.QueryEngineDescription;
|
83 |
|
import org.dataone.service.types.v1_1.QueryEngineList;
|
|
87 |
import org.dataone.service.util.TypeMarshaller;
|
|
88 |
import org.jibx.runtime.JiBXException;
|
84 |
89 |
|
|
90 |
import edu.ucsb.nceas.metacat.DBUtil;
|
85 |
91 |
import edu.ucsb.nceas.metacat.EventLog;
|
86 |
92 |
import edu.ucsb.nceas.metacat.IdentifierManager;
|
87 |
93 |
import edu.ucsb.nceas.metacat.McdbDocNotFoundException;
|
88 |
94 |
import edu.ucsb.nceas.metacat.dataone.hazelcast.HazelcastService;
|
89 |
|
import edu.ucsb.nceas.metacat.index.MetacatSolrIndex;
|
|
95 |
import edu.ucsb.nceas.metacat.properties.PropertyService;
|
|
96 |
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
|
90 |
97 |
|
91 |
98 |
/**
|
92 |
99 |
* Represents Metacat's implementation of the DataONE Coordinating Node
|
... | ... | |
1104 |
1111 |
|
1105 |
1112 |
}
|
1106 |
1113 |
|
|
1114 |
@Override
|
|
1115 |
public ObjectFormatIdentifier addFormat(Session session, ObjectFormatIdentifier formatId, ObjectFormat format)
|
|
1116 |
throws ServiceFailure, NotFound, NotImplemented, NotAuthorized, InvalidToken {
|
|
1117 |
|
|
1118 |
logMetacat.debug("CNodeService.addFormat() called.\n" +
|
|
1119 |
"format ID: " + format.getFormatId() + "\n" +
|
|
1120 |
"format name: " + format.getFormatName() + "\n" +
|
|
1121 |
"format type: " + format.getFormatType() );
|
|
1122 |
|
|
1123 |
// FIXME remove:
|
|
1124 |
if (true)
|
|
1125 |
throw new NotImplemented("0000", "Implementation underway... Will need testing too...");
|
|
1126 |
|
|
1127 |
if (!isAdminAuthorized(session))
|
|
1128 |
throw new NotAuthorized("0000", "Not authorized to call addFormat()");
|
|
1129 |
|
|
1130 |
String separator = ".";
|
|
1131 |
try {
|
|
1132 |
separator = PropertyService.getProperty("document.accNumSeparator");
|
|
1133 |
} catch (PropertyNotFoundException e) {
|
|
1134 |
logMetacat.warn("Unable to find property \"document.accNumSeparator\"\n" + e.getMessage());
|
|
1135 |
}
|
|
1136 |
|
|
1137 |
// find pids of last and next ObjectFormatList
|
|
1138 |
String OBJECT_FORMAT_DOCID = ObjectFormatService.OBJECT_FORMAT_DOCID;
|
|
1139 |
int lastRev = -1;
|
|
1140 |
try {
|
|
1141 |
lastRev = DBUtil.getLatestRevisionInDocumentTable(OBJECT_FORMAT_DOCID);
|
|
1142 |
} catch (SQLException e) {
|
|
1143 |
throw new ServiceFailure("0000", "Unable to locate last revision of the object format list.\n" + e.getMessage());
|
|
1144 |
}
|
|
1145 |
int nextRev = lastRev + 1;
|
|
1146 |
String lastDocID = OBJECT_FORMAT_DOCID + separator + lastRev;
|
|
1147 |
String nextDocID = OBJECT_FORMAT_DOCID + separator + nextRev;
|
|
1148 |
|
|
1149 |
Identifier lastPid = new Identifier();
|
|
1150 |
lastPid.setValue(lastDocID);
|
|
1151 |
Identifier nextPid = new Identifier();
|
|
1152 |
nextPid.setValue(nextDocID);
|
|
1153 |
|
|
1154 |
logMetacat.debug("Last ObjectFormatList document ID: " + lastDocID + "\n"
|
|
1155 |
+ "Next ObjectFormatList document ID: " + nextDocID);
|
|
1156 |
|
|
1157 |
// add new format to the current ObjectFormatList
|
|
1158 |
ObjectFormatList objectFormatList = ObjectFormatService.getInstance().listFormats();
|
|
1159 |
List<ObjectFormat> innerList = objectFormatList.getObjectFormatList();
|
|
1160 |
innerList.add(format);
|
|
1161 |
|
|
1162 |
// get existing (last) sysmeta and make a copy
|
|
1163 |
SystemMetadata lastSysmeta = getSystemMetadata(session, lastPid);
|
|
1164 |
SystemMetadata nextSysmeta = new SystemMetadata();
|
|
1165 |
try {
|
|
1166 |
BeanUtils.copyProperties(nextSysmeta, lastSysmeta);
|
|
1167 |
} catch (IllegalAccessException | InvocationTargetException e) {
|
|
1168 |
throw new ServiceFailure("0000", "Unable to create system metadata for updated object format list.\n" + e.getMessage());
|
|
1169 |
}
|
|
1170 |
|
|
1171 |
// create the new object format list, and update the old sysmeta with obsoletedBy
|
|
1172 |
createNewObjectFormatList(session, lastPid, nextPid, objectFormatList, nextSysmeta);
|
|
1173 |
updateOldObjectFormatList(session, lastPid, nextPid, lastSysmeta);
|
|
1174 |
|
|
1175 |
// TODO add to ObjectFormatService local cache?
|
|
1176 |
|
|
1177 |
return formatId;
|
|
1178 |
}
|
|
1179 |
|
|
1180 |
/**
|
|
1181 |
* Creates the object for the next / updated version of the ObjectFormatList.
|
|
1182 |
*
|
|
1183 |
* @param session
|
|
1184 |
* @param lastPid
|
|
1185 |
* @param nextPid
|
|
1186 |
* @param objectFormatList
|
|
1187 |
* @param lastSysmeta
|
|
1188 |
*/
|
|
1189 |
private void createNewObjectFormatList(Session session, Identifier lastPid, Identifier nextPid,
|
|
1190 |
ObjectFormatList objectFormatList, SystemMetadata lastSysmeta)
|
|
1191 |
throws InvalidToken, ServiceFailure, NotAuthorized, NotImplemented {
|
|
1192 |
|
|
1193 |
PipedInputStream is = new PipedInputStream();
|
|
1194 |
PipedOutputStream os = null;
|
|
1195 |
|
|
1196 |
try {
|
|
1197 |
os = new PipedOutputStream(is);
|
|
1198 |
TypeMarshaller.marshalTypeToOutputStream(objectFormatList, os);
|
|
1199 |
} catch (JiBXException | IOException e) {
|
|
1200 |
throw new ServiceFailure("0000", "Unable to marshal object format list.\n" + e.getMessage());
|
|
1201 |
} finally {
|
|
1202 |
try {
|
|
1203 |
os.flush();
|
|
1204 |
os.close();
|
|
1205 |
} catch (IOException ioe) {
|
|
1206 |
throw new ServiceFailure("0000", "Unable to marshal object format list.\n" + ioe.getMessage());
|
|
1207 |
}
|
|
1208 |
}
|
|
1209 |
|
|
1210 |
BigInteger docSize = lastSysmeta.getSize();
|
|
1211 |
try {
|
|
1212 |
docSize = BigInteger.valueOf(is.available());
|
|
1213 |
} catch (IOException e) {
|
|
1214 |
logMetacat.warn("Unable to set an accurate size for the new object format list.", e);
|
|
1215 |
}
|
|
1216 |
|
|
1217 |
lastSysmeta.setIdentifier(nextPid);
|
|
1218 |
lastSysmeta.setObsoletes(lastPid);
|
|
1219 |
lastSysmeta.setSize(docSize);
|
|
1220 |
lastSysmeta.setSubmitter(session.getSubject());
|
|
1221 |
lastSysmeta.setDateUploaded(new Date());
|
|
1222 |
|
|
1223 |
// create new object format list
|
|
1224 |
try {
|
|
1225 |
create(session, nextPid, is, lastSysmeta);
|
|
1226 |
} catch (IdentifierNotUnique | UnsupportedType | InsufficientResources
|
|
1227 |
| InvalidSystemMetadata | InvalidRequest e) {
|
|
1228 |
throw new ServiceFailure("0000", "Unable to create() new object format list" + e.getMessage());
|
|
1229 |
}
|
|
1230 |
}
|
|
1231 |
|
|
1232 |
/**
|
|
1233 |
* Updates the SystemMetadata for the old version of the ObjectFormatList
|
|
1234 |
* by setting the obsoletedBy value to the pid of the new version of the
|
|
1235 |
* ObjectFormatList.
|
|
1236 |
*
|
|
1237 |
* @param session
|
|
1238 |
* @param lastPid
|
|
1239 |
* @param obsoletedByPid
|
|
1240 |
* @param lastSysmeta
|
|
1241 |
* @throws ServiceFailure
|
|
1242 |
*/
|
|
1243 |
private void updateOldObjectFormatList(Session session, Identifier lastPid, Identifier obsoletedByPid, SystemMetadata lastSysmeta)
|
|
1244 |
throws ServiceFailure {
|
|
1245 |
|
|
1246 |
lastSysmeta.setObsoletedBy(obsoletedByPid);
|
|
1247 |
|
|
1248 |
try {
|
|
1249 |
this.updateSystemMetadata(session, lastPid, lastSysmeta);
|
|
1250 |
} catch (NotImplemented | NotAuthorized | ServiceFailure | InvalidRequest
|
|
1251 |
| InvalidSystemMetadata | InvalidToken e) {
|
|
1252 |
throw new ServiceFailure("0000", "Unable to update metadata of old object format list.\n" + e.getMessage());
|
|
1253 |
}
|
|
1254 |
}
|
1107 |
1255 |
/**
|
1108 |
1256 |
* Returns a list of all object formats registered in the DataONE Object
|
1109 |
1257 |
* Format Vocabulary
|
... | ... | |
1977 |
2125 |
}
|
1978 |
2126 |
}
|
1979 |
2127 |
|
1980 |
|
public void synchronizeObject(Session session, SystemMetadata sysmeta) throws NotAuthorized, InvalidRequest{
|
1981 |
|
if(session == null) {
|
1982 |
|
throw new NotAuthorized("4861", "No Session - could not authorize for synchorinzing object." +
|
1983 |
|
" If you are not logged in, please do so and retry the request.");
|
1984 |
|
}
|
1985 |
|
if(sysmeta == null) {
|
1986 |
|
throw new InvalidRequest("4863", "The system metadata shouldn't be null in synchronizing an object.");
|
1987 |
|
}
|
1988 |
|
Identifier pid = sysmeta.getIdentifier();
|
1989 |
|
//only the authoritative node can call this method
|
1990 |
|
if( !isAuthoritativeMNodeAdmin(session, pid) ){
|
1991 |
|
throw new NotAuthorized("4861", "Only the authoritative node "+sysmeta.getAuthoritativeMemberNode().getValue()+
|
1992 |
|
" of the object "+pid.getValue()+" can have the synchroinzeObject request.");
|
1993 |
|
}
|
1994 |
|
|
1995 |
|
|
|
2128 |
@Override
|
|
2129 |
public boolean synchronize(Session session, Identifier pid) throws NotAuthorized, InvalidRequest, NotImplemented{
|
|
2130 |
throw new NotImplemented("0000", "CN query services are not implemented in Metacat.");
|
|
2131 |
|
1996 |
2132 |
}
|
1997 |
2133 |
|
1998 |
2134 |
@Override
|
... | ... | |
2022 |
2158 |
public Node getCapabilities() throws NotImplemented, ServiceFailure {
|
2023 |
2159 |
throw new NotImplemented("0000", "The CN capabilities are not stored in Metacat.");
|
2024 |
2160 |
}
|
2025 |
|
|
2026 |
|
|
2027 |
|
|
|
2161 |
|
2028 |
2162 |
}
|
Committed the change which Andreit did.
1. Add the code for synchronize(not implemented)
2. Add the code for addForm.