/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved. * * Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners. * * 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle 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-2008 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.ruby.rubyproject.classpath; import java.io.File; import org.netbeans.api.java.classpath.ClassPath; import org.netbeans.api.project.SourceGroup; import org.netbeans.modules.ruby.RubyLanguage; import org.netbeans.modules.ruby.rubyproject.SourceRoots; import org.netbeans.modules.ruby.spi.project.support.rake.PropertyEvaluator; import org.netbeans.modules.ruby.spi.project.support.rake.RakeProjectHelper; import org.netbeans.spi.java.classpath.ClassPathFactory; import org.netbeans.spi.java.classpath.ClassPathProvider; import org.openide.filesystems.FileObject; import org.openide.filesystems.FileUtil; /** * Defines the various load paths for a Ruby project. */ public final class ClassPathProviderImpl implements ClassPathProvider { private static final String JAVAC_CLASSPATH = "javac.classpath"; //NOI18N private static final String JAVAC_TEST_CLASSPATH = "javac.test.classpath"; //NOI18N private static final String RUN_CLASSPATH = "run.classpath"; //NOI18N private static final String RUN_TEST_CLASSPATH = "run.test.classpath"; //NOI18N private final RakeProjectHelper helper; private final File projectDirectory; private final PropertyEvaluator evaluator; private final SourceRoots sourceRoots; private final SourceRoots testSourceRoots; private final ClassPath[] cache = new ClassPath[8]; public ClassPathProviderImpl(RakeProjectHelper helper, PropertyEvaluator evaluator, SourceRoots sourceRoots, SourceRoots testSourceRoots) { this.helper = helper; this.projectDirectory = FileUtil.toFile(helper.getProjectDirectory()); assert this.projectDirectory != null; this.evaluator = evaluator; this.sourceRoots = sourceRoots; this.testSourceRoots = testSourceRoots; } private FileObject[] getPrimarySrcPath() { return this.sourceRoots.getRoots(); } private FileObject[] getTestSrcDir() { return this.testSourceRoots.getRoots(); } /** * Find what a given file represents. * @param file a file in the project * @return one of: <dl> * <dt>0</dt> <dd>normal source</dd> * <dt>1</dt> <dd>test source</dd> * <dt>-1</dt> <dd>something else</dd> * </dl> */ private int getType(FileObject file) { FileObject[] srcPath = getPrimarySrcPath(); for (int i=0; i < srcPath.length; i++) { FileObject root = srcPath[i]; if (root.equals(file) || FileUtil.isParentOf(root, file)) { return 0; } } srcPath = getTestSrcDir(); for (int i=0; i< srcPath.length; i++) { FileObject root = srcPath[i]; if (root.equals(file) || FileUtil.isParentOf(root, file)) { return 1; } } return -1; } private synchronized ClassPath getSourcepath(FileObject file) { int type = getType(file); return this.getSourcepath(type); } private ClassPath getSourcepath(int type) { if (type < 0 || type > 1) { return null; } ClassPath cp = cache[type]; if (cp == null) { switch (type) { case 0: cp = ClassPathFactory.createClassPath(new SourcePathImplementation (this.sourceRoots, helper, evaluator)); break; case 1: //cp = ClassPathFactory.createClassPath(new SourcePathImplementation (this.testSourceRoots)); // See #95927: I need to get the testRoots to also include the source roots. // For Java I assume this is done not via source paths but via compile paths. // Since I don't use compile paths I can't do that (well, I could make compile paths // work but I'm afraid to do that 12 hours before high resistance kicks in for beta2) // so the safest bet is just to include all the source paths here, the way it's done // for Rails projects. So, I have a simple delegating class path implementation which // just delegates its method calls and merges the results as appropriate. cp = ClassPathFactory.createClassPath( new GroupClassPathImplementation( new SourcePathImplementation[]{ new SourcePathImplementation(this.testSourceRoots), new SourcePathImplementation(this.sourceRoots, helper, evaluator) })); break; } } cache[type] = cp; return cp; } private synchronized ClassPath getBootClassPath() { ClassPath cp = cache[7]; if (cp == null) { cp = ClassPathFactory.createClassPath(new BootClassPathImplementation(evaluator)); cache[7] = cp; } return cp; } public ClassPath findClassPath(FileObject file, String type) { /*if (type.equals(RubyLanguage.EXECUTE)) { return getRunTimeClasspath(file); } else */ if (type.equals(RubyLanguage.SOURCE)) { return getSourcepath(file); } else if (type.equals(RubyLanguage.BOOT)) { return getBootClassPath(); } else if (type.equals(RubyLanguage.COMPILE)) { // Bogus return getBootClassPath(); } else { return null; } } /** * Returns array of all classpaths of the given type in the project. * The result is used for example for GlobalPathRegistry registrations. */ public ClassPath[] getProjectClassPaths(String type) { if (RubyLanguage.BOOT.equals(type)) { return new ClassPath[]{getBootClassPath()}; } if (RubyLanguage.SOURCE.equals(type)) { ClassPath[] l = new ClassPath[2]; l[0] = getSourcepath(0); l[1] = getSourcepath(1); return l; } return null; } /** * Returns the given type of the classpath for the project sources * (i.e., excluding tests roots). Valid types are BOOT, SOURCE and COMPILE. */ public ClassPath getProjectSourcesClassPath(String type) { if (RubyLanguage.BOOT.equals(type)) { return getBootClassPath(); } if (RubyLanguage.SOURCE.equals(type)) { return getSourcepath(0); } return null; } public String getPropertyName (SourceGroup sg, String type) { FileObject root = sg.getRootFolder(); FileObject[] path = getPrimarySrcPath(); for (int i=0; i<path.length; i++) { if (root.equals(path[i])) { if (RubyLanguage.COMPILE.equals(type)) { return JAVAC_CLASSPATH; } else if (RubyLanguage.EXECUTE.equals(type)) { return RUN_CLASSPATH; } else { return null; } } } path = getTestSrcDir(); for (int i=0; i<path.length; i++) { if (root.equals(path[i])) { if (RubyLanguage.COMPILE.equals(type)) { return JAVAC_TEST_CLASSPATH; } else if (RubyLanguage.EXECUTE.equals(type)) { return RUN_TEST_CLASSPATH; } else { return null; } } } return null; } }