/* * Copyright 2009 Perforce Software Inc., All Rights Reserved. */ package com.perforce.p4java.impl.mapbased.rpc.sys; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.nio.channels.FileChannel; import com.perforce.p4java.Log; import com.perforce.p4java.exception.NullPointerError; import com.perforce.p4java.impl.generic.client.ClientLineEnding; import com.perforce.p4java.impl.generic.sys.ISystemFileCommandsHelper; import com.perforce.p4java.impl.mapbased.rpc.sys.helper.SysFileHelperBridge; /** * Encapsulates and implements a lot of Perforce-specific information * and operations on Perforce client-side files by extending the basic * java.io.File class with Perforce-specific fields and methods. * * */ public class RpcPerforceFile extends File { public static String TRACE_PREFIX = "RpcPerforceFile"; public static String systemTmpDirName = null; public static final String TMP_FILE_PFX = "p4j"; public static final String TMP_FILE_SFX = ".tmp"; private static final long serialVersionUID = 1L; private RpcPerforceFileType fileType = null; private ClientLineEnding lineEnding = null; public static String createTempFileName(String tmpDirName) { // Kinda cheating, really... File tmpDir = null; try { if (tmpDirName != null) { tmpDir = new File(tmpDirName); } File tmpFile = File.createTempFile(TMP_FILE_PFX, TMP_FILE_SFX, tmpDir); return tmpFile.getPath(); } catch (IOException ioexc) { Log.error( "Unable to create temporary file: " + ioexc.getLocalizedMessage()); } return null; } public RpcPerforceFile(String fileName, String fileTypeStr) { super(fileName); if (fileName == null) { // We don't need or want (much less expect) null paths in the API: throw new NullPointerError( "Null file name passed to RpcPerforceFile constructor"); } this.fileType = RpcPerforceFileType.decodeFromServerString(fileTypeStr); this.lineEnding = ClientLineEnding.decodeFromServerString( fileTypeStr, this.fileType); } public RpcPerforceFile(String fileName, RpcPerforceFileType fileType) { super(fileName); if (fileName == null) { // We don't need or want (much less expect) null paths in the API: throw new NullPointerError( "Null file name passed to RpcPerforceFile constructor"); } this.fileType = fileType; this.lineEnding = ClientLineEnding.FST_L_LOCAL; } /** * Our "special" version of rename, intended to cope with the * cases when the normal rename won't work (typically cross-device * renames) or when we need to do some under-the-covers stitching * up (for example, GKZIP stream decoding). */ public boolean renameTo(File targetFile) { return renameTo(targetFile, false); } /** * Another special version of renameTo to support RPC implementation- * specific needs. This one allows callers to specify whether to * always copy as-is (no munging). */ public boolean renameTo(File targetFile, boolean alwaysCopyUnMunged) { if (targetFile == null) { throw new NullPointerError( "Null target file in RpcPerforceFile.renameTo"); } try { if ((this.fileType == null) || alwaysCopyUnMunged || canCopyAsIs()) { if (super.renameTo(targetFile)) { return true; } else { return copyTo(targetFile); } } else { // !canCopyAsIs... return decodeTo(targetFile); } } catch (IOException ioexc) { Log.error("Unexpected problem with renaming / copying file '" + targetFile.getName() + "': " + ioexc.getLocalizedMessage()); Log.exception(ioexc); return false; } } private boolean setWritable(String filePath) { boolean writable = false; ISystemFileCommandsHelper helper = SysFileHelperBridge.getSysFileCommands(); if( helper != null) { writable = helper.setWritable(filePath, true); } return writable; } /** * Copy this file to another (target file). Assumes no * decoding necessary. If the target file exists, * it's removed before copying. */ public boolean copyTo(File targetFile) throws IOException { if (targetFile == null) { throw new NullPointerError( "Null target file in RpcPerforceFile.copyTo"); } if (targetFile.exists()) { if (!targetFile.delete()) { // Attempt to make the file writable if it isn't deleted, // continue even if it fails as an exception will be thrown by // the output stream if (!targetFile.canWrite()) { if(setWritable(targetFile.getAbsolutePath())) { targetFile.delete(); } } //Warn if file still exists if (targetFile.exists()) { // FIXME: cope better with delete fail -- HR. Log .warn("Unable to delete target file for copy in RpcPerforceFile.copyTo; target: '" + targetFile.getPath()); } } } FileInputStream inStream = null; FileOutputStream outStream = null; FileChannel sourceChannel = null; FileChannel targetChannel = null; try { long bytesTransferred = 0; inStream = new FileInputStream(this); outStream = new FileOutputStream(targetFile); sourceChannel = inStream.getChannel(); targetChannel = outStream.getChannel(); if ((sourceChannel != null) && (targetChannel != null)) { // Light fuse, stand back... bytesTransferred = sourceChannel.transferTo( 0, sourceChannel.size(), targetChannel); if (bytesTransferred != sourceChannel.size()) { Log.error("channel copy for copyTo operation failed with fewer bytes" + " transferred than expected; expected: " + sourceChannel.size() + "; saw: " + bytesTransferred); return false; // FIXME: clean up... } return true; } } finally { try { if (sourceChannel != null) sourceChannel.close(); } catch (Exception exc) { Log.warn("source channel file close error in RpcPerforceFile.copyTo(): " + exc.getLocalizedMessage()); Log.exception(exc); } try{ if (targetChannel != null) targetChannel.close(); } catch (Exception exc) { Log.warn("target channel file close error in RpcPerforceFile.copyTo(): " + exc.getLocalizedMessage()); Log.exception(exc); } try { if (inStream != null) inStream.close(); } catch (Exception exc) { Log.warn("instream file close error in RpcPerforceFile.copyTo(): " + exc.getLocalizedMessage()); Log.exception(exc); } try { if (outStream != null) outStream.close(); } catch (Exception exc) { Log.warn("outstream file close error in RpcPerforceFile.copyTo(): " + exc.getLocalizedMessage()); Log.exception(exc); } } return false; } public boolean decodeTo(File targetFile) throws IOException { if (targetFile == null) { throw new NullPointerError( "Null target file in RpcPerforceFile.decodeTo"); } return copyTo(targetFile); } public RpcPerforceFileType getFileType() { return this.fileType; } public void setFileType(RpcPerforceFileType fileType) { this.fileType = fileType; } public ClientLineEnding getLineEnding() { return lineEnding; } public void setLineEnding(ClientLineEnding lineEnding) { this.lineEnding = lineEnding; } /** * True IFF we should be able to copy this file as-is, i.e. without * GKZIP decoding or munging, etc. Currently all file types can * be copied as-is, but this wasn't always true and may not always * be true... */ public boolean canCopyAsIs() { return true; } /** * @see java.io.File#equals() */ @Override public boolean equals(Object obj) { if ((obj != null) && (obj instanceof RpcPerforceFile)) { if ((super.equals((File)obj)) && (((RpcPerforceFile)obj).getFileType() == this.fileType) && (((RpcPerforceFile)obj).getLineEnding() == this.lineEnding)) { return true; } } return false; } /** * @see java.io.File#hashCode() */ @Override public int hashCode() { return super.hashCode(); } }
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#1 | 19903 | stuartrowe |
Branching //guest/perforce_software/p4java/... to //guest/stuartrowe/p4java/... |
||
//guest/perforce_software/p4java/r14.1/src/main/java/com/perforce/p4java/impl/mapbased/rpc/sys/RpcPerforceFile.java | |||||
#1 | 12541 | Matt Attaway | Initial add of the 14.1 p4java source code |