⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pythonnaturestore.java

📁 Python Development Environment (Python IDE plugin for Eclipse). Features editor, code completion, re
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
/*
 * License: Eclipse Public License v1.0
 * Created on Oct 21, 2006
 * 
 * @author Gergely Kis
 */
package org.python.pydev.plugin.nature;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.QualifiedName;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.python.pydev.core.docutils.StringUtils;
import org.python.pydev.editor.codecompletion.revisited.ProjectModulesManager;
import org.python.pydev.plugin.PydevPlugin;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.ProcessingInstruction;

/**
 * This class stores PythonNature and PythonPathNature properties inside the project in a file instead of persistent properties. This allows PYTHONPATH and Python project version to be checked in into
 * version control systems.
 * 
 * @author Gergely Kis <gergely.kis@gmail.com>
 * 
 */

class PythonNatureStore implements IResourceChangeListener, IPythonNatureStore {

    /**
     * This is the class that does the store job.
     * 
     * @author Fabio
     */
    private final class PythonNatureStoreJob extends Job {
        private final ByteArrayInputStream is;

        private PythonNatureStoreJob(String name, ByteArrayInputStream is) {
            super(name);
            this.is = is;
        }

        @Override
        protected IStatus run(IProgressMonitor monitor) {
            synchronized(xmlFile){
                try{
                    onIgnoreRefresh++;
                    if (!xmlFile.exists()) {
                        xmlFile.create(is, true, monitor);
                        modStamp = xmlFile.getModificationStamp();
                    } else {
                        xmlFile.setContents(is, true, false, monitor);
                        modStamp = xmlFile.getModificationStamp();
                    }
                    xmlFile.refreshLocal(IResource.DEPTH_ZERO, monitor);
                }catch(Exception e){
                    PydevPlugin.log(e);
                }finally{
                    onIgnoreRefresh--;
                }
            }
            return Status.OK_STATUS;
        }
    }

    private final static String STORE_FILE_NAME = ".pydevproject";

    private final static String PYDEV_PROJECT_DESCRIPTION = "pydev_project";

    private final static String PYDEV_NATURE_PROPERTY = "pydev_property";

    private final static String PYDEV_NATURE_PATH_PROPERTY = "pydev_pathproperty";

    private final static String PYDEV_PATH = "path";

    private final static String PYDEV_NATURE_PROPERTY_NAME = "name";

    private volatile IProject project = null;

    private volatile IFile xmlFile = null;

    private volatile long modStamp = IFile.NULL_STAMP;
    
    private volatile int onIgnoreRefresh = 0;

    /**
     * 0 means we're not in a store job
     */
    private volatile int onStoreJob = 0;

    /**
     * Whether the file has already been loaded
     */
    private volatile boolean loaded = false;
    
    /**
     * This is the dom document that is used to manipulate the xml info.
     */
    private volatile Document document = null;
    
    private static final boolean TRACE_PYTHON_NATURE_STORE = false;
    private StringBuffer indent = new StringBuffer();

    private volatile boolean inInit;  
    
    private void traceFunc(String func){
        if(TRACE_PYTHON_NATURE_STORE){
            if(!func.startsWith("END ")){
                System.out.println(indent+func);
                indent.append("  ");
                
            }else{
                indent.delete(0, 2);
                System.out.println(indent+func);
            }
        }
    }
    

    /* (non-Javadoc)
     * @see org.python.pydev.plugin.nature.IPythonNatureStore#setProject(org.eclipse.core.resources.IProject)
     */
    public synchronized void setProject(IProject project) {
        synchronized (this) {
            if(project == null){
                if(this.project == null){
                    return; // already de-configured
                }
                //removing configurations...
                traceFunc("setProject: null");
                ResourcesPlugin.getWorkspace().removeResourceChangeListener(this);
                this.project = null;
                this.xmlFile = null;
                this.document = null;
                
            }else{
                traceFunc("setProject - "+project.getName());
            	try{
        	        this.project = project;
        	        this.xmlFile = project.getFile(STORE_FILE_NAME);
        	        try {
        	            loadFromFile();
        	        } catch (CoreException e) {
        	            throw new RuntimeException("Error loading project: "+project, e);
        	        }
        	        if (!ProjectModulesManager.IN_TESTS) {
        	            project.getWorkspace().addResourceChangeListener(this);
        	        }
                }finally{
                	loaded = true;
                }
                traceFunc("END setProject - "+project.getName());
            }
        }
    }

