--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.core;
+
+import java.util.EventObject;
+
+/**
+ * A buffer changed event describes how a buffer has changed. These events are
+ * used in <code>IBufferChangedListener</code> notifications.
+ * <p>
+ * For text insertions, <code>getOffset</code> is the offset
+ * of the first inserted character, <code>getText</code> is the
+ * inserted text, and <code>getLength</code> is 0.
+ * </p>
+ * <p>
+ * For text removals, <code>getOffset</code> is the offset
+ * of the first removed character, <code>getText</code> is <code>null</code>,
+ * and <code>getLength</code> is the length of the text that was removed.
+ * </p>
+ * <p>
+ * For replacements (including <code>IBuffer.setContents</code>),
+ * <code>getOffset</code> is the offset
+ * of the first replaced character, <code>getText</code> is the replacement
+ * text, and <code>getLength</code> is the length of the original text
+ * that was replaced.
+ * </p>
+ * <p>
+ * When a buffer is closed, <code>getOffset</code> is 0, <code>getLength</code>
+ * is 0, and <code>getText</code> is <code>null</code>.
+ * </p>
+ * <p>
+ * This class is not intended to be instantiated or subclassed by clients.
+ * Instances of this class are automatically created by the Java model.
+ * </p>
+ *
+ * @see IBuffer
+ */
+public class BufferChangedEvent extends EventObject {
+
+ /**
+ * The length of text that has been modified in the buffer.
+ */
+ private int length;
+
+ /**
+ * The offset into the buffer where the modification took place.
+ */
+ private int offset;
+
+ /**
+ * The text that was modified.
+ */
+ private String text;
+
+/**
+ * Creates a new buffer changed event indicating that the given buffer has changed.
+ *
+ * @param buffer the given buffer
+ * @param offset the given offset
+ * @param length the given length
+ * @param text the given text
+ */
+public BufferChangedEvent(IBuffer buffer, int offset, int length, String text) {
+ super(buffer);
+ this.offset = offset;
+ this.length = length;
+ this.text = text;
+}
+/**
+ * Returns the buffer which has changed.
+ *
+ * @return the buffer affected by the change
+ */
+public IBuffer getBuffer() {
+ return (IBuffer) source;
+}
+/**
+ * Returns the length of text removed or replaced in the buffer, or
+ * 0 if text has been inserted into the buffer.
+ *
+ * @return the length of the original text fragment modified by the
+ * buffer change (<code> 0 </code> in case of insertion).
+ */
+public int getLength() {
+ return this.length;
+}
+/**
+ * Returns the index of the first character inserted, removed, or replaced
+ * in the buffer.
+ *
+ * @return the source offset of the textual manipulation in the buffer
+ */
+public int getOffset() {
+ return this.offset;
+}
+/**
+ * Returns the text that was inserted, the replacement text,
+ * or <code>null</code> if text has been removed.
+ *
+ * @return the text corresponding to the buffer change (<code> null </code>
+ * in case of deletion).
+ */
+public String getText() {
+ return this.text;
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.core;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IProgressMonitor;
+
+/**
+ * A buffer contains the text contents of a resource. It is not language-specific.
+ * The contents may be in the process of being edited, differing from the actual contents of the
+ * underlying resource. A buffer has an owner, which is an <code>IOpenable</code>.
+ * If a buffer does not have an underlying resource, saving the buffer has no effect.
+ * Buffers can be read-only.
+ * <p>
+ * Note that java model operations that manipulate an <code>IBuffer</code> (for example,
+ * <code>IType.createMethod(...)</code>) ensures that the same line delimiter
+ * (either <code>"\n"</code> or <code>"\r"</code> or <code>"\r\n"</code>) is
+ * used across the whole buffer. Thus these operations may change the line delimiter(s)
+ * included in the string to be append, or replaced.
+ * However implementers of this interface should be aware that other clients of <code>IBuffer</code>
+ * might not do such transformations beforehand.
+ * <p>
+ * This interface may be implemented by clients.
+ * </p>
+ */
+public interface IBuffer {
+
+/**
+ * Adds the given listener for changes to this buffer.
+ * Has no effect if an identical listener is already registered or if the buffer
+ * is closed.
+ *
+ * @param listener the listener of buffer changes
+ */
+public void addBufferChangedListener(IBufferChangedListener listener);
+/**
+ * Appends the given character array to the contents of the buffer.
+ * This buffer will now have unsaved changes.
+ * Any client can append to the contents of the buffer, not just the owner of the buffer.
+ * Reports a buffer changed event.
+ * <p>
+ * Has no effect if this buffer is read-only.
+ * <p>
+ * A <code>RuntimeException</code> might be thrown if the buffer is closed.
+ *
+ * @param text the given character array to append to contents of the buffer
+ */
+public void append(char[] text);
+/**
+ * Appends the given string to the contents of the buffer.
+ * This buffer will now have unsaved changes.
+ * Any client can append to the contents of the buffer, not just the owner of the buffer.
+ * Reports a buffer changed event.
+ * <p>
+ * Has no effect if this buffer is read-only.
+ * <p>
+ * A <code>RuntimeException</code> might be thrown if the buffer is closed.
+ *
+ * @param text the <code>String</code> to append to the contents of the buffer
+ */
+public void append(String text);
+/**
+ * Closes the buffer. Any unsaved changes are lost. Reports a buffer changed event
+ * with a 0 offset and a 0 length. When this event is fired, the buffer should already
+ * be closed.
+ * <p>
+ * Further operations on the buffer are not allowed, except for close. If an
+ * attempt is made to close an already closed buffer, the second attempt has no effect.
+ */
+public void close();
+/**
+ * Returns the character at the given position in this buffer.
+ * <p>
+ * A <code>RuntimeException</code> might be thrown if the buffer is closed.
+ *
+ * @param position a zero-based source offset in this buffer
+ * @return the character at the given position in this buffer
+ */
+public char getChar(int position);
+/**
+ * Returns the contents of this buffer as a character array, or <code>null</code> if
+ * the buffer has not been initialized.
+ * <p>
+ * Callers should make no assumption about whether the returned character array
+ * is or is not the genuine article or a copy. In other words, if the client
+ * wishes to change this array, they should make a copy. Likewise, if the
+ * client wishes to hang on to the array in its current state, they should
+ * make a copy.
+ * </p>
+ * <p>
+ * A <code>RuntimeException</code> might be thrown if the buffer is closed.
+ *
+ * @return the characters contained in this buffer
+ */
+public char[] getCharacters();
+/**
+ * Returns the contents of this buffer as a <code>String</code>. Like all strings,
+ * the result is an immutable value object., It can also answer <code>null</code> if
+ * the buffer has not been initialized.
+ * <p>
+ * A <code>RuntimeException</code> might be thrown if the buffer is closed.
+ *
+ * @return the contents of this buffer as a <code>String</code>
+ */
+public String getContents();
+/**
+ * Returns number of characters stored in this buffer.
+ * <p>
+ * A <code>RuntimeException</code> might be thrown if the buffer is closed.
+ *
+ * @return the number of characters in this buffer
+ */
+public int getLength();
+/**
+ * Returns the Java openable element owning of this buffer.
+ *
+ * @return the openable element owning this buffer
+ */
+public IOpenable getOwner();
+/**
+ * Returns the given range of text in this buffer.
+ * <p>
+ * A <code>RuntimeException</code> might be thrown if the buffer is closed.
+ *
+ * @param offset the zero-based starting offset
+ * @param length the number of characters to retrieve
+ * @return the given range of text in this buffer
+ */
+public String getText(int offset, int length);
+/**
+ * Returns the underlying resource for which this buffer was opened,
+ * or <code>null</code> if this buffer was not opened on a resource.
+ *
+ * @return the underlying resource for this buffer, or <code>null</code>
+ * if none.
+ */
+public IResource getUnderlyingResource();
+/**
+ * Returns whether this buffer has been modified since it
+ * was opened or since it was last saved.
+ * If a buffer does not have an underlying resource, this method always
+ * returns <code>true</code>.
+ *
+ * @return a <code>boolean</code> indicating presence of unsaved changes (in
+ * the absence of any underlying resource, it will always return <code>true</code>).
+ */
+public boolean hasUnsavedChanges();
+/**
+ * Returns whether this buffer has been closed.
+ *
+ * @return a <code>boolean</code> indicating whether this buffer is closed.
+ */
+public boolean isClosed();
+/**
+ * Returns whether this buffer is read-only.
+ *
+ * @return a <code>boolean</code> indicating whether this buffer is read-only
+ */
+public boolean isReadOnly();
+/**
+ * Removes the given listener from this buffer.
+ * Has no affect if an identical listener is not registered or if the buffer is closed.
+ *
+ * @param listener the listener
+ */
+public void removeBufferChangedListener(IBufferChangedListener listener);
+/**
+ * Replaces the given range of characters in this buffer with the given text.
+ * <code>position</code> and <code>position + length</code> must be in the range [0, getLength()].
+ * <code>length</code> must not be negative.
+ * <p>
+ * A <code>RuntimeException</code> might be thrown if the buffer is closed.
+ *
+ * @param position the zero-based starting position of the affected text range in this buffer
+ * @param length the length of the affected text range in this buffer
+ * @param text the replacing text as a character array
+ */
+public void replace(int position, int length, char[] text);
+/**
+ * Replaces the given range of characters in this buffer with the given text.
+ * <code>position</code> and <code>position + length</code> must be in the range [0, getLength()].
+ * <code>length</code> must not be negative.
+ * <p>
+ * A <code>RuntimeException</code> might be thrown if the buffer is closed.
+ *
+ * @param position the zero-based starting position of the affected text range in this buffer
+ * @param length the length of the affected text range in this buffer
+ * @param text the replacing text as a <code>String</code>
+ */
+public void replace(int position, int length, String text);
+/**
+ * Saves the contents of this buffer to its underlying resource. If
+ * successful, this buffer will have no unsaved changes.
+ * The buffer is left open. Saving a buffer with no unsaved
+ * changes has no effect - the underlying resource is not changed.
+ * If the buffer does not have an underlying resource or is read-only, this
+ * has no effect.
+ * <p>
+ * The <code>force</code> parameter controls how this method deals with
+ * cases where the workbench is not completely in sync with the local file system.
+ * If <code>false</code> is specified, this method will only attempt
+ * to overwrite a corresponding file in the local file system provided
+ * it is in sync with the workbench. This option ensures there is no
+ * unintended data loss; it is the recommended setting.
+ * However, if <code>true</code> is specified, an attempt will be made
+ * to write a corresponding file in the local file system,
+ * overwriting any existing one if need be.
+ * In either case, if this method succeeds, the resource will be marked
+ * as being local (even if it wasn't before).
+ * <p>
+ * A <code>RuntimeException</code> might be thrown if the buffer is closed.
+ *
+ * @param progress the progress monitor to notify
+ * @param force a <code> boolean </code> flag indicating how to deal with resource
+ * inconsistencies.
+ *
+ * @exception JavaModelException if an error occurs writing the buffer
+ * to the underlying resource
+ *
+ * @see org.eclipse.core.resources.IFile#setContents(java.io.InputStream, boolean, boolean, org.eclipse.core.runtime.IProgressMonitor)
+ */
+public void save(IProgressMonitor progress, boolean force) throws JavaModelException;
+/**
+ * Sets the contents of this buffer to the given character array.
+ * This buffer will now have unsaved changes.
+ * Any client can set the contents of the buffer, not just the owner of the buffer.
+ * Reports a buffer changed event.
+ * <p>
+ * Equivalent to <code>replace(0,getLength(),contents)</code>.
+ * </p>
+ * <p>
+ * Has no effect if this buffer is read-only.
+ * <p>
+ * A <code>RuntimeException</code> might be thrown if the buffer is closed.
+ *
+ * @param contents the new contents of this buffer as a character array
+ */
+public void setContents(char[] contents);
+/**
+ * Sets the contents of this buffer to the given <code>String</code>.
+ * This buffer will now have unsaved changes.
+ * Any client can set the contents of the buffer, not just the owner of the buffer.
+ * Reports a buffer changed event.
+ * <p>
+ * Equivalent to <code>replace(0,getLength(),contents)</code>.
+ * </p>
+ * <p>
+ * Has no effect if this buffer is read-only.
+ * <p>
+ * A <code>RuntimeException</code> might be thrown if the buffer is closed.
+ *
+ * @param contents the new contents of this buffer as a <code>String</code>
+ */
+public void setContents(String contents);
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.core;
+
+/**
+ * A listener, which gets notified when the contents of a specific buffer
+ * have changed, or when the buffer is closed.
+ * When a buffer is closed, the listener is notified <em>after</em> the buffer has been closed.
+ * A listener is not notified when a buffer is saved.
+ * <p>
+ * This interface may be implemented by clients.
+ * </p>
+ */
+public interface IBufferChangedListener {
+
+ /**
+ * Notifies that the given event has occurred.
+ *
+ * @param event the change event
+ */
+ public void bufferChanged(BufferChangedEvent event);
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.core;
+
+/**
+ * A factory that creates <code>IBuffer</code>s for openables.
+ * <p>
+ * This interface may be implemented by clients.
+ * </p>
+ * @since 2.0
+ */
+public interface IBufferFactory {
+
+ /**
+ * Creates a buffer for the given owner.
+ * The new buffer will be initialized with the contents of the owner
+ * if and only if it was not already initialized by the factory (a buffer is uninitialized if
+ * its content is <code>null</code>).
+ *
+ * @param owner the owner of the buffer
+ * @see IBuffer
+ */
+ IBuffer createBuffer(IOpenable owner);
+}
+
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.core;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IPath;
+
+/**
+ * Common protocol for all elements provided by the Java model.
+ * Java model elements are exposed to clients as handles to the actual underlying element.
+ * The Java model may hand out any number of handles for each element. Handles
+ * that refer to the same element are guaranteed to be equal, but not necessarily identical.
+ * <p>
+ * Methods annotated as "handle-only" do not require underlying elements to exist.
+ * Methods that require underlying elements to exist throw
+ * a <code>JavaModelException</code> when an underlying element is missing.
+ * <code>JavaModelException.isDoesNotExist</code> can be used to recognize
+ * this common special case.
+ * </p>
+ * <p>
+ * This interface is not intended to be implemented by clients.
+ * </p>
+ */
+public interface IJavaElement extends IAdaptable {
+
+ /**
+ * Constant representing a Java model (workspace level object).
+ * A Java element with this type can be safely cast to <code>IJavaModel</code>.
+ */
+ int JAVA_MODEL = 1;
+
+ /**
+ * Constant representing a Java project.
+ * A Java element with this type can be safely cast to <code>IJavaProject</code>.
+ */
+ int JAVA_PROJECT = 2;
+
+ /**
+ * Constant representing a package fragment root.
+ * A Java element with this type can be safely cast to <code>IPackageFragmentRoot</code>.
+ */
+ int PACKAGE_FRAGMENT_ROOT = 3;
+
+ /**
+ * Constant representing a package fragment.
+ * A Java element with this type can be safely cast to <code>IPackageFragment</code>.
+ */
+ int PACKAGE_FRAGMENT = 4;
+
+ /**
+ * Constant representing a Java compilation unit.
+ * A Java element with this type can be safely cast to <code>ICompilationUnit</code>.
+ */
+ int COMPILATION_UNIT = 5;
+
+ /**
+ * Constant representing a class file.
+ * A Java element with this type can be safely cast to <code>IClassFile</code>.
+ */
+ int CLASS_FILE = 6;
+
+ /**
+ * Constant representing a type (a class or interface).
+ * A Java element with this type can be safely cast to <code>IType</code>.
+ */
+ int TYPE = 7;
+
+ /**
+ * Constant representing a field.
+ * A Java element with this type can be safely cast to <code>IField</code>.
+ */
+ int FIELD = 8;
+
+ /**
+ * Constant representing a method or constructor.
+ * A Java element with this type can be safely cast to <code>IMethod</code>.
+ */
+ int METHOD = 9;
+
+ /**
+ * Constant representing a stand-alone instance or class initializer.
+ * A Java element with this type can be safely cast to <code>IInitializer</code>.
+ */
+ int INITIALIZER = 10;
+
+ /**
+ * Constant representing a package declaration within a compilation unit.
+ * A Java element with this type can be safely cast to <code>IPackageDeclaration</code>.
+ */
+ int PACKAGE_DECLARATION = 11;
+
+ /**
+ * Constant representing all import declarations within a compilation unit.
+ * A Java element with this type can be safely cast to <code>IImportContainer</code>.
+ */
+ int IMPORT_CONTAINER = 12;
+
+ /**
+ * Constant representing an import declaration within a compilation unit.
+ * A Java element with this type can be safely cast to <code>IImportDeclaration</code>.
+ */
+ int IMPORT_DECLARATION = 13;
+
+ /**
+ * Returns whether this Java element exists in the model.
+ * <p>
+ * Java elements are handle objects that may or may not be backed by an
+ * actual element. Java elements that are backed by an actual element are
+ * said to "exist", and this method returns <code>true</code>. For Java
+ * elements that are not working copies, it is always the case that if the
+ * element exists, then its parent also exists (provided it has one) and
+ * includes the element as one of its children. It is therefore possible
+ * to navigated to any existing Java element from the root of the Java model
+ * along a chain of existing Java elements. On the other hand, working
+ * copies are said to exist until they are destroyed (with
+ * <code>IWorkingCopy.destroy</code>). Unlike regular Java elements, a
+ * working copy never shows up among the children of its parent element
+ * (which may or may not exist).
+ * </p>
+ *
+ * @return <code>true</code> if this element exists in the Java model, and
+ * <code>false</code> if this element does not exist
+ */
+ boolean exists();
+
+ /**
+ * Returns the first ancestor of this Java element that has the given type.
+ * Returns <code>null</code> if no such an ancestor can be found.
+ * This is a handle-only method.
+ *
+ * @param ancestorType the given type
+ * @return the first ancestor of this Java element that has the given type, null if no such an ancestor can be found
+ * @since 2.0
+ */
+ IJavaElement getAncestor(int ancestorType);
+
+ /**
+ * Returns the resource that corresponds directly to this element,
+ * or <code>null</code> if there is no resource that corresponds to
+ * this element.
+ * <p>
+ * For example, the corresponding resource for an <code>ICompilationUnit</code>
+ * is its underlying <code>IFile</code>. The corresponding resource for
+ * an <code>IPackageFragment</code> that is not contained in an archive
+ * is its underlying <code>IFolder</code>. An <code>IPackageFragment</code>
+ * contained in an archive has no corresponding resource. Similarly, there
+ * are no corresponding resources for <code>IMethods</code>,
+ * <code>IFields</code>, etc.
+ * <p>
+ *
+ * @return the corresponding resource, or <code>null</code> if none
+ * @exception JavaModelException if this element does not exist or if an
+ * exception occurs while accessing its corresponding resource
+ */
+ IResource getCorrespondingResource() throws JavaModelException;
+
+ /**
+ * Returns the name of this element. This is a handle-only method.
+ *
+ * @return the element name
+ */
+ String getElementName();
+
+ /**
+ * Returns this element's kind encoded as an integer.
+ * This is a handle-only method.
+ *
+ * @return the kind of element; one of the constants declared in
+ * <code>IJavaElement</code>
+ * @see IJavaElement
+ */
+ int getElementType();
+
+ /**
+ * Returns a string representation of this element handle. The format of
+ * the string is not specified; however, the identifier is stable across
+ * workspace sessions, and can be used to recreate this handle via the
+ * <code>JavaCore.create(String)</code> method.
+ *
+ * @return the string handle identifier
+ * @see JavaCore#create(java.lang.String)
+ */
+ String getHandleIdentifier();
+
+ /**
+ * Returns the Java model.
+ * This is a handle-only method.
+ *
+ * @return the Java model
+ */
+ // IJavaModel getJavaModel();
+
+ /**
+ * Returns the Java project this element is contained in,
+ * or <code>null</code> if this element is not contained in any Java project
+ * (for instance, the <code>IJavaModel</code> is not contained in any Java
+ * project).
+ * This is a handle-only method.
+ *
+ * @return the containing Java project, or <code>null</code> if this element is
+ * not contained in a Java project
+ */
+// IJavaProject getJavaProject();
+
+ /**
+ * Returns the first openable parent. If this element is openable, the element
+ * itself is returned. Returns <code>null</code> if this element doesn't have
+ * an openable parent.
+ * This is a handle-only method.
+ *
+ * @return the first openable parent or <code>null</code> if this element doesn't have
+ * an openable parent.
+ * @since 2.0
+ */
+ IOpenable getOpenable();
+
+ /**
+ * Returns the element directly containing this element,
+ * or <code>null</code> if this element has no parent.
+ * This is a handle-only method.
+ *
+ * @return the parent element, or <code>null</code> if this element has no parent
+ */
+ IJavaElement getParent();
+
+ /**
+ * Returns the path to the innermost resource enclosing this element.
+ * If this element is not included in an external archive,
+ * the path returned is the full, absolute path to the underlying resource,
+ * relative to the workbench.
+ * If this element is included in an external archive,
+ * the path returned is the absolute path to the archive in the file system.
+ * This is a handle-only method.
+ *
+ * @return the path to the innermost resource enclosing this element
+ * @since 2.0
+ */
+ IPath getPath();
+
+ /**
+ * Returns the innermost resource enclosing this element.
+ * If this element is included in an archive and this archive is not external,
+ * this is the underlying resource corresponding to the archive.
+ * If this element is included in an external archive, <code>null</code>
+ * is returned.
+ * If this element is a working copy, <code>null</code> is returned.
+ * This is a handle-only method.
+ *
+ * @return the innermost resource enclosing this element, <code>null</code> if this
+ * element is a working copy or is included in an external archive
+ * @since 2.0
+ */
+ IResource getResource();
+
+ /**
+ * Returns the smallest underlying resource that contains
+ * this element, or <code>null</code> if this element is not contained
+ * in a resource.
+ *
+ * @return the underlying resource, or <code>null</code> if none
+ * @exception JavaModelException if this element does not exist or if an
+ * exception occurs while accessing its underlying resource
+ */
+ IResource getUnderlyingResource() throws JavaModelException;
+
+ /**
+ * Returns whether this Java element is read-only. An element is read-only
+ * if its structure cannot be modified by the java model.
+ * <p>
+ * Note this is different from IResource.isReadOnly(). For example, .jar
+ * files are read-only as the java model doesn't know how to add/remove
+ * elements in this file, but the underlying IFile can be writable.
+ * <p>
+ * This is a handle-only method.
+ *
+ * @return <code>true</code> if this element is read-only
+ */
+ boolean isReadOnly();
+
+ /**
+ * Returns whether the structure of this element is known. For example, for a
+ * compilation unit that could not be parsed, <code>false</code> is returned.
+ * If the structure of an element is unknown, navigations will return reasonable
+ * defaults. For example, <code>getChildren</code> will return an empty collection.
+ * <p>
+ * Note: This does not imply anything about consistency with the
+ * underlying resource/buffer contents.
+ * </p>
+ *
+ * @return <code>true</code> if the structure of this element is known
+ * @exception JavaModelException if this element does not exist or if an
+ * exception occurs while accessing its corresponding resource
+ */
+ boolean isStructureKnown() throws JavaModelException;
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.core;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.runtime.IProgressMonitor;
+
+/**
+ * Represent the root Java element corresponding to the workspace.
+ * Since there is only one such root element, it is commonly referred to as
+ * <em>the</em> Java model element.
+ * The Java model element needs to be opened before it can be navigated or manipulated.
+ * The Java model element has no parent (it is the root of the Java element
+ * hierarchy). Its children are <code>IJavaProject</code>s.
+ * <p>
+ * This interface provides methods for performing copy, move, rename, and
+ * delete operations on multiple Java elements.
+ * </p>
+ * <p>
+ * This interface is not intended to be implemented by clients. An instance
+ * of one of these handles can be created via
+ * <code>JavaCore.create(workspace.getRoot())</code>.
+ * </p>
+ *
+ * @see JavaCore#create(org.eclipse.core.resources.IWorkspaceRoot)
+ */
+public interface IJavaModel extends IJavaElement, IOpenable, IParent {
+/**
+ * Returns whether this Java model contains an <code>IJavaElement</code> whose
+ * resource is the given resource or a non-Java resource which is the given resource.
+ * <p>
+ * Note: no existency check is performed on the argument resource. If it is not accessible
+ * (see <code>IResource.isAccessible()</code>) yet but would be located in Java model
+ * range, then it will return <code>true</code>.
+ * </p><p>
+ * If the resource is accessible, it can be reached by navigating the Java model down using the
+ * <code>getChildren()</code> and/or <code>getNonJavaResources()</code> methods.
+ * </p>
+ * @param resource the resource to check
+ * @return true if the resource is accessible through the Java model
+ * @since 2.1
+ */
+boolean contains(IResource resource);
+/**
+ * Copies the given elements to the specified container(s).
+ * If one container is specified, all elements are copied to that
+ * container. If more than one container is specified, the number of
+ * elements and containers must match, and each element is copied to
+ * its associated container.
+ * <p>
+ * Optionally, each copy can positioned before a sibling
+ * element. If <code>null</code> is specified for a given sibling, the copy
+ * is inserted as the last child of its associated container.
+ * </p>
+ * <p>
+ * Optionally, each copy can be renamed. If
+ * <code>null</code> is specified for the new name, the copy
+ * is not renamed.
+ * </p>
+ * <p>
+ * Optionally, any existing child in the destination container with
+ * the same name can be replaced by specifying <code>true</code> for
+ * force. Otherwise an exception is thrown in the event that a name
+ * collision occurs.
+ * </p>
+ *
+ * @param elements the elements to copy
+ * @param containers the container, or list of containers
+ * @param siblings the list of siblings element any of which may be
+ * <code>null</code>; or <code>null</code>
+ * @param renamings the list of new names any of which may be
+ * <code>null</code>; or <code>null</code>
+ * @param replace <code>true</code> if any existing child in a target container
+ * with the target name should be replaced, and <code>false</code> to throw an
+ * exception in the event of a name collision
+ * @param monitor a progress monitor
+ * @exception JavaModelException if an element could not be copied. Reasons include:
+ * <ul>
+ * <li> There is no element to process (NO_ELEMENTS_TO_PROCESS). The given elements is null or empty</li>
+ * <li> A specified element, container, or sibling does not exist (ELEMENT_DOES_NOT_EXIST)</li>
+ * <li> A <code>CoreException</code> occurred while updating an underlying resource</li>
+ * <li> A container is of an incompatible type (<code>INVALID_DESTINATION</code>)</li>
+ * <li> A sibling is not a child of it associated container (<code>INVALID_SIBLING</code>)</li>
+ * <li> A new name is invalid (<code>INVALID_NAME</code>)</li>
+ * <li> A child in its associated container already exists with the same
+ * name and <code>replace</code> has been specified as <code>false</code> (<code>NAME_COLLISION</code>)</li>
+ * <li> A container or element is read-only (<code>READ_ONLY</code>) </li>
+ * </ul>
+ */
+void copy(IJavaElement[] elements, IJavaElement[] containers, IJavaElement[] siblings, String[] renamings, boolean replace, IProgressMonitor monitor) throws JavaModelException;
+/**
+ * Deletes the given elements, forcing the operation if necessary and specified.
+ *
+ * @param elements the elements to delete
+ * @param force a flag controlling whether underlying resources that are not
+ * in sync with the local file system will be tolerated
+ * @param monitor a progress monitor
+ * @exception JavaModelException if an element could not be deleted. Reasons include:
+ * <ul>
+ * <li> There is no element to process (NO_ELEMENTS_TO_PROCESS). The given elements is null or empty</li>
+ * <li> A specified element does not exist (ELEMENT_DOES_NOT_EXIST)</li>
+ * <li> A <code>CoreException</code> occurred while updating an underlying resource</li>
+ * <li> An element is read-only (<code>READ_ONLY</code>) </li>
+ * </ul>
+ */
+void delete(IJavaElement[] elements, boolean force, IProgressMonitor monitor) throws JavaModelException;
+/**
+ * Returns the Java project with the given name. This is a handle-only method.
+ * The project may or may not exist.
+ *
+ * @return the Java project with the given name
+ */
+// IJavaProject getJavaProject(String name);
+/**
+ * Returns the Java projects in this Java model, or an empty array if there
+ * are none.
+ *
+ * @return the Java projects in this Java model, or an empty array if there
+ * are none
+ * @exception JavaModelException if this request fails.
+ */
+// IJavaProject[] getJavaProjects() throws JavaModelException;
+/**
+ * Returns an array of non-Java resources (that is, non-Java projects) in
+ * the workspace.
+ * <p>
+ * Non-Java projects include all projects that are closed (even if they have the
+ * Java nature).
+ * </p>
+ *
+ * @return an array of non-Java projects contained in the workspace.
+ * @throws JavaModelException if this element does not exist or if an
+ * exception occurs while accessing its corresponding resource
+ * @since 2.1
+ */
+Object[] getNonJavaResources() throws JavaModelException;
+/**
+ * Returns the workspace associated with this Java model.
+ *
+ * @return the workspace associated with this Java model
+ */
+IWorkspace getWorkspace();
+/**
+ * Moves the given elements to the specified container(s).
+ * If one container is specified, all elements are moved to that
+ * container. If more than one container is specified, the number of
+ * elements and containers must match, and each element is moved to
+ * its associated container.
+ * <p>
+ * Optionally, each element can positioned before a sibling
+ * element. If <code>null</code> is specified for sibling, the element
+ * is inserted as the last child of its associated container.
+ * </p>
+ * <p>
+ * Optionally, each element can be renamed. If
+ * <code>null</code> is specified for the new name, the element
+ * is not renamed.
+ * </p>
+ * <p>
+ * Optionally, any existing child in the destination container with
+ * the same name can be replaced by specifying <code>true</code> for
+ * force. Otherwise an exception is thrown in the event that a name
+ * collision occurs.
+ * </p>
+ *
+ * @param elements the elements to move
+ * @param containers the container, or list of containers
+ * @param siblings the list of siblings element any of which may be
+ * <code>null</code>; or <code>null</code>
+ * @param renamings the list of new names any of which may be
+ * <code>null</code>; or <code>null</code>
+ * @param replace <code>true</code> if any existing child in a target container
+ * with the target name should be replaced, and <code>false</code> to throw an
+ * exception in the event of a name collision
+ * @param monitor a progress monitor
+ * @exception JavaModelException if an element could not be moved. Reasons include:
+ * <ul>
+ * <li> There is no element to process (NO_ELEMENTS_TO_PROCESS). The given elements is null or empty</li>
+ * <li> A specified element, container, or sibling does not exist (ELEMENT_DOES_NOT_EXIST)</li>
+ * <li> A <code>CoreException</code> occurred while updating an underlying resource</li>
+ * <li> A container is of an incompatible type (<code>INVALID_DESTINATION</code>)</li>
+ * <li> A sibling is not a child of it associated container (<code>INVALID_SIBLING</code>)</li>
+ * <li> A new name is invalid (<code>INVALID_NAME</code>)</li>
+ * <li> A child in its associated container already exists with the same
+ * name and <code>replace</code> has been specified as <code>false</code> (<code>NAME_COLLISION</code>)</li>
+ * <li> A container or element is read-only (<code>READ_ONLY</code>) </li>
+ * </ul>
+ *
+ * @exception IllegalArgumentException any element or container is <code>null</code>
+ */
+void move(IJavaElement[] elements, IJavaElement[] containers, IJavaElement[] siblings, String[] renamings, boolean replace, IProgressMonitor monitor) throws JavaModelException;
+
+/**
+ * Triggers an update of the JavaModel with respect to the referenced external archives.
+ * This operation will issue a JavaModel delta describing the discovered changes, in term
+ * of Java element package fragment roots added, removed or changed.
+ * Note that a collection of elements can be passed so as to narrow the set of archives
+ * to refresh (passing <code>null</code> along is equivalent to refreshing the entire mode).
+ * The elements can be:
+ * <ul>
+ * <li> package fragment roots corresponding to external archives
+ * <li> Java projects, which referenced external archives will be refreshed
+ * <li> Java model, all referenced external archives will be refreshed.
+ * </ul>
+ * <p> In case an archive is used by multiple projects, the delta issued will account for
+ * all of them. This means that even if a project was not part of the elements scope, it
+ * may still be notified of changes if it is referencing a library comprised in the scope.
+ * <p>
+ * @param elementsScope - a collection of elements defining the scope of the refresh
+ * @param monitor - a progress monitor used to report progress
+ * @exception JavaModelException in one of the corresponding situation:
+ * <ul>
+ * <li> an exception occurs while accessing project resources </li>
+ * </ul>
+ *
+ * @see IJavaElementDelta
+ * @since 2.0
+ */
+void refreshExternalArchives(IJavaElement[] elementsScope, IProgressMonitor monitor) throws JavaModelException;
+
+/**
+ * Renames the given elements as specified.
+ * If one container is specified, all elements are renamed within that
+ * container. If more than one container is specified, the number of
+ * elements and containers must match, and each element is renamed within
+ * its associated container.
+ *
+ * @param elements the elements to rename
+ * @param destinations the container, or list of containers
+ * @param names the list of new names
+ * @param replace <code>true</code> if an existing child in a target container
+ * with the target name should be replaced, and <code>false</code> to throw an
+ * exception in the event of a name collision
+ * @param monitor a progress monitor
+ * @exception JavaModelException if an element could not be renamed. Reasons include:
+ * <ul>
+ * <li> There is no element to process (NO_ELEMENTS_TO_PROCESS). The given elements is null or empty</li>
+ * <li> A specified element does not exist (ELEMENT_DOES_NOT_EXIST)</li>
+ * <li> A <code>CoreException</code> occurred while updating an underlying resource
+ * <li> A new name is invalid (<code>INVALID_NAME</code>)
+ * <li> A child already exists with the same name and <code>replace</code> has been specified as <code>false</code> (<code>NAME_COLLISION</code>)
+ * <li> An element is read-only (<code>READ_ONLY</code>)
+ * </ul>
+ */
+void rename(IJavaElement[] elements, IJavaElement[] destinations, String[] names, boolean replace, IProgressMonitor monitor) throws JavaModelException;
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.core;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IStatus;
+
+/**
+ * Represents the outcome of an Java model operation. Status objects are
+ * used inside <code>JavaModelException</code> objects to indicate what went
+ * wrong.
+ * <p>
+ * Java model status object are distinguished by their plug-in id:
+ * <code>getPlugin</code> returns <code>"org.eclipse.jdt.core"</code>.
+ * <code>getCode</code> returns one of the status codes declared in
+ * <code>IJavaModelStatusConstants</code>.
+ * </p>
+ * <p>
+ * A Java model status may also carry additional information (that is, in
+ * addition to the information defined in <code>IStatus</code>):
+ * <ul>
+ * <li>elements - optional handles to Java elements associated with the failure</li>
+ * <li>string - optional string associated with the failure</li>
+ * </ul>
+ * <p>
+ * This interface is not intended to be implemented by clients.
+ * </p>
+ *
+ * @see org.eclipse.core.runtime.IStatus
+ * @see IJavaModelStatusConstants
+ */
+public interface IJavaModelStatus extends IStatus {
+/**
+ * Returns any Java elements associated with the failure (see specification
+ * of the status code), or an empty array if no elements are related to this
+ * particular status code.
+ *
+ * @return the list of Java element culprits
+ * @see IJavaModelStatusConstants
+ */
+public IJavaElement[] getElements();
+
+/**
+ * Returns the path associated with the failure (see specification
+ * of the status code), or <code>null</code> if the failure is not
+ * one of <code>DEVICE_PATH</code>, <code>INVALID_PATH</code>,
+ * <code>PATH_OUTSIDE_PROJECT</code>, or <code>RELATIVE_PATH</code>.
+ *
+ * @return the path that caused the failure, or <code>null</code> if none
+ * @see IJavaModelStatusConstants#DEVICE_PATH
+ * @see IJavaModelStatusConstants#INVALID_PATH
+ * @see IJavaModelStatusConstants#PATH_OUTSIDE_PROJECT
+ * @see IJavaModelStatusConstants#RELATIVE_PATH
+ */
+IPath getPath();
+/**
+ * Returns the string associated with the failure (see specification
+ * of the status code), or <code>null</code> if no string is related to this
+ * particular status code.
+ *
+ * @return the string culprit, or <code>null</code> if none
+ * @see IJavaModelStatusConstants
+ * @deprecated Use IStatus#getMessage instead
+ */
+String getString();
+/**
+ * Returns whether this status indicates that a Java model element does not exist.
+ * This convenience method is equivalent to
+ * <code>getCode() == IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST</code>.
+ *
+ * @return <code>true</code> if the status code indicates that a Java model
+ * element does not exist
+ * @see IJavaModelStatusConstants#ELEMENT_DOES_NOT_EXIST
+ */
+boolean isDoesNotExist();
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.core;
+
+/**
+ * Status codes used with Java model status objects.
+ * <p>
+ * This interface declares constants only; it is not intended to be implemented
+ * or extended.
+ * </p>
+ *
+ * @see IJavaModelStatus
+ * @see org.eclipse.core.runtime.IStatus#getCode()
+ */
+public interface IJavaModelStatusConstants {
+
+ /**
+ * Status constant indicating that a container path was resolved
+ * to invalid entries (null or container).
+ *
+ * @since 2.0
+ */
+ public static final int INVALID_CP_CONTAINER_ENTRY = 962;
+
+ /**
+ * Status constant indicating that a container path was not resolvable
+ * indicating either the referred container is undefined, unbound.
+ *
+ * @since 2.0
+ */
+ public static final int CP_CONTAINER_PATH_UNBOUND = 963;
+
+ /**
+ * Status constant indicating that a classpath entry was invalid
+ */
+ public static final int INVALID_CLASSPATH = 964;
+
+ /**
+ * Status constant indicating that a variable path was not resolvable
+ * indicating either the referred variable is undefined, unbound or the resolved
+ * variable path does not correspond to an existing file or folder.
+ */
+ public static final int CP_VARIABLE_PATH_UNBOUND = 965;
+
+ /**
+ * Status constant indicating a core exception occurred.
+ * Use <code>getException</code> to retrieve a <code>CoreException</code>.
+ */
+ public static final int CORE_EXCEPTION = 966;
+
+ /**
+ * Status constant indicating one or more of the elements
+ * supplied are not of a valid type for the operation to
+ * process.
+ * The element(s) can be retrieved using <code>getElements</code> on the status object.
+ */
+ public static final int INVALID_ELEMENT_TYPES = 967;
+
+ /**
+ * Status constant indicating that no elements were
+ * provided to the operation for processing.
+ */
+ public static final int NO_ELEMENTS_TO_PROCESS = 968;
+
+ /**
+ * Status constant indicating that one or more elements
+ * supplied do not exist.
+ * The element(s) can be retrieved using <code>getElements</code> on the status object.
+ *
+ * @see IJavaModelStatus#isDoesNotExist
+ */
+ public static final int ELEMENT_DOES_NOT_EXIST = 969;
+
+ /**
+ * Status constant indicating that a <code>null</code> path was
+ * supplied to the operation.
+ */
+ public static final int NULL_PATH = 970;
+
+ /**
+ * Status constant indicating that a path outside of the
+ * project was supplied to the operation. The path can be retrieved using
+ * <code>getPath</code> on the status object.
+ */
+ public static final int PATH_OUTSIDE_PROJECT = 971;
+
+ /**
+ * Status constant indicating that a relative path
+ * was supplied to the operation when an absolute path is
+ * required. The path can be retrieved using <code>getPath</code> on the
+ * status object.
+ */
+ public static final int RELATIVE_PATH = 972;
+
+ /**
+ * Status constant indicating that a path specifying a device
+ * was supplied to the operation when a path with no device is
+ * required. The path can be retrieved using <code>getPath</code> on the
+ * status object.
+ */
+ public static final int DEVICE_PATH = 973;
+
+ /**
+ * Status constant indicating that a string
+ * was supplied to the operation that was <code>null</code>.
+ */
+ public static final int NULL_STRING = 974;
+
+ /**
+ * Status constant indicating that the operation encountered
+ * a read-only element.
+ * The element(s) can be retrieved using <code>getElements</code> on the status object.
+ */
+ public static final int READ_ONLY = 976;
+
+ /**
+ * Status constant indicating that a naming collision would occur
+ * if the operation proceeded.
+ */
+ public static final int NAME_COLLISION = 977;
+
+ /**
+ * Status constant indicating that a destination provided for a copy/move/rename operation
+ * is invalid.
+ * The destination element can be retrieved using <code>getElements</code> on the status object.
+ */
+ public static final int INVALID_DESTINATION = 978;
+
+ /**
+ * Status constant indicating that a path provided to an operation
+ * is invalid. The path can be retrieved using <code>getPath</code> on the
+ * status object.
+ */
+ public static final int INVALID_PATH = 979;
+
+ /**
+ * Status constant indicating the given source position is out of bounds.
+ */
+ public static final int INDEX_OUT_OF_BOUNDS = 980;
+
+ /**
+ * Status constant indicating there is an update conflict
+ * for a working copy. The compilation unit on which the
+ * working copy is based has changed since the working copy
+ * was created.
+ */
+ public static final int UPDATE_CONFLICT = 981;
+
+ /**
+ * Status constant indicating that <code>null</code> was specified
+ * as a name argument.
+ */
+ public static final int NULL_NAME = 982;
+
+ /**
+ * Status constant indicating that a name provided is not syntactically correct.
+ * The name can be retrieved from <code>getString</code>.
+ */
+ public static final int INVALID_NAME = 983;
+
+ /**
+ * Status constant indicating that the specified contents
+ * are not valid.
+ */
+ public static final int INVALID_CONTENTS = 984;
+
+ /**
+ * Status constant indicating that an <code>java.io.IOException</code>
+ * occurred.
+ */
+ public static final int IO_EXCEPTION = 985;
+
+ /**
+ * Status constant indicating that a <code>DOMException</code>
+ * occurred.
+ */
+ public static final int DOM_EXCEPTION = 986;
+
+ /**
+ * Status constant indicating that a <code>TargetException</code>
+ * occurred.
+ */
+ public static final int TARGET_EXCEPTION = 987;
+
+ /**
+ * Status constant indicating that the Java builder
+ * could not be initialized.
+ */
+ public static final int BUILDER_INITIALIZATION_ERROR = 990;
+
+ /**
+ * Status constant indicating that the Java builder's last built state
+ * could not be serialized or deserialized.
+ */
+ public static final int BUILDER_SERIALIZATION_ERROR = 991;
+
+ /**
+ * Status constant indicating that an error was encountered while
+ * trying to evaluate a code snippet, or other item.
+ */
+ public static final int EVALUATION_ERROR = 992;
+
+ /**
+ * Status constant indicating that a sibling specified is not valid.
+ */
+ public static final int INVALID_SIBLING = 993;
+
+ /**
+ * Status indicating that a Java element could not be created because
+ * the underlying resource is invalid.
+ * @see JavaCore
+ */
+ public static final int INVALID_RESOURCE = 995;
+
+ /**
+ * Status indicating that a Java element could not be created because
+ * the underlying resource is not of an appropriate type.
+ * @see JavaCore
+ */
+ public static final int INVALID_RESOURCE_TYPE = 996;
+
+ /**
+ * Status indicating that a Java element could not be created because
+ * the project owning underlying resource does not have the Java nature.
+ * @see JavaCore
+ */
+ public static final int INVALID_PROJECT = 997;
+
+ /**
+ * Status indicating that the package declaration in a <code>ICompilationUnit</code>
+ * does not correspond to the <code>IPackageFragment</code> it belongs to.
+ * The <code>getString</code> method of the associated status object
+ * gives the name of the package in which the <code>ICompilationUnit</code> is
+ * declared.
+ */
+ public static final int INVALID_PACKAGE = 998;
+
+ /**
+ * Status indicating that the corresponding resource has no local contents yet.
+ * This might happen when attempting to use a resource before its contents
+ * has been made locally available.
+ */
+ public static final int NO_LOCAL_CONTENTS = 999;
+
+ /**
+ * Status indicating that a .classpath file is ill-formed, and thus cannot
+ * be read/written successfully.
+ * @since 2.1
+ */
+ public static final int INVALID_CLASSPATH_FILE_FORMAT = 1000;
+
+ /**
+ * Status indicating that a project is involved in a build path cycle.
+ * @since 2.1
+ */
+ public static final int CLASSPATH_CYCLE = 1001;
+
+ /**
+ * Status constant indicating that an exclusion pattern got specified
+ * on a classpath source entry, though it was explicitely disabled
+ * according to its project preference settings.
+ * @see org.eclipse.jdt.core.IJavaProject#getOptions(boolean)
+ * @since 2.1
+ */
+ public static final int DISABLED_CP_EXCLUSION_PATTERNS = 1002;
+
+ /**
+ * Status constant indicating that a specific output location got associated
+ * with a source entry, though it was explicitely disabled according to its project
+ * preference settings.
+ * @see org.eclipse.jdt.core.IJavaProject#getOptions(boolean)
+ * @since 2.1
+ */
+ public static final int DISABLED_CP_MULTIPLE_OUTPUT_LOCATIONS = 1003;
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.core;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+
+/**
+ * Common protocol for Java elements that must be opened before they can be
+ * navigated or modified. Opening a textual element (such as a compilation unit)
+ * involves opening a buffer on its contents. While open, any changes to the buffer
+ * can be reflected in the element's structure;
+ * see <code>isConsistent</code> and <code>makeConsistent(IProgressMonitor)</code>.
+ * <p>
+ * To reduce complexity in clients, elements are automatically opened
+ * by the Java model as element properties are accessed. The Java model maintains
+ * an LRU cache of open elements, and automatically closes elements as they
+ * are swapped out of the cache to make room for other elements. Elements with
+ * unsaved changes are never removed from the cache, and thus, if the client
+ * maintains many open elements with unsaved
+ * changes, the LRU cache can grow in size (in this case the cache is not
+ * bounded). However, as elements are saved, the cache will shrink back to its
+ * original bounded size.
+ * </p>
+ * <p>
+ * To open an element, all openable parent elements must be open.
+ * The Java model automatically opens parent elements, as it automatically opens elements.
+ * Opening an element may provide access to direct children and other descendants,
+ * but does not automatically open any descendents which are themselves <code>IOpenable</code>.
+ * For example, opening a compilation unit provides access to all its constituent elements,
+ * but opening a package fragment does not open all compilation units in the package fragment.
+ * </p>
+ * <p>
+ * This interface is not intended to be implemented by clients.
+ * </p>
+ */
+public interface IOpenable {
+
+/**
+ * Closes this element and its buffer (if any).
+ * Closing an element which is not open has no effect.
+ *
+ * <p>Note: although <code>close</code> is exposed in the API, clients are
+ * not expected to open and close elements - the Java model does this automatically
+ * as elements are accessed.
+ *
+ * @exception JavaModelException if an error occurs closing this element
+ */
+public void close() throws JavaModelException;
+/**
+ * Returns the buffer opened for this element, or <code>null</code>
+ * if this element does not have a buffer.
+ *
+ * @exception JavaModelException if this element does not exist or if an
+ * exception occurs while accessing its corresponding resource.
+ * @return the buffer opened for this element, or <code>null</code>
+ * if this element does not have a buffer
+ */
+public IBuffer getBuffer() throws JavaModelException;
+/**
+ * Returns <code>true</code> if this element is open and:
+ * <ul>
+ * <li>its buffer has unsaved changes, or
+ * <li>one of its descendants has unsaved changes, or
+ * <li>a working copy has been created on one of this
+ * element's children and has not yet destroyed
+ * </ul>
+ *
+ * @exception JavaModelException if this element does not exist or if an
+ * exception occurs while accessing its corresponding resource.
+ * @return <code>true</code> if this element is open and:
+ * <ul>
+ * <li>its buffer has unsaved changes, or
+ * <li>one of its descendants has unsaved changes, or
+ * <li>a working copy has been created on one of this
+ * element's children and has not yet destroyed
+ * </ul>
+ */
+boolean hasUnsavedChanges() throws JavaModelException;
+/**
+ * Returns whether the element is consistent with its underlying resource or buffer.
+ * The element is consistent when opened, and is consistent if the underlying resource
+ * or buffer has not been modified since it was last consistent.
+ *
+ * <p>NOTE: Child consistency is not considered. For example, a package fragment
+ * responds <code>true</code> when it knows about all of its
+ * compilation units present in its underlying folder. However, one or more of
+ * the compilation units could be inconsistent.
+ *
+ * @exception JavaModelException if this element does not exist or if an
+ * exception occurs while accessing its corresponding resource.
+ * @return true if the element is consistent with its underlying resource or buffer, false otherwise.
+ * @see IOpenable#makeConsistent
+ */
+boolean isConsistent() throws JavaModelException;
+/**
+ * Returns whether this openable is open. This is a handle-only method.
+ * @return true if this openable is open, false otherwise
+ */
+boolean isOpen();
+/**
+ * Makes this element consistent with its underlying resource or buffer
+ * by updating the element's structure and properties as necessary.
+ *
+ * @param progress the given progress monitor
+ * @exception JavaModelException if the element is unable to access the contents
+ * of its underlying resource. Reasons include:
+ * <ul>
+ * <li>This Java element does not exist (ELEMENT_DOES_NOT_EXIST)</li>
+ * </ul>
+ * @see IOpenable#isConsistent
+ */
+void makeConsistent(IProgressMonitor progress) throws JavaModelException;
+/**
+ * Opens this element and all parent elements that are not already open.
+ * For compilation units, a buffer is opened on the contents of the underlying resource.
+ *
+ * <p>Note: although <code>open</code> is exposed in the API, clients are
+ * not expected to open and close elements - the Java model does this automatically
+ * as elements are accessed.
+ *
+ * @param progress the given progress monitor
+ * @exception JavaModelException if an error occurs accessing the contents
+ * of its underlying resource. Reasons include:
+ * <ul>
+ * <li>This Java element does not exist (ELEMENT_DOES_NOT_EXIST)</li>
+ * </ul>
+ */
+public void open(IProgressMonitor progress) throws JavaModelException;
+/**
+ * Saves any changes in this element's buffer to its underlying resource
+ * via a workspace resource operation. This has no effect if the element has no underlying
+ * buffer, or if there are no unsaved changed in the buffer.
+ * <p>
+ * The <code>force</code> parameter controls how this method deals with
+ * cases where the workbench is not completely in sync with the local file system.
+ * If <code>false</code> is specified, this method will only attempt
+ * to overwrite a corresponding file in the local file system provided
+ * it is in sync with the workbench. This option ensures there is no
+ * unintended data loss; it is the recommended setting.
+ * However, if <code>true</code> is specified, an attempt will be made
+ * to write a corresponding file in the local file system,
+ * overwriting any existing one if need be.
+ * In either case, if this method succeeds, the resource will be marked
+ * as being local (even if it wasn't before).
+ * <p>
+ * As a result of this operation, the element is consistent with its underlying
+ * resource or buffer.
+ *
+ * @param progress the given progress monitor
+ * @param force it controls how this method deals with
+ * cases where the workbench is not completely in sync with the local file system
+ * @exception JavaModelException if an error occurs accessing the contents
+ * of its underlying resource. Reasons include:
+ * <ul>
+ * <li>This Java element does not exist (ELEMENT_DOES_NOT_EXIST)</li>
+ * <li>This Java element is read-only (READ_ONLY)</li>
+ * </ul>
+ */
+public void save(IProgressMonitor progress, boolean force) throws JavaModelException;
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.core;
+
+/**
+ * Common protocol for Java elements that contain other Java elements.
+ * <p>
+ * This interface is not intended to be implemented by clients.
+ * </p>
+ */
+public interface IParent {
+/**
+ * Returns the immediate children of this element.
+ * Unless otherwise specified by the implementing element,
+ * the children are in no particular order.
+ *
+ * @exception JavaModelException if this element does not exist or if an
+ * exception occurs while accessing its corresponding resource
+ * @return the immediate children of this element
+ */
+IJavaElement[] getChildren() throws JavaModelException;
+/**
+ * Returns whether this element has one or more immediate children.
+ * This is a convenience method, and may be more efficient than
+ * testing whether <code>getChildren</code> is an empty array.
+ *
+ * @exception JavaModelException if this element does not exist or if an
+ * exception occurs while accessing its corresponding resource
+ * @return true if the immediate children of this element, false otherwise
+ */
+boolean hasChildren() throws JavaModelException;
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.core;
+
+import net.sourceforge.phpdt.internal.core.JavaModelStatus;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+
+//import org.eclipse.jdt.internal.core.JavaModelStatus;
+
+/**
+ * A checked exception representing a failure in the Java model.
+ * Java model exceptions contain a Java-specific status object describing the
+ * cause of the exception.
+ * <p>
+ * This class is not intended to be subclassed by clients. Instances of this
+ * class are automatically created by the Java model when problems arise, so
+ * there is generally no need for clients to create instances.
+ * </p>
+ *
+ * @see IJavaModelStatus
+ * @see IJavaModelStatusConstants
+ */
+public class JavaModelException extends CoreException {
+ CoreException nestedCoreException;
+/**
+ * Creates a Java model exception that wrappers the given <code>Throwable</code>.
+ * The exception contains a Java-specific status object with severity
+ * <code>IStatus.ERROR</code> and the given status code.
+ *
+ * @param exception the <code>Throwable</code>
+ * @param code one of the Java-specific status codes declared in
+ * <code>IJavaModelStatusConstants</code>
+ * @see IJavaModelStatusConstants
+ * @see org.eclipse.core.runtime.IStatus#ERROR
+ */
+public JavaModelException(Throwable e, int code) {
+ this(new JavaModelStatus(code, e));
+}
+/**
+ * Creates a Java model exception for the given <code>CoreException</code>.
+ * Equivalent to
+ * <code>JavaModelException(exception,IJavaModelStatusConstants.CORE_EXCEPTION</code>.
+ *
+ * @param exception the <code>CoreException</code>
+ */
+public JavaModelException(CoreException exception) {
+ super(exception.getStatus());
+ this.nestedCoreException = exception;
+}
+/**
+ * Creates a Java model exception for the given Java-specific status object.
+ *
+ * @param status the Java-specific status object
+ */
+public JavaModelException(IJavaModelStatus status) {
+ super(status);
+}
+/**
+ * Returns the underlying <code>Throwable</code> that caused the failure.
+ *
+ * @return the wrappered <code>Throwable</code>, or <code>null</code> if the
+ * direct case of the failure was at the Java model layer
+ */
+public Throwable getException() {
+ if (this.nestedCoreException == null) {
+ return getStatus().getException();
+ } else {
+ return this.nestedCoreException;
+ }
+}
+/**
+ * Returns the Java model status object for this exception.
+ * Equivalent to <code>(IJavaModelStatus) getStatus()</code>.
+ *
+ * @return a status object
+ */
+public IJavaModelStatus getJavaModelStatus() {
+ IStatus status = this.getStatus();
+ if (status instanceof IJavaModelStatus) {
+ return (IJavaModelStatus)status;
+ } else {
+ // A regular IStatus is created only in the case of a CoreException.
+ // See bug 13492 Should handle JavaModelExceptions that contains CoreException more gracefully
+ return new JavaModelStatus(this.nestedCoreException);
+ }
+}
+/**
+ * Returns whether this exception indicates that a Java model element does not
+ * exist. Such exceptions have a status with a code of
+ * <code>IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST</code>.
+ * This is a convenience method.
+ *
+ * @return <code>true</code> if this exception indicates that a Java model
+ * element does not exist
+ * @see IJavaModelStatus#isDoesNotExist
+ * @see IJavaModelStatusConstants#ELEMENT_DOES_NOT_EXIST
+ */
+//public boolean isDoesNotExist() {
+// IJavaModelStatus javaModelStatus = getJavaModelStatus();
+// return javaModelStatus != null && javaModelStatus.isDoesNotExist();
+//}
+/**
+ * Returns a printable representation of this exception suitable for debugging
+ * purposes only.
+ */
+public String toString() {
+ StringBuffer buffer= new StringBuffer();
+ buffer.append("Java Model Exception: "); //$NON-NLS-1$
+ if (getException() != null) {
+ if (getException() instanceof CoreException) {
+ CoreException c= (CoreException)getException();
+ buffer.append("Core Exception [code "); //$NON-NLS-1$
+ buffer.append(c.getStatus().getCode());
+ buffer.append("] "); //$NON-NLS-1$
+ buffer.append(c.getStatus().getMessage());
+ } else {
+ buffer.append(getException().toString());
+ }
+ } else {
+ buffer.append(getStatus().toString());
+ }
+ return buffer.toString();
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.core.util;
+
+import java.util.Enumeration;
+
+/**
+ * The <code>ICacheEnumeration</code> is used to iterate over both the keys
+ * and values in an LRUCache. The <code>getValue()</code> method returns the
+ * value of the last key to be retrieved using <code>nextElement()</code>.
+ * The <code>nextElement()</code> method must be called before the
+ * <code>getValue()</code> method.
+ *
+ * <p>The iteration can be made efficient by making use of the fact that values in
+ * the cache (instances of <code>LRUCacheEntry</code>), know their key. For this reason,
+ * Hashtable lookups don't have to be made at each step of the iteration.
+ *
+ * <p>Modifications to the cache must not be performed while using the
+ * enumeration. Doing so will lead to an illegal state.
+ *
+ * @see LRUCache
+ */
+public interface ICacheEnumeration extends Enumeration {
+ /**
+ * Returns the value of the previously accessed key in the enumeration.
+ * Must be called after a call to nextElement().
+ *
+ * @return Value of current cache entry
+ */
+ public Object getValue();
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.core.util;
+
+/**
+ * Types implementing this interface can occupy a variable amount of space
+ * in an LRUCache. Cached items that do not implement this interface are
+ * considered to occupy one unit of space.
+ *
+ * @see LRUCache
+ */
+public interface ILRUCacheable {
+ /**
+ * Returns the space the receiver consumes in an LRU Cache. The default space
+ * value is 1.
+ *
+ * @return int Amount of cache space taken by the receiver
+ */
+ public int getCacheFootprint();
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.core.util;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+/**
+ * The <code>LRUCache</code> is a hashtable that stores a finite number of elements.
+ * When an attempt is made to add values to a full cache, the least recently used values
+ * in the cache are discarded to make room for the new values as necessary.
+ *
+ * <p>The data structure is based on the LRU virtual memory paging scheme.
+ *
+ * <p>Objects can take up a variable amount of cache space by implementing
+ * the <code>ILRUCacheable</code> interface.
+ *
+ * <p>This implementation is NOT thread-safe. Synchronization wrappers would
+ * have to be added to ensure atomic insertions and deletions from the cache.
+ *
+ * @see org.eclipse.jdt.internal.core.util.ILRUCacheable
+ */
+public class LRUCache implements Cloneable {
+
+ /**
+ * This type is used internally by the LRUCache to represent entries
+ * stored in the cache.
+ * It is static because it does not require a pointer to the cache
+ * which contains it.
+ *
+ * @see LRUCache
+ */
+ protected static class LRUCacheEntry {
+
+ /**
+ * Hash table key
+ */
+ public Object _fKey;
+
+ /**
+ * Hash table value (an LRUCacheEntry object)
+ */
+ public Object _fValue;
+
+ /**
+ * Time value for queue sorting
+ */
+ public int _fTimestamp;
+
+ /**
+ * Cache footprint of this entry
+ */
+ public int _fSpace;
+
+ /**
+ * Previous entry in queue
+ */
+ public LRUCacheEntry _fPrevious;
+
+ /**
+ * Next entry in queue
+ */
+ public LRUCacheEntry _fNext;
+
+ /**
+ * Creates a new instance of the receiver with the provided values
+ * for key, value, and space.
+ */
+ public LRUCacheEntry (Object key, Object value, int space) {
+ _fKey = key;
+ _fValue = value;
+ _fSpace = space;
+ }
+
+ /**
+ * Returns a String that represents the value of this object.
+ */
+ public String toString() {
+
+ return "LRUCacheEntry [" + _fKey + "-->" + _fValue + "]"; //$NON-NLS-3$ //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ }
+
+ /**
+ * Amount of cache space used so far
+ */
+ protected int fCurrentSpace;
+
+ /**
+ * Maximum space allowed in cache
+ */
+ protected int fSpaceLimit;
+
+ /**
+ * Counter for handing out sequential timestamps
+ */
+ protected int fTimestampCounter;
+
+ /**
+ * Hash table for fast random access to cache entries
+ */
+ protected Hashtable fEntryTable;
+
+ /**
+ * Start of queue (most recently used entry)
+ */
+ protected LRUCacheEntry fEntryQueue;
+
+ /**
+ * End of queue (least recently used entry)
+ */
+ protected LRUCacheEntry fEntryQueueTail;
+
+ /**
+ * Default amount of space in the cache
+ */
+ protected static final int DEFAULT_SPACELIMIT = 100;
+ /**
+ * Creates a new cache. Size of cache is defined by
+ * <code>DEFAULT_SPACELIMIT</code>.
+ */
+ public LRUCache() {
+
+ this(DEFAULT_SPACELIMIT);
+ }
+ /**
+ * Creates a new cache.
+ * @param size Size of Cache
+ */
+ public LRUCache(int size) {
+
+ fTimestampCounter = fCurrentSpace = 0;
+ fEntryQueue = fEntryQueueTail = null;
+ fEntryTable = new Hashtable(size);
+ fSpaceLimit = size;
+ }
+ /**
+ * Returns a new cache containing the same contents.
+ *
+ * @return New copy of object.
+ */
+ public Object clone() {
+
+ LRUCache newCache = newInstance(fSpaceLimit);
+ LRUCacheEntry qEntry;
+
+ /* Preserve order of entries by copying from oldest to newest */
+ qEntry = this.fEntryQueueTail;
+ while (qEntry != null) {
+ newCache.privateAdd (qEntry._fKey, qEntry._fValue, qEntry._fSpace);
+ qEntry = qEntry._fPrevious;
+ }
+ return newCache;
+ }
+ /**
+ * Flushes all entries from the cache.
+ */
+ public void flush() {
+
+ fCurrentSpace = 0;
+ LRUCacheEntry entry = fEntryQueueTail; // Remember last entry
+ fEntryTable = new Hashtable(); // Clear it out
+ fEntryQueue = fEntryQueueTail = null;
+ while (entry != null) { // send deletion notifications in LRU order
+ privateNotifyDeletionFromCache(entry);
+ entry = entry._fPrevious;
+ }
+ }
+ /**
+ * Flushes the given entry from the cache. Does nothing if entry does not
+ * exist in cache.
+ *
+ * @param key Key of object to flush
+ */
+ public void flush (Object key) {
+
+ LRUCacheEntry entry;
+
+ entry = (LRUCacheEntry) fEntryTable.get(key);
+
+ /* If entry does not exist, return */
+ if (entry == null) return;
+
+ this.privateRemoveEntry (entry, false);
+ }
+ /**
+ * Answers the value in the cache at the given key.
+ * If the value is not in the cache, returns null
+ *
+ * @param key Hash table key of object to retrieve
+ * @return Retreived object, or null if object does not exist
+ */
+ public Object get(Object key) {
+
+ LRUCacheEntry entry = (LRUCacheEntry) fEntryTable.get(key);
+ if (entry == null) {
+ return null;
+ }
+
+ this.updateTimestamp (entry);
+ return entry._fValue;
+ }
+ /**
+ * Returns the amount of space that is current used in the cache.
+ */
+ public int getCurrentSpace() {
+ return fCurrentSpace;
+ }
+ /**
+ * Returns the maximum amount of space available in the cache.
+ */
+ public int getSpaceLimit() {
+ return fSpaceLimit;
+ }
+ /**
+ * Returns an Enumeration of the keys currently in the cache.
+ */
+ public Enumeration keys() {
+
+ return fEntryTable.keys();
+ }
+ /**
+ * Returns an enumeration that iterates over all the keys and values
+ * currently in the cache.
+ */
+ public ICacheEnumeration keysAndValues() {
+ return new ICacheEnumeration() {
+
+ Enumeration fValues = fEntryTable.elements();
+ LRUCacheEntry fEntry;
+
+ public boolean hasMoreElements() {
+ return fValues.hasMoreElements();
+ }
+
+ public Object nextElement() {
+ fEntry = (LRUCacheEntry) fValues.nextElement();
+ return fEntry._fKey;
+ }
+
+ public Object getValue() {
+ if (fEntry == null) {
+ throw new java.util.NoSuchElementException();
+ }
+ return fEntry._fValue;
+ }
+ };
+ }
+ /**
+ * Ensures there is the specified amount of free space in the receiver,
+ * by removing old entries if necessary. Returns true if the requested space was
+ * made available, false otherwise.
+ *
+ * @param space Amount of space to free up
+ */
+ protected boolean makeSpace (int space) {
+
+ int limit;
+
+ limit = this.getSpaceLimit();
+
+ /* if space is already available */
+ if (fCurrentSpace + space <= limit) {
+ return true;
+ }
+
+ /* if entry is too big for cache */
+ if (space > limit) {
+ return false;
+ }
+
+ /* Free up space by removing oldest entries */
+ while (fCurrentSpace + space > limit && fEntryQueueTail != null) {
+ this.privateRemoveEntry (fEntryQueueTail, false);
+ }
+ return true;
+ }
+ /**
+ * Returns a new LRUCache instance
+ */
+ protected LRUCache newInstance(int size) {
+ return new LRUCache(size);
+ }
+ /**
+ * Adds an entry for the given key/value/space.
+ */
+ protected void privateAdd (Object key, Object value, int space) {
+
+ LRUCacheEntry entry;
+
+ entry = new LRUCacheEntry(key, value, space);
+ this.privateAddEntry (entry, false);
+ }
+ /**
+ * Adds the given entry from the receiver.
+ * @param shuffle Indicates whether we are just shuffling the queue
+ * (in which case, the entry table is not modified).
+ */
+ protected void privateAddEntry (LRUCacheEntry entry, boolean shuffle) {
+
+ if (!shuffle) {
+ fEntryTable.put (entry._fKey, entry);
+ fCurrentSpace += entry._fSpace;
+ }
+
+ entry._fTimestamp = fTimestampCounter++;
+ entry._fNext = this.fEntryQueue;
+ entry._fPrevious = null;
+
+ if (fEntryQueue == null) {
+ /* this is the first and last entry */
+ fEntryQueueTail = entry;
+ } else {
+ fEntryQueue._fPrevious = entry;
+ }
+
+ fEntryQueue = entry;
+ }
+ /**
+ * An entry has been removed from the cache, for example because it has
+ * fallen off the bottom of the LRU queue.
+ * Subclasses could over-ride this to implement a persistent cache below the LRU cache.
+ */
+ protected void privateNotifyDeletionFromCache(LRUCacheEntry entry) {
+ // Default is NOP.
+ }
+ /**
+ * Removes the entry from the entry queue.
+ * @param shuffle indicates whether we are just shuffling the queue
+ * (in which case, the entry table is not modified).
+ */
+ protected void privateRemoveEntry (LRUCacheEntry entry, boolean shuffle) {
+
+ LRUCacheEntry previous, next;
+
+ previous = entry._fPrevious;
+ next = entry._fNext;
+
+ if (!shuffle) {
+ fEntryTable.remove(entry._fKey);
+ fCurrentSpace -= entry._fSpace;
+ privateNotifyDeletionFromCache(entry);
+ }
+
+ /* if this was the first entry */
+ if (previous == null) {
+ fEntryQueue = next;
+ } else {
+ previous._fNext = next;
+ }
+
+ /* if this was the last entry */
+ if (next == null) {
+ fEntryQueueTail = previous;
+ } else {
+ next._fPrevious = previous;
+ }
+ }
+ /**
+ * Sets the value in the cache at the given key. Returns the value.
+ *
+ * @param key Key of object to add.
+ * @param value Value of object to add.
+ * @return added value.
+ */
+ public Object put(Object key, Object value) {
+
+ int newSpace, oldSpace, newTotal;
+ LRUCacheEntry entry;
+
+ /* Check whether there's an entry in the cache */
+ newSpace = spaceFor (key, value);
+ entry = (LRUCacheEntry) fEntryTable.get (key);
+
+ if (entry != null) {
+
+ /**
+ * Replace the entry in the cache if it would not overflow
+ * the cache. Otherwise flush the entry and re-add it so as
+ * to keep cache within budget
+ */
+ oldSpace = entry._fSpace;
+ newTotal = getCurrentSpace() - oldSpace + newSpace;
+ if (newTotal <= getSpaceLimit()) {
+ updateTimestamp (entry);
+ entry._fValue = value;
+ entry._fSpace = newSpace;
+ this.fCurrentSpace = newTotal;
+ return value;
+ } else {
+ privateRemoveEntry (entry, false);
+ }
+ }
+ if (makeSpace(newSpace)) {
+ privateAdd (key, value, newSpace);
+ }
+ return value;
+ }
+ /**
+ * Removes and returns the value in the cache for the given key.
+ * If the key is not in the cache, returns null.
+ *
+ * @param key Key of object to remove from cache.
+ * @return Value removed from cache.
+ */
+ public Object removeKey (Object key) {
+
+ LRUCacheEntry entry = (LRUCacheEntry) fEntryTable.get(key);
+ if (entry == null) {
+ return null;
+ }
+ Object value = entry._fValue;
+ this.privateRemoveEntry (entry, false);
+ return value;
+ }
+ /**
+ * Sets the maximum amount of space that the cache can store
+ *
+ * @param limit Number of units of cache space
+ */
+ public void setSpaceLimit(int limit) {
+ if (limit < fSpaceLimit) {
+ makeSpace(fSpaceLimit - limit);
+ }
+ fSpaceLimit = limit;
+ }
+ /**
+ * Returns the space taken by the given key and value.
+ */
+ protected int spaceFor (Object key, Object value) {
+
+ if (value instanceof ILRUCacheable) {
+ return ((ILRUCacheable) value).getCacheFootprint();
+ } else {
+ return 1;
+ }
+ }
+/**
+ * Returns a String that represents the value of this object. This method
+ * is for debugging purposes only.
+ */
+public String toString() {
+ return
+ "LRUCache " + (fCurrentSpace * 100.0 / fSpaceLimit) + "% full\n" + //$NON-NLS-1$ //$NON-NLS-2$
+ this.toStringContents();
+}
+/**
+ * Returns a String that represents the contents of this object. This method
+ * is for debugging purposes only.
+ */
+protected String toStringContents() {
+ StringBuffer result = new StringBuffer();
+ int length = fEntryTable.size();
+ Object[] unsortedKeys = new Object[length];
+ String[] unsortedToStrings = new String[length];
+ Enumeration e = this.keys();
+ for (int i = 0; i < length; i++) {
+ Object key = e.nextElement();
+ unsortedKeys[i] = key;
+// unsortedToStrings[i] =
+// (key instanceof org.eclipse.jdt.internal.core.JavaElement) ?
+// ((org.eclipse.jdt.internal.core.JavaElement)key).getElementName() :
+// key.toString();
+ unsortedToStrings[i] = key.toString();
+ }
+ ToStringSorter sorter = new ToStringSorter();
+ sorter.sort(unsortedKeys, unsortedToStrings);
+ for (int i = 0; i < length; i++) {
+ String toString = sorter.sortedStrings[i];
+ Object value = this.get(sorter.sortedObjects[i]);
+ result.append(toString);
+ result.append(" -> "); //$NON-NLS-1$
+ result.append(value);
+ result.append("\n"); //$NON-NLS-1$
+ }
+ return result.toString();
+}
+ /**
+ * Updates the timestamp for the given entry, ensuring that the queue is
+ * kept in correct order. The entry must exist
+ */
+ protected void updateTimestamp (LRUCacheEntry entry) {
+
+ entry._fTimestamp = fTimestampCounter++;
+ if (fEntryQueue != entry) {
+ this.privateRemoveEntry (entry, true);
+ this.privateAddEntry (entry, true);
+ }
+ return;
+ }
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.core.util;
+
+/**
+ * The SortOperation takes a collection of objects and returns
+ * a sorted collection of these objects. The sorting of these
+ * objects is based on their toString(). They are sorted in
+ * alphabetical order.
+ */
+public class ToStringSorter {
+ Object[] sortedObjects;
+ String[] sortedStrings;
+/**
+ * Returns true if stringTwo is 'greater than' stringOne
+ * This is the 'ordering' method of the sort operation.
+ */
+public boolean compare(String stringOne, String stringTwo) {
+ return stringOne.compareTo(stringTwo) < 0;
+}
+/**
+ * Sort the objects in sorted collection and return that collection.
+ */
+private void quickSort(int left, int right) {
+ int originalLeft = left;
+ int originalRight = right;
+ int midIndex = (left + right) / 2;
+ String midToString = this.sortedStrings[midIndex];
+
+ do {
+ while (compare(this.sortedStrings[left], midToString))
+ left++;
+ while (compare(midToString, this.sortedStrings[right]))
+ right--;
+ if (left <= right) {
+ Object tmp = this.sortedObjects[left];
+ this.sortedObjects[left] = this.sortedObjects[right];
+ this.sortedObjects[right] = tmp;
+ String tmpToString = this.sortedStrings[left];
+ this.sortedStrings[left] = this.sortedStrings[right];
+ this.sortedStrings[right] = tmpToString;
+ left++;
+ right--;
+ }
+ } while (left <= right);
+
+ if (originalLeft < right)
+ quickSort(originalLeft, right);
+ if (left < originalRight)
+ quickSort(left, originalRight);
+}
+/**
+ * Return a new sorted collection from this unsorted collection.
+ * Sort using quick sort.
+ */
+public void sort(Object[] unSortedObjects, String[] unsortedStrings) {
+ int size = unSortedObjects.length;
+ this.sortedObjects = new Object[size];
+ this.sortedStrings = new String[size];
+
+ //copy the array so can return a new sorted collection
+ System.arraycopy(unSortedObjects, 0, this.sortedObjects, 0, size);
+ System.arraycopy(unsortedStrings, 0, this.sortedStrings, 0, size);
+ if (size > 1)
+ quickSort(0, size - 1);
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.core;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+
+import net.sourceforge.phpdt.core.BufferChangedEvent;
+import net.sourceforge.phpdt.core.IBuffer;
+import net.sourceforge.phpdt.core.IBufferChangedListener;
+import net.sourceforge.phpdt.core.IJavaModelStatusConstants;
+import net.sourceforge.phpdt.core.IOpenable;
+import net.sourceforge.phpdt.core.JavaModelException;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.ISafeRunnable;
+import org.eclipse.core.runtime.Platform;
+
+/**
+ * @see IBuffer
+ */
+public class Buffer implements IBuffer {
+ protected IFile file;
+ protected int flags;
+ protected char[] contents;
+ protected ArrayList changeListeners;
+ protected IOpenable owner;
+ protected int gapStart= -1;
+ protected int gapEnd= -1;
+
+ protected Object lock= new Object();
+
+ protected static final int F_HAS_UNSAVED_CHANGES= 1;
+ protected static final int F_IS_READ_ONLY= 2;
+ protected static final int F_IS_CLOSED= 4;
+
+/**
+ * Creates a new buffer on an underlying resource.
+ */
+protected Buffer(IFile file, IOpenable owner, boolean readOnly) {
+ this.file = file;
+ this.owner = owner;
+ if (file == null) {
+ setReadOnly(readOnly);
+ }
+}
+/**
+ * @see IBuffer
+ */
+public void addBufferChangedListener(IBufferChangedListener listener) {
+ if (this.changeListeners == null) {
+ this.changeListeners = new ArrayList(5);
+ }
+ if (!this.changeListeners.contains(listener)) {
+ this.changeListeners.add(listener);
+ }
+}
+/**
+ * Append the <code>text</code> to the actual content, the gap is moved
+ * to the end of the <code>text</code>.
+ */
+public void append(char[] text) {
+ if (!isReadOnly()) {
+ if (text == null || text.length == 0) {
+ return;
+ }
+ int length = getLength();
+ moveAndResizeGap(length, text.length);
+ System.arraycopy(text, 0, this.contents, length, text.length);
+ this.gapStart += text.length;
+ this.flags |= F_HAS_UNSAVED_CHANGES;
+ notifyChanged(new BufferChangedEvent(this, length, 0, new String(text)));
+ }
+}
+/**
+ * Append the <code>text</code> to the actual content, the gap is moved
+ * to the end of the <code>text</code>.
+ */
+public void append(String text) {
+ if (text == null) {
+ return;
+ }
+ this.append(text.toCharArray());
+}
+/**
+ * @see IBuffer
+ */
+public void close() throws IllegalArgumentException {
+ BufferChangedEvent event = null;
+ synchronized (this.lock) {
+ if (isClosed())
+ return;
+ event = new BufferChangedEvent(this, 0, 0, null);
+ this.contents = null;
+ this.flags |= F_IS_CLOSED;
+ }
+ notifyChanged(event); // notify outside of synchronized block
+ this.changeListeners = null;
+}
+/**
+ * @see IBuffer
+ */
+public char getChar(int position) {
+ synchronized (this.lock) {
+ if (position < this.gapStart) {
+ return this.contents[position];
+ }
+ int gapLength = this.gapEnd - this.gapStart;
+ return this.contents[position + gapLength];
+ }
+}
+/**
+ * @see IBuffer
+ */
+public char[] getCharacters() {
+ if (this.contents == null) return null;
+ synchronized (this.lock) {
+ if (this.gapStart < 0) {
+ return this.contents;
+ }
+ int length = this.contents.length;
+ char[] newContents = new char[length - this.gapEnd + this.gapStart];
+ System.arraycopy(this.contents, 0, newContents, 0, this.gapStart);
+ System.arraycopy(this.contents, this.gapEnd, newContents, this.gapStart, length - this.gapEnd);
+ return newContents;
+ }
+}
+/**
+ * @see IBuffer
+ */
+public String getContents() {
+ char[] chars = this.getCharacters();
+ if (chars == null) return null;
+ return new String(chars);
+}
+/**
+ * @see IBuffer
+ */
+public int getLength() {
+ synchronized (this.lock) {
+ int length = this.gapEnd - this.gapStart;
+ return (this.contents.length - length);
+ }
+}
+/**
+ * @see IBuffer
+ */
+public IOpenable getOwner() {
+ return this.owner;
+}
+/**
+ * @see IBuffer
+ */
+public String getText(int offset, int length) {
+ if (this.contents == null)
+ return ""; //$NON-NLS-1$
+ synchronized (this.lock) {
+ if (offset + length < this.gapStart)
+ return new String(this.contents, offset, length);
+ if (this.gapStart < offset) {
+ int gapLength = this.gapEnd - this.gapStart;
+ return new String(this.contents, offset + gapLength, length);
+ }
+ StringBuffer buf = new StringBuffer();
+ buf.append(this.contents, offset, this.gapStart - offset);
+ buf.append(this.contents, this.gapEnd, offset + length - this.gapStart);
+ return buf.toString();
+ }
+}
+/**
+ * @see IBuffer
+ */
+public IResource getUnderlyingResource() {
+ return this.file;
+}
+/**
+ * @see IBuffer
+ */
+public boolean hasUnsavedChanges() {
+ return (this.flags & F_HAS_UNSAVED_CHANGES) != 0;
+}
+/**
+ * @see IBuffer
+ */
+public boolean isClosed() {
+ return (this.flags & F_IS_CLOSED) != 0;
+}
+/**
+ * @see IBuffer
+ */
+public boolean isReadOnly() {
+ if (this.file == null) {
+ return (this.flags & F_IS_READ_ONLY) != 0;
+ } else {
+ return this.file.isReadOnly();
+ }
+}
+/**
+ * Moves the gap to location and adjust its size to the
+ * anticipated change size. The size represents the expected
+ * range of the gap that will be filled after the gap has been moved.
+ * Thus the gap is resized to actual size + the specified size and
+ * moved to the given position.
+ */
+protected void moveAndResizeGap(int position, int size) {
+ char[] content = null;
+ int oldSize = this.gapEnd - this.gapStart;
+ if (size < 0) {
+ if (oldSize > 0) {
+ content = new char[this.contents.length - oldSize];
+ System.arraycopy(this.contents, 0, content, 0, this.gapStart);
+ System.arraycopy(this.contents, this.gapEnd, content, this.gapStart, content.length - this.gapStart);
+ this.contents = content;
+ }
+ this.gapStart = this.gapEnd = position;
+ return;
+ }
+ content = new char[this.contents.length + (size - oldSize)];
+ int newGapStart = position;
+ int newGapEnd = newGapStart + size;
+ if (oldSize == 0) {
+ System.arraycopy(this.contents, 0, content, 0, newGapStart);
+ System.arraycopy(this.contents, newGapStart, content, newGapEnd, content.length - newGapEnd);
+ } else
+ if (newGapStart < this.gapStart) {
+ int delta = this.gapStart - newGapStart;
+ System.arraycopy(this.contents, 0, content, 0, newGapStart);
+ System.arraycopy(this.contents, newGapStart, content, newGapEnd, delta);
+ System.arraycopy(this.contents, this.gapEnd, content, newGapEnd + delta, this.contents.length - this.gapEnd);
+ } else {
+ int delta = newGapStart - this.gapStart;
+ System.arraycopy(this.contents, 0, content, 0, this.gapStart);
+ System.arraycopy(this.contents, this.gapEnd, content, this.gapStart, delta);
+ System.arraycopy(this.contents, this.gapEnd + delta, content, newGapEnd, content.length - newGapEnd);
+ }
+ this.contents = content;
+ this.gapStart = newGapStart;
+ this.gapEnd = newGapEnd;
+}
+/**
+ * Notify the listeners that this buffer has changed.
+ * To avoid deadlock, this should not be called in a synchronized block.
+ */
+protected void notifyChanged(final BufferChangedEvent event) {
+ if (this.changeListeners != null) {
+ for (int i = 0, size = this.changeListeners.size(); i < size; ++i) {
+ final IBufferChangedListener listener = (IBufferChangedListener) this.changeListeners.get(i);
+ Platform.run(new ISafeRunnable() {
+ public void handleException(Throwable exception) {
+ Util.log(exception, "Exception occurred in listener of buffer change notification"); //$NON-NLS-1$
+ }
+ public void run() throws Exception {
+ listener.bufferChanged(event);
+ }
+ });
+
+ }
+ }
+}
+/**
+ * @see IBuffer
+ */
+public void removeBufferChangedListener(IBufferChangedListener listener) {
+ if (this.changeListeners != null) {
+ this.changeListeners.remove(listener);
+ if (this.changeListeners.size() == 0) {
+ this.changeListeners = null;
+ }
+ }
+}
+/**
+ * Replaces <code>length</code> characters starting from <code>position</code> with <code>text<code>.
+ * After that operation, the gap is placed at the end of the
+ * inserted <code>text</code>.
+ */
+public void replace(int position, int length, char[] text) {
+ if (!isReadOnly()) {
+ int textLength = text == null ? 0 : text.length;
+ synchronized (this.lock) {
+ // move gap
+ moveAndResizeGap(position + length, textLength - length);
+
+ // overwrite
+ int min = Math.min(textLength, length);
+ if (min > 0) {
+ System.arraycopy(text, 0, this.contents, position, min);
+ }
+ if (length > textLength) {
+ // enlarge the gap
+ this.gapStart -= length - textLength;
+ } else if (textLength > length) {
+ // shrink gap
+ this.gapStart += textLength - length;
+ System.arraycopy(text, 0, this.contents, position, textLength);
+ }
+ }
+ this.flags |= F_HAS_UNSAVED_CHANGES;
+ String string = null;
+ if (textLength > 0) {
+ string = new String(text);
+ }
+ notifyChanged(new BufferChangedEvent(this, position, length, string));
+ }
+}
+/**
+ * Replaces <code>length</code> characters starting from <code>position</code> with <code>text<code>.
+ * After that operation, the gap is placed at the end of the
+ * inserted <code>text</code>.
+ */
+public void replace(int position, int length, String text) {
+ this.replace(position, length, text == null ? null : text.toCharArray());
+}
+/**
+ * @see IBuffer
+ */
+public void save(IProgressMonitor progress, boolean force) throws JavaModelException {
+
+ // determine if saving is required
+ if (isReadOnly() || this.file == null) {
+ return;
+ }
+ synchronized (this.lock) {
+ if (!hasUnsavedChanges())
+ return;
+
+ // use a platform operation to update the resource contents
+ try {
+// String encoding = ((IJavaElement)this.owner).getJavaProject().getOption(PHPCore.CORE_ENCODING, true);
+ String encoding = null;
+ String contents = this.getContents();
+ if (contents == null) return;
+ byte[] bytes = encoding == null
+ ? contents.getBytes()
+ : contents.getBytes(encoding);
+ ByteArrayInputStream stream = new ByteArrayInputStream(bytes);
+
+ this.file.setContents(
+ stream,
+ force ? IResource.FORCE | IResource.KEEP_HISTORY : IResource.KEEP_HISTORY,
+ null);
+ } catch (IOException e) {
+ throw new JavaModelException(e, IJavaModelStatusConstants.IO_EXCEPTION);
+ } catch (CoreException e) {
+ throw new JavaModelException(e);
+ }
+
+ // the resource no longer has unsaved changes
+ this.flags &= ~ (F_HAS_UNSAVED_CHANGES);
+ }
+}
+/**
+ * @see IBuffer
+ */
+public void setContents(char[] newContents) {
+ // allow special case for first initialization
+ // after creation by buffer factory
+ if (this.contents == null) {
+ this.contents = newContents;
+ this.flags &= ~ (F_HAS_UNSAVED_CHANGES);
+ return;
+ }
+
+ if (!isReadOnly()) {
+ String string = null;
+ if (newContents != null) {
+ string = new String(newContents);
+ }
+ BufferChangedEvent event = new BufferChangedEvent(this, 0, this.getLength(), string);
+ synchronized (this.lock) {
+ this.contents = newContents;
+ this.flags |= F_HAS_UNSAVED_CHANGES;
+ this.gapStart = -1;
+ this.gapEnd = -1;
+ }
+ notifyChanged(event);
+ }
+}
+/**
+ * @see IBuffer
+ */
+public void setContents(String newContents) {
+ this.setContents(newContents.toCharArray());
+}
+/**
+ * Sets this <code>Buffer</code> to be read only.
+ */
+protected void setReadOnly(boolean readOnly) {
+ if (readOnly) {
+ this.flags |= F_IS_READ_ONLY;
+ } else {
+ this.flags &= ~(F_IS_READ_ONLY);
+ }
+}
+public String toString() {
+ StringBuffer buffer = new StringBuffer();
+// buffer.append("Owner: " + ((JavaElement)this.owner).toStringWithAncestors()); //$NON-NLS-1$
+ buffer.append("Owner: " + (this.owner).toString()); //$NON-NLS-1$
+ buffer.append("\nHas unsaved changes: " + this.hasUnsavedChanges()); //$NON-NLS-1$
+ buffer.append("\nIs readonly: " + this.isReadOnly()); //$NON-NLS-1$
+ buffer.append("\nIs closed: " + this.isClosed()); //$NON-NLS-1$
+ buffer.append("\nContents:\n"); //$NON-NLS-1$
+ char[] contents = this.getCharacters();
+ if (contents == null) {
+ buffer.append("<null>"); //$NON-NLS-1$
+ } else {
+ int length = contents.length;
+ for (int i = 0; i < length; i++) {
+ char car = contents[i];
+ switch (car) {
+ case '\n':
+ buffer.append("\\n\n"); //$NON-NLS-1$
+ break;
+ case '\r':
+ if (i < length-1 && this.contents[i+1] == '\n') {
+ buffer.append("\\r\\n\n"); //$NON-NLS-1$
+ i++;
+ } else {
+ buffer.append("\\r\n"); //$NON-NLS-1$
+ }
+ break;
+ default:
+ buffer.append(car);
+ break;
+ }
+ }
+ }
+ return buffer.toString();
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.core;
+
+import net.sourceforge.phpdt.core.IBuffer;
+import net.sourceforge.phpdt.core.util.LRUCache;
+
+/**
+ * An LRU cache of <code>IBuffers</code>.
+ */
+public class BufferCache extends OverflowingLRUCache {
+/**
+ * Constructs a new buffer cache of the given size.
+ */
+public BufferCache(int size) {
+ super(size);
+}
+/**
+ * Constructs a new buffer cache of the given size.
+ */
+public BufferCache(int size, int overflow) {
+ super(size, overflow);
+}
+/**
+ * Returns true if the buffer is successfully closed and
+ * removed from the cache, otherwise false.
+ *
+ * <p>NOTE: this triggers an external removal of this buffer
+ * by closing the buffer.
+ */
+protected boolean close(LRUCacheEntry entry) {
+ IBuffer buffer= (IBuffer) entry._fValue;
+ if (buffer.hasUnsavedChanges()) {
+ return false;
+ } else {
+ buffer.close();
+ return true;
+ }
+}
+ /**
+ * Returns a new instance of the reciever.
+ */
+ protected LRUCache newInstance(int size, int overflow) {
+ return new BufferCache(size, overflow);
+ }
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.core;
+
+import java.util.Enumeration;
+
+import net.sourceforge.phpdt.core.IBuffer;
+import net.sourceforge.phpdt.core.IBufferFactory;
+import net.sourceforge.phpdt.core.IJavaElement;
+import net.sourceforge.phpdt.core.IOpenable;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+
+
+/**
+ * The buffer manager manages the set of open buffers.
+ * It implements an LRU cache of buffers.
+ */
+public class BufferManager implements IBufferFactory {
+
+ protected static BufferManager DEFAULT_BUFFER_MANAGER;
+
+ /**
+ * LRU cache of buffers. The key and value for an entry
+ * in the table is the identical buffer.
+ */
+ protected OverflowingLRUCache openBuffers = new BufferCache(60);
+
+/**
+ * Creates a new buffer manager.
+ */
+public BufferManager() {
+}
+/**
+ * Adds a buffer to the table of open buffers.
+ */
+protected void addBuffer(IBuffer buffer) {
+ openBuffers.put(buffer.getOwner(), buffer);
+}
+/**
+ * @see IBufferFactory#createBuffer(IOpenable)
+ */
+public IBuffer createBuffer(IOpenable owner) {
+ IJavaElement element = (IJavaElement)owner;
+ IResource resource = element.getResource();
+ return
+ new Buffer(
+ resource instanceof IFile ? (IFile)resource : null,
+ owner,
+ element.isReadOnly());
+}
+
+/**
+ * Returns the open buffer associated with the given owner,
+ * or <code>null</code> if the owner does not have an open
+ * buffer associated with it.
+ */
+public IBuffer getBuffer(IOpenable owner) {
+ return (IBuffer)openBuffers.get(owner);
+}
+/**
+ * Returns the default buffer manager.
+ */
+public synchronized static BufferManager getDefaultBufferManager() {
+ if (DEFAULT_BUFFER_MANAGER == null) {
+ DEFAULT_BUFFER_MANAGER = new BufferManager();
+ }
+ return DEFAULT_BUFFER_MANAGER;
+}
+/**
+ * Returns the default buffer factory.
+ */
+public IBufferFactory getDefaultBufferFactory() {
+ return this;
+}
+/**
+ * Returns an enumeration of all open buffers.
+ * <p>
+ * The <code>Enumeration</code> answered is thread safe.
+ *
+ * @see OverflowingLRUCache
+ * @return Enumeration of IBuffer
+ */
+public Enumeration getOpenBuffers() {
+ synchronized (openBuffers) {
+ openBuffers.shrink();
+ return openBuffers.elements();
+ }
+}
+
+
+/**
+ * Removes a buffer from the table of open buffers.
+ */
+protected void removeBuffer(IBuffer buffer) {
+ openBuffers.remove(buffer.getOwner());
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.core;
+
+import net.sourceforge.phpdt.core.IJavaElement;
+import net.sourceforge.phpdt.core.IJavaModel;
+import net.sourceforge.phpdt.core.IJavaModelStatusConstants;
+import net.sourceforge.phpdt.core.IOpenable;
+import net.sourceforge.phpdt.core.IParent;
+import net.sourceforge.phpdt.core.JavaModelException;
+import net.sourceforge.phpdt.internal.corext.Assert;
+
+import org.eclipse.core.resources.IResourceStatus;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.PlatformObject;
+
+/**
+ * Root of Java element handle hierarchy.
+ *
+ * @see IJavaElement
+ */
+public abstract class JavaElement extends PlatformObject implements IJavaElement {
+
+ public static final char JEM_JAVAPROJECT= '=';
+ public static final char JEM_PACKAGEFRAGMENTROOT= Path.SEPARATOR;
+ public static final char JEM_PACKAGEFRAGMENT= '<';
+ public static final char JEM_FIELD= '^';
+ public static final char JEM_METHOD= '~';
+ public static final char JEM_INITIALIZER= '|';
+ public static final char JEM_COMPILATIONUNIT= '{';
+ public static final char JEM_CLASSFILE= '(';
+ public static final char JEM_TYPE= '[';
+ public static final char JEM_PACKAGEDECLARATION= '%';
+ public static final char JEM_IMPORTDECLARATION= '#';
+
+ /**
+ * A count to uniquely identify this element in the case
+ * that a duplicate named element exists. For example, if
+ * there are two fields in a compilation unit with the
+ * same name, the occurrence count is used to distinguish
+ * them. The occurrence count starts at 1 (thus the first
+ * occurrence is occurrence 1, not occurrence 0).
+ */
+ protected int fOccurrenceCount = 1;
+
+
+ /**
+ * This element's type - one of the constants defined
+ * in IJavaLanguageElementTypes.
+ */
+ protected int fLEType = 0;
+
+ /**
+ * This element's parent, or <code>null</code> if this
+ * element does not have a parent.
+ */
+ protected IJavaElement fParent;
+
+ /**
+ * This element's name, or an empty <code>String</code> if this
+ * element does not have a name.
+ */
+ protected String fName;
+
+ protected static final Object NO_INFO = new Object();
+
+ /**
+ * Constructs a handle for a java element of the specified type, with
+ * the given parent element and name.
+ *
+ * @param type - one of the constants defined in IJavaLanguageElement
+ *
+ * @exception IllegalArgumentException if the type is not one of the valid
+ * Java element type constants
+ *
+ */
+ protected JavaElement(int type, IJavaElement parent, String name) throws IllegalArgumentException {
+ if (type < JAVA_MODEL || type > IMPORT_DECLARATION) {
+ throw new IllegalArgumentException(Util.bind("element.invalidType")); //$NON-NLS-1$
+ }
+ fLEType= type;
+ fParent= parent;
+ fName= name;
+ }
+ /**
+ * @see IOpenable
+ */
+// public void close() throws JavaModelException {
+// Object info = JavaModelManager.getJavaModelManager().peekAtInfo(this);
+// if (info != null) {
+// boolean wasVerbose = false;
+// try {
+// if (JavaModelManager.VERBOSE) {
+// System.out.println("CLOSING Element ("+ Thread.currentThread()+"): " + this.toStringWithAncestors()); //$NON-NLS-1$//$NON-NLS-2$
+// wasVerbose = true;
+// JavaModelManager.VERBOSE = false;
+// }
+// if (this instanceof IParent) {
+// IJavaElement[] children = ((JavaElementInfo) info).getChildren();
+// for (int i = 0, size = children.length; i < size; ++i) {
+// JavaElement child = (JavaElement) children[i];
+// child.close();
+// }
+// }
+// closing(info);
+// JavaModelManager.getJavaModelManager().removeInfo(this);
+// if (wasVerbose) {
+// System.out.println("-> Package cache size = " + JavaModelManager.getJavaModelManager().cache.pkgSize()); //$NON-NLS-1$
+// System.out.println("-> Openable cache filling ratio = " + JavaModelManager.getJavaModelManager().cache.openableFillingRatio() + "%"); //$NON-NLS-1$//$NON-NLS-2$
+// }
+// } finally {
+// JavaModelManager.VERBOSE = wasVerbose;
+// }
+// }
+// }
+ /**
+ * This element is being closed. Do any necessary cleanup.
+ */
+ protected void closing(Object info) throws JavaModelException {
+ }
+ /**
+ * Returns true if this handle represents the same Java element
+ * as the given handle. By default, two handles represent the same
+ * element if they are identical or if they represent the same type
+ * of element, have equal names, parents, and occurrence counts.
+ *
+ * <p>If a subclass has other requirements for equality, this method
+ * must be overridden.
+ *
+ * @see Object#equals
+ */
+ public boolean equals(Object o) {
+
+ if (this == o) return true;
+
+ // Java model parent is null
+ if (fParent == null) return super.equals(o);
+
+ if (o instanceof JavaElement) {
+ JavaElement other = (JavaElement) o;
+ if (fLEType != other.fLEType) return false;
+
+ return fName.equals(other.fName) &&
+ fParent.equals(other.fParent) &&
+ fOccurrenceCount == other.fOccurrenceCount;
+ }
+ return false;
+ }
+ /**
+ * Returns true if this <code>JavaElement</code> is equivalent to the given
+ * <code>IDOMNode</code>.
+ */
+// protected boolean equalsDOMNode(IDOMNode node) throws JavaModelException {
+// return false;
+// }
+ /**
+ * @see IJavaElement
+ */
+// public boolean exists() {
+//
+// try {
+// getElementInfo();
+// return true;
+// } catch (JavaModelException e) {
+// }
+// return false;
+// }
+
+ /**
+ * Returns the <code>IDOMNode</code> that corresponds to this <code>JavaElement</code>
+ * or <code>null</code> if there is no corresponding node.
+ */
+// public IDOMNode findNode(IDOMCompilationUnit dom) {
+// int type = getElementType();
+// if (type == IJavaElement.COMPILATION_UNIT ||
+// type == IJavaElement.FIELD ||
+// type == IJavaElement.IMPORT_DECLARATION ||
+// type == IJavaElement.INITIALIZER ||
+// type == IJavaElement.METHOD ||
+// type == IJavaElement.PACKAGE_DECLARATION ||
+// type == IJavaElement.TYPE) {
+// ArrayList path = new ArrayList();
+// IJavaElement element = this;
+// while (element != null && element.getElementType() != IJavaElement.COMPILATION_UNIT) {
+// if (element.getElementType() != IJavaElement.IMPORT_CONTAINER) {
+// // the DOM does not have import containers, so skip them
+// path.add(0, element);
+// }
+// element = element.getParent();
+// }
+// if (path.size() == 0) {
+// try {
+// if (equalsDOMNode(dom)) {
+// return dom;
+// } else {
+// return null;
+// }
+// } catch(JavaModelException e) {
+// return null;
+// }
+// }
+// return ((JavaElement) path.get(0)).followPath(path, 0, dom.getFirstChild());
+// } else {
+// return null;
+// }
+// }
+// /**
+// */
+// protected IDOMNode followPath(ArrayList path, int position, IDOMNode node) {
+//
+// try {
+// if (equalsDOMNode(node)) {
+// if (position == (path.size() - 1)) {
+// return node;
+// } else {
+// if (node.getFirstChild() != null) {
+// position++;
+// return ((JavaElement)path.get(position)).followPath(path, position, node.getFirstChild());
+// } else {
+// return null;
+// }
+// }
+// } else if (node.getNextNode() != null) {
+// return followPath(path, position, node.getNextNode());
+// } else {
+// return null;
+// }
+// } catch (JavaModelException e) {
+// return null;
+// }
+//
+// }
+ /**
+ * @see IJavaElement
+ */
+ public IJavaElement getAncestor(int ancestorType) {
+
+ IJavaElement element = this;
+ while (element != null) {
+ if (element.getElementType() == ancestorType) return element;
+ element= element.getParent();
+ }
+ return null;
+ }
+ /**
+ * @see IParent
+ */
+// public IJavaElement[] getChildren() throws JavaModelException {
+// return ((JavaElementInfo)getElementInfo()).getChildren();
+// }
+ /**
+ * Returns a collection of (immediate) children of this node of the
+ * specified type.
+ *
+ * @param type - one of constants defined by IJavaLanguageElementTypes
+ */
+// public ArrayList getChildrenOfType(int type) throws JavaModelException {
+// IJavaElement[] children = getChildren();
+// int size = children.length;
+// ArrayList list = new ArrayList(size);
+// for (int i = 0; i < size; ++i) {
+// JavaElement elt = (JavaElement)children[i];
+// if (elt.getElementType() == type) {
+// list.add(elt);
+// }
+// }
+// return list;
+// }
+ /**
+ * @see IMember
+ */
+// public IClassFile getClassFile() {
+// return null;
+// }
+// /**
+// * @see IMember
+// */
+// public ICompilationUnit getCompilationUnit() {
+// return null;
+// }
+ /**
+ * Returns the info for this handle.
+ * If this element is not already open, it and all of its parents are opened.
+ * Does not return null.
+ * NOTE: BinaryType infos are NJOT rooted under JavaElementInfo.
+ * @exception JavaModelException if the element is not present or not accessible
+ */
+// public Object getElementInfo() throws JavaModelException {
+//
+// // workaround to ensure parent project resolved classpath is available to avoid triggering initializers
+// // while the JavaModelManager lock is acquired (can cause deadlocks in clients)
+// IJavaProject project = getJavaProject();
+// if (project != null && !project.isOpen()) {
+// // TODO: need to revisit, since deadlock could still occur if perProjectInfo is removed concurrent before entering the lock
+// try {
+// project.getResolvedClasspath(true); // trigger all possible container/variable initialization outside the model lock
+// } catch (JavaModelException e) {
+// // project is not accessible or is not a java project
+// }
+// }
+//
+// // element info creation is done inside a lock on the JavaModelManager
+// JavaModelManager manager;
+// synchronized(manager = JavaModelManager.getJavaModelManager()){
+// Object info = manager.getInfo(this);
+// if (info == null) {
+// openHierarchy();
+// info= manager.getInfo(this);
+// if (info == null) {
+// throw newNotPresentException();
+// }
+// }
+// return info;
+// }
+// }
+ /**
+ * @see IAdaptable
+ */
+ public String getElementName() {
+ return fName;
+ }
+ /**
+ * @see IJavaElement
+ */
+ public int getElementType() {
+ return fLEType;
+ }
+ /**
+ * @see IJavaElement
+ */
+ public String getHandleIdentifier() {
+ return getHandleMemento();
+ }
+ /**
+ * @see JavaElement#getHandleMemento()
+ */
+ public String getHandleMemento(){
+ StringBuffer buff= new StringBuffer(((JavaElement)getParent()).getHandleMemento());
+ buff.append(getHandleMementoDelimiter());
+ buff.append(getElementName());
+ return buff.toString();
+ }
+ /**
+ * Returns the <code>char</code> that marks the start of this handles
+ * contribution to a memento.
+ */
+ protected abstract char getHandleMementoDelimiter();
+ /**
+ * @see IJavaElement
+ */
+ public IJavaModel getJavaModel() {
+ IJavaElement current = this;
+ do {
+ if (current instanceof IJavaModel) return (IJavaModel) current;
+ } while ((current = current.getParent()) != null);
+ return null;
+ }
+//
+// /**
+// * @see IJavaElement
+// */
+// public IJavaProject getJavaProject() {
+// IJavaElement current = this;
+// do {
+// if (current instanceof IJavaProject) return (IJavaProject) current;
+// } while ((current = current.getParent()) != null);
+// return null;
+// }
+ /**
+ * Returns the occurrence count of the handle.
+ */
+ protected int getOccurrenceCount() {
+ return fOccurrenceCount;
+ }
+ /*
+ * @see IJavaElement
+ */
+ public IOpenable getOpenable() {
+ return this.getOpenableParent();
+ }
+ /**
+ * Return the first instance of IOpenable in the parent
+ * hierarchy of this element.
+ *
+ * <p>Subclasses that are not IOpenable's must override this method.
+ */
+ public IOpenable getOpenableParent() {
+
+ return (IOpenable)fParent;
+ }
+ /**
+ * @see IJavaElement
+ */
+ public IJavaElement getParent() {
+ return fParent;
+ }
+
+ /**
+ * Returns the element that is located at the given source position
+ * in this element. This is a helper method for <code>ICompilationUnit#getElementAt</code>,
+ * and only works on compilation units and types. The position given is
+ * known to be within this element's source range already, and if no finer
+ * grained element is found at the position, this element is returned.
+ */
+// protected IJavaElement getSourceElementAt(int position) throws JavaModelException {
+// if (this instanceof ISourceReference) {
+// IJavaElement[] children = getChildren();
+// int i;
+// for (i = 0; i < children.length; i++) {
+// IJavaElement aChild = children[i];
+// if (aChild instanceof SourceRefElement) {
+// SourceRefElement child = (SourceRefElement) children[i];
+// ISourceRange range = child.getSourceRange();
+// if (position < range.getOffset() + range.getLength() && position >= range.getOffset()) {
+// if (child instanceof IParent) {
+// return child.getSourceElementAt(position);
+// } else {
+// return child;
+// }
+// }
+// }
+// }
+// } else {
+// // should not happen
+// Assert.isTrue(false);
+// }
+// return this;
+// }
+ /**
+ * Returns the SourceMapper facility for this element, or
+ * <code>null</code> if this element does not have a
+ * SourceMapper.
+ */
+// public SourceMapper getSourceMapper() {
+// return ((JavaElement)getParent()).getSourceMapper();
+// }
+
+ /**
+ * Returns the hash code for this Java element. By default,
+ * the hash code for an element is a combination of its name
+ * and parent's hash code. Elements with other requirements must
+ * override this method.
+ */
+ public int hashCode() {
+ if (fParent == null) return super.hashCode();
+ return Util.combineHashCodes(fName.hashCode(), fParent.hashCode());
+ }
+ /**
+ * Returns true if this element is an ancestor of the given element,
+ * otherwise false.
+ */
+ protected boolean isAncestorOf(IJavaElement e) {
+ IJavaElement parent= e.getParent();
+ while (parent != null && !parent.equals(this)) {
+ parent= parent.getParent();
+ }
+ return parent != null;
+ }
+
+ /**
+ * @see IJavaElement
+ */
+ public boolean isReadOnly() {
+ return false;
+ }
+ /**
+ * @see IJavaElement
+ */
+// public boolean isStructureKnown() throws JavaModelException {
+// return ((JavaElementInfo)getElementInfo()).isStructureKnown();
+// }
+// /**
+// * Creates and returns and not present exception for this element.
+// */
+// protected JavaModelException newNotPresentException() {
+// return new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this));
+// }
+// /**
+// * Opens this element and all parents that are not already open.
+// *
+// * @exception JavaModelException this element is not present or accessible
+// */
+// protected void openHierarchy() throws JavaModelException {
+// if (this instanceof IOpenable) {
+// ((Openable) this).openWhenClosed(null);
+// } else {
+// Openable openableParent = (Openable)getOpenableParent();
+// if (openableParent != null) {
+// JavaElementInfo openableParentInfo = (JavaElementInfo) JavaModelManager.getJavaModelManager().getInfo((IJavaElement) openableParent);
+// if (openableParentInfo == null) {
+// openableParent.openWhenClosed(null);
+// } else {
+// throw newNotPresentException();
+// }
+// }
+// }
+// }
+ /**
+ * This element has just been opened. Do any necessary setup.
+ */
+ protected void opening(Object info) {
+ }
+ /**
+ */
+ public String readableName() {
+ return this.getElementName();
+ }
+ /**
+ * Removes all cached info from the Java Model, including all children,
+ * but does not close this element.
+ */
+// protected void removeInfo() {
+// Object info = JavaModelManager.getJavaModelManager().peekAtInfo(this);
+// if (info != null) {
+// if (this instanceof IParent) {
+// IJavaElement[] children = ((JavaElementInfo)info).getChildren();
+// for (int i = 0, size = children.length; i < size; ++i) {
+// JavaElement child = (JavaElement) children[i];
+// child.removeInfo();
+// }
+// }
+// JavaModelManager.getJavaModelManager().removeInfo(this);
+// }
+// }
+// /**
+// * Returns a copy of this element rooted at the given project.
+// */
+// public abstract IJavaElement rootedAt(IJavaProject project);
+// /**
+// * Runs a Java Model Operation
+// */
+// public static void runOperation(JavaModelOperation operation, IProgressMonitor monitor) throws JavaModelException {
+// try {
+// if (operation.isReadOnly() || ResourcesPlugin.getWorkspace().isTreeLocked()) {
+// operation.run(monitor);
+// } else {
+// // use IWorkspace.run(...) to ensure that a build will be done in autobuild mode
+// ResourcesPlugin.getWorkspace().run(operation, monitor);
+// }
+// } catch (CoreException ce) {
+// if (ce instanceof JavaModelException) {
+// throw (JavaModelException)ce;
+// } else {
+// if (ce.getStatus().getCode() == IResourceStatus.OPERATION_FAILED) {
+// Throwable e= ce.getStatus().getException();
+// if (e instanceof JavaModelException) {
+// throw (JavaModelException) e;
+// }
+// }
+// throw new JavaModelException(ce);
+// }
+// }
+// }
+ /**
+ * Sets the occurrence count of the handle.
+ */
+ protected void setOccurrenceCount(int count) {
+ fOccurrenceCount = count;
+ }
+ protected String tabString(int tab) {
+ StringBuffer buffer = new StringBuffer();
+ for (int i = tab; i > 0; i--)
+ buffer.append(" "); //$NON-NLS-1$
+ return buffer.toString();
+ }
+ /**
+ * Debugging purposes
+ */
+ public String toDebugString() {
+ StringBuffer buffer = new StringBuffer();
+ this.toStringInfo(0, buffer, NO_INFO);
+ return buffer.toString();
+ }
+ /**
+ * Debugging purposes
+ */
+ public String toString() {
+ StringBuffer buffer = new StringBuffer();
+ toString(0, buffer);
+ return buffer.toString();
+ }
+ /**
+ * Debugging purposes
+ */
+ protected void toString(int tab, StringBuffer buffer) {
+ // Object info = this.toStringInfo(tab, buffer);
+ Object info = null;
+ if (tab == 0) {
+ this.toStringAncestors(buffer);
+ }
+ this.toStringChildren(tab, buffer, info);
+ }
+ /**
+ * Debugging purposes
+ */
+ public String toStringWithAncestors() {
+ StringBuffer buffer = new StringBuffer();
+ this.toStringInfo(0, buffer, NO_INFO);
+ this.toStringAncestors(buffer);
+ return buffer.toString();
+ }
+ /**
+ * Debugging purposes
+ */
+ protected void toStringAncestors(StringBuffer buffer) {
+ JavaElement parent = (JavaElement)this.getParent();
+ if (parent != null && parent.getParent() != null) {
+ buffer.append(" [in "); //$NON-NLS-1$
+ parent.toStringInfo(0, buffer, NO_INFO);
+ parent.toStringAncestors(buffer);
+ buffer.append("]"); //$NON-NLS-1$
+ }
+ }
+ /**
+ * Debugging purposes
+ */
+ protected void toStringChildren(int tab, StringBuffer buffer, Object info) {
+ if (info == null || !(info instanceof JavaElementInfo)) return;
+ IJavaElement[] children = ((JavaElementInfo)info).getChildren();
+ for (int i = 0; i < children.length; i++) {
+ buffer.append("\n"); //$NON-NLS-1$
+ ((JavaElement)children[i]).toString(tab + 1, buffer);
+ }
+ }
+ /**
+ * Debugging purposes
+ */
+// public Object toStringInfo(int tab, StringBuffer buffer) {
+// Object info = JavaModelManager.getJavaModelManager().peekAtInfo(this);
+// this.toStringInfo(tab, buffer, info);
+// return info;
+// }
+ /**
+ * Debugging purposes
+ */
+ protected void toStringInfo(int tab, StringBuffer buffer, Object info) {
+ buffer.append(this.tabString(tab));
+ buffer.append(getElementName());
+ if (info == null) {
+ buffer.append(" (not open)"); //$NON-NLS-1$
+ }
+ }
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.core;
+
+import net.sourceforge.phpdt.core.IJavaElement;
+
+
+
+/**
+ * Holds cached structure and properties for a Java element.
+ * Subclassed to carry properties for specific kinds of elements.
+ */
+/* package */ class JavaElementInfo {
+
+ /**
+ * Collection of handles of immediate children of this
+ * object. This is an empty array if this element has
+ * no children.
+ */
+ protected IJavaElement[] fChildren;
+
+ /**
+ * Shared empty collection used for efficiency.
+ */
+ protected static IJavaElement[] fgEmptyChildren = new IJavaElement[]{};
+ /**
+ * Is the structure of this element known
+ * @see IJavaElement#isStructureKnown()
+ */
+ protected boolean fIsStructureKnown = false;
+
+ /**
+ * Shared empty collection used for efficiency.
+ */
+ static Object[] NO_NON_JAVA_RESOURCES = new Object[] {};
+ protected JavaElementInfo() {
+ fChildren = fgEmptyChildren;
+ }
+ public void addChild(IJavaElement child) {
+ if (fChildren == fgEmptyChildren) {
+ setChildren(new IJavaElement[] {child});
+ } else {
+ if (!includesChild(child)) {
+ setChildren(growAndAddToArray(fChildren, child));
+ }
+ }
+ }
+ public Object clone() {
+ try {
+ return super.clone();
+ }
+ catch (CloneNotSupportedException e) {
+ throw new Error();
+ }
+ }
+ public IJavaElement[] getChildren() {
+ return fChildren;
+ }
+ /**
+ * Adds the new element to a new array that contains all of the elements of the old array.
+ * Returns the new array.
+ */
+ protected IJavaElement[] growAndAddToArray(IJavaElement[] array, IJavaElement addition) {
+ IJavaElement[] old = array;
+ array = new IJavaElement[old.length + 1];
+ System.arraycopy(old, 0, array, 0, old.length);
+ array[old.length] = addition;
+ return array;
+ }
+ /**
+ * Returns <code>true</code> if this child is in my children collection
+ */
+ protected boolean includesChild(IJavaElement child) {
+
+ for (int i= 0; i < fChildren.length; i++) {
+ if (fChildren[i].equals(child)) {
+ return true;
+ }
+ }
+ return false;
+ }
+ /**
+ * @see IJavaElement#isStructureKnown()
+ */
+ public boolean isStructureKnown() {
+ return fIsStructureKnown;
+ }
+ /**
+ * Returns an array with all the same elements as the specified array except for
+ * the element to remove. Assumes that the deletion is contained in the array.
+ */
+ protected IJavaElement[] removeAndShrinkArray(IJavaElement[] array, IJavaElement deletion) {
+ IJavaElement[] old = array;
+ array = new IJavaElement[old.length - 1];
+ int j = 0;
+ for (int i = 0; i < old.length; i++) {
+ if (!old[i].equals(deletion)) {
+ array[j] = old[i];
+ } else {
+ System.arraycopy(old, i + 1, array, j, old.length - (i + 1));
+ return array;
+ }
+ j++;
+ }
+ return array;
+ }
+ public void removeChild(IJavaElement child) {
+ if (includesChild(child)) {
+ setChildren(removeAndShrinkArray(fChildren, child));
+ }
+ }
+ public void setChildren(IJavaElement[] children) {
+ fChildren = children;
+ }
+ /**
+ * Sets whether the structure of this element known
+ * @see IJavaElement#isStructureKnown()
+ */
+ public void setIsStructureKnown(boolean newIsStructureKnown) {
+ fIsStructureKnown = newIsStructureKnown;
+ }
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.core;
+
+import net.sourceforge.phpdt.core.IJavaElement;
+import net.sourceforge.phpdt.core.IJavaModelStatus;
+import net.sourceforge.phpdt.core.IJavaModelStatusConstants;
+import net.sourceforge.phpeclipse.PHPCore;
+
+import org.eclipse.core.resources.IResourceStatus;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+
+/**
+ * @see IJavaModelStatus
+ */
+
+public class JavaModelStatus
+ extends Status
+ implements IJavaModelStatus, IJavaModelStatusConstants, IResourceStatus {
+
+ /**
+ * The elements related to the failure, or <code>null</code>
+ * if no elements are involved.
+ */
+ protected IJavaElement[] fElements = new IJavaElement[0];
+
+ /**
+ * The path related to the failure, or <code>null</code>
+ * if no path is involved.
+ */
+ protected IPath fPath;
+ /**
+ * The <code>String</code> related to the failure, or <code>null</code>
+ * if no <code>String</code> is involved.
+ */
+ protected String fString;
+ /**
+ * Empty children
+ */
+ protected final static IStatus[] fgEmptyChildren = new IStatus[] {
+ };
+ protected IStatus[] fChildren = fgEmptyChildren;
+
+ /**
+ * Shared empty collection used for efficiency.
+ */
+ protected static IJavaElement[] fgObjectEmptyChildren = new IJavaElement[]{};
+
+
+ /**
+ * Singleton OK object
+ */
+ public static final IJavaModelStatus VERIFIED_OK = new JavaModelStatus(OK, OK, Util.bind("status.OK")); //$NON-NLS-1$
+
+ /**
+ * Constructs an Java model status with no corresponding elements.
+ */
+ public JavaModelStatus() {
+ // no code for an multi-status
+ super(ERROR, PHPCore.PLUGIN_ID, 0, "JavaModelStatus", null); //$NON-NLS-1$
+ }
+ /**
+ * Constructs an Java model status with no corresponding elements.
+ */
+ public JavaModelStatus(int code) {
+ super(ERROR, PHPCore.PLUGIN_ID, code, "JavaModelStatus", null); //$NON-NLS-1$
+ // fElements= JavaElementInfo.fgEmptyChildren;
+ fElements = fgObjectEmptyChildren;
+ }
+ /**
+ * Constructs an Java model status with the given corresponding
+ * elements.
+ */
+ public JavaModelStatus(int code, IJavaElement[] elements) {
+ super(ERROR, PHPCore.PLUGIN_ID, code, "JavaModelStatus", null); //$NON-NLS-1$
+ fElements = elements;
+ fPath = null;
+ }
+ /**
+ * Constructs an Java model status with no corresponding elements.
+ */
+ public JavaModelStatus(int code, String string) {
+ this(ERROR, code, string);
+ }
+ /**
+ * Constructs an Java model status with no corresponding elements.
+ */
+ public JavaModelStatus(int severity, int code, String string) {
+ super(severity, PHPCore.PLUGIN_ID, code, "JavaModelStatus", null); //$NON-NLS-1$
+ // fElements= JavaElementInfo.fgEmptyChildren;
+ fElements = fgObjectEmptyChildren;
+ fPath = null;
+ fString = string;
+ }
+ /**
+ * Constructs an Java model status with no corresponding elements.
+ */
+ public JavaModelStatus(int code, Throwable throwable) {
+ super(ERROR, PHPCore.PLUGIN_ID, code, "JavaModelStatus", throwable); //$NON-NLS-1$
+ // fElements= JavaElementInfo.fgEmptyChildren;
+ fElements = fgObjectEmptyChildren;
+ }
+ /**
+ * Constructs an Java model status with no corresponding elements.
+ */
+ public JavaModelStatus(int code, IPath path) {
+ super(ERROR, PHPCore.PLUGIN_ID, code, "JavaModelStatus", null); //$NON-NLS-1$
+ // fElements= JavaElementInfo.fgEmptyChildren;
+ fElements = fgObjectEmptyChildren;
+ fPath = path;
+ }
+ /**
+ * Constructs an Java model status with the given corresponding
+ * element.
+ */
+ // public JavaModelStatus(int code, IJavaElement element) {
+ // this(code, new IJavaElement[]{element});
+ // }
+ /**
+ * Constructs an Java model status with the given corresponding
+ * element and string
+ */
+ // public JavaModelStatus(int code, IJavaElement element, String string) {
+ // this(code, new IJavaElement[]{element});
+ // fString = string;
+ // }
+ //
+ // /**
+ // * Constructs an Java model status with the given corresponding
+ // * element and path
+ // */
+ // public JavaModelStatus(int code, IJavaElement element, IPath path) {
+ // this(code, new IJavaElement[]{element});
+ // fPath = path;
+ // }
+ /**
+ * Constructs an Java model status with no corresponding elements.
+ */
+ public JavaModelStatus(CoreException coreException) {
+ super(ERROR, PHPCore.PLUGIN_ID, CORE_EXCEPTION, "JavaModelStatus", coreException); //$NON-NLS-1$
+ // fElements= JavaElementInfo.fgEmptyChildren;
+ fElements = fgObjectEmptyChildren;
+ }
+ protected int getBits() {
+ int severity = 1 << (getCode() % 100 / 33);
+ int category = 1 << ((getCode() / 100) + 3);
+ return severity | category;
+ }
+ /**
+ * @see IStatus
+ */
+ public IStatus[] getChildren() {
+ return fChildren;
+ }
+ /**
+ * @see IJavaModelStatus
+ */
+ public IJavaElement[] getElements() {
+ return fElements;
+ }
+ /**
+ * Returns the message that is relevant to the code of this status.
+ */
+ public String getMessage() {
+ Throwable exception = getException();
+ if (exception == null) {
+ switch (getCode()) {
+ case CORE_EXCEPTION :
+ return Util.bind("status.coreException"); //$NON-NLS-1$
+
+ case BUILDER_INITIALIZATION_ERROR :
+ return Util.bind("build.initializationError"); //$NON-NLS-1$
+
+ case BUILDER_SERIALIZATION_ERROR :
+ return Util.bind("build.serializationError"); //$NON-NLS-1$
+
+ case DEVICE_PATH :
+ return Util.bind("status.cannotUseDeviceOnPath", getPath().toString()); //$NON-NLS-1$
+
+ case DOM_EXCEPTION :
+ return Util.bind("status.JDOMError"); //$NON-NLS-1$
+
+// case ELEMENT_DOES_NOT_EXIST:
+// return Util.bind("element.doesNotExist",((JavaElement)fElements[0]).toStringWithAncestors()); //$NON-NLS-1$
+
+ case EVALUATION_ERROR :
+ return Util.bind("status.evaluationError", fString); //$NON-NLS-1$
+
+ case INDEX_OUT_OF_BOUNDS :
+ return Util.bind("status.indexOutOfBounds"); //$NON-NLS-1$
+
+ case INVALID_CONTENTS :
+ return Util.bind("status.invalidContents"); //$NON-NLS-1$
+
+ // case INVALID_DESTINATION:
+ // return Util.bind("status.invalidDestination", ((JavaElement)fElements[0]).toStringWithAncestors()); //$NON-NLS-1$
+ //
+ // case INVALID_ELEMENT_TYPES:
+ // StringBuffer buff= new StringBuffer(Util.bind("operation.notSupported")); //$NON-NLS-1$
+ // for (int i= 0; i < fElements.length; i++) {
+ // if (i > 0) {
+ // buff.append(", "); //$NON-NLS-1$
+ // }
+ // buff.append(((JavaElement)fElements[i]).toStringWithAncestors());
+ // }
+ // return buff.toString();
+
+ case INVALID_NAME :
+ return Util.bind("status.invalidName", fString); //$NON-NLS-1$
+
+ case INVALID_PACKAGE :
+ return Util.bind("status.invalidPackage", fString); //$NON-NLS-1$
+
+ case INVALID_PATH :
+ if (fString != null) {
+ return fString;
+ } else {
+ return Util.bind("status.invalidPath", getPath() == null ? "null" : getPath().toString()); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ case INVALID_PROJECT :
+ return Util.bind("status.invalidProject", fString); //$NON-NLS-1$
+
+ case INVALID_RESOURCE :
+ return Util.bind("status.invalidResource", fString); //$NON-NLS-1$
+
+ case INVALID_RESOURCE_TYPE :
+ return Util.bind("status.invalidResourceType", fString); //$NON-NLS-1$
+
+ // case INVALID_SIBLING:
+ // if (fString != null) {
+ // return Util.bind("status.invalidSibling", fString); //$NON-NLS-1$
+ // } else {
+ // return Util.bind("status.invalidSibling", ((JavaElement)fElements[0]).toStringWithAncestors()); //$NON-NLS-1$
+ // }
+
+ case IO_EXCEPTION :
+ return Util.bind("status.IOException"); //$NON-NLS-1$
+
+ // case NAME_COLLISION:
+ // if (fElements != null && fElements.length > 0) {
+ // IJavaElement element = fElements[0];
+ // String name = element.getElementName();
+ // if (element instanceof IPackageFragment && name.equals(IPackageFragment.DEFAULT_PACKAGE_NAME)) {
+ // return Util.bind("operation.cannotRenameDefaultPackage"); //$NON-NLS-1$
+ // }
+ // }
+ // if (fString != null) {
+ // return fString;
+ // } else {
+ // return Util.bind("status.nameCollision", ""); //$NON-NLS-1$ //$NON-NLS-2$
+ // }
+ case NO_ELEMENTS_TO_PROCESS :
+ return Util.bind("operation.needElements"); //$NON-NLS-1$
+
+ case NULL_NAME :
+ return Util.bind("operation.needName"); //$NON-NLS-1$
+
+ case NULL_PATH :
+ return Util.bind("operation.needPath"); //$NON-NLS-1$
+
+ case NULL_STRING :
+ return Util.bind("operation.needString"); //$NON-NLS-1$
+
+ // case PATH_OUTSIDE_PROJECT:
+ // return Util.bind("operation.pathOutsideProject", fString, ((JavaElement)fElements[0]).toStringWithAncestors()); //$NON-NLS-1$
+ //
+ // case READ_ONLY:
+ // IJavaElement element = fElements[0];
+ // String name = element.getElementName();
+ // if (element instanceof IPackageFragment && name.equals(IPackageFragment.DEFAULT_PACKAGE_NAME)) {
+ // return Util.bind("status.defaultPackageReadOnly"); //$NON-NLS-1$
+ // }
+ // return Util.bind("status.readOnly", name); //$NON-NLS-1$
+
+ case RELATIVE_PATH :
+ return Util.bind("operation.needAbsolutePath", getPath().toString()); //$NON-NLS-1$
+
+ case TARGET_EXCEPTION :
+ return Util.bind("status.targetException"); //$NON-NLS-1$
+
+ case UPDATE_CONFLICT :
+ return Util.bind("status.updateConflict"); //$NON-NLS-1$
+
+ case NO_LOCAL_CONTENTS :
+ return Util.bind("status.noLocalContents", getPath().toString()); //$NON-NLS-1$
+
+ // case CP_CONTAINER_PATH_UNBOUND:
+ // IPath path = this.fPath;
+ // IJavaProject javaProject = (IJavaProject)fElements[0];
+ // ClasspathContainerInitializer initializer = PHPCore.getClasspathContainerInitializer(path.segment(0));
+ // String description = null;
+ // if (initializer != null) description = initializer.getDescription(path, javaProject);
+ // if (description == null) description = path.makeRelative().toString();
+ // return Util.bind("classpath.unboundContainerPath", description); //$NON-NLS-1$
+ //
+ // case INVALID_CP_CONTAINER_ENTRY:
+ // path = this.fPath;
+ // javaProject = (IJavaProject)fElements[0];
+ // IClasspathContainer container = null;
+ // description = null;
+ // try {
+ // container = PHPCore.getClasspathContainer(path, javaProject);
+ // } catch(JavaModelException e){
+ // }
+ // if (container == null) {
+ // initializer = PHPCore.getClasspathContainerInitializer(path.segment(0));
+ // if (initializer != null) description = initializer.getDescription(path, javaProject);
+ // } else {
+ // description = container.getDescription();
+ // }
+ // if (description == null) description = path.makeRelative().toString();
+ // return Util.bind("classpath.invalidContainer", description); //$NON-NLS-1$
+ //
+ // case CP_VARIABLE_PATH_UNBOUND:
+ // path = this.fPath;
+ // return Util.bind("classpath.unboundVariablePath", path.makeRelative().toString()); //$NON-NLS-1$
+ //
+ // case CLASSPATH_CYCLE:
+ // javaProject = (IJavaProject)fElements[0];
+ // return Util.bind("classpath.cycle", javaProject.getElementName()); //$NON-NLS-1$
+
+ // case DISABLED_CP_EXCLUSION_PATTERNS:
+ // path = this.fPath;
+ // return Util.bind("classpath.disabledExclusionPatterns", path.makeRelative().toString()); //$NON-NLS-1$
+ //
+ // case DISABLED_CP_MULTIPLE_OUTPUT_LOCATIONS:
+ // path = this.fPath;
+ // return Util.bind("classpath.disabledMultipleOutputLocations", path.makeRelative().toString()); //$NON-NLS-1$
+ }
+ if (fString != null) {
+ return fString;
+ } else {
+ return ""; // //$NON-NLS-1$
+ }
+ } else {
+ String message = exception.getMessage();
+ if (message != null) {
+ return message;
+ } else {
+ return exception.toString();
+ }
+ }
+ }
+ /**
+ * @see IJavaModelStatus#getPath()
+ */
+ public IPath getPath() {
+ return fPath;
+ }
+ /**
+ * @see IStatus#getSeverity()
+ */
+ public int getSeverity() {
+ if (fChildren == fgEmptyChildren)
+ return super.getSeverity();
+ int severity = -1;
+ for (int i = 0, max = fChildren.length; i < max; i++) {
+ int childrenSeverity = fChildren[i].getSeverity();
+ if (childrenSeverity > severity) {
+ severity = childrenSeverity;
+ }
+ }
+ return severity;
+ }
+ /**
+ * @see IJavaModelStatus#getString()
+ * @deprecated
+ */
+ public String getString() {
+ return fString;
+ }
+ /**
+ * @see IJavaModelStatus#isDoesNotExist()
+ */
+ public boolean isDoesNotExist() {
+ return getCode() == ELEMENT_DOES_NOT_EXIST;
+ }
+ /**
+ * @see IStatus#isMultiStatus()
+ */
+ public boolean isMultiStatus() {
+ return fChildren != fgEmptyChildren;
+ }
+ /**
+ * @see IStatus#isOK()
+ */
+ public boolean isOK() {
+ return getCode() == OK;
+ }
+ /**
+ * @see IStatus#matches(int)
+ */
+ public boolean matches(int mask) {
+ if (!isMultiStatus()) {
+ return matches(this, mask);
+ } else {
+ for (int i = 0, max = fChildren.length; i < max; i++) {
+ if (matches((JavaModelStatus) fChildren[i], mask))
+ return true;
+ }
+ return false;
+ }
+ }
+ /**
+ * Helper for matches(int).
+ */
+ protected boolean matches(JavaModelStatus status, int mask) {
+ int severityMask = mask & 0x7;
+ int categoryMask = mask & ~0x7;
+ int bits = status.getBits();
+ return ((severityMask == 0) || (bits & severityMask) != 0)
+ && ((categoryMask == 0) || (bits & categoryMask) != 0);
+ }
+ /**
+ * Creates and returns a new <code>IJavaModelStatus</code> that is a
+ * a multi-status status.
+ *
+ * @see IStatus#isMultiStatus()
+ */
+ public static IJavaModelStatus newMultiStatus(IJavaModelStatus[] children) {
+ JavaModelStatus jms = new JavaModelStatus();
+ jms.fChildren = children;
+ return jms;
+ }
+ /**
+ * Returns a printable representation of this exception for debugging
+ * purposes.
+ */
+ public String toString() {
+ if (this == VERIFIED_OK) {
+ return "JavaModelStatus[OK]"; //$NON-NLS-1$
+ }
+ StringBuffer buffer = new StringBuffer();
+ buffer.append("Java Model Status ["); //$NON-NLS-1$
+ buffer.append(getMessage());
+ buffer.append("]"); //$NON-NLS-1$
+ return buffer.toString();
+ }
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.core;
+
+import java.util.Enumeration;
+
+/**
+ * The <code>LRUCacheEnumerator</code> returns its elements in
+ * the order they are found in the <code>LRUCache</code>, with the
+ * most recent elements first.
+ *
+ * Once the enumerator is created, elements which are later added
+ * to the cache are not returned by the enumerator. However,
+ * elements returned from the enumerator could have been closed
+ * by the cache.
+ */
+public class LRUCacheEnumerator implements Enumeration {
+ /**
+ * Current element;
+ */
+ protected LRUEnumeratorElement fElementQueue;
+
+ public static class LRUEnumeratorElement {
+ /**
+ * Value returned by <code>nextElement()</code>;
+ */
+ public Object fValue;
+
+ /**
+ * Next element
+ */
+ public LRUEnumeratorElement fNext;
+
+ /**
+ * Constructor
+ */
+ public LRUEnumeratorElement(Object value) {
+ fValue = value;
+ }
+ }
+/**
+ * Creates a CacheEnumerator on the list of <code>LRUEnumeratorElements</code>.
+ */
+public LRUCacheEnumerator(LRUEnumeratorElement firstElement) {
+ fElementQueue = firstElement;
+}
+/**
+ * Returns true if more elements exist.
+ */
+public boolean hasMoreElements() {
+ return fElementQueue != null;
+}
+/**
+ * Returns the next element.
+ */
+public Object nextElement() {
+ Object temp = fElementQueue.fValue;
+ fElementQueue = fElementQueue.fNext;
+ return temp;
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.core;
+
+import java.util.Enumeration;
+import java.util.Iterator;
+
+import net.sourceforge.phpdt.core.util.LRUCache;
+
+/**
+ * The <code>OverflowingLRUCache</code> is an LRUCache which attempts
+ * to maintain a size equal or less than its <code>fSpaceLimit</code>
+ * by removing the least recently used elements.
+ *
+ * <p>The cache will remove elements which successfully close and all
+ * elements which are explicitly removed.
+ *
+ * <p>If the cache cannot remove enough old elements to add new elements
+ * it will grow beyond <code>fSpaceLimit</code>. Later, it will attempt to
+ * shink back to the maximum space limit.
+ *
+ * The method <code>close</code> should attempt to close the element. If
+ * the element is successfully closed it will return true and the element will
+ * be removed from the cache. Otherwise the element will remain in the cache.
+ *
+ * <p>The cache implicitly attempts shrinks on calls to <code>put</code>and
+ * <code>setSpaceLimit</code>. Explicitly calling the <code>shrink</code> method
+ * will also cause the cache to attempt to shrink.
+ *
+ * <p>The cache calculates the used space of all elements which implement
+ * <code>ILRUCacheable</code>. All other elements are assumed to be of size one.
+ *
+ * <p>Use the <code>#peek(Object)</code> and <code>#disableTimestamps()</code> method to
+ * circumvent the timestamp feature of the cache. This feature is intended to be used
+ * only when the <code>#close(LRUCacheEntry)</code> method causes changes to the cache.
+ * For example, if a parent closes its children when </code>#close(LRUCacheEntry)</code> is called,
+ * it should be careful not to change the LRU linked list. It can be sure it is not causing
+ * problems by calling <code>#peek(Object)</code> instead of <code>#get(Object)</code> method.
+ *
+ * @see LRUCache
+ */
+public abstract class OverflowingLRUCache extends LRUCache {
+ /**
+ * Indicates if the cache has been over filled and by how much.
+ */
+ protected int fOverflow = 0;
+ /**
+ * Indicates whether or not timestamps should be updated
+ */
+ protected boolean fTimestampsOn = true;
+ /**
+ * Indicates how much space should be reclaimed when the cache overflows.
+ * Inital load factor of one third.
+ */
+ protected double fLoadFactor = 0.333;
+/**
+ * Creates a OverflowingLRUCache.
+ * @param size Size limit of cache.
+ */
+public OverflowingLRUCache(int size) {
+ this(size, 0);
+}
+/**
+ * Creates a OverflowingLRUCache.
+ * @param size Size limit of cache.
+ * @param overflow Size of the overflow.
+ */
+public OverflowingLRUCache(int size, int overflow) {
+ super(size);
+ fOverflow = overflow;
+}
+ /**
+ * Returns a new cache containing the same contents.
+ *
+ * @return New copy of this object.
+ */
+ public Object clone() {
+
+ OverflowingLRUCache newCache = (OverflowingLRUCache)newInstance(fSpaceLimit, fOverflow);
+ LRUCacheEntry qEntry;
+
+ /* Preserve order of entries by copying from oldest to newest */
+ qEntry = this.fEntryQueueTail;
+ while (qEntry != null) {
+ newCache.privateAdd (qEntry._fKey, qEntry._fValue, qEntry._fSpace);
+ qEntry = qEntry._fPrevious;
+ }
+ return newCache;
+ }
+/**
+ * Returns true if the element is successfully closed and
+ * removed from the cache, otherwise false.
+ *
+ * <p>NOTE: this triggers an external remove from the cache
+ * by closing the obejct.
+ *
+ */
+protected abstract boolean close(LRUCacheEntry entry);
+ /**
+ * Returns an enumerator of the values in the cache with the most
+ * recently used first.
+ */
+ public Enumeration elements() {
+ if (fEntryQueue == null)
+ return new LRUCacheEnumerator(null);
+ LRUCacheEnumerator.LRUEnumeratorElement head =
+ new LRUCacheEnumerator.LRUEnumeratorElement(fEntryQueue._fValue);
+ LRUCacheEntry currentEntry = fEntryQueue._fNext;
+ LRUCacheEnumerator.LRUEnumeratorElement currentElement = head;
+ while(currentEntry != null) {
+ currentElement.fNext = new LRUCacheEnumerator.LRUEnumeratorElement(currentEntry._fValue);
+ currentElement = currentElement.fNext;
+
+ currentEntry = currentEntry._fNext;
+ }
+ return new LRUCacheEnumerator(head);
+ }
+ public double fillingRatio() {
+ return (fCurrentSpace + fOverflow) * 100.0 / fSpaceLimit;
+ }
+ /**
+ * For internal testing only.
+ * This method exposed only for testing purposes!
+ *
+ * @return Hashtable of entries
+ */
+ public java.util.Hashtable getEntryTable() {
+ return fEntryTable;
+ }
+/**
+ * Returns the load factor for the cache. The load factor determines how
+ * much space is reclaimed when the cache exceeds its space limit.
+ * @return double
+ */
+public double getLoadFactor() {
+ return fLoadFactor;
+}
+ /**
+ * @return The space by which the cache has overflown.
+ */
+ public int getOverflow() {
+ return fOverflow;
+ }
+ /**
+ * Ensures there is the specified amount of free space in the receiver,
+ * by removing old entries if necessary. Returns true if the requested space was
+ * made available, false otherwise. May not be able to free enough space
+ * since some elements cannot be removed until they are saved.
+ *
+ * @param space Amount of space to free up
+ */
+ protected boolean makeSpace(int space) {
+
+ int limit = fSpaceLimit;
+ if (fOverflow == 0) {
+ /* if space is already available */
+ if (fCurrentSpace + space <= limit) {
+ return true;
+ }
+ }
+
+ /* Free up space by removing oldest entries */
+ int spaceNeeded = (int)((1 - fLoadFactor) * fSpaceLimit);
+ spaceNeeded = (spaceNeeded > space) ? spaceNeeded : space;
+ LRUCacheEntry entry = fEntryQueueTail;
+
+ while (fCurrentSpace + spaceNeeded > limit && entry != null) {
+ this.privateRemoveEntry(entry, false, false);
+ entry = entry._fPrevious;
+ }
+
+ /* check again, since we may have aquired enough space */
+ if (fCurrentSpace + space <= limit) {
+ fOverflow = 0;
+ return true;
+ }
+
+ /* update fOverflow */
+ fOverflow = fCurrentSpace + space - limit;
+ return false;
+ }
+ /**
+ * Returns a new instance of the reciever.
+ */
+ protected abstract LRUCache newInstance(int size, int overflow);
+ /**
+ * Answers the value in the cache at the given key.
+ * If the value is not in the cache, returns null
+ *
+ * This function does not modify timestamps.
+ */
+ public Object peek(Object key) {
+
+ LRUCacheEntry entry = (LRUCacheEntry) fEntryTable.get(key);
+ if (entry == null) {
+ return null;
+ }
+ return entry._fValue;
+ }
+/**
+ * For testing purposes only
+ */
+public void printStats() {
+ int forwardListLength = 0;
+ LRUCacheEntry entry = fEntryQueue;
+ while(entry != null) {
+ forwardListLength++;
+ entry = entry._fNext;
+ }
+ System.out.println("Forward length: " + forwardListLength); //$NON-NLS-1$
+
+ int backwardListLength = 0;
+ entry = fEntryQueueTail;
+ while(entry != null) {
+ backwardListLength++;
+ entry = entry._fPrevious;
+ }
+ System.out.println("Backward length: " + backwardListLength); //$NON-NLS-1$
+
+ Enumeration keys = fEntryTable.keys();
+ class Temp {
+ public Class fClass;
+ public int fCount;
+ public Temp(Class aClass) {
+ fClass = aClass;
+ fCount = 1;
+ }
+ public String toString() {
+ return "Class: " + fClass + " has " + fCount + " entries."; //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-1$
+ }
+ }
+ java.util.HashMap h = new java.util.HashMap();
+ while(keys.hasMoreElements()) {
+ entry = (LRUCacheEntry)fEntryTable.get(keys.nextElement());
+ Class key = entry._fValue.getClass();
+ Temp t = (Temp)h.get(key);
+ if (t == null) {
+ h.put(key, new Temp(key));
+ } else {
+ t.fCount++;
+ }
+ }
+
+ for (Iterator iter = h.keySet().iterator(); iter.hasNext();){
+ System.out.println(h.get(iter.next()));
+ }
+}
+ /**
+ * Removes the entry from the entry queue.
+ * Calls <code>privateRemoveEntry</code> with the external functionality enabled.
+ *
+ * @param shuffle indicates whether we are just shuffling the queue
+ * (in which case, the entry table is not modified).
+ */
+ protected void privateRemoveEntry (LRUCacheEntry entry, boolean shuffle) {
+ privateRemoveEntry(entry, shuffle, true);
+ }
+/**
+ * Removes the entry from the entry queue. If <i>external</i> is true, the entry is removed
+ * without checking if it can be removed. It is assumed that the client has already closed
+ * the element it is trying to remove (or will close it promptly).
+ *
+ * If <i>external</i> is false, and the entry could not be closed, it is not removed and the
+ * pointers are not changed.
+ *
+ * @param shuffle indicates whether we are just shuffling the queue
+ * (in which case, the entry table is not modified).
+ */
+protected void privateRemoveEntry(LRUCacheEntry entry, boolean shuffle, boolean external) {
+
+ if (!shuffle) {
+ if (external) {
+ fEntryTable.remove(entry._fKey);
+ fCurrentSpace -= entry._fSpace;
+ privateNotifyDeletionFromCache(entry);
+ } else {
+ if (!close(entry)) return;
+ // buffer close will recursively call #privateRemoveEntry with external==true
+ // thus entry will already be removed if reaching this point.
+ if (fEntryTable.get(entry._fKey) == null){
+ return;
+ } else {
+ // basic removal
+ fEntryTable.remove(entry._fKey);
+ fCurrentSpace -= entry._fSpace;
+ privateNotifyDeletionFromCache(entry);
+ }
+ }
+ }
+ LRUCacheEntry previous = entry._fPrevious;
+ LRUCacheEntry next = entry._fNext;
+
+ /* if this was the first entry */
+ if (previous == null) {
+ fEntryQueue = next;
+ } else {
+ previous._fNext = next;
+ }
+ /* if this was the last entry */
+ if (next == null) {
+ fEntryQueueTail = previous;
+ } else {
+ next._fPrevious = previous;
+ }
+}
+ /**
+ * Sets the value in the cache at the given key. Returns the value.
+ *
+ * @param key Key of object to add.
+ * @param value Value of object to add.
+ * @return added value.
+ */
+ public Object put(Object key, Object value) {
+ /* attempt to rid ourselves of the overflow, if there is any */
+ if (fOverflow > 0)
+ shrink();
+
+ /* Check whether there's an entry in the cache */
+ int newSpace = spaceFor (key, value);
+ LRUCacheEntry entry = (LRUCacheEntry) fEntryTable.get (key);
+
+ if (entry != null) {
+
+ /**
+ * Replace the entry in the cache if it would not overflow
+ * the cache. Otherwise flush the entry and re-add it so as
+ * to keep cache within budget
+ */
+ int oldSpace = entry._fSpace;
+ int newTotal = fCurrentSpace - oldSpace + newSpace;
+ if (newTotal <= fSpaceLimit) {
+ updateTimestamp (entry);
+ entry._fValue = value;
+ entry._fSpace = newSpace;
+ fCurrentSpace = newTotal;
+ fOverflow = 0;
+ return value;
+ } else {
+ privateRemoveEntry (entry, false, false);
+ }
+ }
+
+ // attempt to make new space
+ makeSpace(newSpace);
+
+ // add without worring about space, it will
+ // be handled later in a makeSpace call
+ privateAdd (key, value, newSpace);
+
+ return value;
+ }
+ /**
+ * Removes and returns the value in the cache for the given key.
+ * If the key is not in the cache, returns null.
+ *
+ * @param key Key of object to remove from cache.
+ * @return Value removed from cache.
+ */
+ public Object remove(Object key) {
+ return removeKey(key);
+ }
+/**
+ * Sets the load factor for the cache. The load factor determines how
+ * much space is reclaimed when the cache exceeds its space limit.
+ * @param newLoadFactor double
+ * @throws IllegalArgumentException when the new load factor is not in (0.0, 1.0]
+ */
+public void setLoadFactor(double newLoadFactor) throws IllegalArgumentException {
+ if(newLoadFactor <= 1.0 && newLoadFactor > 0.0)
+ fLoadFactor = newLoadFactor;
+ else
+ throw new IllegalArgumentException(Util.bind("cache.invalidLoadFactor")); //$NON-NLS-1$
+}
+ /**
+ * Sets the maximum amount of space that the cache can store
+ *
+ * @param limit Number of units of cache space
+ */
+ public void setSpaceLimit(int limit) {
+ if (limit < fSpaceLimit) {
+ makeSpace(fSpaceLimit - limit);
+ }
+ fSpaceLimit = limit;
+ }
+ /**
+ * Attempts to shrink the cache if it has overflown.
+ * Returns true if the cache shrinks to less than or equal to <code>fSpaceLimit</code>.
+ */
+ public boolean shrink() {
+ if (fOverflow > 0)
+ return makeSpace(0);
+ return true;
+ }
+/**
+ * Returns a String that represents the value of this object. This method
+ * is for debugging purposes only.
+ */
+public String toString() {
+ return
+ "OverflowingLRUCache " + this.fillingRatio() + "% full\n" + //$NON-NLS-1$ //$NON-NLS-2$
+ this.toStringContents();
+}
+/**
+ * Updates the timestamp for the given entry, ensuring that the queue is
+ * kept in correct order. The entry must exist.
+ *
+ * <p>This method will do nothing if timestamps have been disabled.
+ */
+protected void updateTimestamp(LRUCacheEntry entry) {
+ if (fTimestampsOn) {
+ entry._fTimestamp = fTimestampCounter++;
+ if (fEntryQueue != entry) {
+ this.privateRemoveEntry(entry, true);
+ this.privateAddEntry(entry, true);
+ }
+ }
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.core;
+
+import java.util.Locale;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+import java.util.StringTokenizer;
+
+import net.sourceforge.phpdt.core.JavaModelException;
+import net.sourceforge.phpdt.core.compiler.CharOperation;
+import net.sourceforge.phpdt.internal.core.util.CharArrayBuffer;
+import net.sourceforge.phpdt.internal.corext.Assert;
+import net.sourceforge.phpeclipse.PHPCore;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+
+/**
+ * Provides convenient utility methods to other types in this package.
+ */
+public class Util {
+
+ private final static char[] DOUBLE_QUOTES = "''".toCharArray(); //$NON-NLS-1$
+ private final static char[] SINGLE_QUOTE = "'".toCharArray(); //$NON-NLS-1$
+ private static final String ARGUMENTS_DELIMITER = "#"; //$NON-NLS-1$
+ private static final String EMPTY_ARGUMENT = " "; //$NON-NLS-1$
+
+ public interface Comparable {
+ /**
+ * Returns 0 if this and c are equal, >0 if this is greater than c,
+ * or <0 if this is less than c.
+ */
+ int compareTo(Comparable c);
+ }
+
+ public interface Comparer {
+ /**
+ * Returns 0 if a and b are equal, >0 if a is greater than b,
+ * or <0 if a is less than b.
+ */
+ int compare(Object a, Object b);
+ }
+
+ public interface Displayable {
+ String displayString(Object o);
+ }
+
+ public static final String[] fgEmptyStringArray = new String[0];
+
+ /**
+ * Are we running JDK 1.1?
+ */
+ private static boolean JDK1_1 = false;
+
+ /* Bundle containing messages */
+ protected static ResourceBundle bundle;
+ private final static String bundleName = "org.eclipse.jdt.internal.core.messages"; //$NON-NLS-1$
+
+ public final static char[] SUFFIX_class = ".class".toCharArray(); //$NON-NLS-1$
+ public final static char[] SUFFIX_CLASS = ".CLASS".toCharArray(); //$NON-NLS-1$
+ public final static char[] SUFFIX_java = ".java".toCharArray(); //$NON-NLS-1$
+ public final static char[] SUFFIX_JAVA = ".JAVA".toCharArray(); //$NON-NLS-1$
+ public final static char[] SUFFIX_jar = ".jar".toCharArray(); //$NON-NLS-1$
+ public final static char[] SUFFIX_JAR = ".JAR".toCharArray(); //$NON-NLS-1$
+ public final static char[] SUFFIX_zip = ".zip".toCharArray(); //$NON-NLS-1$
+ public final static char[] SUFFIX_ZIP = ".ZIP".toCharArray(); //$NON-NLS-1$
+
+ static {
+ String ver = System.getProperty("java.version"); //$NON-NLS-1$
+ JDK1_1 = ((ver != null) && ver.startsWith("1.1")); //$NON-NLS-1$
+ relocalize();
+ }
+
+ /**
+ * Lookup the message with the given ID in this catalog
+ */
+ public static String bind(String id) {
+ return bind(id, (String[])null);
+ }
+
+ /**
+ * Lookup the message with the given ID in this catalog and bind its
+ * substitution locations with the given string values.
+ */
+ public static String bind(String id, String[] bindings) {
+ if (id == null)
+ return "No message available"; //$NON-NLS-1$
+ String message = null;
+ try {
+ message = bundle.getString(id);
+ } catch (MissingResourceException e) {
+ // If we got an exception looking for the message, fail gracefully by just returning
+ // the id we were looking for. In most cases this is semi-informative so is not too bad.
+ return "Missing message: " + id + " in: " + bundleName; //$NON-NLS-2$ //$NON-NLS-1$
+ }
+ // for compatibility with MessageFormat which eliminates double quotes in original message
+ char[] messageWithNoDoubleQuotes =
+ CharOperation.replace(message.toCharArray(), DOUBLE_QUOTES, SINGLE_QUOTE);
+ message = new String(messageWithNoDoubleQuotes);
+
+ if (bindings == null)
+ return message;
+
+ int length = message.length();
+ int start = -1;
+ int end = length;
+ StringBuffer output = new StringBuffer(80);
+ while (true) {
+ if ((end = message.indexOf('{', start)) > -1) {
+ output.append(message.substring(start + 1, end));
+ if ((start = message.indexOf('}', end)) > -1) {
+ int index = -1;
+ try {
+ index = Integer.parseInt(message.substring(end + 1, start));
+ output.append(bindings[index]);
+ } catch (NumberFormatException nfe) {
+ output.append(message.substring(end + 1, start + 1));
+ } catch (ArrayIndexOutOfBoundsException e) {
+ output.append("{missing " + Integer.toString(index) + "}"); //$NON-NLS-2$ //$NON-NLS-1$
+ }
+ } else {
+ output.append(message.substring(end, length));
+ break;
+ }
+ } else {
+ output.append(message.substring(start + 1, length));
+ break;
+ }
+ }
+ return output.toString();
+ }
+
+ /**
+ * Lookup the message with the given ID in this catalog and bind its
+ * substitution locations with the given string.
+ */
+ public static String bind(String id, String binding) {
+ return bind(id, new String[] {binding});
+ }
+
+ /**
+ * Lookup the message with the given ID in this catalog and bind its
+ * substitution locations with the given strings.
+ */
+ public static String bind(String id, String binding1, String binding2) {
+ return bind(id, new String[] {binding1, binding2});
+ }
+
+ /**
+ * Checks the type signature in String sig,
+ * starting at start and ending before end (end is not included).
+ * Returns the index of the character immediately after the signature if valid,
+ * or -1 if not valid.
+ */
+ private static int checkTypeSignature(String sig, int start, int end, boolean allowVoid) {
+ if (start >= end) return -1;
+ int i = start;
+ char c = sig.charAt(i++);
+ int nestingDepth = 0;
+ while (c == '[') {
+ ++nestingDepth;
+ if (i >= end) return -1;
+ c = sig.charAt(i++);
+ }
+ switch (c) {
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'F':
+ case 'I':
+ case 'J':
+ case 'S':
+ case 'Z':
+ break;
+ case 'V':
+ if (!allowVoid) return -1;
+ // array of void is not allowed
+ if (nestingDepth != 0) return -1;
+ break;
+ case 'L':
+ int semicolon = sig.indexOf(';', i);
+ // Must have at least one character between L and ;
+ if (semicolon <= i || semicolon >= end) return -1;
+ i = semicolon + 1;
+ break;
+ default:
+ return -1;
+ }
+ return i;
+ }
+
+ /**
+ * Combines two hash codes to make a new one.
+ */
+ public static int combineHashCodes(int hashCode1, int hashCode2) {
+ return hashCode1 * 17 + hashCode2;
+ }
+
+ /**
+ * Compares two byte arrays.
+ * Returns <0 if a byte in a is less than the corresponding byte in b, or if a is shorter, or if a is null.
+ * Returns >0 if a byte in a is greater than the corresponding byte in b, or if a is longer, or if b is null.
+ * Returns 0 if they are equal or both null.
+ */
+ public static int compare(byte[] a, byte[] b) {
+ if (a == b)
+ return 0;
+ if (a == null)
+ return -1;
+ if (b == null)
+ return 1;
+ int len = Math.min(a.length, b.length);
+ for (int i = 0; i < len; ++i) {
+ int diff = a[i] - b[i];
+ if (diff != 0)
+ return diff;
+ }
+ if (a.length > len)
+ return 1;
+ if (b.length > len)
+ return -1;
+ return 0;
+ }
+
+ /**
+ * Compares two char arrays lexicographically.
+ * The comparison is based on the Unicode value of each character in
+ * the char arrays.
+ * @return the value <code>0</code> if a is equal to
+ * b; a value less than <code>0</code> if a
+ * is lexicographically less than b; and a
+ * value greater than <code>0</code> if a is
+ * lexicographically greater than b.
+ */
+ public static int compare(char[] v1, char[] v2) {
+ int len1 = v1.length;
+ int len2 = v2.length;
+ int n = Math.min(len1, len2);
+ int i = 0;
+ while (n-- != 0) {
+ if (v1[i] != v2[i]) {
+ return v1[i] - v2[i];
+ }
+ ++i;
+ }
+ return len1 - len2;
+ }
+
+ /**
+ * Concatenate two strings with a char in between.
+ * @see #concat(String, String)
+ */
+ public static String concat(String s1, char c, String s2) {
+ if (s1 == null) s1 = "null"; //$NON-NLS-1$
+ if (s2 == null) s2 = "null"; //$NON-NLS-1$
+ int l1 = s1.length();
+ int l2 = s2.length();
+ char[] buf = new char[l1 + 1 + l2];
+ s1.getChars(0, l1, buf, 0);
+ buf[l1] = c;
+ s2.getChars(0, l2, buf, l1 + 1);
+ return new String(buf);
+ }
+
+ /**
+ * Concatenate two strings.
+ * Much faster than using +, which:
+ * - creates a StringBuffer,
+ * - which is synchronized,
+ * - of default size, so the resulting char array is
+ * often larger than needed.
+ * This implementation creates an extra char array, since the
+ * String constructor copies its argument, but there's no way around this.
+ */
+ public static String concat(String s1, String s2) {
+ if (s1 == null) s1 = "null"; //$NON-NLS-1$
+ if (s2 == null) s2 = "null"; //$NON-NLS-1$
+ int l1 = s1.length();
+ int l2 = s2.length();
+ char[] buf = new char[l1 + l2];
+ s1.getChars(0, l1, buf, 0);
+ s2.getChars(0, l2, buf, l1);
+ return new String(buf);
+ }
+
+ /**
+ * Concatenate three strings.
+ * @see #concat(String, String)
+ */
+ public static String concat(String s1, String s2, String s3) {
+ if (s1 == null) s1 = "null"; //$NON-NLS-1$
+ if (s2 == null) s2 = "null"; //$NON-NLS-1$
+ if (s3 == null) s3 = "null"; //$NON-NLS-1$
+ int l1 = s1.length();
+ int l2 = s2.length();
+ int l3 = s3.length();
+ char[] buf = new char[l1 + l2 + l3];
+ s1.getChars(0, l1, buf, 0);
+ s2.getChars(0, l2, buf, l1);
+ s3.getChars(0, l3, buf, l1 + l2);
+ return new String(buf);
+ }
+
+ /**
+ * Converts a type signature from the IBinaryType representation to the DC representation.
+ */
+ public static String convertTypeSignature(char[] sig) {
+ return new String(sig).replace('/', '.');
+ }
+
+ /**
+ * Returns true iff str.toLowerCase().endsWith(end.toLowerCase())
+ * implementation is not creating extra strings.
+ */
+ public final static boolean endsWithIgnoreCase(String str, String end) {
+
+ int strLength = str == null ? 0 : str.length();
+ int endLength = end == null ? 0 : end.length();
+
+ // return false if the string is smaller than the end.
+ if(endLength > strLength)
+ return false;
+
+ // return false if any character of the end are
+ // not the same in lower case.
+ for(int i = 1 ; i <= endLength; i++){
+ if(Character.toLowerCase(end.charAt(endLength - i)) != Character.toLowerCase(str.charAt(strLength - i)))
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Compares two arrays using equals() on the elements.
+ * Either or both arrays may be null.
+ * Returns true if both are null.
+ * Returns false if only one is null.
+ * If both are arrays, returns true iff they have the same length and
+ * all elements are equal.
+ */
+ public static boolean equalArraysOrNull(int[] a, int[] b) {
+ if (a == b)
+ return true;
+ if (a == null || b == null)
+ return false;
+ int len = a.length;
+ if (len != b.length)
+ return false;
+ for (int i = 0; i < len; ++i) {
+ if (a[i] != b[i])
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Compares two arrays using equals() on the elements.
+ * Either or both arrays may be null.
+ * Returns true if both are null.
+ * Returns false if only one is null.
+ * If both are arrays, returns true iff they have the same length and
+ * all elements compare true with equals.
+ */
+ public static boolean equalArraysOrNull(Object[] a, Object[] b) {
+ if (a == b) return true;
+ if (a == null || b == null) return false;
+
+ int len = a.length;
+ if (len != b.length) return false;
+ for (int i = 0; i < len; ++i) {
+ if (a[i] == null) {
+ if (b[i] != null) return false;
+ } else {
+ if (!a[i].equals(b[i])) return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Compares two String arrays using equals() on the elements.
+ * The arrays are first sorted.
+ * Either or both arrays may be null.
+ * Returns true if both are null.
+ * Returns false if only one is null.
+ * If both are arrays, returns true iff they have the same length and
+ * iff, after sorting both arrays, all elements compare true with equals.
+ * The original arrays are left untouched.
+ */
+ public static boolean equalArraysOrNullSortFirst(String[] a, String[] b) {
+ if (a == b) return true;
+ if (a == null || b == null) return false;
+ int len = a.length;
+ if (len != b.length) return false;
+ if (len >= 2) { // only need to sort if more than two items
+ a = sortCopy(a);
+ b = sortCopy(b);
+ }
+ for (int i = 0; i < len; ++i) {
+ if (!a[i].equals(b[i])) return false;
+ }
+ return true;
+ }
+
+ /**
+ * Compares two arrays using equals() on the elements.
+ * The arrays are first sorted.
+ * Either or both arrays may be null.
+ * Returns true if both are null.
+ * Returns false if only one is null.
+ * If both are arrays, returns true iff they have the same length and
+ * iff, after sorting both arrays, all elements compare true with equals.
+ * The original arrays are left untouched.
+ */
+ public static boolean equalArraysOrNullSortFirst(Comparable[] a, Comparable[] b) {
+ if (a == b) return true;
+ if (a == null || b == null) return false;
+ int len = a.length;
+ if (len != b.length) return false;
+ if (len >= 2) { // only need to sort if more than two items
+ a = sortCopy(a);
+ b = sortCopy(b);
+ }
+ for (int i = 0; i < len; ++i) {
+ if (!a[i].equals(b[i])) return false;
+ }
+ return true;
+ }
+
+ /**
+ * Compares two objects using equals().
+ * Either or both array may be null.
+ * Returns true if both are null.
+ * Returns false if only one is null.
+ * Otherwise, return the result of comparing with equals().
+ */
+ public static boolean equalOrNull(Object a, Object b) {
+ if (a == b) {
+ return true;
+ }
+ if (a == null || b == null) {
+ return false;
+ }
+ return a.equals(b);
+ }
+
+ /**
+ * Given a qualified name, extract the last component.
+ * If the input is not qualified, the same string is answered.
+ */
+ public static String extractLastName(String qualifiedName) {
+ int i = qualifiedName.lastIndexOf('.');
+ if (i == -1) return qualifiedName;
+ return qualifiedName.substring(i+1);
+ }
+
+ /**
+ * Extracts the parameter types from a method signature.
+ */
+ public static String[] extractParameterTypes(char[] sig) {
+ int count = getParameterCount(sig);
+ String[] result = new String[count];
+ if (count == 0)
+ return result;
+ int i = CharOperation.indexOf('(', sig) + 1;
+ count = 0;
+ int len = sig.length;
+ int start = i;
+ for (;;) {
+ if (i == len)
+ break;
+ char c = sig[i];
+ if (c == ')')
+ break;
+ if (c == '[') {
+ ++i;
+ } else
+ if (c == 'L') {
+ i = CharOperation.indexOf(';', sig, i + 1) + 1;
+ Assert.isTrue(i != 0);
+ result[count++] = convertTypeSignature(CharOperation.subarray(sig, start, i));
+ start = i;
+ } else {
+ ++i;
+ result[count++] = convertTypeSignature(CharOperation.subarray(sig, start, i));
+ start = i;
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Extracts the return type from a method signature.
+ */
+ public static String extractReturnType(String sig) {
+ int i = sig.lastIndexOf(')');
+ Assert.isTrue(i != -1);
+ return sig.substring(i+1);
+ }
+
+ /**
+ * Finds the first line separator used by the given text.
+ *
+ * @return </code>"\n"</code> or </code>"\r"</code> or </code>"\r\n"</code>,
+ * or <code>null</code> if none found
+ */
+ public static String findLineSeparator(char[] text) {
+ // find the first line separator
+ int length = text.length;
+ if (length > 0) {
+ char nextChar = text[0];
+ for (int i = 0; i < length; i++) {
+ char currentChar = nextChar;
+ nextChar = i < length-1 ? text[i+1] : ' ';
+ switch (currentChar) {
+ case '\n': return "\n"; //$NON-NLS-1$
+ case '\r': return nextChar == '\n' ? "\r\n" : "\r"; //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ }
+ }
+ // not found
+ return null;
+ }
+
+ /**
+ * Returns the line separator used by the given buffer.
+ * Uses the given text if none found.
+ *
+ * @return </code>"\n"</code> or </code>"\r"</code> or </code>"\r\n"</code>
+ */
+ private static String getLineSeparator(char[] text, char[] buffer) {
+ // search in this buffer's contents first
+ String lineSeparator = findLineSeparator(buffer);
+ if (lineSeparator == null) {
+ // search in the given text
+ lineSeparator = findLineSeparator(text);
+ if (lineSeparator == null) {
+ // default to system line separator
+ return System.getProperty("line.separator");
+ }
+ }
+ return lineSeparator;
+ }
+
+ /**
+ * Returns the number of parameter types in a method signature.
+ */
+ public static int getParameterCount(char[] sig) {
+ int i = CharOperation.indexOf('(', sig) + 1;
+ Assert.isTrue(i != 0);
+ int count = 0;
+ int len = sig.length;
+ for (;;) {
+ if (i == len)
+ break;
+ char c = sig[i];
+ if (c == ')')
+ break;
+ if (c == '[') {
+ ++i;
+ } else
+ if (c == 'L') {
+ ++count;
+ i = CharOperation.indexOf(';', sig, i + 1) + 1;
+ Assert.isTrue(i != 0);
+ } else {
+ ++count;
+ ++i;
+ }
+ }
+ return count;
+ }
+
+// /**
+// * Returns the given file's contents as a byte array.
+// */
+// public static byte[] getResourceContentsAsByteArray(IFile file) throws JavaModelException {
+// InputStream stream= null;
+// try {
+// stream = new BufferedInputStream(file.getContents(true));
+// } catch (CoreException e) {
+// throw new JavaModelException(e);
+// }
+// try {
+// return org.eclipse.jdt.internal.compiler.util.Util.getInputStreamAsByteArray(stream, -1);
+// } catch (IOException e) {
+// throw new JavaModelException(e, IJavaModelStatusConstants.IO_EXCEPTION);
+// } finally {
+// try {
+// stream.close();
+// } catch (IOException e) {
+// }
+// }
+// }
+//
+// /**
+// * Returns the given file's contents as a character array.
+// */
+// public static char[] getResourceContentsAsCharArray(IFile file) throws JavaModelException {
+// String encoding = JavaCore.create(file.getProject()).getOption(JavaCore.CORE_ENCODING, true);
+// return getResourceContentsAsCharArray(file, encoding);
+// }
+//
+// public static char[] getResourceContentsAsCharArray(IFile file, String encoding) throws JavaModelException {
+// InputStream stream= null;
+// try {
+// stream = new BufferedInputStream(file.getContents(true));
+// } catch (CoreException e) {
+// throw new JavaModelException(e, IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST);
+// }
+// try {
+// return org.eclipse.jdt.internal.compiler.util.Util.getInputStreamAsCharArray(stream, -1, encoding);
+// } catch (IOException e) {
+// throw new JavaModelException(e, IJavaModelStatusConstants.IO_EXCEPTION);
+// } finally {
+// try {
+// stream.close();
+// } catch (IOException e) {
+// }
+// }
+// }
+//
+// /**
+// * Returns a trimmed version the simples names returned by Signature.
+// */
+// public static String[] getTrimmedSimpleNames(String name) {
+// String[] result = Signature.getSimpleNames(name);
+// if (result == null) return null;
+// for (int i = 0, length = result.length; i < length; i++) {
+// result[i] = result[i].trim();
+// }
+// return result;
+// }
+
+ /**
+ * Returns true iff str.toLowerCase().endsWith(".class")
+ * implementation is not creating extra strings.
+ */
+ public final static boolean isClassFileName(String name) {
+ int nameLength = name == null ? 0 : name.length();
+ int suffixLength = SUFFIX_CLASS.length;
+ if (nameLength < suffixLength) return false;
+
+ for (int i = 0, offset = nameLength - suffixLength; i < suffixLength; i++) {
+ char c = name.charAt(offset + i);
+ if (c != SUFFIX_class[i] && c != SUFFIX_CLASS[i]) return false;
+ }
+ return true;
+ }
+
+ /*
+ * Returns whether the given java element is exluded from its root's classpath.
+ */
+// public static final boolean isExcluded(IJavaElement element) {
+// int elementType = element.getElementType();
+// switch (elementType) {
+// case IJavaElement.PACKAGE_FRAGMENT:
+// PackageFragmentRoot root = (PackageFragmentRoot)element.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
+// IResource resource = element.getResource();
+// return resource != null && Util.isExcluded(resource, root.fullExclusionPatternChars());
+// case IJavaElement.COMPILATION_UNIT:
+// root = (PackageFragmentRoot)element.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
+// resource = element.getResource();
+// if (resource != null && Util.isExcluded(resource, root.fullExclusionPatternChars()))
+// return true;
+// return isExcluded(element.getParent());
+// default:
+// IJavaElement cu = element.getAncestor(IJavaElement.COMPILATION_UNIT);
+// return cu != null && isExcluded(cu);
+// }
+// }
+ /*
+ * Returns whether the given resource path matches one of the exclusion
+ * patterns.
+ *
+ * @see IClasspathEntry#getExclusionPatterns
+ */
+ public final static boolean isExcluded(IPath resourcePath, char[][] exclusionPatterns) {
+ if (exclusionPatterns == null) return false;
+ char[] path = resourcePath.toString().toCharArray();
+ for (int i = 0, length = exclusionPatterns.length; i < length; i++)
+ if (CharOperation.pathMatch(exclusionPatterns[i], path, true, '/'))
+ return true;
+ return false;
+ }
+
+ /*
+ * Returns whether the given resource matches one of the exclusion patterns.
+ *
+ * @see IClasspathEntry#getExclusionPatterns
+ */
+ public final static boolean isExcluded(IResource resource, char[][] exclusionPatterns) {
+ IPath path = resource.getFullPath();
+ // ensure that folders are only excluded if all of their children are excluded
+ if (resource.getType() == IResource.FOLDER)
+ path = path.append("*"); //$NON-NLS-1$
+ return isExcluded(path, exclusionPatterns);
+ }
+
+ /**
+ * Returns true iff str.toLowerCase().endsWith(".jar" or ".zip")
+ * implementation is not creating extra strings.
+ */
+ public final static boolean isArchiveFileName(String name) {
+ int nameLength = name == null ? 0 : name.length();
+ int suffixLength = SUFFIX_JAR.length;
+ if (nameLength < suffixLength) return false;
+
+ int i, offset;
+ for ( i = 0, offset = nameLength - suffixLength; i < suffixLength; i++) {
+ char c = name.charAt(offset + i);
+ if (c != SUFFIX_jar[i] && c != SUFFIX_JAR[i]) break;
+ }
+ if (i == suffixLength) return true;
+ for ( i = 0, offset = nameLength - suffixLength; i < suffixLength; i++) {
+ char c = name.charAt(offset + i);
+ if (c != SUFFIX_zip[i] && c != SUFFIX_ZIP[i]) return false;
+ }
+ return true;
+ }
+
+ /**
+ * Validate the given compilation unit name.
+ * A compilation unit name must obey the following rules:
+ * <ul>
+ * <li> it must not be null
+ * <li> it must include the <code>".java"</code> suffix
+ * <li> its prefix must be a valid identifier
+ * </ul>
+ * </p>
+ * @param name the name of a compilation unit
+ * @return a status object with code <code>IStatus.OK</code> if
+ * the given name is valid as a compilation unit name, otherwise a status
+ * object indicating what is wrong with the name
+ */
+// public static boolean isValidCompilationUnitName(String name) {
+// return JavaConventions.validateCompilationUnitName(name).getSeverity() != IStatus.ERROR;
+// }
+
+ /**
+ * Validate the given .class file name.
+ * A .class file name must obey the following rules:
+ * <ul>
+ * <li> it must not be null
+ * <li> it must include the <code>".class"</code> suffix
+ * <li> its prefix must be a valid identifier
+ * </ul>
+ * </p>
+ * @param name the name of a .class file
+ * @return a status object with code <code>IStatus.OK</code> if
+ * the given name is valid as a .class file name, otherwise a status
+ * object indicating what is wrong with the name
+ */
+// public static boolean isValidClassFileName(String name) {
+// return JavaConventions.validateClassFileName(name).getSeverity() != IStatus.ERROR;
+// }
+
+ /**
+ * Returns true iff str.toLowerCase().endsWith(".java")
+ * implementation is not creating extra strings.
+ */
+ public final static boolean isJavaFileName(String name) {
+ int nameLength = name == null ? 0 : name.length();
+ int suffixLength = SUFFIX_JAVA.length;
+ if (nameLength < suffixLength) return false;
+
+ for (int i = 0, offset = nameLength - suffixLength; i < suffixLength; i++) {
+ char c = name.charAt(offset + i);
+ if (c != SUFFIX_java[i] && c != SUFFIX_JAVA[i]) return false;
+ }
+ return true;
+ }
+
+ /**
+ * Returns true if the given method signature is valid,
+ * false if it is not.
+ */
+ public static boolean isValidMethodSignature(String sig) {
+ int len = sig.length();
+ if (len == 0) return false;
+ int i = 0;
+ char c = sig.charAt(i++);
+ if (c != '(') return false;
+ if (i >= len) return false;
+ while (sig.charAt(i) != ')') {
+ // Void is not allowed as a parameter type.
+ i = checkTypeSignature(sig, i, len, false);
+ if (i == -1) return false;
+ if (i >= len) return false;
+ }
+ ++i;
+ i = checkTypeSignature(sig, i, len, true);
+ return i == len;
+ }
+
+ /**
+ * Returns true if the given type signature is valid,
+ * false if it is not.
+ */
+ public static boolean isValidTypeSignature(String sig, boolean allowVoid) {
+ int len = sig.length();
+ return checkTypeSignature(sig, 0, len, allowVoid) == len;
+ }
+
+ /**
+ * Returns true if the given folder name is valid for a package,
+ * false if it is not.
+ */
+// public static boolean isValidFolderNameForPackage(String folderName) {
+// return JavaConventions.validateIdentifier(folderName).getSeverity() != IStatus.ERROR;
+// }
+
+ /*
+ * Add a log entry
+ */
+ public static void log(Throwable e, String message) {
+ Throwable nestedException;
+ if (e instanceof JavaModelException
+ && (nestedException = ((JavaModelException)e).getException()) != null) {
+ e = nestedException;
+ }
+ IStatus status= new Status(
+ IStatus.ERROR,
+ PHPCore.getPlugin().getDescriptor().getUniqueIdentifier(),
+ IStatus.ERROR,
+ message,
+ e);
+ PHPCore.getPlugin().getLog().log(status);
+ }
+
+ /**
+ * Normalizes the cariage returns in the given text.
+ * They are all changed to use the given buffer's line separator.
+ */
+ public static char[] normalizeCRs(char[] text, char[] buffer) {
+ CharArrayBuffer result = new CharArrayBuffer();
+ int lineStart = 0;
+ int length = text.length;
+ if (length == 0) return text;
+ String lineSeparator = getLineSeparator(text, buffer);
+ char nextChar = text[0];
+ for (int i = 0; i < length; i++) {
+ char currentChar = nextChar;
+ nextChar = i < length-1 ? text[i+1] : ' ';
+ switch (currentChar) {
+ case '\n':
+ int lineLength = i-lineStart;
+ char[] line = new char[lineLength];
+ System.arraycopy(text, lineStart, line, 0, lineLength);
+ result.append(line);
+ result.append(lineSeparator);
+ lineStart = i+1;
+ break;
+ case '\r':
+ lineLength = i-lineStart;
+ if (lineLength >= 0) {
+ line = new char[lineLength];
+ System.arraycopy(text, lineStart, line, 0, lineLength);
+ result.append(line);
+ result.append(lineSeparator);
+ if (nextChar == '\n') {
+ nextChar = ' ';
+ lineStart = i+2;
+ } else {
+ // when line separator are mixed in the same file
+ // \r might not be followed by a \n. If not, we should increment
+ // lineStart by one and not by two.
+ lineStart = i+1;
+ }
+ } else {
+ // when line separator are mixed in the same file
+ // we need to prevent NegativeArraySizeException
+ lineStart = i+1;
+ }
+ break;
+ }
+ }
+ char[] lastLine;
+ if (lineStart > 0) {
+ int lastLineLength = length-lineStart;
+ if (lastLineLength > 0) {
+ lastLine = new char[lastLineLength];
+ System.arraycopy(text, lineStart, lastLine, 0, lastLineLength);
+ result.append(lastLine);
+ }
+ return result.getContents();
+ } else {
+ return text;
+ }
+ }
+
+ /**
+ * Normalizes the cariage returns in the given text.
+ * They are all changed to use given buffer's line sepatator.
+ */
+ public static String normalizeCRs(String text, String buffer) {
+ return new String(normalizeCRs(text.toCharArray(), buffer.toCharArray()));
+ }
+
+ /**
+ * Sort the objects in the given collection using the given sort order.
+ */
+ private static void quickSort(Object[] sortedCollection, int left, int right, int[] sortOrder) {
+ int original_left = left;
+ int original_right = right;
+ int mid = sortOrder[ (left + right) / 2];
+ do {
+ while (sortOrder[left] < mid) {
+ left++;
+ }
+ while (mid < sortOrder[right]) {
+ right--;
+ }
+ if (left <= right) {
+ Object tmp = sortedCollection[left];
+ sortedCollection[left] = sortedCollection[right];
+ sortedCollection[right] = tmp;
+ int tmp2 = sortOrder[left];
+ sortOrder[left] = sortOrder[right];
+ sortOrder[right] = tmp2;
+ left++;
+ right--;
+ }
+ } while (left <= right);
+ if (original_left < right) {
+ quickSort(sortedCollection, original_left, right, sortOrder);
+ }
+ if (left < original_right) {
+ quickSort(sortedCollection, left, original_right, sortOrder);
+ }
+ }
+
+ /**
+ * Sort the objects in the given collection using the given comparer.
+ */
+ private static void quickSort(Object[] sortedCollection, int left, int right, Comparer comparer) {
+ int original_left = left;
+ int original_right = right;
+ Object mid = sortedCollection[ (left + right) / 2];
+ do {
+ while (comparer.compare(sortedCollection[left], mid) < 0) {
+ left++;
+ }
+ while (comparer.compare(mid, sortedCollection[right]) < 0) {
+ right--;
+ }
+ if (left <= right) {
+ Object tmp = sortedCollection[left];
+ sortedCollection[left] = sortedCollection[right];
+ sortedCollection[right] = tmp;
+ left++;
+ right--;
+ }
+ } while (left <= right);
+ if (original_left < right) {
+ quickSort(sortedCollection, original_left, right, comparer);
+ }
+ if (left < original_right) {
+ quickSort(sortedCollection, left, original_right, comparer);
+ }
+ }
+
+ /**
+ * Sort the strings in the given collection.
+ */
+ private static void quickSort(String[] sortedCollection, int left, int right) {
+ int original_left = left;
+ int original_right = right;
+ String mid = sortedCollection[ (left + right) / 2];
+ do {
+ while (sortedCollection[left].compareTo(mid) < 0) {
+ left++;
+ }
+ while (mid.compareTo(sortedCollection[right]) < 0) {
+ right--;
+ }
+ if (left <= right) {
+ String tmp = sortedCollection[left];
+ sortedCollection[left] = sortedCollection[right];
+ sortedCollection[right] = tmp;
+ left++;
+ right--;
+ }
+ } while (left <= right);
+ if (original_left < right) {
+ quickSort(sortedCollection, original_left, right);
+ }
+ if (left < original_right) {
+ quickSort(sortedCollection, left, original_right);
+ }
+ }
+
+ /**
+ * Converts the given relative path into a package name.
+ * Returns null if the path is not a valid package name.
+ */
+// public static String packageName(IPath pkgPath) {
+// StringBuffer pkgName = new StringBuffer(IPackageFragment.DEFAULT_PACKAGE_NAME);
+// for (int j = 0, max = pkgPath.segmentCount(); j < max; j++) {
+// String segment = pkgPath.segment(j);
+// if (!isValidFolderNameForPackage(segment)) {
+// return null;
+// }
+// pkgName.append(segment);
+// if (j < pkgPath.segmentCount() - 1) {
+// pkgName.append("." ); //$NON-NLS-1$
+// }
+// }
+// return pkgName.toString();
+// }
+
+ /**
+ * Sort the comparable objects in the given collection.
+ */
+ private static void quickSort(Comparable[] sortedCollection, int left, int right) {
+ int original_left = left;
+ int original_right = right;
+ Comparable mid = sortedCollection[ (left + right) / 2];
+ do {
+ while (sortedCollection[left].compareTo(mid) < 0) {
+ left++;
+ }
+ while (mid.compareTo(sortedCollection[right]) < 0) {
+ right--;
+ }
+ if (left <= right) {
+ Comparable tmp = sortedCollection[left];
+ sortedCollection[left] = sortedCollection[right];
+ sortedCollection[right] = tmp;
+ left++;
+ right--;
+ }
+ } while (left <= right);
+ if (original_left < right) {
+ quickSort(sortedCollection, original_left, right);
+ }
+ if (left < original_right) {
+ quickSort(sortedCollection, left, original_right);
+ }
+ }
+
+ /**
+ * Sort the strings in the given collection in reverse alphabetical order.
+ */
+ private static void quickSortReverse(String[] sortedCollection, int left, int right) {
+ int original_left = left;
+ int original_right = right;
+ String mid = sortedCollection[ (left + right) / 2];
+ do {
+ while (sortedCollection[left].compareTo(mid) > 0) {
+ left++;
+ }
+ while (mid.compareTo(sortedCollection[right]) > 0) {
+ right--;
+ }
+ if (left <= right) {
+ String tmp = sortedCollection[left];
+ sortedCollection[left] = sortedCollection[right];
+ sortedCollection[right] = tmp;
+ left++;
+ right--;
+ }
+ } while (left <= right);
+ if (original_left < right) {
+ quickSortReverse(sortedCollection, original_left, right);
+ }
+ if (left < original_right) {
+ quickSortReverse(sortedCollection, left, original_right);
+ }
+ }
+
+ /**
+ * Sorts an array of objects in place, using the sort order given for each item.
+ */
+ public static void sort(Object[] objects, int[] sortOrder) {
+ if (objects.length > 1)
+ quickSort(objects, 0, objects.length - 1, sortOrder);
+ }
+
+ /**
+ * Sorts an array of objects in place.
+ * The given comparer compares pairs of items.
+ */
+ public static void sort(Object[] objects, Comparer comparer) {
+ if (objects.length > 1)
+ quickSort(objects, 0, objects.length - 1, comparer);
+ }
+
+ /**
+ * Sorts an array of strings in place using quicksort.
+ */
+ public static void sort(String[] strings) {
+ if (strings.length > 1)
+ quickSort(strings, 0, strings.length - 1);
+ }
+
+ /**
+ * Sorts an array of Comparable objects in place.
+ */
+ public static void sort(Comparable[] objects) {
+ if (objects.length > 1)
+ quickSort(objects, 0, objects.length - 1);
+ }
+
+ /**
+ * Sorts an array of Strings, returning a new array
+ * with the sorted items. The original array is left untouched.
+ */
+ public static Object[] sortCopy(Object[] objects, Comparer comparer) {
+ int len = objects.length;
+ Object[] copy = new Object[len];
+ System.arraycopy(objects, 0, copy, 0, len);
+ sort(copy, comparer);
+ return copy;
+ }
+
+ /**
+ * Sorts an array of Strings, returning a new array
+ * with the sorted items. The original array is left untouched.
+ */
+ public static String[] sortCopy(String[] objects) {
+ int len = objects.length;
+ String[] copy = new String[len];
+ System.arraycopy(objects, 0, copy, 0, len);
+ sort(copy);
+ return copy;
+ }
+
+ /**
+ * Sorts an array of Comparable objects, returning a new array
+ * with the sorted items. The original array is left untouched.
+ */
+ public static Comparable[] sortCopy(Comparable[] objects) {
+ int len = objects.length;
+ Comparable[] copy = new Comparable[len];
+ System.arraycopy(objects, 0, copy, 0, len);
+ sort(copy);
+ return copy;
+ }
+
+ /**
+ * Sorts an array of strings in place using quicksort
+ * in reverse alphabetical order.
+ */
+ public static void sortReverseOrder(String[] strings) {
+ if (strings.length > 1)
+ quickSortReverse(strings, 0, strings.length - 1);
+ }
+
+ /**
+ * Converts a String[] to char[][].
+ */
+ public static char[][] toCharArrays(String[] a) {
+ int len = a.length;
+ char[][] result = new char[len][];
+ for (int i = 0; i < len; ++i) {
+ result[i] = toChars(a[i]);
+ }
+ return result;
+ }
+
+ /**
+ * Converts a String to char[].
+ */
+ public static char[] toChars(String s) {
+ int len = s.length();
+ char[] chars = new char[len];
+ s.getChars(0, len, chars, 0);
+ return chars;
+ }
+
+ /**
+ * Converts a String to char[][], where segments are separate by '.'.
+ */
+ public static char[][] toCompoundChars(String s) {
+ int len = s.length();
+ if (len == 0) {
+ return CharOperation.NO_CHAR_CHAR;
+ }
+ int segCount = 1;
+ for (int off = s.indexOf('.'); off != -1; off = s.indexOf('.', off + 1)) {
+ ++segCount;
+ }
+ char[][] segs = new char[segCount][];
+ int start = 0;
+ for (int i = 0; i < segCount; ++i) {
+ int dot = s.indexOf('.', start);
+ int end = (dot == -1 ? s.length() : dot);
+ segs[i] = new char[end - start];
+ s.getChars(start, end, segs[i], 0);
+ start = end + 1;
+ }
+ return segs;
+ }
+
+ /**
+ * Converts a char[][] to String, where segments are separated by '.'.
+ */
+ public static String toString(char[][] c) {
+ StringBuffer sb = new StringBuffer();
+ for (int i = 0, max = c.length; i < max; ++i) {
+ if (i != 0) sb.append('.');
+ sb.append(c[i]);
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Converts a char[][] and a char[] to String, where segments are separated by '.'.
+ */
+ public static String toString(char[][] c, char[] d) {
+ if (c == null) return new String(d);
+ StringBuffer sb = new StringBuffer();
+ for (int i = 0, max = c.length; i < max; ++i) {
+ sb.append(c[i]);
+ sb.append('.');
+ }
+ sb.append(d);
+ return sb.toString();
+ }
+
+ /**
+ * Converts a char[] to String.
+ */
+ public static String toString(char[] c) {
+ return new String(c);
+ }
+
+ /**
+ * Converts an array of Objects into String.
+ */
+ public static String toString(Object[] objects) {
+ return toString(objects,
+ new Displayable(){
+ public String displayString(Object o) {
+ if (o == null) return "null"; //$NON-NLS-1$
+ return o.toString();
+ }
+ });
+ }
+
+ /**
+ * Converts an array of Objects into String.
+ */
+ public static String toString(Object[] objects, Displayable renderer) {
+ if (objects == null) return ""; //$NON-NLS-1$
+ StringBuffer buffer = new StringBuffer(10);
+ for (int i = 0; i < objects.length; i++){
+ if (i > 0) buffer.append(", "); //$NON-NLS-1$
+ buffer.append(renderer.displayString(objects[i]));
+ }
+ return buffer.toString();
+ }
+
+ /**
+ * Asserts that the given method signature is valid.
+ */
+ public static void validateMethodSignature(String sig) {
+ Assert.isTrue(isValidMethodSignature(sig));
+ }
+
+ /**
+ * Asserts that the given type signature is valid.
+ */
+ public static void validateTypeSignature(String sig, boolean allowVoid) {
+ Assert.isTrue(isValidTypeSignature(sig, allowVoid));
+ }
+
+ /**
+ * Creates a NLS catalog for the given locale.
+ */
+ public static void relocalize() {
+ try {
+ bundle = ResourceBundle.getBundle(bundleName, Locale.getDefault());
+ } catch(MissingResourceException e) {
+ System.out.println("Missing resource : " + bundleName.replace('.', '/') + ".properties for locale " + Locale.getDefault()); //$NON-NLS-1$//$NON-NLS-2$
+ throw e;
+ }
+ }
+
+ /**
+ * Put all the arguments in one String.
+ */
+ public static String getProblemArgumentsForMarker(String[] arguments){
+ StringBuffer args = new StringBuffer(10);
+
+ args.append(arguments.length);
+ args.append(':');
+
+
+ for (int j = 0; j < arguments.length; j++) {
+ if(j != 0)
+ args.append(ARGUMENTS_DELIMITER);
+
+ if(arguments[j].length() == 0) {
+ args.append(EMPTY_ARGUMENT);
+ } else {
+ args.append(arguments[j]);
+ }
+ }
+
+ return args.toString();
+ }
+
+ /**
+ * Separate all the arguments of a String made by getProblemArgumentsForMarker
+ */
+ public static String[] getProblemArgumentsFromMarker(String argumentsString){
+ if (argumentsString == null) return null;
+ int index = argumentsString.indexOf(':');
+ if(index == -1)
+ return null;
+
+ int length = argumentsString.length();
+ int numberOfArg;
+ try{
+ numberOfArg = Integer.parseInt(argumentsString.substring(0 , index));
+ } catch (NumberFormatException e) {
+ return null;
+ }
+ argumentsString = argumentsString.substring(index + 1, length);
+
+ String[] args = new String[length];
+ int count = 0;
+
+ StringTokenizer tokenizer = new StringTokenizer(argumentsString, ARGUMENTS_DELIMITER);
+ while(tokenizer.hasMoreTokens()) {
+ String argument = tokenizer.nextToken();
+ if(argument.equals(EMPTY_ARGUMENT))
+ argument = ""; //$NON-NLS-1$
+ args[count++] = argument;
+ }
+
+ if(count != numberOfArg)
+ return null;
+
+ System.arraycopy(args, 0, args = new String[count], 0, count);
+ return args;
+ }
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.core.util;
+
+/**
+ * The <code>CharArrayBuffer</code> is intended as a lightweight partial implementation
+ * of the StringBuffer class, but using <code>char[]'s</code> instead of Strings.
+ *
+ * <p>The <code>CharArrayBuffer</code> maintains a list of <code>char[]'s</code>
+ * which don't get appended until the user asks for them. The following
+ * code illustrates how to use the class.
+ *
+ * <code>
+ * CharArrayBuffer buffer = new CharArrayBuffer(myCharArray);
+ * buffer.append(moreBytes, 0, someLength);
+ * myCharArray = buffer.getContents();
+ * </code>
+ *
+ * <p>NOTE: This class is not Thread safe!
+ */
+public class CharArrayBuffer {
+ /**
+ * This is the buffer of char arrays which must be appended together
+ * during the getContents method.
+ */
+ protected char[][] fBuffer;
+
+ /**
+ * The default buffer size.
+ */
+ public static final int DEFAULT_BUFFER_SIZE = 10;
+
+ /**
+ * The end of the buffer
+ */
+ protected int fEnd;
+
+ /**
+ * The current size of the buffer.
+ */
+ protected int fSize;
+
+ /**
+ * A buffer of ranges which is maintained along with
+ * the buffer. Ranges are of the form {start, length}.
+ * Enables append(char[] array, int start, int end).
+ */
+ protected int[][] fRanges;
+/**
+ * Creates a <code>CharArrayBuffer</code> with the default buffer size (10).
+ */
+public CharArrayBuffer() {
+ this(null, DEFAULT_BUFFER_SIZE);
+}
+/**
+ * Creates a <code>CharArrayBuffer</code> with the default buffer size,
+ * and sets the first element in the buffer to be the given char[].
+ *
+ * @param first - the first element to be placed in the buffer, ignored if null
+ */
+public CharArrayBuffer(char[] first) {
+ this(first, DEFAULT_BUFFER_SIZE);
+}
+/**
+ * Creates a <code>CharArrayBuffer</code> with the given buffer size,
+ * and sets the first element in the buffer to be the given char array.
+ *
+ * @param first - the first element of the buffer, ignored if null.
+ * @param size - the buffer size, if less than 1, set to the DEFAULT_BUFFER_SIZE.
+ */
+public CharArrayBuffer(char[] first, int size) {
+ fSize = (size > 0) ? size : DEFAULT_BUFFER_SIZE;
+ fBuffer = new char[fSize][];
+ fRanges = new int[fSize][];
+ fEnd = 0;
+ if (first != null)
+ append(first, 0, first.length);
+}
+/**
+ * Creates a <code>CharArrayBuffer</code> with the given buffer size.
+ *
+ * @param size - the size of the buffer.
+ */
+public CharArrayBuffer(int size) {
+ this(null, size);
+}
+/**
+ * Appends the entire given char array. Given for convenience.
+ *
+ * @param src - a char array which is appended to the end of the buffer.
+ */
+public CharArrayBuffer append(char[] src) {
+ if (src != null)
+ append(src, 0, src.length);
+ return this;
+}
+/**
+ * Appends a sub array of the given array to the buffer.
+ *
+ * @param src - the next array of characters to be appended to the buffer, ignored if null
+ * @param start - the start index in the src array.
+ * @param length - the number of characters from start to be appended
+ *
+ * @throws ArrayIndexOutOfBoundsException - if arguments specify an array index out of bounds.
+ */
+public CharArrayBuffer append(char[] src, int start, int length) {
+ if (start < 0) throw new ArrayIndexOutOfBoundsException();
+ if (length < 0) throw new ArrayIndexOutOfBoundsException();
+ if (src != null) {
+ int srcLength = src.length;
+ if (start > srcLength) throw new ArrayIndexOutOfBoundsException();
+ if (length + start > srcLength) throw new ArrayIndexOutOfBoundsException();
+ /** do length check here to allow exceptions to be thrown */
+ if (length > 0) {
+ if (fEnd == fSize) {
+ int size2 = fSize * 2;
+ System.arraycopy(fBuffer, 0, (fBuffer = new char[size2][]), 0, fSize);
+ System.arraycopy(fRanges, 0, (fRanges = new int[size2][]), 0, fSize);
+ fSize *= 2;
+ }
+ fBuffer[fEnd] = src;
+ fRanges[fEnd] = new int[] {start, length};
+ fEnd++;
+ }
+ }
+ return this;
+}
+/**
+ * Appends the given char. Given for convenience.
+ *
+ * @param src - a char which is appended to the end of the buffer.
+ */
+public CharArrayBuffer append(char c) {
+ append(new char[] {c}, 0, 1);
+ return this;
+}
+/**
+ * Appends the given String to the buffer. Given for convenience, use
+ * #append(char[]) if possible
+ *
+ * @param src - a char array which is appended to the end of the buffer.
+ */
+public CharArrayBuffer append(String src) {
+ if (src != null)
+ append(src.toCharArray(), 0, src.length());
+ return this;
+}
+/**
+ * Returns the entire contents of the buffer as one
+ * char[] or null if nothing has been put in the buffer.
+ */
+public char[] getContents() {
+ if (fEnd == 0)
+ return null;
+
+ // determine the size of the array
+ int size = 0;
+ for (int i = 0; i < fEnd; i++)
+ size += fRanges[i][1];
+
+ if (size > 0) {
+ char[] result = new char[size];
+ int current = 0;
+ // copy the results
+ for(int i = 0; i < fEnd; i++) {
+ int[] range = fRanges[i];
+ int length = range[1];
+ System.arraycopy(fBuffer[i], range[0], result, current, length);
+ current += length;
+ }
+ return result;
+ }
+ return null;
+}
+/**
+ * Returns the contents of the buffer as a String, or
+ * <code>null</code> if the buffer is empty.
+ */
+public String toString() {
+ char[] contents = getContents();
+ return (contents != null) ? new String(contents) : null;
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.corext.phpdoc;
+
+import net.sourceforge.phpdt.core.IBuffer;
+import net.sourceforge.phpdt.internal.corext.util.Strings;
+
+
+/**
+ * Reads a java doc comment from a java doc comment. Skips star-character
+ * on begin of line
+ */
+public class PHPDocCommentReader extends SingleCharReader {
+
+ private IBuffer fBuffer;
+
+ private int fCurrPos;
+ private int fStartPos;
+ private int fEndPos;
+
+ private boolean fWasNewLine;
+
+ public PHPDocCommentReader(IBuffer buf, int start, int end) {
+ fBuffer= buf;
+ fStartPos= start + 3;
+ fEndPos= end - 2;
+
+ reset();
+ }
+
+ /**
+ * @see java.io.Reader#read()
+ */
+ public int read() {
+ if (fCurrPos < fEndPos) {
+ char ch;
+ if (fWasNewLine) {
+ do {
+ ch= fBuffer.getChar(fCurrPos++);
+ } while (fCurrPos < fEndPos && Character.isWhitespace(ch));
+ if (ch == '*') {
+ if (fCurrPos < fEndPos) {
+ do {
+ ch= fBuffer.getChar(fCurrPos++);
+ } while (ch == '*');
+ } else {
+ return -1;
+ }
+ }
+ } else {
+ ch= fBuffer.getChar(fCurrPos++);
+ }
+ fWasNewLine= Strings.isLineDelimiterChar(ch);
+
+ return ch;
+ }
+ return -1;
+ }
+
+ /**
+ * @see java.io.Reader#close()
+ */
+ public void close() {
+ fBuffer= null;
+ }
+
+ /**
+ * @see java.io.Reader#reset()
+ */
+ public void reset() {
+ fCurrPos= fStartPos;
+ fWasNewLine= true;
+ }
+
+
+}
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
package net.sourceforge.phpdt.internal.corext.phpdoc;
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
import java.io.IOException;
import java.io.Reader;
}
return buf.toString();
}
-}
\ No newline at end of file
+}
+++ /dev/null
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-package net.sourceforge.phpdt.internal.corext.util;
-
-import org.eclipse.jface.text.BadLocationException;
-import org.eclipse.jface.text.DefaultLineTracker;
-import org.eclipse.jface.text.ILineTracker;
-import org.eclipse.jface.text.IRegion;
-
-//import org.eclipse.jdt.internal.corext.Assert;
-
-/**
- * Helper class to provide String manipulation functions not available in standard JDK.
- */
-public class Strings {
-
- public static String removeNewLine(String message) {
- StringBuffer result= new StringBuffer();
- int current= 0;
- int index= message.indexOf('\n', 0);
- while (index != -1) {
- result.append(message.substring(current, index));
- if (current < index && index != 0)
- result.append(' ');
- current= index + 1;
- index= message.indexOf('\n', current);
- }
- result.append(message.substring(current));
- return result.toString();
- }
-
- /**
- * Converts the given string into an array of lines. The lines
- * don't contain any line delimiter characters.
- *
- * @return the string converted into an array of strings. Returns <code>
- * null</code> if the input string can't be converted in an array of lines.
- */
- public static String[] convertIntoLines(String input) {
- try {
- ILineTracker tracker= new DefaultLineTracker();
- tracker.set(input);
- int size= tracker.getNumberOfLines();
- String result[]= new String[size];
- for (int i= 0; i < size; i++) {
- IRegion region= tracker.getLineInformation(i);
- int offset= region.getOffset();
- result[i]= input.substring(offset, offset + region.getLength());
- }
- return result;
- } catch (BadLocationException e) {
- return null;
- }
- }
-
- /**
- * Returns <code>true</code> if the given string only consists of
- * white spaces according to Java. If the string is empty, <code>true
- * </code> is returned.
- *
- * @return <code>true</code> if the string only consists of white
- * spaces; otherwise <code>false</code> is returned
- *
- * @see java.lang.Character#isWhitespace(char)
- */
- public static boolean containsOnlyWhitespaces(String s) {
- int size= s.length();
- for (int i= 0; i < size; i++) {
- if (!Character.isWhitespace(s.charAt(i)))
- return false;
- }
- return true;
- }
-
- /**
- * Removes leading tabs and spaces from the given string. If the string
- * doesn't contain any leading tabs or spaces then the string itself is
- * returned.
- */
- public static String trimLeadingTabsAndSpaces(String line) {
- int size= line.length();
- int start= size;
- for (int i= 0; i < size; i++) {
- char c= line.charAt(i);
- if (c != '\t' && !Character.isSpaceChar(c)) {
- start= i;
- break;
- }
- }
- if (start == 0)
- return line;
- else if (start == size)
- return ""; //$NON-NLS-1$
- else
- return line.substring(start);
- }
-
- public static String trimTrailingTabsAndSpaces(String line) {
- int size= line.length();
- int end= size;
- for (int i= size - 1; i >= 0; i--) {
- char c= line.charAt(i);
- if (c == '\t' || Character.isSpaceChar(c)) {
- end= i;
- } else {
- break;
- }
- }
- if (end == size)
- return line;
- else if (end == 0)
- return ""; //$NON-NLS-1$
- else
- return line.substring(0, end);
- }
-
- /**
- * Returns the indent of the given string.
- *
- * @param line the text line
- * @param tabWidth the width of the '\t' character.
- */
- public static int computeIndent(String line, int tabWidth) {
- int result= 0;
- int blanks= 0;
- int size= line.length();
- for (int i= 0; i < size; i++) {
- char c= line.charAt(i);
- if (c == '\t') {
- result++;
- blanks= 0;
- } else if (Character.isSpaceChar(c)) {
- blanks++;
- if (blanks == tabWidth) {
- result++;
- blanks= 0;
- }
- } else {
- return result;
- }
- }
- return result;
- }
-
- /**
- * Removes the given number of idents from the line. Asserts that the given line
- * has the requested number of indents. If <code>indentsToRemove <= 0</code>
- * the line is returned.
- */
- public static String trimIndent(String line, int indentsToRemove, int tabWidth) {
- if (line == null || indentsToRemove <= 0)
- return line;
-
- int start= 0;
- int indents= 0;
- int blanks= 0;
- int size= line.length();
- for (int i= 0; i < size; i++) {
- char c= line.charAt(i);
- if (c == '\t') {
- indents++;
- blanks= 0;
- } else if (Character.isSpaceChar(c)) {
- blanks++;
- if (blanks == tabWidth) {
- indents++;
- blanks= 0;
- }
- } else {
-// Assert.isTrue(false, "Line does not have requested number of indents"); //$NON-NLS-1$
- }
- if (indents == indentsToRemove) {
- start= i + 1;
- break;
- }
- }
- if (start == size)
- return ""; //$NON-NLS-1$
- else
- return line.substring(start);
- }
-
- /**
- * Removes all leading indents from the given line. If the line doesn't contain
- * any indents the line itself is returned.
- */
- public static String trimIndents(String s, int tabWidth) {
- int indent= computeIndent(s, tabWidth);
- if (indent == 0)
- return s;
- return trimIndent(s, indent, tabWidth);
- }
-
- /**
- * Removes the common number of indents from all lines. If a line
- * only consists out of white space it is ignored.
- */
- public static void trimIndentation(String[] lines, int tabWidth) {
- String[] toDo= new String[lines.length];
- // find indentation common to all lines
- int minIndent= Integer.MAX_VALUE; // very large
- for (int i= 0; i < lines.length; i++) {
- String line= lines[i];
- if (containsOnlyWhitespaces(line))
- continue;
- toDo[i]= line;
- int indent= computeIndent(line, tabWidth);
- if (indent < minIndent) {
- minIndent= indent;
- }
- }
-
- if (minIndent > 0) {
- // remove this indent from all lines
- for (int i= 0; i < toDo.length; i++) {
- String s= toDo[i];
- if (s != null)
- lines[i]= trimIndent(s, minIndent, tabWidth);
- else {
- String line= lines[i];
- int indent= computeIndent(line, tabWidth);
- if (indent > minIndent)
- lines[i]= trimIndent(line, minIndent, tabWidth);
- else
- lines[i]= trimLeadingTabsAndSpaces(line);
- }
- }
- }
- }
-
- public static String getIndentString(String line, int tabWidth) {
- int size= line.length();
- int end= 0;
- int blanks= 0;
- for (int i= 0; i < size; i++) {
- char c= line.charAt(i);
- if (c == '\t') {
- end= i;
- blanks= 0;
- } else if (Character.isSpaceChar(c)) {
- blanks++;
- if (blanks == tabWidth) {
- end= i;
- blanks= 0;
- }
- } else {
- break;
- }
- }
- if (end == 0)
- return ""; //$NON-NLS-1$
- else if (end == size)
- return line;
- else
- return line.substring(0, end + 1);
- }
-}
-
case IResource.FILE :
IFile fileResource = (IFile) resource;
- if ( "php".equals(fileResource.getFileExtension()) ||
- "php3".equals(fileResource.getFileExtension()) ||
- "php4".equals(fileResource.getFileExtension()) ) {
+ if ( PHPFileUtil.isPHPFile(fileResource) ) {
phpFiles.add(fileResource);
return true;
}
--- /dev/null
+/*
+ * Created on 09.08.2003
+ *
+ */
+package net.sourceforge.phpdt.internal.ui.util;
+
+import org.eclipse.core.resources.IFile;
+
+/**
+ * @author khartlage
+ *
+ */
+public class PHPFileUtil {
+ static public boolean isPHPFile(IFile file) {
+ if ("php".equalsIgnoreCase(file.getFileExtension())
+ || "php3".equalsIgnoreCase(file.getFileExtension())
+ || "php4".equalsIgnoreCase(file.getFileExtension())
+ || "inc".equalsIgnoreCase(file.getFileExtension())) {
+ return true;
+ }
+ return false;
+ }
+}
public static final String PHP_PARSER_DEFAULT = "_php_parser_default";
public static final String PHP_INTERNAL_PARSER = "_php_internal_parser";
public static final String PHP_EXTERNAL_PARSER = "_php_external_parser";
- public static final String PHP_PARSE_ON_SAVE = "_php_parse_on_save";
+ // public static final String PHP_PARSE_ON_SAVE = "_php_parse_on_save";
public static final String PHP_MULTILINE_COMMENT = "_php_multilineComment";
public static final String PHP_MULTILINE_COMMENT_BOLD = "_php_multilineComment_bold";
public static final String PHP_MULTILINE_COMMENT_ITALIC = "_php_multilineComment_italic";
RadioGroupFieldEditor chooseParser;
StringFieldEditor externalParserSFE;
- BooleanFieldEditor parseOnSave;
+ // BooleanFieldEditor parseOnSave;
public PHPEclipseParserPreferencePage() {
super();
protected void performDefaults() {
chooseParser.loadDefault();
externalParserSFE.loadDefault();
- parseOnSave.loadDefault();
+// parseOnSave.loadDefault();
super.performDefaults();
}
public boolean performOk() {
chooseParser.store();
externalParserSFE.store();
- parseOnSave.store();
+// parseOnSave.store();
return super.performOk();
}
externalParserSFE.setPreferenceStore(getPreferenceStore());
externalParserSFE.load();
- parseOnSave =
- new BooleanFieldEditor(
- PHPeclipsePlugin.PHP_PARSE_ON_SAVE,
- PHPPreferencesMessages.getString("PHPBasePreferencePage.parsers.pos"),
- parserSettingsGroup);
- parseOnSave.setPreferencePage(this);
- parseOnSave.setPreferenceStore(getPreferenceStore());
- parseOnSave.load();
+// parseOnSave =
+// new BooleanFieldEditor(
+// PHPeclipsePlugin.PHP_PARSE_ON_SAVE,
+// PHPPreferencesMessages.getString("PHPBasePreferencePage.parsers.pos"),
+// parserSettingsGroup);
+// parseOnSave.setPreferencePage(this);
+// parseOnSave.setPreferenceStore(getPreferenceStore());
+// parseOnSave.load();
return composite;
}
*/
public static final String PLUGIN_ID = "net.sourceforge.phpeclipse"; //$NON-NLS-1$
public final static String PHP_NATURE_ID = PLUGIN_ID + ".phpnature";
+
+ /**
+ * id of builder - matches plugin.xml (concatenate pluginid.builderid)
+ */
+ public static final String BUILDER_INDEX_ID = PLUGIN_ID + ".indexbuilder";
+ public static final String BUILDER_PARSER_ID = PLUGIN_ID + ".parserbuilder";
+
// public static final String PHP_RESOURCES_VIEW_ID = PLUGIN_ID + ".resourcesview.ViewPHPResources"; //$NON-NLS-1$
public static final String PHP_CODING_ACTION_SET_ID = PLUGIN_ID + ".ui.CodingActionSet"; //$NON-NLS-1$
store.setDefault(PHP_INTERNAL_PARSER, "false");
store.setDefault(PHP_EXTERNAL_PARSER, "true");
- store.setDefault(PHP_PARSE_ON_SAVE, "true");
+// store.setDefault(PHP_PARSE_ON_SAVE, "true");
// show line numbers:
// store.setDefault(LINE_NUMBER_RULER, "false");
protected IWorkbenchWindow activeWindow = null;
public void run(IAction action) {
- final IPreferenceStore store = PHPeclipsePlugin.getDefault().getPreferenceStore();
+ final IPreferenceStore store =
+ PHPeclipsePlugin.getDefault().getPreferenceStore();
String documentRoot = store.getString(PHPeclipsePlugin.DOCUMENTROOT_PREF);
// replace backslash with slash in the DocumentRoot under Windows
documentRoot = documentRoot.replace('\\', '/');
String[] arguments = { documentRoot };
- MessageFormat form = new MessageFormat(store.getString(PHPeclipsePlugin.APACHE_START_PREF));
+ MessageFormat form =
+ new MessageFormat(store.getString(PHPeclipsePlugin.APACHE_START_PREF));
execute(
"apache_start",
store.getString(PHPeclipsePlugin.APACHE_RUN_PREF),
* @param arguments arguments for this configuration
* @param background run this configuration in background mode
*/
- public static void execute(String command, String executable, String arguments, boolean background) {
+ public static void execute(
+ String command,
+ String executable,
+ String arguments,
+ boolean background) {
PHPConsole console = PHPConsole.getInstance();
String consoleMessage;
if (background) {
- consoleMessage = "run in background mode-" + command + ": " + executable + " " + arguments;
+ consoleMessage =
+ "run in background mode-"
+ + command
+ + ": "
+ + executable
+ + " "
+ + arguments;
} else {
- consoleMessage = "run in foreground mode-" + command + ": " + executable + " " + arguments;
+ consoleMessage =
+ "run in foreground mode-"
+ + command
+ + ": "
+ + executable
+ + " "
+ + arguments;
}
console.write(consoleMessage + "\n");
public static String getParserOutput(String command, String consoleMessage) {
// MessageDialog.openInformation(activeWindow.getShell(), "Exec command: ", command);
try {
- PHPConsole console = PHPConsole.getInstance();
- if (console != null) {
- console.write(consoleMessage + command + "\n");
+ PHPConsole console = null;
+ try {
+ console = PHPConsole.getInstance();
+ if (console != null) {
+ console.write(consoleMessage + command + "\n");
+ }
+ } catch (Throwable th) {
+
}
Runtime runtime = Runtime.getRuntime();
--- /dev/null
+package net.sourceforge.phpeclipse.builder;
+
+import java.util.Map;
+
+import net.sourceforge.phpdt.internal.ui.util.PHPFileUtil;
+import net.sourceforge.phpeclipse.phpeditor.PHPParserAction;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceDelta;
+import org.eclipse.core.resources.IResourceVisitor;
+import org.eclipse.core.resources.IncrementalProjectBuilder;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+
+/**
+ * Builder for .php files.
+ *
+ *
+ * @see org.eclipse.core.resources.IncrementalProjectBuilder
+ * @see org.eclipse.core.resources.IResourceDelta
+ */
+public class ParserBuilder extends IncrementalProjectBuilder {
+ private final static int TOTAL_WORK = 100;
+
+ /**
+ * Constructor
+ */
+ public ParserBuilder() {
+ }
+
+ /**
+ *
+ */
+ protected IProject[] build(int kind, Map args, IProgressMonitor monitor)
+ throws CoreException {
+ monitor.beginTask("Parsing files", TOTAL_WORK);
+
+ if (kind == IncrementalProjectBuilder.FULL_BUILD) {
+ IResourceDelta delta = getDelta(getProject());
+
+ processFull(getProject(), monitor);
+
+ } else { // INCREMENTAL_BUILD or AUTO_BUILD
+
+ IResourceDelta delta = getDelta(getProject());
+ if (delta != null) {
+ delta.accept(new ParserVisitor(monitor));
+ }
+
+ }
+ monitor.done();
+ return null;
+ }
+
+ /**
+ * Performs a <code>FULL_BUILD</code> by visiting all nodes in the resource
+ * tree under the specified project.
+ *
+ * @param iProject
+ */
+ public void processFull(IProject iProject, final IProgressMonitor monitor) {
+
+ // Create resource visitor logic
+ IResourceVisitor myVisitor = new IResourceVisitor() {
+ public boolean visit(IResource resource) throws CoreException {
+ if (resource.getType() == IResource.FILE) {
+ if (monitor.isCanceled()) {
+ throw new OperationCanceledException();
+ }
+ if ((resource.getFileExtension() != null)
+ && PHPFileUtil.isPHPFile((IFile) resource)) {
+ monitor.worked(1);
+ monitor.subTask("Parsing: " + resource.getFullPath());
+ PHPParserAction.parseFile((IFile) resource);
+ }
+ }
+
+ return true;
+ }
+ };
+
+ // Process the project using the visitor just created
+ try {
+ iProject.accept(myVisitor);
+ } catch (CoreException e) {
+ e.printStackTrace();
+ }
+
+ }
+
+ /**
+ * Sets initialization data for this builder.
+ * <p>
+ * This method is part of the <code>IExecutableExtension</code>
+ * interface.
+ * </p>
+ * <p>
+ * Subclasses are free to extend this method to pick up
+ * initialization parameters from the plug-in plug-in manifest
+ * (<code>plugin.xml</code>) file,
+ * but should be sure to invoke this method on their superclass.
+ * <p>
+ * For example, the following method looks for a boolean-valued
+ * parameter named "trace":
+ * <pre>
+ * public void setInitializationData(IConfigurationElement cfig,
+ * String propertyName, Object data)
+ * throws CoreException {
+ * super.setInitializationData(cfig, propertyName, data);
+ * if (data instanceof Hashtable) {
+ * Hashtable args = (Hashtable) data;
+ * String traceValue = (String) args.get("trace");
+ * TRACING = (traceValue!=null && traceValue.equals("true"));
+ * }
+ * }
+ * </pre>
+ * </p>
+ */
+ public void setInitializationData(
+ IConfigurationElement config,
+ String propertyName,
+ Object data)
+ throws CoreException {
+ super.setInitializationData(config, propertyName, data);
+
+ }
+
+ /**
+ * Informs this builder that it is being started by the build management
+ * infrastructure. By the time this method is run, the builder's project
+ * is available and <code>setInitializationData</code> has been called.
+ * The default implementation should be called by all overriding methods.
+ *
+ * @see #setInitializationData
+ */
+ protected void startupOnInitialize() {
+ // traceMsg("Parse Builder Initialize - startupOnInitialize()");
+ }
+
+ /**
+ * Write trace statements.
+ * System.out.println with prefix tagging used for simplicity.
+ */
+ // private void traceMsg(String msg) {
+ // if (PHPeclipsePlugin.DEBUG | traceEnabled)
+ // System.out.println(
+ // buildMode
+ // + "<"
+ // + getProject()
+ // + "> "
+ // + "\t\t\t"
+ // + buildMark
+ // + msg);
+ // }
+}
\ No newline at end of file
--- /dev/null
+package net.sourceforge.phpeclipse.builder;
+
+import net.sourceforge.phpdt.internal.ui.util.PHPFileUtil;
+import net.sourceforge.phpeclipse.phpeditor.PHPParserAction;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceDelta;
+import org.eclipse.core.resources.IResourceDeltaVisitor;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+
+/**
+ *
+ * @see org.eclipse.core.resources.IResourceDelta
+ * @see org.eclipse.core.resources.IResourceDeltaVisitor
+ */
+public class ParserVisitor implements IResourceDeltaVisitor {
+ final IProgressMonitor fMonitor;
+ public ParserVisitor(IProgressMonitor monitor) {
+ fMonitor = monitor;
+ }
+
+ protected void checkCancel() {
+ if (fMonitor.isCanceled()) {
+ throw new OperationCanceledException();
+ }
+ }
+ /**
+ * Visits the given resource delta.
+ *
+ * @return <code>true</code> if the resource delta's children should
+ * be visited; <code>false</code> if they should be skipped.
+ * @exception CoreException if the visit fails for some reason.
+ */
+ public boolean visit(IResourceDelta delta) throws CoreException {
+
+ IResource resource = delta.getResource();
+ int resourceType = resource.getType();
+ checkCancel();
+
+ switch (delta.getKind()) {
+ case IResourceDelta.ADDED :
+ if (resourceType == IResource.FILE) {
+ if ((resource.getFileExtension() != null)
+ && PHPFileUtil.isPHPFile((IFile) resource)) {
+ fMonitor.worked(1);
+ fMonitor.subTask("Parsing: " + resource.getFullPath());
+ PHPParserAction.parseFile((IFile) resource);
+ }
+ }
+ break;
+
+ case IResourceDelta.CHANGED :
+ if (resourceType == IResource.FILE) {
+ if ((resource.getFileExtension() != null)
+ && PHPFileUtil.isPHPFile((IFile) resource)) {
+ fMonitor.worked(1);
+ fMonitor.subTask("Parsing: " + resource.getFullPath());
+ PHPParserAction.parseFile((IFile) resource);
+ }
+ }
+ break;
+
+ case IResourceDelta.REMOVED :
+ }
+ return true; // carry on
+ }
+
+}
\ No newline at end of file
super.doSave(monitor);
// compile or not, according to the user preferences
IPreferenceStore store = getPreferenceStore(); // fPHPPrefStore;
- if (store.getBoolean(PHPeclipsePlugin.PHP_PARSE_ON_SAVE)) {
- IAction a = PHPParserAction.getInstance();
- if (a != null)
- a.run();
- }
+
+ // the parse on save was changed to the eclipse "builders" concept
+ // if (store.getBoolean(PHPeclipsePlugin.PHP_PARSE_ON_SAVE)) {
+ // IAction a = PHPParserAction.getInstance();
+ // if (a != null)
+ // a.run();
+ // }
+
// if (SWT.getPlatform().equals("win32")) {
// IAction a = ShowExternalPreviewAction.getInstance();
// if (a != null)
*/
public void editorContextMenuAboutToShow(MenuManager menu) {
super.editorContextMenuAboutToShow(menu);
- menu.appendToGroup(ITextEditorActionConstants.GROUP_UNDO, new Separator(IContextMenuConstants.GROUP_OPEN));
- menu.insertAfter(IContextMenuConstants.GROUP_OPEN, new GroupMarker(IContextMenuConstants.GROUP_SHOW));
-
- ActionContext context= new ActionContext(getSelectionProvider().getSelection());
- fContextMenuGroup.setContext(context);
- fContextMenuGroup.fillContextMenu(menu);
- fContextMenuGroup.setContext(null);
-// addAction(menu, ITextEditorActionConstants.GROUP_EDIT, "Format"); //$NON-NLS-1$
-//
-// ActionContext context =
-// new ActionContext(getSelectionProvider().getSelection());
-// fContextMenuGroup.setContext(context);
-// fContextMenuGroup.fillContextMenu(menu);
-// fContextMenuGroup.setContext(null);
+ menu.appendToGroup(
+ ITextEditorActionConstants.GROUP_UNDO,
+ new Separator(IContextMenuConstants.GROUP_OPEN));
+ menu.insertAfter(
+ IContextMenuConstants.GROUP_OPEN,
+ new GroupMarker(IContextMenuConstants.GROUP_SHOW));
+
+ ActionContext context =
+ new ActionContext(getSelectionProvider().getSelection());
+ fContextMenuGroup.setContext(context);
+ fContextMenuGroup.fillContextMenu(menu);
+ fContextMenuGroup.setContext(null);
+ // addAction(menu, ITextEditorActionConstants.GROUP_EDIT, "Format"); //$NON-NLS-1$
+ //
+ // ActionContext context =
+ // new ActionContext(getSelectionProvider().getSelection());
+ // fContextMenuGroup.setContext(context);
+ // fContextMenuGroup.fillContextMenu(menu);
+ // fContextMenuGroup.setContext(null);
}
protected void updateStateDependentActions() {
*/
public void run() {
boolean phpFlag = false;
- try {
+
+ // try {
fileToParse = getPHPFile();
- if (fileToParse == null) {
- // should never happen
- System.err.println("Error : no file in the editor");
- // should throw an exception
- return;
- }
- String name = fileToParse.getName().toLowerCase();
- for (int i = 0; i<EXTENSIONS.length; i++) {
- if (name.endsWith(EXTENSIONS[i])) {
- phpFlag = true; // php file extension
- break;
- }
- }
- if (phpFlag) {
- IPreferenceStore store = PHPeclipsePlugin.getDefault().getPreferenceStore();
- if (store.getString(PHPeclipsePlugin.PHP_PARSER_DEFAULT).equals(PHPeclipsePlugin.PHP_INTERNAL_PARSER)) {
- // first delete all the previous markers
- fileToParse.deleteMarkers(IMarker.PROBLEM, false, 0);
-
- //the tasks are removed here
- fileToParse.deleteMarkers(IMarker.TASK, false, 0);
-
- try {
- InputStream iStream = fileToParse.getContents();
- // int c = iStream.read();
- parse(iStream);
- iStream.close();
- } catch (IOException e) {
- }
- } else {
- PHPParserSuperclass.phpExternalParse(fileToParse);
- }
- }
- } catch (CoreException e) {
- }
-
+ parseFile(fileToParse);
}
+ public static void parseFile(IFile fileToParse) {
+ boolean phpFlag = false;
+ try {
+
+ if (fileToParse == null) {
+ // should never happen
+ System.err.println("Error : no file in the editor");
+ // should throw an exception
+ return;
+ }
+ String name = fileToParse.getName().toLowerCase();
+ for (int i = 0; i<EXTENSIONS.length; i++) {
+ if (name.endsWith(EXTENSIONS[i])) {
+ phpFlag = true; // php file extension
+ break;
+ }
+ }
+ if (phpFlag) {
+ IPreferenceStore store = PHPeclipsePlugin.getDefault().getPreferenceStore();
+ if (store.getString(PHPeclipsePlugin.PHP_PARSER_DEFAULT).equals(PHPeclipsePlugin.PHP_INTERNAL_PARSER)) {
+ // first delete all the previous markers
+ fileToParse.deleteMarkers(IMarker.PROBLEM, false, 0);
+
+ //the tasks are removed here
+ fileToParse.deleteMarkers(IMarker.TASK, false, 0);
+
+ try {
+ InputStream iStream = fileToParse.getContents();
+ // int c = iStream.read();
+ parse(fileToParse,iStream);
+ iStream.close();
+ } catch (IOException e) {
+ }
+ } else {
+ PHPParserSuperclass.phpExternalParse(fileToParse);
+ }
+ }
+ } catch (CoreException e) {
+ }
+
+ }
/**
* Finds the file that's currently opened in the PHP Text Editor
*/
// return identifier.toString();
// }
- protected void parse(InputStream iStream) {
+ protected static void parse(IFile fileToParse, InputStream iStream) {
StringBuffer buf = new StringBuffer();
int c0;
import net.sourceforge.phpeclipse.LoadPathEntry;
import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import org.eclipse.core.resources.ICommand;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IProjectNature;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.xml.sax.XMLReader;
public class PHPProject implements IProjectNature, PHPElement {
- protected IProject fProject;
- protected List loadPathEntries;
- protected boolean scratched;
-
- public PHPProject() {}
-
- public void configure() throws CoreException {}
-
- public void deconfigure() throws CoreException {}
-
- public IProject getProject() {
- return fProject;
- }
-
- protected IProject getProject(String name) {
- return PHPeclipsePlugin.getWorkspace().getRoot().getProject(name);
- }
-
- public void setProject(IProject aProject) {
- fProject = aProject;
- }
-
- public void addLoadPathEntry(IProject anotherPHPProject) {
- scratched = true;
-
- LoadPathEntry newEntry = new LoadPathEntry(anotherPHPProject);
- getLoadPathEntries().add(newEntry);
- }
-
- public void removeLoadPathEntry(IProject anotherPHPProject) {
- Iterator entries = getLoadPathEntries().iterator();
- while (entries.hasNext()) {
- LoadPathEntry entry = (LoadPathEntry) entries.next();
- if (entry.getType() == LoadPathEntry.TYPE_PROJECT && entry.getProject().getName().equals(anotherPHPProject.getName())) {
- getLoadPathEntries().remove(entry);
- scratched = true;
- break;
- }
- }
- }
-
- public List getLoadPathEntries() {
- if (loadPathEntries == null) {
- loadLoadPathEntries();
- }
-
- return loadPathEntries;
- }
-
- public List getReferencedProjects() {
- List referencedProjects = new ArrayList();
-
- Iterator iterator = getLoadPathEntries().iterator();
- while (iterator.hasNext()) {
- LoadPathEntry pathEntry = (LoadPathEntry) iterator.next();
- if (pathEntry.getType() == LoadPathEntry.TYPE_PROJECT)
- referencedProjects.add(pathEntry.getProject());
- }
-
- return referencedProjects;
- }
-
- protected void loadLoadPathEntries() {
- loadPathEntries = new ArrayList();
-
- IFile loadPathsFile = getLoadPathEntriesFile();
-
- XMLReader reader = null;
- try {
- reader = SAXParserFactory.newInstance().newSAXParser().getXMLReader();
- reader.setContentHandler(getLoadPathEntriesContentHandler());
- reader.parse(new InputSource(loadPathsFile.getContents()));
- } catch (Exception e) {
- //the file is nonextant or unreadable
- }
- }
-
- protected ContentHandler getLoadPathEntriesContentHandler() {
- return new ContentHandler() {
- public void characters(char[] arg0, int arg1, int arg2) throws SAXException {}
-
- public void endDocument() throws SAXException {}
-
- public void endElement(String arg0, String arg1, String arg2) throws SAXException {}
-
- public void endPrefixMapping(String arg0) throws SAXException {}
-
- public void ignorableWhitespace(char[] arg0, int arg1, int arg2) throws SAXException {}
-
- public void processingInstruction(String arg0, String arg1) throws SAXException {}
-
- public void setDocumentLocator(Locator arg0) {}
-
- public void skippedEntity(String arg0) throws SAXException {}
-
- public void startDocument() throws SAXException {}
-
- public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
- if ("pathentry".equals(qName))
- if ("project".equals(atts.getValue("type"))) {
- IPath referencedProjectPath = new Path(atts.getValue("path"));
- IProject referencedProject = getProject(referencedProjectPath.lastSegment());
- loadPathEntries.add(new LoadPathEntry(referencedProject));
- }
- }
-
- public void startPrefixMapping(String arg0, String arg1) throws SAXException {}
- };
- }
-
- protected IFile getLoadPathEntriesFile() {
- return fProject.getFile(".loadpath");
- }
-
- public void save() throws CoreException {
- if (scratched) {
- InputStream xmlPath = new ByteArrayInputStream(getLoadPathXML().getBytes());
- IFile loadPathsFile = getLoadPathEntriesFile();
- if (!loadPathsFile.exists())
- loadPathsFile.create(xmlPath, true, null);
- else
- loadPathsFile.setContents(xmlPath, true, false, null);
-
- scratched = false;
- }
- }
-
- protected String getLoadPathXML() {
- StringBuffer buffer = new StringBuffer();
- buffer.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?><loadpath>");
-
- Iterator pathEntriesIterator = loadPathEntries.iterator();
-
- while (pathEntriesIterator.hasNext()) {
- LoadPathEntry entry = (LoadPathEntry) pathEntriesIterator.next();
- buffer.append(entry.toXML());
- }
-
- buffer.append("</loadpath>");
- return buffer.toString();
- }
-
- public IResource getUnderlyingResource() {
- return fProject;
- }
+ protected IProject fProject;
+ protected List loadPathEntries;
+ protected boolean scratched;
+
+ public PHPProject() {
+ }
+
+ public void configure() throws CoreException {
+ // get project description and then the associated build commands
+ IProjectDescription desc = fProject.getDescription();
+ ICommand[] commands = desc.getBuildSpec();
+
+ // determine if builder already associated
+ boolean found = false;
+ for (int i = 0; i < commands.length; ++i) {
+ if (commands[i].getBuilderName().equals(PHPeclipsePlugin.BUILDER_PARSER_ID)) {
+ found = true;
+ break;
+ }
+ }
+
+ // add builder if not already in project
+ if (!found) {
+ ICommand command = desc.newCommand();
+ command.setBuilderName(PHPeclipsePlugin.BUILDER_PARSER_ID);
+ ICommand[] newCommands = new ICommand[commands.length + 1];
+
+ // Add it before other builders.
+ System.arraycopy(commands, 0, newCommands, 1, commands.length);
+ newCommands[0] = command;
+ desc.setBuildSpec(newCommands);
+ fProject.setDescription(desc, null);
+ }
+ }
+
+ public void deconfigure() throws CoreException {
+ }
+
+ public IProject getProject() {
+ return fProject;
+ }
+
+ protected IProject getProject(String name) {
+ return PHPeclipsePlugin.getWorkspace().getRoot().getProject(name);
+ }
+
+ public void setProject(IProject aProject) {
+ fProject = aProject;
+ }
+
+ public void addLoadPathEntry(IProject anotherPHPProject) {
+ scratched = true;
+
+ LoadPathEntry newEntry = new LoadPathEntry(anotherPHPProject);
+ getLoadPathEntries().add(newEntry);
+ }
+
+ public void removeLoadPathEntry(IProject anotherPHPProject) {
+ Iterator entries = getLoadPathEntries().iterator();
+ while (entries.hasNext()) {
+ LoadPathEntry entry = (LoadPathEntry) entries.next();
+ if (entry.getType() == LoadPathEntry.TYPE_PROJECT
+ && entry.getProject().getName().equals(anotherPHPProject.getName())) {
+ getLoadPathEntries().remove(entry);
+ scratched = true;
+ break;
+ }
+ }
+ }
+
+ public List getLoadPathEntries() {
+ if (loadPathEntries == null) {
+ loadLoadPathEntries();
+ }
+
+ return loadPathEntries;
+ }
+
+ public List getReferencedProjects() {
+ List referencedProjects = new ArrayList();
+
+ Iterator iterator = getLoadPathEntries().iterator();
+ while (iterator.hasNext()) {
+ LoadPathEntry pathEntry = (LoadPathEntry) iterator.next();
+ if (pathEntry.getType() == LoadPathEntry.TYPE_PROJECT)
+ referencedProjects.add(pathEntry.getProject());
+ }
+
+ return referencedProjects;
+ }
+
+ protected void loadLoadPathEntries() {
+ loadPathEntries = new ArrayList();
+
+ IFile loadPathsFile = getLoadPathEntriesFile();
+
+ XMLReader reader = null;
+ try {
+ reader = SAXParserFactory.newInstance().newSAXParser().getXMLReader();
+ reader.setContentHandler(getLoadPathEntriesContentHandler());
+ reader.parse(new InputSource(loadPathsFile.getContents()));
+ } catch (Exception e) {
+ //the file is nonextant or unreadable
+ }
+ }
+
+ protected ContentHandler getLoadPathEntriesContentHandler() {
+ return new ContentHandler() {
+ public void characters(char[] arg0, int arg1, int arg2)
+ throws SAXException {
+ }
+
+ public void endDocument() throws SAXException {
+ }
+
+ public void endElement(String arg0, String arg1, String arg2)
+ throws SAXException {
+ }
+
+ public void endPrefixMapping(String arg0) throws SAXException {
+ }
+
+ public void ignorableWhitespace(char[] arg0, int arg1, int arg2)
+ throws SAXException {
+ }
+
+ public void processingInstruction(String arg0, String arg1)
+ throws SAXException {
+ }
+
+ public void setDocumentLocator(Locator arg0) {
+ }
+
+ public void skippedEntity(String arg0) throws SAXException {
+ }
+
+ public void startDocument() throws SAXException {
+ }
+
+ public void startElement(
+ String namespaceURI,
+ String localName,
+ String qName,
+ Attributes atts)
+ throws SAXException {
+ if ("pathentry".equals(qName))
+ if ("project".equals(atts.getValue("type"))) {
+ IPath referencedProjectPath = new Path(atts.getValue("path"));
+ IProject referencedProject =
+ getProject(referencedProjectPath.lastSegment());
+ loadPathEntries.add(new LoadPathEntry(referencedProject));
+ }
+ }
+
+ public void startPrefixMapping(String arg0, String arg1)
+ throws SAXException {
+ }
+ };
+ }
+
+ protected IFile getLoadPathEntriesFile() {
+ return fProject.getFile(".loadpath");
+ }
+
+ public void save() throws CoreException {
+ if (scratched) {
+ InputStream xmlPath =
+ new ByteArrayInputStream(getLoadPathXML().getBytes());
+ IFile loadPathsFile = getLoadPathEntriesFile();
+ if (!loadPathsFile.exists())
+ loadPathsFile.create(xmlPath, true, null);
+ else
+ loadPathsFile.setContents(xmlPath, true, false, null);
+
+ scratched = false;
+ }
+ }
+
+ protected String getLoadPathXML() {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?><loadpath>");
+
+ Iterator pathEntriesIterator = loadPathEntries.iterator();
+
+ while (pathEntriesIterator.hasNext()) {
+ LoadPathEntry entry = (LoadPathEntry) pathEntriesIterator.next();
+ buffer.append(entry.toXML());
+ }
+
+ buffer.append("</loadpath>");
+ return buffer.toString();
+ }
+
+ public IResource getUnderlyingResource() {
+ return fProject;
+ }
}
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PartInitException;
-import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.part.ViewPart;
/**
*/
public class PHPConsole extends ViewPart {
- public static final String CONSOLE_ID = "net.sourceforge.phpeclipse.views.phpconsoleview";
+ public static final String CONSOLE_ID =
+ "net.sourceforge.phpeclipse.views.phpconsoleview";
private int COMMAND_COMBO_SIZE = 10;
private TextViewer fViewer = null;
private Document fDocument = null;
private StyledText fStyledText;
// private Combo fCommandCombo;
-// private ProcessOutputWriter consoleOut;
-// private ProcessOutputWriter consoleErr;
+ // private ProcessOutputWriter consoleOut;
+ // private ProcessOutputWriter consoleErr;
// private Action goAction;
* @see ViewPart#createPartControl
*/
public void createPartControl(Composite parent) {
-// Composite container = new Composite(parent, SWT.NULL);
-// // control = container;
-// GridLayout layout = new GridLayout();
-// layout.marginWidth = 0;
-// layout.marginHeight = 0;
-// layout.verticalSpacing = 0;
-// container.setLayout(layout);
-// Composite navContainer = new Composite(container, SWT.NONE);
-// layout = new GridLayout();
-// layout.numColumns = 2;
-// layout.marginHeight = 1;
-// navContainer.setLayout(layout);
-// createCommandBar(navContainer);
-// navContainer.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ // Composite container = new Composite(parent, SWT.NULL);
+ // // control = container;
+ // GridLayout layout = new GridLayout();
+ // layout.marginWidth = 0;
+ // layout.marginHeight = 0;
+ // layout.verticalSpacing = 0;
+ // container.setLayout(layout);
+ // Composite navContainer = new Composite(container, SWT.NONE);
+ // layout = new GridLayout();
+ // layout.numColumns = 2;
+ // layout.marginHeight = 1;
+ // navContainer.setLayout(layout);
+ // createCommandBar(navContainer);
+ // navContainer.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
fViewer = new TextViewer(parent, SWT.WRAP | SWT.V_SCROLL | SWT.H_SCROLL);
GridData viewerData = new GridData(GridData.FILL_BOTH);
fViewer.setEditable(false);
fStyledText = fViewer.getTextWidget();
- fStyledText.setFont(JFaceResources.getFontRegistry().get(JFaceResources.TEXT_FONT));
+ fStyledText.setFont(
+ JFaceResources.getFontRegistry().get(JFaceResources.TEXT_FONT));
cutAction.setText("Cut");
copyAction.setText("Copy");
}
private void createCommandBar(Composite parent) {
-// Label addressLabel = new Label(parent, SWT.NONE);
-// addressLabel.setText("Command:");
+ // Label addressLabel = new Label(parent, SWT.NONE);
+ // addressLabel.setText("Command:");
// fCommandCombo = new Combo(parent, SWT.DROP_DOWN | SWT.BORDER);
// fCommandCombo.addModifyListener(new ModifyListener() {
}
public static PHPConsole getInstance() {
- IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
+ // IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
+ IWorkbenchPage page =
+ PHPeclipsePlugin
+ .getDefault()
+ .getWorkbench()
+ .getActiveWorkbenchWindow()
+ .getActivePage();
PHPConsole console = (PHPConsole) page.findView(PHPConsole.CONSOLE_ID);
- if (PHPeclipsePlugin.getDefault().getPreferenceStore().getBoolean(PHPeclipsePlugin.SHOW_OUTPUT_IN_CONSOLE) == true) {
+ if (PHPeclipsePlugin
+ .getDefault()
+ .getPreferenceStore()
+ .getBoolean(PHPeclipsePlugin.SHOW_OUTPUT_IN_CONSOLE)
+ == true) {
try {
page.showView(PHPConsole.CONSOLE_ID);
if (console == null) {
IStatus.ERROR,
PHPeclipsePlugin.getPluginId(),
0,
- PHPActionMessages.getString("PHPStartApacheAction.consoleViewOpeningProblem"),
+ PHPActionMessages.getString(
+ "PHPStartApacheAction.consoleViewOpeningProblem"),
e));
}
}
/**
* Creates a string buffer from the given input stream
*/
- public static String getStringFromStream(InputStream stream) throws IOException {
+ public static String getStringFromStream(InputStream stream)
+ throws IOException {
StringBuffer buffer = new StringBuffer();
byte[] b = new byte[100];
int finished = 0;
public void run() {
try {
- BufferedReader in = new BufferedReader(new InputStreamReader(fInputStream));
+ BufferedReader in =
+ new BufferedReader(new InputStreamReader(fInputStream));
String line;
while ((line = in.readLine()) != null) {