/* $File: //guest/paul_krause/perforce/integrations/jdev/src/com/perforce/jdev/P4File.java $ * Copyright 2000-2002 SoundBite Corporation. All Rights Reserved. */ package com.perforce.jdev; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.rmi.RemoteException; import javax.swing.Icon; import oracle.ide.model.Document; import oracle.ide.scm.SCMFile; import oracle.ide.scm.SCMFileStatus; import oracle.ide.scm.SCMOptions; import oracle.ide.scm.SCMSystem; import oracle.ide.scm.env.SCMFileFactory; import oracle.ide.scm.error.SCMException; import oracle.ide.scm.error.SCMFileSystemException; import com.perforce.api.Branch; import com.perforce.api.Change; import com.perforce.api.Env; import com.perforce.api.FileEntry; import com.perforce.api.PerforceException; import com.perforce.api.SourceControlObject; import com.perforce.jdev.res.Icons; import com.perforce.jdev.res.Overlays; import com.perforce.api.P4Process; /** * Describe class <code>P4File</code> here. * * @author <a href="mailto:PKrause@PKRAUSE"></a> * @version 1.0 */ public class P4File extends P4Node implements Document, Icons { /** Line seperator. */ public static final String NL = System.getProperty("line.seperator", "\n"); /** File's depot entry. */ private final FileEntry p4Entry; /** Lock info for locked files; is null for other files. */ private P4Lock writeLock = null; private static SCMFile createSCMFile (FileEntry fe) { final SCMFileFactory util = SCMSystem.getEnvironment().getFileFactory(); return util.createFile(fe.getClientPath()); } /** * Constructs the model for a depot entry. * * @param fe a depot <code>FileEntry</code> */ public P4File(FileEntry fe) { super(createSCMFile(fe), fe); p4Entry = fe; } /** * Constructs the model for the depot entry implied by a file and * environment. * * @param f an <code>SCMFile</code> * @param env an <code>Env</code> value */ public P4File(SCMFile f, Env env) { this(f, new FileEntry(env, f.getPath())); } /** * Creates a new <code>P4File</code> from an existing depot entry. * * @param f a <code>SCMFile</code> value * @param fe a <code>FileEntry</code> value */ public P4File(SCMFile f, FileEntry fe) { super(f, fe); p4Entry = fe; } /** * Gets the depot entry for use be superclass. * * @return a <code>FileEntry</code> object */ protected SourceControlObject getP4Object() { return p4Entry; } /** * Gets the value of the resolved property * * @return The Resolved value */ boolean isCurrent() { return p4Entry.getHeadRev() == p4Entry.getHaveRev(); } /** * Gets the value of the open for action property * * @param action add, edit, delete, etc. * @return true if open */ boolean isOpenFor(String action) { return action.equals(p4Entry.getAction()); } /** * Gets the value of the locked property * * @return The Locked value */ boolean isLocked() { return writeLock != null; } /** * Description of the Method * * @return Description of the Returned Value */ Change defaultChange() { return Change.getChange(p4Entry.getEnv(), p4Entry.getChange(), false); } /** * Description of the Method * * @param opts <code>SCMOptions</code> command options * @exception SCMException if an I/O error occurs while opening file */ void openForEdit(SCMOptions opts) throws SCMException { try { final boolean force = getBooleanOption(opts, "force", false); final boolean lock = getBooleanOption(opts, "lock", false); p4Entry.openForEdit(force, lock); refreshOverlay(); } catch (IOException e) { throw new SCMException("Perforce Exception", e); } catch (PerforceException e) { throw new SCMException("Perforce Exception", e); } } /** * Locks the depot file. Others users are prevented from submitting * updates to a file when it is locked. * * @exception SCMException if not open * @exception IOException if unable to lock * @exception PerforceException if unable to sync */ void lock() throws SCMException, IOException, PerforceException { if (!isOpen()) { final String msg = "File must be open before it can be locked"; throw new SCMFileSystemException(msg); } p4Entry.obtainLock(); writeLock = new P4Lock(this); refreshOverlay(); } void openForAdd() throws SCMException { try { p4Entry.openForAdd(); refreshOverlay(); } catch (IOException e) { final String msg = "Unable to add {0}"; throw new SCMException(msg, new Object[] { p4Entry }, e); } catch (PerforceException e) { final String msg = "Unable to add {0}"; throw new SCMException(msg, new Object[] { p4Entry }, e); } } void openForAdd(SCMOptions opts) throws SCMException { if (opts == null) { openForAdd(); } else { openForAdd(getChange(opts)); } } void openForAdd(Change c) throws SCMException { try { FileEntry.openForAdd(p4Entry.getEnv(), p4Entry.getClientPath(), c); refreshOverlay(); } catch (IOException e){ final String msg = "Unable to add {0} to {1}"; throw new SCMException(msg, new Object[] { p4Entry, c }, e); } catch (PerforceException e){ final String msg = "Unable to add {0} to {1}"; throw new SCMException(msg, new Object[] { p4Entry, c }, e); } } Change getChange() { return Change.getChange(p4Entry.getEnv(), p4Entry.getChange(), false); } Change getChange(SCMOptions opts) { final Object ch = opts.getOption(this, "change"); if (ch == null) return getChange(); if (ch instanceof Change) return (Change) ch; if (ch instanceof Integer) { final int n = ((Integer) ch).intValue(); return Change.getChange(p4Entry.getEnv(), n, true); } return Change.getChange(p4Entry.getEnv(), ch.toString(), false); } /** * Prepare to delete this file. * * @exception IOException if unable to delete * @exception PerforceException if unable to sync */ void openForDelete() throws IOException, PerforceException { p4Entry.openForDelete(); refreshOverlay(); } /** * Description of the Method * * @param force Description of Parameter * @param lock Description of Parameter * @param x Description of Parameter * @exception IOException if unable to delete * @exception PerforceException if unable to sync */ void openForDelete(boolean force, boolean lock, Change x) throws IOException, PerforceException { p4Entry.openForDelete(force, lock, x); refreshOverlay(); } void integrate(SCMFile targ, Change ch) throws SCMException { try { final Env env = p4Entry.getEnv(); final StringBuffer sb = new StringBuffer(); Branch.integrate(env, getPath(), targ.getPath(), sb, ch); if (sb.length() != 0) P4Client.getLog().write(sb.toString()); } catch (PerforceException e) { throw new SCMException(e.getMessage(), e); } } /** * Gets the value of the overlay icon property * * @return The OverlayIcon value */ public Icon getOverlayIcon() { if (!isControlled()) { return null; } if (isLocked()) { return Overlays.LOCKED; } if (!isOpen()) { if (!isCurrent()) { return Overlays.NEEDUPDATE; } return Overlays.UPTODATE; } final String act = p4Entry.getAction(); switch (act.charAt(0)) { case 'a': // add return Overlays.ADDED; case 'd': // delete return Overlays.REMOVED; case 'e': // edit if (!isCurrent()) { return Overlays.CONFLICTS; } return Overlays.OPEN; default: // unknown return null; } } /** * Gets the latest value of the status property. * Refresh if last update was less than 10 seconds ago. * * @return The LatestStatus value * @exception SCMException not thrown */ public SCMFileStatus getLatestStatus() throws SCMException { if (isControlled()) { final long age = System.currentTimeMillis() - p4Entry.getUpdateTime(); if (age > 10000L) { p4Entry.sync(); hasSynced = true; } } return this; } /** * Gets a string descrbing this SCMStatus for debugging. * * @return a debugging <code>String</code> */ public String getString() { if (!isControlled()) { return "not controlled"; } if (isLocked()) { return "locked"; } if (!isOpen()) { if (!isCurrent()) { return "need update"; } return "uptodate"; } final String act = p4Entry.getAction(); switch (act.charAt(0)) { case 'a': return "added"; case 'd': return "removed"; case 'e': if (!isCurrent()) { return "has conflicts"; } return "open"; default: return "status unknown"; } } /** * Gets text for ToolTip. * * @return a <code>String</code> value */ public String getToolTipText() { return p4Entry.getDepotPath() + "#" + p4Entry.getHaveRev() + " " + getString(); } /** * Gets the value of the path property * * @return The Path value */ public String getPath() { return p4Entry.getClientPath(); } private boolean hasSynced = false; /** * Asks whether this file is in the depot. * * @return The Controlled verdict */ public boolean isControlled() { if (p4Entry.getDepotPath() != null) return true; if (hasSynced) return false; p4Entry.sync(); hasSynced = true; return (p4Entry.getDepotPath() != null); } /** * Asks whether this file is versioned. * * @return The Versioned verdict */ public boolean isVersioned() { return p4Entry.getHeadRev() != 0; } /** * Asks whether this file is open. * * @return The Open verdict */ public boolean isOpen() { return p4Entry.getAction().length() != 0; } /** * Gets an input stream for this Document. * * @return The InputStream value * @exception IOException if there is an I/O error */ public InputStream getInputStream() throws IOException { final String content = p4Entry.getFileContents(p4Entry.getEnv(), getPath()); return new ByteArrayInputStream(content.getBytes()); } /** * Opens (a new revision of) the Document. * * @exception IOException if an I/O error occurs */ public void open() throws IOException{ try { p4Entry.openForEdit(); refreshOverlay(); } catch (PerforceException e) { throw new RemoteException("Can't open", e); } } public String diff(SCMOptions opts) throws IOException { final P4Process p = new P4Process(p4Entry.getEnv()); try { p.exec(new String[] {"p4", "diff", getPath()}); final StringBuffer sb = new StringBuffer(1024); for (String line = p.readLine(); line != null; line = p.readLine()) { sb.append(line).append(NL); } return sb.toString(); } finally { p.outClose(); } } /** * Closes -- without saving? -- (the current revsion of) the Document * * @exception IOException if an I/O error occurs */ public void close() throws IOException { p4Entry.revertFile(); } public int getCategory() { throw new UnsupportedOperationException(); } }
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#8 | 2218 | Paul Krause | add a (not very good) diff | ||
#7 | 2213 | Paul Krause | support multiple connections - no wizard yet, need to edit Connections.xml by hand | ||
#6 | 2112 | Paul Krause |
jdev 903 API changes - SCMUtilitySet.createFile replaced with SCMFileFactory.createFile - addCategory(Class) replaced with addCateogry(Class[]) - SCMAsserter.fail replaced with SCMAssert.fail() - SCMPropertyCustomizer added validateProperties |
||
#5 | 2076 | Paul Krause | jdev 9.0.2 baseline (upgrading to jdev 9.0.3) | ||
#4 | 1901 | Paul Krause | add support for delete command | ||
#3 | 1777 | Paul Krause |
Getting closer - add wrappers for projects and workspaces. - sync each workspace once to prep file entries - fix constructor and isVersioned in FileEntry |
||
#2 | 1721 | Paul Krause | using modified p4package, use getAction instead of getHeadAction | ||
#1 | 1716 | Paul Krause | first cut at a jdev integration |