/* * 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.arcgis.agportal.synchronizer; import com.esri.gpt.catalog.arcgis.agportal.itemInfo.ESRI_ItemInformation; import com.esri.gpt.catalog.arcgis.agportal.publication.EndPoint; import com.esri.gpt.catalog.arcgis.agportal.publication.ItemInfoLuceneAdapter; import com.esri.gpt.catalog.arcgis.agportal.publication.PublicationRequest; import com.esri.gpt.framework.collection.StringAttributeMap; import com.esri.gpt.framework.context.RequestContext; import com.esri.gpt.framework.http.CredentialProvider; import com.esri.gpt.framework.scheduler.IScheduledTask; import com.esri.gpt.framework.sql.ManagedConnection; import com.esri.gpt.framework.util.Val; import java.io.*; import java.sql.*; import java.util.Date; import java.util.logging.Level; import java.util.logging.Logger; /** * Reverse ArcGIS portal synchronizer. * NOTE! This is EXPERIMENTAL feature. It might be removed at any time in the future. */ public class ReverseSynchronizer implements Runnable, IScheduledTask { /** class variables ========================================================= */ private static final Logger LOGGER = Logger.getLogger(ReverseSynchronizer.class.getName()); /** instance variables ====================================================== */ private StringAttributeMap parameters; /** constructors =========================================================== */ /** Default constructor. */ public ReverseSynchronizer() { } /** properties ============================================================= */ /** * Sets the configuration parameters for the task. * @param parameters the configuration parameters */ @Override public void setParameters(StringAttributeMap parameters) { this.parameters = parameters; } /** methods ================================================================= */ /** * Run the synchronization process. */ @Override public void run() { try { Timestamp ts = new Timestamp(new Date().getTime()); LOGGER.info("Starting reverse sycnhronization."); RequestContext context = RequestContext.extract(null); PublicationRequest request = createPublicationRequest(context); publishAnythingWithUrl(context, request); setLastSynchronizationDate(ts); } catch (Exception e) { LOGGER.log(Level.SEVERE, "Error in reverse synchronization.", e); } finally { LOGGER.info("Reverse sycnhronization completed."); } } private void publishAnythingWithUrl(RequestContext context, PublicationRequest request) throws SQLException { PreparedStatement st = null; ResultSet rs = null; try { StringBuilder sbSql = new StringBuilder(); sbSql.append("SELECT DOCUUID, HOST_URL FROM "); sbSql.append(getResourceTableName(context)); sbSql.append(" WHERE HOST_URL IS NOT NULL AND (APPROVALSTATUS='approved' OR APPROVALSTATUS='reviewed') "); sbSql.append(" AND UPDATEDATE >= ?"); ManagedConnection mc = context.getConnectionBroker().returnConnection(""); Connection con = mc.getJdbcConnection(); st = con.prepareStatement(sbSql.toString()); st.setTimestamp(1, getLastSynchronizationDate()); rs = st.executeQuery(); while (rs.next()) { String hostUrl = rs.getString("HOST_URL"); if (assertHostUrl(hostUrl)) { String docuuid = rs.getString("DOCUUID"); publishUuid(context, request, docuuid); } } } finally { SQLclose(rs); SQLclose(st); } } private void SQLclose(ResultSet rs) { if (rs != null) { try { rs.close(); } catch (SQLException ex) { } } } private void SQLclose(Statement st) { if (st != null) { try { st.close(); } catch (SQLException ex) { } } } private String getDateStore() { return getParameter("datestore"); } private void publishUuid(RequestContext context, PublicationRequest request, String uuid) { try { ItemInfoLuceneAdapter iiAdapter = new ItemInfoLuceneAdapter(); ESRI_ItemInformation ii = iiAdapter.makeItemInfoByUuid(context, null, uuid); if (ii != null) { request.publish(ii); LOGGER.log(Level.FINE, "Record: {0} has been published.", uuid); } } catch (Exception ex) { LOGGER.log(Level.SEVERE, "Record: {0} has NOT been published. {1}", new Object[]{uuid, ex.getMessage()}); } } /** * Gets resource table name. * @param context request context * @return resource table name */ private String getResourceTableName(RequestContext context) { return context.getApplicationConfiguration().getCatalogConfiguration().getResourceTableName(); } /** * Creates publication request. * @param context request context * @return publication request * @throws Exception if creating publication request fails */ private PublicationRequest createPublicationRequest(RequestContext context) throws Exception { return new PublicationRequest(context, EndPoint.extract(context), getCredentialProvider(), getParameter("referer")); } /** * Gets last synchronization date. * @return last synchronization date */ private Timestamp getLastSynchronizationDate() { File file = new File(getDateStore()); if (file.exists()) { FileInputStream fis = null; ObjectInputStream is = null; try { fis = new FileInputStream(file); is = new ObjectInputStream(fis); Timestamp ts = (Timestamp) is.readObject(); return ts; } catch (Exception ex) { } finally { if (is != null) { try { is.close(); } catch (IOException e) { } } if (fis != null) { try { fis.close(); } catch (IOException e) { } } } } return new Timestamp(0); } /** * Sets last synchronization date. * @param ts last synchronization date */ private void setLastSynchronizationDate(Timestamp ts) { File file = new File(getDateStore()); FileOutputStream fis = null; ObjectOutputStream is = null; try { fis = new FileOutputStream(file); is = new ObjectOutputStream(fis); is.writeObject(ts); } catch (Exception ex) { } finally { if (is != null) { try { is.close(); } catch (IOException e) { } } if (fis != null) { try { fis.close(); } catch (IOException e) { } } } } /** * Creates credential provider. * Credential provider is created based on the following thread parameters: * "username", and "password. * @return credential provider. */ private CredentialProvider getCredentialProvider() { String username = getParameter("username"); String password = getParameter("password"); if (username.length() > 0 && password.length() > 0) { return new CredentialProvider(username, password); } return null; } /** * Gets thread parameter. * @param name parameter name * @return parameter value */ private String getParameter(String name) { return parameters != null ? Val.chkStr(parameters.getValue(name)) : ""; } /** * Checks if given URL has a chance to be published in ArcGIS portal * @param hostUrl url * @return <code>true</code> if url has a chance to be published in ArcGIS portal */ private boolean assertHostUrl(String hostUrl) { hostUrl = Val.chkStr(hostUrl); if (hostUrl.contains(".mpk") || hostUrl.contains(".eaz") || hostUrl.contains(".nmf") || hostUrl.contains(".esriaddin") || hostUrl.contains(".lpk") || hostUrl.contains(".zip") || hostUrl.contains(".ncfg") || hostUrl.contains(".wmpk") || (hostUrl.contains("/rest/services/") /*&& hostUrl.endsWith("Server")*/)) { return true; } return false; } }