    /**
     * @param function the function that is checking for load
     */
    private synchronized void checkLoad(String function) {
        traceFunc("checkLoad");
        synchronized (this) {
        	if(!loaded){
                PydevPlugin.log(new RuntimeException(StringUtils.format("%s still not loaded and '%s' already called.", xmlFile, function)));
            }
        }
        traceFunc("END checkLoad");
    }
    
    /* (non-Javadoc)
     * @see org.python.pydev.plugin.nature.IPythonNatureStore#getPathProperty(org.eclipse.core.runtime.QualifiedName)
     */
    public synchronized String getPathProperty(QualifiedName key) throws CoreException {
        if(this.project == null){
            return "";
        }
        traceFunc("getPathProperty - "+key);
        synchronized (this) {
        	checkLoad("getPathProperty");
            String ret = getPathStringFromArray(getPathPropertyFromXml(key));
            traceFunc("END getPathProperty - "+ret);
            return ret;
        }
    }

	/* (non-Javadoc)
     * @see org.python.pydev.plugin.nature.IPythonNatureStore#setPathProperty(org.eclipse.core.runtime.QualifiedName, java.lang.String)
     */
    public synchronized void setPathProperty(QualifiedName key, String value) throws CoreException {
        traceFunc("setPathProperty");
        synchronized (this) {
        	checkLoad("setPathProperty");
            setPathPropertyToXml(key, getArrayFromPathString(value), true);
        }
        traceFunc("END setPathProperty");
    }

    /**
     * Loads the Xml representation of the PythonNature properties from the project resource. If the project resource does not exist then an empty representation is created, and its storage is
     * requested in the project folder.
     * 
     * @return true if some change has actually happened in the file and false otherwise
     * @throws CoreException
     */
    private synchronized boolean loadFromFile() throws CoreException {
        if(this.project == null){
            return false; //deconfigured...
        }
        
        traceFunc("loadFromFile");
        boolean ret;
        synchronized (this) {
            try {
                DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
                try{
                    onIgnoreRefresh++;
                    xmlFile.refreshLocal(IResource.DEPTH_ZERO, null);
                }finally{
                    onIgnoreRefresh--;
                }
                if (!xmlFile.exists()) {
                    if (document != null) {
                        // Someone removed the project descriptor, store it from the memory model
                        doStore();
                        ret = true;
                    } else {
                        // The document never existed
                        document = parser.newDocument();
                        ProcessingInstruction version = document.createProcessingInstruction("eclipse-pydev", "version=\"1.0\""); //$NON-NLS-1$ //$NON-NLS-2$
                        document.appendChild(version);
                        Element configRootElement = document.createElement(PYDEV_PROJECT_DESCRIPTION);
                        document.appendChild(configRootElement);
    
                        migrateProperty(PythonNature.getPythonProjectVersionQualifiedName());
                        migratePath(PythonPathNature.getProjectSourcePathQualifiedName());
                        migratePath(PythonPathNature.getProjectExternalSourcePathQualifiedName());
                        doStore();
                        ret = true;
                    }
                } else {
                	try{
                	    onIgnoreRefresh++;
                		xmlFile.refreshLocal(0, new NullProgressMonitor());
                	}catch(Exception e){
                		PydevPlugin.log(e);
                	}finally{
                        onIgnoreRefresh--;   
                    }
                    document = parser.parse(xmlFile.getContents());
                    modStamp = xmlFile.getModificationStamp();
                    ret = true;
                }
            } catch (Exception e) {
                e.printStackTrace();
                IStatus status = new Status(IStatus.ERROR, "PythonNatureStore", -1, e.toString(), e);
                throw new CoreException(status);
            }
        }
        
        traceFunc("END loadFromFile");
        return ret;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -