From 4573875f5e17d404a84518f4f6d8e704f8be0d72 Mon Sep 17 00:00:00 2001 From: Andreas Romeyke <andreas.romeyke@slub-dresden.de> Date: Wed, 6 Jun 2018 14:58:42 +0200 Subject: [PATCH] - added missed IEWebServices_Service - logic completed - problem: ieGfs.getFileCreationDate() and ieGfs.getFileModificationDate() only return a NULL value --- ..._DnxMoveFileOriginalPathDublettesClean.xml | 69 ++++++- .../repository/ifc/IEWebServices_Service.java | 71 +++++++ ...DnxMoveFileOriginalPathDublettesClean.java | 183 ++++++++++++++++-- 3 files changed, 304 insertions(+), 19 deletions(-) create mode 100644 src/com/exlibris/digitool/repository/ifc/IEWebServices_Service.java diff --git a/src/PLUGIN-INF/metadata_DnxMoveFileOriginalPathDublettesClean.xml b/src/PLUGIN-INF/metadata_DnxMoveFileOriginalPathDublettesClean.xml index b2a6b83..8cf7a19 100644 --- a/src/PLUGIN-INF/metadata_DnxMoveFileOriginalPathDublettesClean.xml +++ b/src/PLUGIN-INF/metadata_DnxMoveFileOriginalPathDublettesClean.xml @@ -4,10 +4,77 @@ <pl:className>org.slub.rosetta.plugins.repositoryTask.DnxMoveFileOriginalPathDublettesClean</pl:className> <pl:initParameters> <fr:x_form xmlns:fr="http://com/exlibris/digitool/common/forms/xmlbeans"> + <form_name>SLUBVirusCheckClamAVPlugin_Params</form_name> + <description>SLUBVirusCheckClamAVPlugin_parameters_form</description> + <version>0.1</version> + <grid_x>1</grid_x> + <md_format>1</md_format> + <x_fields> + <x_field> + <field_name>hostname</field_name> + <label>host</label> + <ui_tool_tip>add hostname for Rosetta</ui_tool_tip> + <mandatory>true</mandatory> + <x_logic_type>String</x_logic_type> + <x_ui_type>TextField</x_ui_type> + <default_value>localhost</default_value> + <css_class>width40</css_class> + <x_options></x_options> + </x_field> + <x_field> + <field_name>pdshostname</field_name> + <label>pdshost</label> + <ui_tool_tip>add pdshostname for Rosetta</ui_tool_tip> + <mandatory>true</mandatory> + <x_logic_type>String</x_logic_type> + <x_ui_type>TextField</x_ui_type> + <default_value>localhost</default_value> + <css_class>width40</css_class> + <x_options></x_options> + </x_field> + + <x_field> + <field_name>user</field_name> + <label>user</label> + <ui_tool_tip>add processing user for Rosetta</ui_tool_tip> + <mandatory>true</mandatory> + <x_logic_type>String</x_logic_type> + <x_ui_type>TextField</x_ui_type> + <default_value>localhost</default_value> + <css_class>width40</css_class> + <x_options></x_options> + </x_field> + + <x_field> + <field_name>institution</field_name> + <label>Inst</label> + <ui_tool_tip>add processing institution for Rosetta</ui_tool_tip> + <mandatory>true</mandatory> + <x_logic_type>String</x_logic_type> + <x_ui_type>TextField</x_ui_type> + <default_value>localhost</default_value> + <css_class>width40</css_class> + <x_options></x_options> + </x_field> + + <x_field> + <field_name>password</field_name> + <label>password</label> + <ui_tool_tip>add password for Rosetta</ui_tool_tip> + <mandatory>true</mandatory> + <x_logic_type>String</x_logic_type> + <x_ui_type>TextField</x_ui_type> + <default_value>localhost</default_value> + <css_class>width40</css_class> + <x_options></x_options> + </x_field> + + </x_fields> + </fr:x_form> </pl:initParameters> <pl:description>repairs broken file original paths with dublettes, see <a href="https://intranet.slub-dresden.de/display/LZA/Umgang+mit+Updates+auf+alte+Kitodo-AIPs">https://intranet.slub-dresden.de/display/LZA/Umgang+mit+Updates+auf+alte+Kitodo-AIPs</a></pl:description> - <pl:version>1.0</pl:version> + <pl:version>1.3</pl:version> <pl:materialType>DIGITAL</pl:materialType> <pl:module>Repository</pl:module> <pl:generalType>TASK</pl:generalType> diff --git a/src/com/exlibris/digitool/repository/ifc/IEWebServices_Service.java b/src/com/exlibris/digitool/repository/ifc/IEWebServices_Service.java new file mode 100644 index 0000000..06f2100 --- /dev/null +++ b/src/com/exlibris/digitool/repository/ifc/IEWebServices_Service.java @@ -0,0 +1,71 @@ + +package com.exlibris.digitool.repository.ifc; + +import javax.xml.namespace.QName; +import javax.xml.ws.Service; +import javax.xml.ws.WebEndpoint; +import javax.xml.ws.WebServiceClient; +import javax.xml.ws.WebServiceFeature; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.logging.Logger; + + +/** + * This class was generated by the JAX-WS RI. + * JAX-WS RI 2.1.6 in JDK 6 + * Generated source version: 2.1 + * + */ +@WebServiceClient(name = "IEWebServices", targetNamespace = "http://dps.exlibris.com/", wsdlLocation = "http://localhost:1801/dpsws/repository/IEWebServices?wsdl") +public class IEWebServices_Service + extends Service +{ + + private final static URL IEWEBSERVICES_WSDL_LOCATION; + private final static Logger logger = Logger.getLogger(com.exlibris.digitool.repository.ifc.IEWebServices_Service.class.getName()); + + static { + URL url = null; + try { + URL baseUrl; + baseUrl = com.exlibris.digitool.repository.ifc.IEWebServices_Service.class.getResource("."); + url = new URL(baseUrl, "http://localhost:1801/dpsws/repository/IEWebServices?wsdl"); + } catch (MalformedURLException e) { + logger.warning("Failed to create URL for the wsdl Location: 'http://localhost:1801/dpsws/repository/IEWebServices?wsdl', retrying as a local file"); + logger.warning(e.getMessage()); + } + IEWEBSERVICES_WSDL_LOCATION = url; + } + + public IEWebServices_Service(URL wsdlLocation, QName serviceName) { + super(wsdlLocation, serviceName); + } + + public IEWebServices_Service() { + super(IEWEBSERVICES_WSDL_LOCATION, new QName("http://dps.exlibris.com/", "IEWebServices")); + } + + /** + * + * @return + * returns IEWebServices + */ + @WebEndpoint(name = "IEWebServicesPort") + public IEWebServices getIEWebServicesPort() { + return super.getPort(new QName("http://dps.exlibris.com/", "IEWebServicesPort"), IEWebServices.class); + } + + /** + * + * @param features + * A list of {@link javax.xml.ws.WebServiceFeature} to configure on the proxy. Supported features not in the <code>features</code> parameter will have their default values. + * @return + * returns IEWebServices + */ + @WebEndpoint(name = "IEWebServicesPort") + public IEWebServices getIEWebServicesPort(WebServiceFeature... features) { + return super.getPort(new QName("http://dps.exlibris.com/", "IEWebServicesPort"), IEWebServices.class, features); + } + +} diff --git a/src/org/slub/rosetta/plugins/repositoryTask/DnxMoveFileOriginalPathDublettesClean.java b/src/org/slub/rosetta/plugins/repositoryTask/DnxMoveFileOriginalPathDublettesClean.java index e4fa1f9..bd15147 100644 --- a/src/org/slub/rosetta/plugins/repositoryTask/DnxMoveFileOriginalPathDublettesClean.java +++ b/src/org/slub/rosetta/plugins/repositoryTask/DnxMoveFileOriginalPathDublettesClean.java @@ -6,16 +6,111 @@ import com.exlibris.digitool.common.dnx.DnxDocumentHelper; import com.exlibris.digitool.exceptions.DigitoolException; import com.exlibris.digitool.repository.api.IEEditor; import com.exlibris.digitool.repository.api.RepositoryTaskPlugin; +import com.exlibris.digitool.repository.ifc.IEWebServices; +import com.exlibris.digitool.repository.ifc.IEWebServices_Service; +import com.exlibris.digitool.repository.ifc.RepresentationContent; +import com.exlibris.dps.sdk.pds.PdsClient; +import javafx.util.Pair; +import javax.xml.namespace.QName; +import javax.xml.ws.BindingProvider; +import java.net.MalformedURLException; +import java.net.URL; +import java.text.DateFormat; +import java.text.SimpleDateFormat; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.*; +import java.util.concurrent.TimeUnit; import java.util.regex.Matcher; import java.util.regex.Pattern; +import static com.exlibris.digitool.repository.ifc.RepresentationContent.Operation.REMOVE; + + public class DnxMoveFileOriginalPathDublettesClean implements RepositoryTaskPlugin { - private ExLogger log = ExLogger.getExLogger(DnxMoveFileOriginalPathDublettesClean.class); + private ExLogger log = ExLogger.getExLogger(DnxMoveFileOriginalPathDublettesClean.class); + private String institution; + private String userName; + private String password; + private String pdshostname; + private String hostname; + + private class DeleteUpdatedFilePid { + private String iePid; + private String repPid; + private String filePid; + + + DeleteUpdatedFilePid(String iePid, String repPid, String filePid) { + this.iePid = iePid; + this.repPid = repPid; + this.filePid = filePid; + } + + String getIePid() { + return this.iePid; + } + + String getrepPid() { + return this.repPid; + } + + String getfilePid() { + return this.filePid; + } + }; + + private ArrayList<DeleteUpdatedFilePid> filepids_to_delete; + private Set<String> IEPids; + private Set<String> RepPids; + + + public void doRep() throws Exception, MalformedURLException { + final String WSDL_URL = "http://" + this.hostname + ":1801/dpsws/backoffice/IEWebServices?wsdl"; + final String PDS_URL = "http://" + this.pdshostname + ":8991"; + String pdsHandle; + + // Connecting to PDS + PdsClient pds = PdsClient.getInstance(); + pds.init(PDS_URL, false); + pdsHandle = pds.login(institution, userName, password); + + for (String iePid : this.IEPids) { + for (String repPid: this.RepPids ) { +// prepare for operation + ArrayList<RepresentationContent> repcontent = new ArrayList<RepresentationContent>(); + for (DeleteUpdatedFilePid fptd : filepids_to_delete) { + if ( + (0 == fptd.getIePid().compareTo(iePid)) + && (0 ==fptd.getrepPid().compareTo(repPid)) + ) { + RepresentationContent content_entry = new RepresentationContent(); + content_entry.setOperation(REMOVE); + content_entry.setOldFilePid(fptd.getfilePid()); + repcontent.add(content_entry); + } + } + RepresentationContent[] content = repcontent.toArray(new RepresentationContent[0]); + + String submissionReason = "delete outdated and substituted file by DnxMoveFileOriginalPathDublettesClean-plugin for IE " + iePid; + + // call WebService + IEWebServices_Service service = new IEWebServices_Service( + new URL(WSDL_URL), + new QName("http://dps.exlibris.com/") + ); + IEWebServices ieWebServices = service.getPort( + new QName("http://dps.exlibris.com/", + "IEWebServicesPort"), IEWebServices.class + ); + BindingProvider ie_bindingProvider = (BindingProvider) ieWebServices; + ieWebServices.updateRepresentation(pdsHandle, iePid, repPid, submissionReason, content); + } + } + } + public DnxMoveFileOriginalPathDublettesClean() { super(); @@ -29,6 +124,7 @@ public class DnxMoveFileOriginalPathDublettesClean implements RepositoryTaskPlug public TaskResults execute(IEEditor ieEditor, Map<String, String> initParams, TaskResults taskResults) { log.info("Executing DnxMoveFileOriginalPathDublettesClean for " + ieEditor.getIEPid()); + init(initParams); boolean IEsuccess = true; int countFiles=0; @@ -41,20 +137,27 @@ public class DnxMoveFileOriginalPathDublettesClean implements RepositoryTaskPlug try { List<String> filePids = ieEditor.getFilesForRep(repPid); // for each rep pid mark all fileoriginalpaths to detect copies - Map<String, String> filePathsWithModificationDate = new HashMap<>(); + Map<String, Pair<String,Date>> filePathsWithModificationDate = new HashMap<>(); for (String filePid : filePids) { try { DnxDocumentHelper ieDnxH = ieEditor.getDnxHelper(filePid); DnxDocumentHelper.GeneralFileCharacteristics ieGfs = ieDnxH.getGeneralFileCharacteristics(); - String currentUpdateDate = ieGfs.getFileModificationDate(); + DateFormat date = new SimpleDateFormat(); + String file_mod_date = ieGfs.getInternalFileModificationDate(); + String file_cre_date = ieGfs.getInternalFileCreationDate(); + log.info( "found1 filecreationdate='" + file_cre_date + "' filemoddate='" + file_mod_date + "' for filepid=" + filePid ); + Date currentUpdateDate = date.parse( file_mod_date ); + String currentFileOriginalPath = ieGfs.getFileOriginalPath(); // workaround to check if fileOriginalPath has no "file://" because the replacement // always(!) starts with "file://" + if (currentFileOriginalPath.startsWith("file://") ) { - filePathsWithModificationDate.put(currentFileOriginalPath, currentUpdateDate); + filePathsWithModificationDate.put(currentFileOriginalPath, new Pair<String, Date>(filePid, currentUpdateDate)); } else { - filePathsWithModificationDate.put("file://" + currentFileOriginalPath, currentUpdateDate); + filePathsWithModificationDate.put("file://" + currentFileOriginalPath, new Pair<String, Date>(filePid, currentUpdateDate)); + } } catch (DigitoolException e) { IEsuccess = false; @@ -62,13 +165,16 @@ public class DnxMoveFileOriginalPathDublettesClean implements RepositoryTaskPlug log.error(err); e.printStackTrace(); taskResults.addResult(ieEditor.getIEPid(), null, false, err); + } catch (java.text.ParseException e) { + IEsuccess = false; + log.error(e.getMessage()); + taskResults.addResult(ieEditor.getIEPid(), null, false, "ModificationDate could not be parsed" + e.getMessage()); } } countFiles+= filePids.size(); // process each filePid for replace for (String filePid : filePids) { try { - if (replaceFileOriginalPath(ieEditor, repPid, filePid, filePathsWithModificationDate)) { countSuccess++; } @@ -83,6 +189,10 @@ public class DnxMoveFileOriginalPathDublettesClean implements RepositoryTaskPlug IEsuccess = false; log.error(e.getMessage()); taskResults.addResult(ieEditor.getIEPid(), null, false, e.getMessage()); + } catch (java.text.ParseException e) { + IEsuccess = false; + log.error(e.getMessage()); + taskResults.addResult(ieEditor.getIEPid(), null, false, "ModificationDate could not be parsed" + e.getMessage()); } } } catch (DigitoolException e) { @@ -127,6 +237,12 @@ public class DnxMoveFileOriginalPathDublettesClean implements RepositoryTaskPlug String err = "unknown Digitool exception: " + e; log.error( err ); e.printStackTrace(); + } + try { + TimeUnit.SECONDS.sleep(2); + doRep(); + } catch (Exception e) { + } return taskResults; } @@ -135,11 +251,17 @@ public class DnxMoveFileOriginalPathDublettesClean implements RepositoryTaskPlug /* replace file original path if it starts with "file://data/" or "/data/" */ - private boolean replaceFileOriginalPath(IEEditor ieEditor, String repPid, String filePid, Map<String, String> filePathsWithModificationDate) throws DigitoolException, FileOriginalPathCollisionException { + private boolean replaceFileOriginalPath(IEEditor ieEditor, String repPid, String filePid, Map<String, Pair<String,Date>> filePathsWithModificationDate) throws DigitoolException, FileOriginalPathCollisionException, java.text.ParseException { DnxDocumentHelper ieDnxH = ieEditor.getDnxHelper(filePid); DnxDocumentHelper.GeneralFileCharacteristics ieGfs = ieDnxH.getGeneralFileCharacteristics(); String currentFileOriginalPath = ieGfs.getFileOriginalPath(); - String currentModificationDate = ieGfs.getFileModificationDate(); + String iePid = ieEditor.getIEPid(); + DateFormat date = new SimpleDateFormat(); + String file_mod_date = ieGfs.getInternalFileModificationDate(); + String file_cre_date = ieGfs.getInternalFileCreationDate(); + log.info( "found2 filecreationdate='" + file_cre_date + "' filemoddate='" + file_mod_date + "' for filepid=" + filePid ); + + Date currentModificationDate = date.parse( file_mod_date ); String updatedFileOriginalPath = currentFileOriginalPath; /* default to current to avoid empty string */ boolean updated = false; final String replacement = "file://"; @@ -148,12 +270,34 @@ public class DnxMoveFileOriginalPathDublettesClean implements RepositoryTaskPlug /* if something is updated */ if (matcher.lookingAt()) { // update it updatedFileOriginalPath = matcher.replaceFirst( replacement ); - if (filePathsWithModificationDate.containsKey( updatedFileOriginalPath )) { - // TODO: check Date! - throw new FileOriginalPathCollisionException("update needed for IE " + ieEditor.getIEPid() + " RepPid " + repPid + " FilePid " + filePid + - " (old file_original_path='" + currentFileOriginalPath + "') to new file_original_path='" + - updatedFileOriginalPath + "', but new file_original_path already exists!" - ); + if (filePathsWithModificationDate.containsKey( updatedFileOriginalPath )) { //collision found as expected + // find file and check date + Date updatedFileModificationDate = new Date(); + String updatedFilePid = new String(); // file pid which is outdated now + for(Map.Entry<String, Pair<String, Date>> entry : filePathsWithModificationDate.entrySet()) { + if (entry.getKey() == updatedFileOriginalPath) { + updatedFilePid = entry.getValue().getKey(); + updatedFileModificationDate = entry.getValue().getValue(); + break; + } + } + // compare the two dates, if current has an update-candidate with newer modification date, throw an exception + if (currentModificationDate.before( updatedFileModificationDate )) { + throw new FileOriginalPathCollisionException( + "update needed for IE " + ieEditor.getIEPid() + " RepPid " + repPid + " FilePid " + filePid + + " (old file_original_path='" + currentFileOriginalPath + "' (modification date=" + currentModificationDate + + ") to new file_original_path='" + updatedFileOriginalPath + "' (modification date=" + updatedFileModificationDate + + " filepid=" + updatedFilePid + "), but new file_original_path already exists!" + ); + } + // mark to delete old entry + this.IEPids.add(iePid); + this.RepPids.add(repPid); + DeleteUpdatedFilePid tmp = new DeleteUpdatedFilePid(iePid, repPid, updatedFilePid); // delete outdated filepid + this.filepids_to_delete.add( tmp ); + + } else { // no collision but candidate to rename found + // Do nothing, because we set fileoriginalpath to updated version } updated = true; log.info("update needed for IE " + ieEditor.getIEPid() + " RepPid " + repPid + " FilePid " + filePid + @@ -165,8 +309,7 @@ public class DnxMoveFileOriginalPathDublettesClean implements RepositoryTaskPlug log.info("No update needed for IE " + ieEditor.getIEPid() + " RepPid " + repPid + " FilePid " + filePid + " (file_original_path='" + currentFileOriginalPath + "')"); } - // TODO: delete old entry! - ieGfs.setFileOriginalPath(updatedFileOriginalPath); + ieGfs.setFileOriginalPath(updatedFileOriginalPath); // new set of fileoriginalpath ieDnxH.setGeneralFileCharacteristics(ieGfs); ieEditor.setDnx(ieDnxH, filePid); /* necessary to commit changes on filePID */ return updated; @@ -174,8 +317,12 @@ public class DnxMoveFileOriginalPathDublettesClean implements RepositoryTaskPlug - private void init(Map<String, String> initParams) { - + private void init(Map<String, String> initp) { + this.hostname = initp.get("hostname"); + this.password = initp.get("password"); + this.institution = initp.get("institution"); + this.userName = initp.get("user"); + this.pdshostname = initp.get("pdshostname"); } public boolean isReadOnly() { -- GitLab