ImplicitCatalogSupport.java :  » IDE-Netbeans » compapp » org » netbeans » modules » compapp » projects » common » Java Open Source

Java Open Source » IDE Netbeans » compapp 
compapp » org » netbeans » modules » compapp » projects » common » ImplicitCatalogSupport.java
/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
 *
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common
 * Development and Distribution License("CDDL") (collectively, the
 * "License"). You may not use this file except in compliance with the
 * License. You can obtain a copy of the License at
 * http://www.netbeans.org/cddl-gplv2.html
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
 * specific language governing permissions and limitations under the
 * License.  When distributing the software, include this License Header
 * Notice in each file and include the License file at
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the GPL Version 2 section of the License file that
 * accompanied this code. If applicable, add the following below the
 * License Header, with the fields enclosed by brackets [] replaced by
 * your own identifying information:
 * "Portions Copyrighted [year] [name of copyright owner]"
 *
 * Contributor(s):
 *
 * The Original Software is NetBeans. The Initial Developer of the Original
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
 * Microsystems, Inc. All Rights Reserved.
 *
 * If you wish your version of this file to be governed by only the CDDL
 * or only the GPL Version 2, indicate your decision by adding
 * "[Contributor] elects to include this software in this distribution
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
 * single choice of license, a recipient has the option to distribute
 * your version of this file under either the CDDL, the GPL Version 2 or
 * to extend the choice of license to its licensees as provided above.
 * However, if you add GPL Version 2 code and therefore, elected the GPL
 * Version 2 license, then the option applies only if the new code is
 * made subject to such option by the copyright holder.
 */

package org.netbeans.modules.compapp.projects.common;

import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.netbeans.api.project.FileOwnerQuery;
import org.netbeans.api.project.Project;
import org.netbeans.api.project.ProjectUtils;
import org.netbeans.api.project.SourceGroup;
import org.netbeans.api.project.Sources;
import org.netbeans.modules.compapp.projects.common.CatalogWSDL.Entry;
import org.netbeans.modules.compapp.projects.common.CatalogWSDL.EntryType;
import org.netbeans.modules.xml.catalogsupport.DefaultProjectCatalogSupport;
import org.netbeans.modules.xml.catalogsupport.ProjectConstants;
import org.netbeans.modules.xml.catalogsupport.util.ProjectReferenceUtility;
import org.netbeans.modules.xml.retriever.catalog.CatalogWriteModel;
import org.netbeans.modules.xml.retriever.catalog.CatalogWriteModelFactory;
import org.netbeans.modules.xml.retriever.catalog.ProjectCatalogSupport;
import org.netbeans.modules.xml.xam.locator.CatalogModelException;
import org.netbeans.spi.project.SubprojectProvider;
import org.netbeans.spi.project.support.ant.AntProjectHelper;
import org.netbeans.spi.project.support.ant.PropertyUtils;
import org.netbeans.spi.project.support.ant.ReferenceHelper;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;

/**
 * This class represents the main interface to support the implicit namespace 
 * reference resolver in SOA projects based on composite application project
 * infrastructure. 
 * <p>
 * This class implements ProjectCatalogSupport to support cross project wsdl/xsd
 * import references as well as the implicit namespace references corresponding
 * to the wsdl/xsd files.
 * <p>
 * Each SOA project(Service Unit deployment project for SE or BC), would register
 * this implemenation in the Project's lookup in addition to the DefaultProjectCatalogSupport
 * from the catalog support module to resolve the implicit references as well as the 
 * explicit references of the wsdl/xsd files.
 * <p>
 * SU project should use the ImplicitCatalogSupport(Project, AntProjectHelper,ReferenceHelper)
 * constructor to create the instance to register it in the project's lookup and use 
 * ImplicitCatalogSupport.getInstance(Project) to get the instance of this class which looks up
 * the instance from the project's lookup or create a new one to the user. 
 * 
 * <p><blockquote><pre>
 * // registering the instance in project's lookup
 * Lookups.fixed(new Object[] {
 *  ...,
 *  new DefaultProjectCatalogSupport(prj, antHelper, refHelper),  
 *  ...,  
 *  new ImplicitCatalogSupport(prj, antHelper, refHelper)
 * });
 * </blockquote></pre></p>
 * <p><blockquote><pre>
 * // get the instance of ImplicitCatalogSupport instance
 * // using project object
 * ImplicitCatalogSupport catSupport = ImplicitCatalogSupport.getInstance(prj);
 * // or source file object
 * ImplicitCatalogSupport catSupport = ImplicitCatalogSupport.getInstance(myXmlFO);
 * // add the implicit reference to the catalog support
 * URI uriRef = catSupport.createImplicitCatalogEntry(...);
 * 
 * // resolve the implicit reference to the file object 
 * FileObject xsdFO = 
 * catSupport.resolveImplicitReference("http://ns/mynamespace", EntryType.XSD);
 *                     
 * </blockquote></pre></p>
 * <p>
 * @see CatalogWSDL
 * @author chikkala
 */
