use nio.Path instead of io.File in jps project serializers with check on file existence
[idea/community.git] / java / idea-ui / src / com / intellij / jarFinder / IvyAttachSourceProvider.java
1 /*
2  * Copyright 2000-2016 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.intellij.jarFinder;
17
18 import com.intellij.ide.JavaUiBundle;
19 import com.intellij.notification.Notification;
20 import com.intellij.notification.NotificationType;
21 import com.intellij.openapi.diagnostic.Logger;
22 import com.intellij.openapi.roots.LibraryOrderEntry;
23 import com.intellij.openapi.roots.OrderRootType;
24 import com.intellij.openapi.roots.libraries.Library;
25 import com.intellij.openapi.util.text.StringUtil;
26 import com.intellij.openapi.vfs.JarFileSystem;
27 import com.intellij.openapi.vfs.VfsUtilCore;
28 import com.intellij.openapi.vfs.VirtualFile;
29 import com.intellij.psi.PsiFile;
30 import com.intellij.util.ArrayUtil;
31 import org.jetbrains.annotations.NotNull;
32 import org.jetbrains.annotations.Nullable;
33
34 import java.io.IOException;
35 import java.io.StringReader;
36 import java.util.Collection;
37 import java.util.Collections;
38 import java.util.List;
39 import java.util.Properties;
40
41 /**
42  * @author Sergey Evdokimov
43  */
44 public class IvyAttachSourceProvider extends AbstractAttachSourceProvider {
45   private static final Logger LOG = Logger.getInstance(IvyAttachSourceProvider.class);
46
47   @NotNull
48   @Override
49   public Collection<AttachSourcesAction> getActions(List<LibraryOrderEntry> orderEntries, PsiFile psiFile) {
50     VirtualFile jar = getJarByPsiFile(psiFile);
51     if (jar == null) return Collections.emptyList();
52
53     VirtualFile jarsDir = jar.getParent();
54     if (jarsDir == null || !jarsDir.getName().equals("jars")) return Collections.emptyList();
55
56     VirtualFile artifactDir = jarsDir.getParent();
57     if (artifactDir == null) return Collections.emptyList();
58
59     String jarNameWithoutExt = jar.getNameWithoutExtension();
60     String artifactName = artifactDir.getName();
61
62     if (!jarNameWithoutExt.startsWith(artifactName) || !jarNameWithoutExt.substring(artifactName.length()).startsWith("-")) {
63       return Collections.emptyList();
64     }
65
66     String version = jarNameWithoutExt.substring(artifactName.length() + 1);
67
68     //noinspection SpellCheckingInspection
69     VirtualFile propertiesFile = artifactDir.findChild("ivydata-" + version + ".properties");
70     if (propertiesFile == null) return Collections.emptyList();
71
72     Library library = getLibraryFromOrderEntriesList(orderEntries);
73     if (library == null) return Collections.emptyList();
74
75     String sourceFileName = artifactName + '-' + version + "-sources.jar";
76
77     VirtualFile sources = artifactDir.findChild("sources");
78     if (sources != null) {
79       VirtualFile srcFile = sources.findChild(sourceFileName);
80       if (srcFile != null) {
81         // File already downloaded.
82         VirtualFile jarRoot = JarFileSystem.getInstance().getJarRootForLocalFile(srcFile);
83         if (jarRoot == null || ArrayUtil.contains(jarRoot, (Object[])library.getFiles(OrderRootType.SOURCES))) {
84           return Collections.emptyList(); // Sources already attached.
85         }
86
87         return Collections.singleton(new AttachExistingSourceAction(jarRoot, library,
88                                                                     JavaUiBundle.message("ivi.attach.source.provider.action.name")));
89       }
90     }
91
92     String url = extractUrl(propertiesFile, artifactName);
93     if (StringUtil.isEmptyOrSpaces(url)) return Collections.emptyList();
94
95     return Collections.singleton(new DownloadSourcesAction(psiFile.getProject(), "Downloading Ivy Sources", url) {
96       @Override
97       protected void storeFile(byte[] content) {
98         try {
99           VirtualFile existingSourcesFolder = sources;
100           if (existingSourcesFolder == null) {
101             existingSourcesFolder = artifactDir.createChildDirectory(this, "sources");
102           }
103
104           VirtualFile srcFile = existingSourcesFolder.createChildData(this, sourceFileName);
105           srcFile.setBinaryContent(content);
106
107           addSourceFile(JarFileSystem.getInstance().getJarRootForLocalFile(srcFile), library);
108         }
109         catch (IOException e) {
110           String message = JavaUiBundle.message("error.message.failed.to.save.0", artifactDir.getPath() + "/sources/" + sourceFileName);
111           new Notification(myMessageGroupId, JavaUiBundle.message("notification.title.io.error"), message, NotificationType.ERROR).notify(myProject);
112           LOG.warn(e);
113         }
114       }
115     });
116   }
117
118   @Nullable
119   private static String extractUrl(VirtualFile properties, String artifactName) {
120     String prefix = "artifact:" + artifactName + "#source#jar#";
121
122     try {
123       Properties p = new Properties();
124       p.load(new StringReader(VfsUtilCore.loadText(properties)));
125       for (Object o : p.keySet()) {
126         String key = o.toString();
127         if (key != null && key.startsWith(prefix) && key.endsWith(".location")) {
128           return p.getProperty(key);
129         }
130       }
131     }
132     catch (Exception e) {
133       LOG.debug(properties.getPath(), e);
134     }
135
136     return null;
137   }
138 }