/* See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * Esri Inc. licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.esri.gpt.catalog.publication; import com.esri.gpt.catalog.arcims.ImsMetadataAdminDao; import com.esri.gpt.catalog.arcims.ImsServiceException; import com.esri.gpt.catalog.arcims.PutMetadataInfo; import com.esri.gpt.catalog.arcims.PutMetadataRequest; import com.esri.gpt.catalog.context.CatalogIndexException; import com.esri.gpt.catalog.management.MmdEnums; import com.esri.gpt.catalog.management.MmdEnums.ApprovalStatus; import com.esri.gpt.catalog.schema.MetadataDocument; import com.esri.gpt.catalog.schema.Schema; import com.esri.gpt.catalog.schema.SchemaException; import com.esri.gpt.catalog.schema.Schemas; import com.esri.gpt.framework.collection.StringAttributeMap; import com.esri.gpt.framework.context.RequestContext; import com.esri.gpt.framework.security.principal.Publisher; import com.esri.gpt.framework.sql.IClobMutator; import com.esri.gpt.framework.sql.ManagedConnection; import com.esri.gpt.framework.util.UuidUtil; import com.esri.gpt.framework.util.Val; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; /** * Super-class for a metadata document publication request. */ public class PublicationRequest { // class variables ============================================================= // instance variables ========================================================== private boolean _hasMetadataServer = false; private Publisher _publisher; private PublicationRecord _record = new PublicationRecord(); private RequestContext _requestContext; private boolean _updateIndex = true; // constructors ================================================================ /** Default constructor. */ public PublicationRequest() {} /** * Constructs a request to publish a metadata document. * @param requestContext the request context * @param publisher the publisher * @param sourceXml the XML content */ public PublicationRequest(RequestContext requestContext, Publisher publisher, String sourceXml) { setRequestContext(requestContext); setPublisher(publisher); getPublicationRecord().setSourceXml(sourceXml); // check for auto-approval (only applies to new records) if (requestContext != null) { StringAttributeMap params = requestContext.getCatalogConfiguration().getParameters(); String sAuto = Val.chkStr(params.getValue("publicationRequest.autoApprove")); if (sAuto.toLowerCase().equals("true")) { this.getPublicationRecord().setAutoApprove(true); } } } public boolean getUpdateIndex() { return _updateIndex; } public void setUpdateIndex(boolean _updateIndex) { this._updateIndex = _updateIndex; } // properties ================================================================== /** * Gets the configured schemas. * @return the configured schemas */ protected Schemas getConfiguredSchemas() { return getRequestContext().getCatalogConfiguration().getConfiguredSchemas(); } /** * Gets the publisher associated with the request. * @return the publisher */ public Publisher getPublisher() { return _publisher; } /** * Sets the publisher associated with the request. * @param publisher the publisher */ private void setPublisher(Publisher publisher) { _publisher = publisher; } /** * Gets the associated publication record. * @return the publication record */ public PublicationRecord getPublicationRecord() { return _record; } /** * Gets the associated request context. * @return the request context */ public RequestContext getRequestContext() { return _requestContext; } /** * Sets the associated request context. * @param requestContext the request context */ private void setRequestContext(RequestContext requestContext) { _requestContext = requestContext; } // methods ===================================================================== /** * Determines and sets the source URI for the document. * @param schema the evaluated schema for the document being published */ protected void determineSourceUri(Schema schema) { PublicationRecord rec = getPublicationRecord(); if (rec.getSourceUri().length() == 0) { String sUri = ""; if (rec.getSourceFileName().length() > 0) { boolean bUsePrefix = true; String sTmp = rec.getSourceFileName().toLowerCase(); if (sTmp.startsWith("http://") || sTmp.startsWith("https://") || sTmp.startsWith("ftp://") || sTmp.startsWith("ftps://") || sTmp.startsWith("\\\\")) { bUsePrefix = false; } if (bUsePrefix) { sUri = "userid:"+getPublisher().getLocalID()+"/"+rec.getSourceFileName(); } else { sUri = rec.getSourceFileName(); } } rec.setSourceUri(sUri); } } /** * Determines and sets the UUID for the document. * <br/>If the UUID has not been set, this step will attempt * to avoid duplication by querying the fileIdentifier and sourceUri. * If an existing record is not located, a new UUID is generated. * @param schema the evaluated schema for the document being published * @throws SQLException if a database exception occurs */ protected void determineUuid(Schema schema) throws SQLException { ImsMetadataAdminDao imsDao = null; PublicationRecord rec = getPublicationRecord(); rec.setFileIdentifier(schema.getMeaning().getFileIdentifier()); if (rec.getUuid().length() == 0) { String sEsriDocID = schema.getMeaning().getEsriDocID(); if (UuidUtil.isUuid(sEsriDocID)) { rec.setUuid(sEsriDocID); } } if (rec.getUuid().length() == 0) { if (imsDao == null) imsDao = new ImsMetadataAdminDao(getRequestContext()); String sUuid = imsDao.findExistingUuid(rec.getFileIdentifier(),null); if (sUuid.length() > 0) { rec.setUuid(sUuid); } } if (rec.getUuid().length() == 0) { String sFile = rec.getSourceFileName(); if (sFile.endsWith(".xml")) { sFile = sFile.substring(0,sFile.length()-4); if (UuidUtil.isUuid(sFile)) { rec.setUuid(sFile); } } } if (rec.getUuid().length() == 0) { if (imsDao == null) imsDao = new ImsMetadataAdminDao(getRequestContext()); String sUuid = imsDao.findExistingUuid(null,rec.getSourceUri()); if (sUuid.length()>0) { rec.setUuid(sUuid); } else if (UuidUtil.isUuid(rec.getSourceUri())) { rec.setUuid(rec.getSourceUri()); } else { sUuid = UuidUtil.makeUuid(true); rec.setUuid(sUuid); } } } /** * Reads the XML associated with a document uuid. * @param uuid the UUID for the record to read * @return the associated XML string (null if no match was found) * @throws SQLException if a database exception occurs */ private String readCurrentXml(String uuid) throws SQLException { PreparedStatement st = null; ResultSet rs = null; try { String adminTable = this.getRequestContext().getCatalogConfiguration().getResourceTableName(); String metaTable = this.getRequestContext().getCatalogConfiguration().getResourceDataTableName(); ManagedConnection mc = this.getRequestContext().getConnectionBroker().returnConnection(""); Connection con = mc.getJdbcConnection(); String sql = "SELECT DOCUUID FROM "+adminTable+" WHERE DOCUUID=?"; st = con.prepareStatement(sql); st.setString(1,uuid); rs = st.executeQuery(); if (rs.next()) { try {if (rs != null) rs.close();} catch (Exception ef) {} try {if (st != null) st.close();} catch (Exception ef) {} IClobMutator cm = mc.getClobMutator(); sql = "SELECT XML FROM "+metaTable+" WHERE DOCUUID=?"; st = con.prepareStatement(sql); st.setString(1,uuid); rs = st.executeQuery(); if (rs.next()) { return cm.get(rs,1); } } } finally { try {if (rs != null) rs.close();} catch (Exception ef) {} try {if (st != null) st.close();} catch (Exception ef) {} } return null; } /** * Queries the approval status associated with a document. * @param uuid the document UUID * @return the approval status (empty string if not found) * @throws SQLException if a database exception occurs */ private String readStatus(String uuid) throws SQLException { PreparedStatement st = null; try { String adminTable = this.getRequestContext().getCatalogConfiguration().getResourceTableName(); ManagedConnection mc = this.getRequestContext().getConnectionBroker().returnConnection(""); Connection con = mc.getJdbcConnection(); String sql = "SELECT APPROVALSTATUS FROM "+adminTable+" WHERE DOCUUID=?"; st = con.prepareStatement(sql); st.setString(1,uuid); ResultSet rs = st.executeQuery(); if (rs.next()) { return rs.getString(1); } } finally { try {if (st != null) st.close();} catch (Exception ef) {} } return null; } /** * Prepares publication record for publication. * @return schema * @throws SchemaException if record can not have associated schema * @throws SQLException if accessing database fails */ public Schema prepareForPublication() throws SchemaException, SQLException { // prepare the schema for publication, send the request MetadataDocument document = new MetadataDocument(); Schema schema = document.prepareForPublication(this); determineSourceUri(schema); determineUuid(schema); return schema; } /** * Publishes the document. * @param schema document schema * @throws ImsServiceException in an exception occurs while communication * with the ArcIMS metadata publishing service * @throws SQLException if a database exception occurs * @throws CatalogIndexException if a document indexing exception occurs */ public void publish(Schema schema) throws SQLException, ImsServiceException, CatalogIndexException { // don't update if the xml hasn't changed boolean bSend = true; String meth = Val.chkStr(this.getPublicationRecord().getPublicationMethod()); boolean isEditor = meth.equalsIgnoreCase("editor") || meth.equalsIgnoreCase("seditor"); if (!_hasMetadataServer && !isEditor && this.getPublicationRecord().getUpdateOnlyIfXmlHasChanged()) { String status = Val.chkStr(this.readStatus(getPublicationRecord().getUuid())); if (!status.equalsIgnoreCase("draft")) { String currentXml = Val.chkStr(this.readCurrentXml(getPublicationRecord().getUuid())); if (currentXml.length() > 0) { if (currentXml.equals(this.getPublicationRecord().getSourceXml())) { bSend = false; getPublicationRecord().setWasDocumentReplaced(true); getPublicationRecord().setWasDocumentUnchanged(true); } } } } if (bSend) { sendPublicationRequest(schema); } } /** * Publishes the document. * @throws SchemaException if a schems related exception occurs * @throws ImsServiceException in an exception occurs while communication * with the ArcIMS metadata publishing service * @throws SQLException if a database exception occurs * @throws CatalogIndexException if a document indexing exception occurs */ public void publish() throws SchemaException, ImsServiceException, SQLException, CatalogIndexException { Schema schema = prepareForPublication(); publish(schema); } /** * Sends the publication request to ArcIMS, updates the administration table. * @throws ImsServiceException in an exception occurs while communication * with the ArcIMS metadata publishing service * @throws SQLException if a database exception occurs * @throws CatalogIndexException if a document indexing exception occurs */ private void sendPublicationRequest(Schema schema) throws ImsServiceException, SQLException, CatalogIndexException { // prepare the ArcIMS request PutMetadataRequest imsRequest; imsRequest = new PutMetadataRequest(getRequestContext(),getPublisher()); imsRequest.setLockTitle(getPublicationRecord().getLockTitle()); PutMetadataInfo putInfo = new PutMetadataInfo(); putInfo.setUuid(getPublicationRecord().getUuid()); putInfo.setXml(getPublicationRecord().getSourceXml()); putInfo.setFileIdentifier(schema.getMeaning().getFileIdentifier()); putInfo.setName(getPublicationRecord().getAlternativeTitle().length()>0? getPublicationRecord().getAlternativeTitle(): schema.getMeaning().getTitle()); putInfo.setThumbnailBinary(schema.getMeaning().getThumbnailBinary()); //putInfo.setParentUuid(getPublisher().getFolderUuid()); //putInfo.setEnvelope(schema.getMeaning().getEnvelope()); //putInfo.setToEsriIsoXslt(schema.getToEsriXslt()); //putInfo.setContentType(schema.getMeaning().getArcIMSContentType()); //putInfo.setOnlink(schema.getMeaning().getWebsiteUrl()); //putInfo.setServer(schema.getMeaning().getResourceUrl()); //putInfo.setService(schema.getMeaning().getServiceName()); //putInfo.setServiceType(schema.getMeaning().getResourceType()); // send the request to ArcIMS, determine if the document was replaced if(this._record != null ) { this.getRequestContext().getObjectMap().put(MmdEnums.INCOMING_STATUS, this._record.getApprovalStatus()); } imsRequest.executePut(putInfo); String sReplaced = PutMetadataRequest.ACTION_STATUS_REPLACED; boolean bReplaced = imsRequest.getActionStatus().equals(sReplaced); getPublicationRecord().setWasDocumentReplaced(bReplaced); if (!bReplaced && getPublicationRecord().getAutoApprove()) { String status = Val.chkStr(getPublicationRecord().getApprovalStatus()); if (status.length() == 0) { getPublicationRecord().setApprovalStatus("approved"); } } // update the administrative table ImsMetadataAdminDao imsDao = new ImsMetadataAdminDao(getRequestContext()); imsDao.setUpdateIndex(getUpdateIndex()); imsDao.updateRecord(schema,getPublicationRecord()); } }