public class ImplicitCatalogSupport extends ProjectCatalogSupport {

    /** logger */
    private static final Logger sLogger = Logger.getLogger(ImplicitCatalogSupport.class.getName());
    /** project that registered this instance in its lookup*/
    private Project mProject;
    /** ant project helper of the project */
    private AntProjectHelper mAntPrjHelper;
    /** project reference helper of the project */
    private ReferenceHelper mPrjRefHelper;

    /**
     * Constructor that will be used in adding this class instance in the project's lookup
     * to support the Implicit wsdl/xsd references in this project's sources. 
     * @param project
     * @param helper
     * @param refHelper
     */
    public ImplicitCatalogSupport(Project project, AntProjectHelper helper,
            ReferenceHelper refHelper) {
        assert project != null;
        this.mProject = project;
        this.mAntPrjHelper = helper;
        this.mPrjRefHelper = refHelper;
    }

    /**
     * Constructor that will be used to create a default instance in #getInstance
     * implemenation if user did not register the instance of this class in project 
     * lookup support on a particular project.
     * @see #getInstance 
     * @param project
     */
    protected ImplicitCatalogSupport(Project project) {
        this(project, null, null);
    }

    /**
     * this will try to lookup the instance from the project's lookup. if not
     * existing, will create a new instance. 
     * @param prj
     * @return ImplicitCatalogSupport
     */
    public static ImplicitCatalogSupport getInstance(Project prj) {
        Project owner = prj;
        if (owner != null) {
            ImplicitCatalogSupport support =
                    (ImplicitCatalogSupport) owner.getLookup().lookup(ImplicitCatalogSupport.class);
            if (support != null) {
                return support;
            }
        }
        return new ImplicitCatalogSupport(owner);
    }

    /**
     * DefaultProjectCatalogSupport equivalent creation method.
     * @param source
     * @return ImplicitCatalogSupport
     */
    public static ImplicitCatalogSupport getInstance(FileObject source) {
        return getInstance(FileOwnerQuery.getOwner(source));
    }

    /**
     * used to delegate most of the implementation to the DefaultProjectCatalog.
     * @return DefaultProjectCatalogSupport
     */
    protected DefaultProjectCatalogSupport getDefaultProjectCatalogSupport() {
        Project owner = this.mProject;
        if (owner != null) {
            DefaultProjectCatalogSupport support = (DefaultProjectCatalogSupport) owner.getLookup().lookup(DefaultProjectCatalogSupport.class);
            if (support != null) {
                return support;
            }
        }
        if (this.mAntPrjHelper != null) {
            return new DefaultProjectCatalogSupport(owner, this.mAntPrjHelper, this.mPrjRefHelper);
        } else {
            return new DefaultProjectCatalogSupport(owner);
        }
    }

    /**
     * delegates the method call to the default project catalog support
     * @see org.netbeans.modules.xml.catalogsupport.ProjectCatalogSupport
     * @param foTobeAddedInCat
     * @return
     */
    @Override
    public URI constructProjectProtocol(FileObject foTobeAddedInCat) {
        return getDefaultProjectCatalogSupport().constructProjectProtocol(foTobeAddedInCat);
    }

    /**
     * delegates the method call to the default project catalog support
     * @see org.netbeans.modules.xml.catalogsupport.ProjectCatalogSupport
     * @param uriStoredInCatFile
     * @return
     */
    @Override
    public boolean isProjectProtocol(URI uriStoredInCatFile) {
        return getDefaultProjectCatalogSupport().isProjectProtocol(uriStoredInCatFile);
    }

