/***************************************************************************** * All public interface based on Starteam API are a property of Borland, * those interface are reproduced here only for testing purpose. You should * never use those interface to create a competitive product to the Starteam * Server. * * The implementation is given AS-IS and should not be considered a reference * to the API. The behavior on a lots of method and class will not be the * same as the real API. The reproduction only seek to mimic some basic * operation. You will not found anything here that can be deduced by using * the real API. * * Fake-Starteam is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *****************************************************************************/ package com.starbase.starteam; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.util.List; import java.util.Properties; import org.ossnoize.fakestarteam.FileUtility; import org.ossnoize.fakestarteam.InternalPropertiesProvider; import org.ossnoize.fakestarteam.SimpleTypedResourceIDProvider; import org.ossnoize.fakestarteam.exception.InvalidOperationException; import com.starbase.util.OLEDate; public class Item extends SimpleTypedResource implements ISecurableObject { public static interface LockType { public static final int UNLOCKED = 0; public static final int EXCLUSIVE = 1; public static final int NONEXCLUSIVE = 2; public static final int BREAK_FLAG = 16; public static final int UNCHANGED = 3; } protected static final PropertyNames propertyKeys = new PropertyNames(); protected static final PropertyEnums propertyEnums = new PropertyEnums(); protected static final String FOLDER_PROPERTIES = "folder.properties"; protected static final String FILE_PROPERTIES = "file.properties"; protected boolean isNew; protected boolean isFromHistory; protected Properties itemProperties; protected File holdingPlace; protected View view; protected Folder parent; protected Item() { } public String getComment() { return itemProperties.getProperty(propertyKeys.COMMENT); } public void setComment(String comment) { itemProperties.setProperty(propertyKeys.COMMENT, comment); } public int getRevisionNumber() { if(itemProperties.containsKey(propertyKeys.REVISION_NUMBER)) { try { return Integer.parseInt(itemProperties.getProperty(propertyKeys.REVISION_NUMBER)); } catch (NumberFormatException ne) { throw new InvalidOperationException("The REVISION_NUMBER Property is not a number: " + itemProperties.getProperty(propertyKeys.REVISION_NUMBER)); } } return 0; } protected void setRevisionNumber(int rev) { if(itemProperties.containsKey(propertyKeys._VIEW_ID)) { int viewId = Integer.parseInt(itemProperties.getProperty(propertyKeys._VIEW_ID)); if(viewId != view.getID()) { throw new InvalidOperationException("View branching is not supported yet"); } } itemProperties.setProperty(propertyKeys.REVISION_NUMBER, Integer.toString(rev)); } protected int findRightRevision(int id) { if(getView().getConfiguration().isTip()) { isFromHistory = false; return findLastRevision(id); } else if (getView().getConfiguration().isTimeBased()) { isFromHistory = true; return findTimeRevision(id); } else if (getView().getConfiguration().isLabelBased()) { isFromHistory = true; Label aLabel = new Label(getView().getID(), getView().getConfiguration().getLabelID()); return aLabel.getRevisionOfItem(id); } throw new InvalidOperationException("Cannot find a revision with this view configuration"); } protected int findLastRevision(int id) { int max = 0; java.io.File storage = InternalPropertiesProvider.getInstance().getStorageLocation(); try { java.io.File tempLocation = new java.io.File(storage.getCanonicalPath() + java.io.File.separator + id); if(tempLocation.exists()) { for(String aRevision : tempLocation.list()) { try { int tocheck = Integer.parseInt(aRevision.trim()); if(tocheck > max) { max = tocheck; } } catch (NumberFormatException ne) { ne.printStackTrace(); } } } } catch (IOException e) { e.printStackTrace(); } return max; } protected int findTimeRevision(int id) { int revision = 0; java.io.File storage = InternalPropertiesProvider.getInstance().getStorageLocation(); OLEDate time = getView().getConfiguration().getTime(); if(null == time) { throw new Error("Cannot find a time revision without a time parameter"); } long javaTime = time.getLongValue(); long bestTime = Long.MIN_VALUE; try { java.io.File location = new java.io.File(storage.getCanonicalPath() + java.io.File.separator + id); if(location.exists()) { for(String name : location.list()) { // check if it is a file java.io.File aFile = new java.io.File(location.getCanonicalPath() + java.io.File.separator + name + java.io.File.separator + FILE_PROPERTIES); if(!aFile.exists()) { // if not then check if it is a folder aFile = new java.io.File(location.getCanonicalPath() + java.io.File.separator + name + java.io.File.separator + FOLDER_PROPERTIES); } if(aFile.exists()) { Properties prop = new Properties(); FileInputStream in = new FileInputStream(aFile); try { prop.load(in); long modificationTime = Long.parseLong(prop.getProperty(propertyKeys.MODIFIED_TIME, "0")); if(modificationTime <= javaTime && modificationTime > bestTime) { bestTime = modificationTime; revision = Integer.parseInt(name); } } catch (IOException e) { e.printStackTrace(); } finally { FileUtility.close(in); } } } } } catch (IOException e) { e.printStackTrace(); } return revision; } protected void setView(View view) { this.view = view; } public int getModifiedBy() { try { return Integer.parseInt(itemProperties.getProperty(propertyKeys.MODIFIED_USER_ID)); } catch (NumberFormatException ne) { throw new InvalidOperationException("The MODIFIED_USER_ID Property is not a number: " + itemProperties.getProperty(propertyKeys.MODIFIED_USER_ID)); } } public Item getFromHistoryByVersion(int viewVersion) { if (getType().getName().equals(getTypeNames().FILE)) { // In the fake storage version numbering start at 0 // Technically wrong as the view Version != Content Version => fake-starteam doesn't make any difference. return new com.starbase.starteam.File(getItemID(), viewVersion - 1, getView()); } // don't be fooled this work with the real starteam throw new InvalidOperationException("The operation isn't supported for anything that isn't a file"); } public Item getFromHistoryByLabelID(int labelID) { Label toFindInHistory = new Label(getView().getID(), labelID); if (getType().getName().equals(getTypeNames().FILE)) { if (toFindInHistory.hasItemIdInList(getItemID())) { return new com.starbase.starteam.File(getItemID(), toFindInHistory.getRevisionOfItem(getItemID()), getView()); } return null; } // don't be fooled this work with the real starteam throw new InvalidOperationException("The operation isn't supported for anything that isn't a file"); } protected void setModifiedBy() { int myUserID = InternalPropertiesProvider.getInstance().getCurrentServer().getMyUserAccount().getID(); itemProperties.setProperty(propertyKeys.MODIFIED_USER_ID, Integer.toString(myUserID)); } protected void setCreatedTime() { itemProperties.setProperty(propertyKeys.CREATED_TIME, Long.toString(InternalPropertiesProvider.getInstance().getCurrentServer().getCurrentTime().getLongValue())); } public OLEDate getCreatedTime() { try { return new OLEDate(Long.parseLong(itemProperties.getProperty(propertyKeys.CREATED_TIME))); } catch (NumberFormatException nfe) { throw new InvalidOperationException("The item as a invalid java time: " + itemProperties.getProperty(propertyKeys.CREATED_TIME)); } } protected void setModifiedTime() { itemProperties.setProperty(propertyKeys.MODIFIED_TIME, Long.toString(InternalPropertiesProvider.getInstance().getCurrentServer().getCurrentTime().getLongValue())); } public OLEDate getModifiedTime() { try { return new OLEDate(Long.parseLong(itemProperties.getProperty(propertyKeys.MODIFIED_TIME))); } catch (NumberFormatException nfe) { throw new InvalidOperationException("The item as a invalid java time: " + itemProperties.getProperty(propertyKeys.MODIFIED_TIME)); } } @Override public int getID() { return hashCode(); } public int getItemID() { return getObjectID(); } public int getObjectID() { return Integer.parseInt(itemProperties.getProperty(propertyKeys.OBJECT_ID)); } public int getParentObjectID() { if(itemProperties.containsKey(propertyKeys.PARENT_OBJECT_ID)) { return Integer.parseInt(itemProperties.getProperty(propertyKeys.PARENT_OBJECT_ID)); } return 0; } public boolean isNew() { return isNew; } public boolean isFromHistory() { return isFromHistory; } public Folder getParentFolder() { return parent; } public void update() { // Save in the File Database. throw new UnsupportedOperationException("Not implemented at this level"); } public void refresh() { throw new UnsupportedOperationException("Not implemented at this level"); } public View getView() { return view; } protected List<Item> loadHistory() { throw new UnsupportedOperationException("Not implemented at this level"); } public Item[] getHistory() { List<Item> history = loadHistory(); Item[] ret = new Item[history.size()]; history.toArray(ret); return ret; } public String getParentFolderHierarchy() { if(null == parent.getParentFolder()) { if(null == view.getParentView()) { return view.getProject().getName() + File.separator; } return view.getName() + File.separator; } else { return parent.getParentFolderHierarchy() + parent + File.separator; } } public String getParentFolderQualifiedName() { if(0 == getParentObjectID()) { return view.getName(); } return itemProperties.getProperty(propertyKeys.FOLDER_PATH); } @Override public TypeNames getTypeNames() { return super.getTypeNames(); } @Override public Type getType() { return new Type(getTypeNames().ITEM, view.getServer()); } public Item shareTo(Folder folder) { if(!(folder instanceof org.ossnoize.fakestarteam.TrashFolder)) incrementRefCount(); return this; } protected void incrementRefCount() { int refCount; if(itemProperties.containsKey(propertyKeys._REF_COUNT)) refCount = Integer.parseInt(itemProperties.getProperty(propertyKeys._REF_COUNT)); else refCount = 0; refCount += 1; itemProperties.setProperty(propertyKeys._REF_COUNT, Integer.toString(refCount)); } protected void decrementRefCount() { int refCount; if(itemProperties.containsKey(propertyKeys._REF_COUNT)) refCount = Integer.parseInt(itemProperties.getProperty(propertyKeys._REF_COUNT)); else refCount = 1; refCount -= 1; itemProperties.setProperty(propertyKeys._REF_COUNT, Integer.toString(refCount)); } public boolean isDeleted() { return itemProperties.containsKey(propertyKeys._REF_COUNT) && itemProperties.getProperty(propertyKeys._REF_COUNT).equals("0"); } public void moveTo(Folder folder) { itemProperties.setProperty(propertyKeys.PARENT_OBJECT_ID, Integer.toString(folder.getObjectID())); parent = folder; decrementRefCount(); shareTo(folder); } public void remove() { decrementRefCount(); if(itemProperties.getProperty(propertyKeys._REF_COUNT).equals("0")) { itemProperties.setProperty(propertyKeys.DELETED_TIME, Long.toString(InternalPropertiesProvider.getInstance().getCurrentServer().getCurrentTime().getLongValue())); itemProperties.setProperty(propertyKeys.DELETED_USER_ID, Integer.toString(InternalPropertiesProvider.getInstance().getCurrentServer().getMyUserAccount().getID())); itemProperties.setProperty(PropertyNames.ITEM_DELETED_TIME, itemProperties.getProperty(propertyKeys.DELETED_TIME)); itemProperties.setProperty(PropertyNames.ITEM_DELETED_USER_ID, itemProperties.getProperty(propertyKeys.DELETED_USER_ID)); } update(); } public OLEDate getDeletedTime() { if(itemProperties.containsKey(propertyKeys.DELETED_TIME)) { long date = Long.parseLong(itemProperties.getProperty(propertyKeys.DELETED_TIME)); return new OLEDate(date); } return new OLEDate(0); } public int getDeletedUserID() { if(itemProperties.containsKey(propertyKeys.DELETED_USER_ID)) { int userId = Integer.parseInt(itemProperties.getProperty(propertyKeys.DELETED_USER_ID)); return userId; } return -1; } public void discard() { SimpleTypedResourceIDProvider.getProvider().clearExisting(getView(), getObjectID()); } protected void loadProperties() { } protected int getObjectSpecificVersion() { throw new InvalidOperationException("Shall not be called at this level"); } public int getViewVersion() { return getObjectSpecificVersion(); } @Override public PropertyNames getPropertyNames() { return propertyKeys; } public Label[] getAllLabels() { throw new UnsupportedOperationException("Not supported yet."); } @Override public Object get(String key) throws NoSuchPropertyException { return itemProperties.get(key); } public int getCreatedBy(){ return getModifiedBy(); } public String getFlagDisplayName(int flag) { throw new UnsupportedOperationException("Not supported yet."); } public Server getServer(){ return getView().getServer(); } @Override public boolean equals(Object obj) { if (obj instanceof Item) { Item other = (Item) obj; return other.getObjectID() == getObjectID() && other.getRevisionNumber() == getRevisionNumber(); } return false; } }