/* Copyright 2004-2014 Jim Voris * * Licensed 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.qumasoft.guitools.qwin.operation; import com.qumasoft.guitools.qwin.QWinFrame; import com.qumasoft.guitools.qwin.QWinUtility; import com.qumasoft.guitools.qwin.dialog.CheckInDialog; import com.qumasoft.guitools.qwin.dialog.ProgressDialog; import com.qumasoft.qvcslib.ArchiveAttributes; import com.qumasoft.qvcslib.ArchiveDirManagerInterface; import com.qumasoft.qvcslib.ArchiveDirManagerProxy; import com.qumasoft.qvcslib.CheckOutCommentManager; import com.qumasoft.qvcslib.ClientTransactionManager; import com.qumasoft.qvcslib.KeywordExpansionContext; import com.qumasoft.qvcslib.KeywordManagerFactory; import com.qumasoft.qvcslib.KeywordManagerInterface; import com.qumasoft.qvcslib.MergedInfoInterface; import com.qumasoft.qvcslib.QVCSConstants; import com.qumasoft.qvcslib.QVCSException; import com.qumasoft.qvcslib.TransportProxyInterface; import com.qumasoft.qvcslib.UserLocationProperties; import com.qumasoft.qvcslib.Utility; import com.qumasoft.qvcslib.commandargs.CheckInCommandArgs; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.Date; import java.util.List; import java.util.concurrent.atomic.AtomicReference; import java.util.logging.Level; import javax.swing.JOptionPane; import javax.swing.JTable; import javax.swing.SwingUtilities; /** * Check in a new revision. * @author Jim Voris */ public class OperationCheckInArchive extends OperationBaseClass { /** * Create a checkin archive operation. * @param fileTable the file table. * @param serverName the server name. * @param projectName the project name. * @param viewName the view name. * @param userLocationProperties user location properties. */ public OperationCheckInArchive(JTable fileTable, final String serverName, final String projectName, final String viewName, UserLocationProperties userLocationProperties) { super(fileTable, serverName, projectName, viewName, userLocationProperties); } @Override public void executeOperation() { if (getFileTable() != null) { try { List<MergedInfoInterface> mergedInfoArray = getSelectedFiles(); if (mergedInfoArray.size() > 0) { // Make sure that none of the non-binary files require a merge... for (MergedInfoInterface mergedInfo : mergedInfoArray) { if ((mergedInfo.getStatusIndex() == MergedInfoInterface.MERGE_REQUIRED_STATUS_INDEX) && (!mergedInfo.getAttributes().getIsBinaryfile())) { final String message = String.format("You must merge your changes to [%s] before checkin!", mergedInfo.getShortWorkfileName()); Runnable later = new Runnable() { @Override public void run() { JOptionPane.showConfirmDialog(QWinFrame.getQWinFrame(), message, "Merge Required!", JOptionPane.PLAIN_MESSAGE); } }; SwingUtilities.invokeLater(later); return; } } CheckInDialog checkInDialog = new CheckInDialog(QWinFrame.getQWinFrame(), mergedInfoArray, QWinFrame.getQWinFrame().getCheckinComments(), false, this); checkInDialog.setVisible(true); } } catch (Exception e) { QWinUtility.logProblem(Level.WARNING, "Caught exception in operationCheckIn: " + e.getClass().toString() + ": " + e.getLocalizedMessage()); QWinUtility.logProblem(Level.WARNING, Utility.expandStackTraceToString(e)); } } } /** * Process the dialog choices. * @param mergedInfoArray the array of files to operate on. * @param checkIn the dialog from which we may get additional information. */ public void processDialogResult(final List<MergedInfoInterface> mergedInfoArray, final CheckInDialog checkIn) { // Display the progress dialog. final ProgressDialog progressMonitor = createProgressDialog("Checking in revisions to QVCS Archive", mergedInfoArray.size()); Runnable worker = new Runnable() { @Override public void run() { TransportProxyInterface transportProxy = null; int transactionID = 0; try { int size = mergedInfoArray.size(); KeywordManagerInterface keywordManager = KeywordManagerFactory.getInstance().getNewKeywordManager(); for (int i = 0; i < size; i++) { if (progressMonitor.getIsCancelled()) { break; } MergedInfoInterface mergedInfo = mergedInfoArray.get(i); if (i == 0) { ArchiveDirManagerInterface archiveDirManager = mergedInfo.getArchiveDirManager(); ArchiveDirManagerProxy archiveDirManagerProxy = (ArchiveDirManagerProxy) archiveDirManager; transportProxy = archiveDirManagerProxy.getTransportProxy(); transactionID = ClientTransactionManager.getInstance().sendBeginTransaction(transportProxy); } // Don't bother unless we have an archive file. if (mergedInfo.getArchiveInfo() == null) { continue; } // Don't bother if the file is obsolete. if (mergedInfo.getIsObsolete()) { continue; } // Do not request a checkin if the file is in the cemetery. String appendedPath = mergedInfo.getArchiveDirManager().getAppendedPath(); if (0 == appendedPath.compareTo(QVCSConstants.QVCS_CEMETERY_DIRECTORY)) { QWinUtility.logProblem(Level.INFO, "Checkin request for cemetery file ignored for [" + mergedInfo.getShortWorkfileName() + "]"); continue; } // Do not request a checkin if the file is in the branch archive directory. if (0 == appendedPath.compareTo(QVCSConstants.QVCS_BRANCH_ARCHIVES_DIRECTORY)) { QWinUtility.logProblem(Level.INFO, "Checkin request for branch archive directory file ignored for [" + mergedInfo.getShortWorkfileName() + "]"); continue; } // Update the progress monitor. OperationBaseClass.updateProgressDialog(i, "Checking in: [" + mergedInfo.getArchiveInfo().getShortWorkfileName() + "]", progressMonitor); String shortWorkfilename = mergedInfo.getShortWorkfileName(); String fullWorkfileName = mergedInfo.getWorkfileInfo().getFullWorkfileName(); // The command args CheckInCommandArgs commandArgs = new CheckInCommandArgs(); commandArgs.setUserName(mergedInfo.getUserName()); String lockedRevision; if (mergedInfo.getAttributes().getIsCheckLock()) { lockedRevision = mergedInfo.getLockedRevisionString(mergedInfo.getUserName()); if (lockedRevision == null) { throw new QVCSException("User [" + mergedInfo.getUserName() + "] has no revisions locked for [" + shortWorkfilename + "]"); } commandArgs.setLockedRevisionString(lockedRevision); } else { commandArgs.setLockedRevisionString(mergedInfo.getArchiveInfo().getDefaultRevisionString()); } if (checkIn.getChangesDescription().length() > 0) { commandArgs.setCheckInComment(checkIn.getChangesDescription()); } else { if (CheckOutCommentManager.getInstance().commentExists(mergedInfo)) { commandArgs.setCheckInComment(CheckOutCommentManager.getInstance().lookupComment(mergedInfo)); } else { commandArgs.setCheckInComment("No Comment"); } } // Create a File associated with the File we check in File checkInFile = mergedInfo.getWorkfile(); // If the user defined an alternate checkin file, we need // to use that instead... if ((mergedInfoArray.size() == 1) && (checkIn.getWorkfileLocation().length() > 0)) { checkInFile = new File(checkIn.getWorkfileLocation()); } commandArgs.setInputfileTimeStamp(new Date(checkInFile.lastModified())); commandArgs.setFullWorkfileName(mergedInfo.getFullWorkfileName()); commandArgs.setShortWorkfileName(mergedInfo.getShortWorkfileName()); // Set flags; commandArgs.setLockFlag(checkIn.getLockFlag()); commandArgs.setForceBranchFlag(checkIn.getForceBranchFlag()); commandArgs.setApplyLabelFlag(checkIn.getApplyLabelFlag()); commandArgs.setFloatLabelFlag(checkIn.getFloatLabelFlag()); commandArgs.setReuseLabelFlag(checkIn.getReUseLabelFlag()); commandArgs.setCreateNewRevisionIfEqual(checkIn.getCreateNewRevisionIfEqual()); commandArgs.setNoExpandKeywordsFlag(checkIn.getNoExpandKeywordsFlag()); commandArgs.setProtectWorkfileFlag(checkIn.getProtectWorkfileFlag()); // Set some other values commandArgs.setLabel(checkIn.getLabelString()); commandArgs.setProjectName(getProjectName()); // Contract keywords if needed. String checkInFilename = contractKeywords(checkInFile, mergedInfo, commandArgs, keywordManager); // The checkInFilename will be null if we are not able to read it. if (checkInFilename != null) { if (mergedInfo.checkInRevision(commandArgs, checkInFilename, false)) { // This is where I would log the success to the status pane. QWinUtility.logProblem(Level.INFO, "Sent request to check in: [" + fullWorkfileName + "] to server."); // Remove any checkout comment. if (CheckOutCommentManager.getInstance().commentExists(mergedInfo)) { CheckOutCommentManager.getInstance().removeComment(mergedInfo); } } } } } catch (QVCSException e) { QWinUtility.logProblem(Level.WARNING, "Caught exception in operationCheckIn: " + e.getClass().toString() + ": " + e.getLocalizedMessage()); QWinUtility.logProblem(Level.WARNING, Utility.expandStackTraceToString(e)); } finally { progressMonitor.close(); ClientTransactionManager.getInstance().sendEndTransaction(transportProxy, transactionID); } } }; // Put all this on a separate worker thread. new Thread(worker).start(); } private String contractKeywords(File checkInFile, MergedInfoInterface mergedInfo, CheckInCommandArgs commandArgs, KeywordManagerInterface keywordManager) { String returnFilename = null; try { returnFilename = checkInFile.getCanonicalPath(); ArchiveAttributes attributes = mergedInfo.getAttributes(); if (attributes.getIsExpandKeywords()) { FileInputStream inStream = null; FileOutputStream outStream = null; try { if (checkInFile.canWrite()) { // We need to contract keywords before creating the new revision. inStream = new FileInputStream(checkInFile); File contractedOutputFile = File.createTempFile("QVCS", "tmp"); contractedOutputFile.deleteOnExit(); outStream = new FileOutputStream(contractedOutputFile); returnFilename = contractedOutputFile.getCanonicalPath(); KeywordExpansionContext keywordExpansionContext = new KeywordExpansionContext(outStream, contractedOutputFile, mergedInfo.getArchiveInfo().getLogfileInfo(), 0, "", "", mergedInfo.getArchiveDirManager().getProjectProperties()); if (attributes.getIsBinaryfile()) { keywordExpansionContext.setBinaryFileFlag(true); keywordManager.expandKeywords(inStream, keywordExpansionContext); } else { keywordExpansionContext.setBinaryFileFlag(false); AtomicReference<String> checkInComment = new AtomicReference<>(); keywordManager.contractKeywords(inStream, outStream, checkInComment, mergedInfo.getArchiveDirManager().getProjectProperties(), false); // Snag any contractions of the Comment keyword. if (checkInComment.get() != null) { String newComment = commandArgs.getCheckInComment() + "; " + checkInComment.get(); commandArgs.setCheckInComment(newComment); } } } else { QWinUtility.logProblem(Level.WARNING, "Cannot write '" + returnFilename + "' to expand keywords. Checkin failed."); returnFilename = null; } } catch (QVCSException | IOException e) { QWinUtility.logProblem(Level.WARNING, e.getLocalizedMessage()); returnFilename = null; } finally { try { if (inStream != null) { inStream.close(); } if (outStream != null) { outStream.close(); } } catch (IOException e) { QWinUtility.logProblem(Level.WARNING, e.getLocalizedMessage()); } } } else { if (!checkInFile.canRead()) { QWinUtility.logProblem(Level.WARNING, "Cannot read [" + returnFilename + "]. Checkin failed."); returnFilename = null; } } } catch (IOException e) { QWinUtility.logProblem(Level.WARNING, e.getLocalizedMessage()); } return returnFilename; } }