    /**
     * delegates the method call to the default project catalog support
     * @see org.netbeans.modules.xml.catalogsupport.ProjectCatalogSupport
     * @param uriToBeResolved
     * @return
     */
    @Override
    public FileObject resolveProjectProtocol(URI uriToBeResolved) {
        return getDefaultProjectCatalogSupport().resolveProjectProtocol(uriToBeResolved);
    }

    /**
     * This generates the catalog entry relative to the source file or relative
     * to the project. @see #createCatalogEntry(FileObject) for more details on
     * project relative catalog entry.
     * @param source. If non null, creates a source relative entry. If null,
     * creates a project relative entry.
     * @param target target file object to which the reference is created.
     * @return uri reference of the entry created.
     * @throws org.netbeans.modules.xml.xam.locator.CatalogModelException
     * @throws java.io.IOException
     */
    @Override
    public URI createCatalogEntry(FileObject source, FileObject target) throws CatalogModelException, IOException {
        if (source == null) {
            return createCatalogEntry(target);
        } else {
            return getDefaultProjectCatalogSupport().createCatalogEntry(source, target);
        }
    }

    /**
     * removes the specified systemid uri entry
     * @see org.netbeans.modules.xml.catalogsupport.ProjectCatalogSupport
     * @param uri system id uri entry in the catalog.
     * @return true if removed, false if it is not remove
     * @throws java.io.IOException
     */
    @Override
    public boolean removeCatalogEntry(URI uri) throws IOException {
        return getDefaultProjectCatalogSupport().removeCatalogEntry(uri);
    }

    /**
     * creates a target entry into the catalog.xml. The target entry generated 
     * will be project relative either external or internal reference.
     * @param target
     * @return the systemId uri that was entered in the catalog for target.
     * @throws org.netbeans.modules.xml.xam.locator.CatalogModelException
     * @throws java.io.IOException
     */
    public URI createCatalogEntry(FileObject target) throws CatalogModelException, IOException {
        assert target != null;
        CatalogWriteModel cwm = CatalogWriteModelFactory.getInstance().
                getCatalogWriteModelForProject(this.mProject.getProjectDirectory());
        assert cwm != null;
        Project targetProject = FileOwnerQuery.getOwner(target);
        URI systemId = null;
        URI uriReference = null;

        systemId = generateSystemID(targetProject, target);
        uriReference = generateURIReference(targetProject, target);

        if (systemId == null || uriReference == null) {
            //TODO log info. why they are null.
            return null;
        }
        cwm.addURI(systemId, uriReference);
        return systemId;
    }

    /**
     * adds implicit catalog entry to the catalog support. An entry for the
     * target with the namespace specified will be added to the catalog.xml and 
     * catalog.wsdl to resolve this implicit catalog entry.
     * 
     * @param namespace
     * @param target
     * @param type
     * @return
     * @throws org.netbeans.modules.xml.xam.locator.CatalogModelException
     * @throws java.io.IOException
     */
    public URI createImplicitCatalogEntry(String namespace, FileObject target, CatalogWSDL.EntryType type) throws CatalogModelException, IOException {
        // update catalog.xml
        URI systemId = createCatalogEntry(target);
        // update catalog.wsdl        
        String location = systemId.toASCIIString();
        Entry entry = null;
        // create catalog wsdl entry object
        if (EntryType.WSDL.equals(type)) {
            entry = Entry.createWSDLEntry(namespace, location);
        } else if (EntryType.XSD.equals(type)) {
            entry = Entry.createXSDEntry(namespace, location);
        } else {
            entry = null;
        }
        // add the entry to catalog wsdl and save.
        if (entry != null) {
            CatalogWSDL catWSDL = CatalogWSDL.loadCatalogWSDL(this.mProject);
            catWSDL.addEntry(entry);
            CatalogWSDL.saveCatalogWSDL(catWSDL, this.mProject);
        } else {
            //Log
            sLogger.fine("#### NO ENTRY WAS ADDED IN CatalogWSDL for namespace " + namespace);
        }
        return systemId;
    }

