| /* |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. |
| * |
| * Copyright 2009-2017 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 2009-2010 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.jackpot30.remoting.downloadable; |
| |
| import java.io.*; |
| import java.net.URISyntaxException; |
| import java.net.URL; |
| import java.util.Collection; |
| import java.util.Iterator; |
| import java.util.Properties; |
| import java.util.logging.Level; |
| import java.util.logging.Logger; |
| import org.netbeans.api.java.classpath.ClassPath; |
| import org.netbeans.api.java.classpath.JavaClassPathConstants; |
| import org.netbeans.api.java.queries.AnnotationProcessingQuery; |
| import org.netbeans.api.java.queries.AnnotationProcessingQuery.Result; |
| import org.netbeans.api.java.queries.SourceLevelQuery; |
| import org.netbeans.modules.parsing.impl.indexing.friendapi.DownloadedIndexPatcher; |
| import org.openide.filesystems.FileObject; |
| import org.openide.filesystems.URLMapper; |
| import org.openide.util.Exceptions; |
| import org.openide.util.lookup.ServiceProvider; |
| |
| /** |
| * |
| * @author lahvac |
| */ |
| @ServiceProvider(service=DownloadedIndexPatcher.class) |
| public class DownloadedIndexPatcherImpl implements DownloadedIndexPatcher { |
| |
| @Override |
| public boolean updateIndex(URL sourceRoot, URL indexFolder) { |
| try { |
| File cache = new File(indexFolder.toURI()); |
| File checksums = new File(cache, "java/15/checksums.properties"); |
| |
| if (!checksums.canRead()) return true; //nothing to fix |
| |
| FileObject srcFolderFO = URLMapper.findFileObject(sourceRoot); |
| |
| if (srcFolderFO == null) return false; |
| |
| Properties cs = loadProperties(checksums); |
| |
| if (cs.isEmpty()) return true; //apparently nothing to do |
| |
| //XXX HACK: |
| String origPrefix = null; |
| String in = (String) cs.keySet().iterator().next(); |
| |
| int idx = Integer.MAX_VALUE; |
| |
| while ((idx = in.lastIndexOf('/', idx - 1)) != (-1)) { |
| FileObject foundChild = srcFolderFO.getFileObject(in.substring(idx + 1)); |
| if (foundChild != null && foundChild.canRead()) { |
| origPrefix = in.substring(0, idx + 1); |
| break; |
| } |
| } |
| |
| if (origPrefix == null) { |
| //cannot find the original prefix |
| return false; |
| } |
| |
| String newPrefix = srcFolderFO.toURL().toString(); |
| |
| fixAbsolutePath(checksums, origPrefix, newPrefix); |
| fixAbsolutePath(new File(cache, "java/15/fqn2files.properties"), origPrefix, newPrefix); |
| |
| if (srcFolderFO != null) { |
| verifyAttributes(srcFolderFO, indexFolder, false); |
| ensureSourcePath(srcFolderFO, indexFolder); |
| } |
| |
| return true; |
| } catch (URISyntaxException ex) { |
| Logger.getLogger(DownloadedIndexPatcherImpl.class.getName()).log(Level.SEVERE, null, ex); |
| return false; |
| } catch (IOException ex) { |
| Logger.getLogger(DownloadedIndexPatcherImpl.class.getName()).log(Level.SEVERE, null, ex); |
| return false; |
| } |
| } |
| |
| private void fixAbsolutePath(File properties, String origPrefix, String targetPrefix) throws IOException { |
| Properties inProps = loadProperties(properties); |
| Properties outProps = new Properties(); |
| |
| for (String k : (Collection<String>) (Collection) inProps.keySet()) { |
| String orig = inProps.getProperty(k); |
| |
| //XXX HACK |
| |
| if (k.startsWith(origPrefix)) k = targetPrefix + k.substring(origPrefix.length()); |
| if (orig.startsWith(origPrefix)) orig = targetPrefix + orig.substring(origPrefix.length()); |
| |
| outProps.setProperty(k, orig); |
| } |
| |
| storeProperties(properties, outProps); |
| } |
| |
| private static final String PROCESSOR_PATH = "processorPath"; //NOI18N |
| private static final String APT_ENABLED = "aptEnabled"; //NOI18N |
| private static final String ANNOTATION_PROCESSORS = "annotationProcessors"; //NOI18N |
| private static final String SOURCE_LEVEL_ROOT = "sourceLevel"; //NOI18N |
| private static final String SOURCE_PATH = "sourcePath"; //NOI18N |
| |
| boolean verifyAttributes(FileObject root, URL cache, boolean checkOnly) { |
| if (root == null) |
| return false; |
| boolean vote = false; |
| try { |
| if (ensureAttributeValue(cache, SOURCE_LEVEL_ROOT, SourceLevelQuery.getSourceLevel(root), checkOnly)) { |
| vote = true; |
| if (checkOnly) { |
| return vote; |
| } |
| } |
| Result aptOptions = AnnotationProcessingQuery.getAnnotationProcessingOptions(root); |
| boolean apEnabledOnScan = aptOptions.annotationProcessingEnabled().contains(AnnotationProcessingQuery.Trigger.ON_SCAN); |
| if (ensureAttributeValue(cache, APT_ENABLED, apEnabledOnScan ? Boolean.TRUE.toString() : null, checkOnly)) { |
| vote = true; |
| if (checkOnly) { |
| return vote; |
| } |
| } |
| if (!apEnabledOnScan) { |
| //no need to check further: |
| return vote; |
| } |
| ClassPath processorPath = ClassPath.getClassPath(root, JavaClassPathConstants.PROCESSOR_PATH); |
| if (processorPath != null && ensureAttributeValue(cache, PROCESSOR_PATH, processorPath.toString(), checkOnly)) { |
| vote = true; |
| if (checkOnly) { |
| return vote; |
| } |
| } |
| if (ensureAttributeValue(cache, ANNOTATION_PROCESSORS, encodeToStirng(aptOptions.annotationProcessorsToRun()), checkOnly)) { |
| vote = true; |
| if (checkOnly) { |
| return vote; |
| } |
| } |
| } catch (URISyntaxException ex) { |
| Exceptions.printStackTrace(ex); |
| } catch (IOException ioe) { |
| Exceptions.printStackTrace(ioe); |
| } |
| return vote; |
| } |
| |
| public static boolean ensureAttributeValue(final URL root, final String attributeName, final String attributeValue, boolean checkOnly) throws IOException, URISyntaxException { |
| File rootFile = new File(root.toURI()); |
| File attributes = new File(rootFile, "java/15/attributes.properties"); |
| Properties p = loadProperties(attributes); |
| final String current = p.getProperty(attributeName); |
| if (current == null) { |
| if (attributeValue != null) { |
| if (!checkOnly) { |
| p.setProperty(attributeName, attributeValue); |
| storeProperties(attributes, p); |
| } |
| return true; |
| } else { |
| return false; |
| } |
| } |
| if (current.equals(attributeValue)) { |
| return false; |
| } |
| if (!checkOnly) { |
| if (attributeValue != null) { |
| p.setProperty(attributeName, attributeValue); |
| } else { |
| p.remove(attributeName); |
| } |
| storeProperties(attributes, p); |
| } |
| return true; |
| } |
| |
| private String encodeToStirng(Iterable<? extends String> strings) { |
| if (strings == null) |
| return null; |
| StringBuilder sb = new StringBuilder(); |
| for (Iterator it = strings.iterator(); it.hasNext();) { |
| sb.append(it.next()); |
| if (it.hasNext()) |
| sb.append(','); |
| } |
| return sb.length() > 0 ? sb.toString() : null; |
| } |
| |
| private static boolean ensureSourcePath(final FileObject root, URL cache) throws IOException, URISyntaxException { |
| final ClassPath srcPath = ClassPath.getClassPath(root, ClassPath.SOURCE); |
| String srcPathStr; |
| if (srcPath != null) { |
| final StringBuilder sb = new StringBuilder(); |
| for (ClassPath.Entry entry : srcPath.entries()) { |
| sb.append(entry.getURL()).append(' '); //NOI18N |
| } |
| srcPathStr = sb.toString(); |
| } else { |
| srcPathStr = ""; //NOI18N |
| } |
| return ensureAttributeValue(cache, SOURCE_PATH, srcPathStr, false); |
| } |
| |
| private static Properties loadProperties(File properties) throws IOException, FileNotFoundException { |
| Properties inProps = new Properties(); |
| InputStream inPropsIS = new FileInputStream(properties); |
| try { |
| inProps.load(inPropsIS); |
| inPropsIS.close(); |
| } finally { |
| inPropsIS.close(); |
| } |
| return inProps; |
| } |
| |
| private static void storeProperties(File properties, Properties outProps) throws IOException, FileNotFoundException { |
| OutputStream outPropsOS = new FileOutputStream(properties); |
| |
| try { |
| outProps.store(outPropsOS, ""); |
| outPropsOS.close(); |
| } finally { |
| outPropsOS.close(); |
| } |
| } |
| |
| } |