    /**
     * removes implicit catalog entry from the catalog support. This only removes
     * the catalog entry correpsonds to the namespace from the catalog.wsdl. It
     * will not remove the entry in the catalog.xml corresponds to this namespace
     * as that entry might be used by some other explicit refernce. To cleanup the
     * unused catalog.xml entries users can use the project customizer.
     * 
     * @param namespace
     * @param type
     * @return
     * @throws org.netbeans.modules.xml.xam.locator.CatalogModelException
     * @throws java.io.IOException
     */
    public boolean removeImplicitCatalogEntry(String namespace, CatalogWSDL.EntryType type) throws CatalogModelException, IOException {
        CatalogWSDL catWSDL = CatalogWSDL.loadCatalogWSDL(this.mProject);
        Entry entry = catWSDL.getEntry(type, namespace, null);
        boolean removed = catWSDL.removeEntry(entry);
        CatalogWSDL.saveCatalogWSDL(catWSDL, this.mProject);
        return removed;
    }

    /**
     * resolves the implicit reference to the file object using the implicit
     * catalog support. It uses both the catalog.wsdl and the catalog.xml to 
     * resolve the reference. If the type is null, it returns the fileobject
     * corresponding to the first entry with the namespace (wsdl or xsd).
     * 
     * @param namespace  namespace to lookup
     * @param type wsdl or xsd file type correpsonding to the namespace
     * @return fileobject correpsonding to the namespace or null
     * @throws org.netbeans.modules.xml.xam.locator.CatalogModelException
     * @throws java.io.IOException
     */
    public FileObject resolveImplicitReference(String namespace, CatalogWSDL.EntryType type) throws CatalogModelException, IOException {
        FileObject refFO = null;
        CatalogWSDL catWSDL = CatalogWSDL.loadCatalogWSDL(this.mProject);
        Entry entry = null;
        if ( type == null ) {
            List<Entry> entries = catWSDL.getEntries(namespace);
            if (entries.size() > 0 ) {
                entry = entries.get(0);
            }
        } else {
            entry = catWSDL.getEntry(type, namespace, null);
        }
        if ( entry != null ) {
            refFO = resolveImplicitReference(entry.getLocation());
        }
        return refFO;
    }

    /**
     * resolves the implicit reference to the file object using the implicit
     * catalog support. It uses both the catalog.wsdl and the catalog.xml to 
     * resolve the reference.
     * 
     * @param location location in the catalog entry
     * @return fileobject correpsonding to the namespace or null.
     * @throws org.netbeans.modules.xml.xam.locator.CatalogModelException
     * @throws java.io.IOException
     */
    public FileObject resolveImplicitReference(String location) throws CatalogModelException, IOException {
        FileObject refFO = null;
        if ( location == null ) {
            return refFO;
        }
        try {            
            URI systemIdUri = new URI(location);
            CatalogWriteModel cwm =
                    CatalogWriteModelFactory.getInstance().getCatalogWriteModelForProject(
                    this.mProject.getProjectDirectory());
            URI uriReference = cwm.searchURI(systemIdUri);

            if (uriReference != null) {
                refFO = resolveProjectProtocol(uriReference);
                if (refFO == null) {
                    // it is not project protocol. so resolve it as project relative uri.
                    // uriReference.re
                    refFO = resolveRelativeReference(uriReference);
                }
                if (refFO == null) {
                    sLogger.fine("Can not find file object for SystemId: " + systemIdUri + " URIReference: " + uriReference + "in catalog.xml");
                }
            } else {
                sLogger.fine("Can not find the URI reference for SystemId" + systemIdUri + "in catalog.xml");
            }
        } catch (URISyntaxException ex) {
            sLogger.log(Level.FINE, ex.getMessage(), ex);
        }
        return refFO;
    }

    /**
     * checks if this instance supports the cross project references
     * @return
     */
    public boolean supportsCrossProject() {
        return this.mAntPrjHelper != null;
    }

    /**
     * returns the sub project references 
     * @return
     */
    public Set getProjectReferences() {
        SubprojectProvider provider = (SubprojectProvider) this.mProject.getLookup().
                lookup(SubprojectProvider.class);
        return provider.getSubprojects();
    }

    /**
     * returns the file object in the same project represented by the relative
     * uriReference from the project directory.
     * @param uriReference
     * @return
     */
    protected FileObject resolveRelativeReference(URI uriReference) {
        File myPrjRoot = FileUtil.toFile(this.mProject.getProjectDirectory());
        File refFile = new File(myPrjRoot.toURI().resolve(uriReference));
        FileObject refFO = FileUtil.toFileObject(FileUtil.normalizeFile(refFile));
        return refFO;
    }

    /**
     * generates the URI references w.r.t the target project for both internal
     * or external file targets.
     * 
     * @param targetProject
     * @param target
     * @return
     */
    protected URI generateURIReference(Project targetProject, FileObject target) {
        assert targetProject != null && target != null;

        if (this.mProject != targetProject) {
            // external reference. generate uri reference with project protocol
            if (!getProjectReferences().contains(targetProject) &&
                    supportsCrossProject()) {
                ProjectReferenceUtility.addProjectReference(this.mPrjRefHelper, targetProject);
            }
            return constructProjectProtocol(target);
        } else {
            try {
                // internal reference. generate the relative uri w.r.t. project root
                String relativePath = FileUtil.getRelativePath(this.mProject.getProjectDirectory(), target);
                return new URI(relativePath);
            } catch (URISyntaxException ex) {
                //TODO: log the exception
                sLogger.log(Level.FINE, ex.getMessage(), ex);
                return null;
            }
        }
    }

    /**
     * generates the system id for the target file within or outside the target
     * project w.r.t. the target project.
     * 
     * @param targetProject
     * @param target
     * @return
     */
    protected URI generateSystemID(Project targetProject, FileObject target) {
        assert targetProject != null && target != null;
        try {
            if (this.mProject != targetProject) {

                // external reference. generate w.r.t. external project source root.
                FileObject targetSourceFolder = getSourceFolder(targetProject, target);
                String projectName = getUsableProjectName(targetProject);
                String relativePath = FileUtil.getRelativePath(targetSourceFolder, target);
                return new URI(projectName + "/" + relativePath);
            } else {
                // internal reference. generate w.r.t. source root
                FileObject targetSourceFolder = getSourceFolder(target);
                if (targetSourceFolder == null) {
                    throw new IllegalArgumentException(target.getPath() + " is not in project source"); //NOI18N
                }
                String relativePath = FileUtil.getRelativePath(targetSourceFolder, target);
                return new URI(relativePath);
            }
        } catch (URISyntaxException ex) {
            //TODO: log ex
            sLogger.log(Level.FINE, ex.getMessage(), ex);
            return null;
        }
    }

    /**
     * usable project name
     * @param project
     * @return
     */
    private static String getUsableProjectName(Project project) {
        return PropertyUtils.getUsablePropertyName(ProjectUtils.getInformation(project).getName()).replace('.', '_');
    }

    /**
     * return the source folder of the source file.
     * @param source
     * @return
     */
    private FileObject getSourceFolder(FileObject source) {
        return getSourceFolder(this.mProject, source);
    }
    /** supported sources from which a file reference can be resolved */
    private static String[] sourceTypes = new String[]{
        ProjectConstants.SOURCES_TYPE_XML,
        ProjectConstants.SOURCES_TYPE_JAVA,
        ProjectConstants.TYPE_DOC_ROOT,
        ProjectConstants.TYPE_WEB_INF
    };

    /**
     * 
     * @param project
     * @param source
     * @return
     */
    private static FileObject getSourceFolder(Project project, FileObject source) {
        Sources sources = ProjectUtils.getSources(project);
        assert sources != null;
        ArrayList<SourceGroup> sourceGroups = new ArrayList<SourceGroup>();
        for (String type : sourceTypes) {
            SourceGroup[] groups = sources.getSourceGroups(type);
            if (groups != null) {
                sourceGroups.addAll(Arrays.asList(groups));
            }
        }

        assert sourceGroups.size() > 0;
        for (SourceGroup sourceGroup : sourceGroups) {
            if (FileUtil.isParentOf(sourceGroup.getRootFolder(), source)) {
                return sourceGroup.getRootFolder();
            }
        }

        FileObject metaInf = project.getProjectDirectory().getFileObject("src/conf"); //NOI18N
        if (metaInf != null) {
            if (FileUtil.isParentOf(metaInf, source)) {
                return metaInf;
            }
        }
        return null;
    }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.