├── .gitignore ├── LICENSE ├── README.md ├── lib ├── dom4j-1.6.1.jar ├── externalSystem-dependencyUpdater.jar ├── jsoup-1.11.3.jar ├── okhttp-3.14.4.jar └── okio-1.17.2.jar ├── resources └── META-INF │ └── plugin.xml ├── show1.gif ├── show2.gif ├── show3.gif ├── show4.gif └── src ├── actions ├── AppSettingsState.java ├── ApplicationSettingsConfigurable.java ├── MavenDependencyHelperAction.java └── MyInvocationHandler.java ├── model ├── Artifact.java └── Dependency.java ├── searcher ├── DependencySearcher.java ├── DependencySearcherManager.java └── impl │ ├── AliyunMavenDependencySearcher.java │ ├── MvnRepositoryComDependencySearcher.java │ └── SearchMavenOrgDependencySearcher.java ├── ui ├── AppSettingsForm.form └── AppSettingsForm.java └── util └── OkHttpUtils.java /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Example user template template 3 | ### Example user template 4 | 5 | # IntelliJ project files 6 | .idea 7 | *.iml 8 | out 9 | *.zip -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 yiyingcanfeng 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Maven Dependency Helper 2 | ### [Jetbrains plugin repository page](https://plugins.jetbrains.com/plugin/12041-maven-dependency-helper) 3 | ### Install 4 | - Settings -> Plugins -> Marketplace, search "Maven Dependency Helper" 5 | - Settings -> Plugins -> Install plugin from disk 6 | ### Shortcuts 7 | Ctrl+Shift+D 8 | ### Show 9 | 10 | ![show4.gif](https://github.com/yiyingcanfeng/maven-dependency-helper/blob/master/show4.gif?raw=true) 11 | 12 | ![show1.gif](https://github.com/yiyingcanfeng/maven-dependency-helper/blob/master/show1.gif?raw=true) 13 | 14 | ![show2.gif](https://github.com/yiyingcanfeng/maven-dependency-helper/blob/master/show2.gif?raw=true) 15 | 16 | ![show3.gif](https://github.com/yiyingcanfeng/maven-dependency-helper/blob/master/show3.gif?raw=true) 17 | -------------------------------------------------------------------------------- /lib/dom4j-1.6.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yiyingcanfeng/maven-dependency-helper/5b43ed2172fef6401a0b08f657fd10971eac0c53/lib/dom4j-1.6.1.jar -------------------------------------------------------------------------------- /lib/externalSystem-dependencyUpdater.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yiyingcanfeng/maven-dependency-helper/5b43ed2172fef6401a0b08f657fd10971eac0c53/lib/externalSystem-dependencyUpdater.jar -------------------------------------------------------------------------------- /lib/jsoup-1.11.3.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yiyingcanfeng/maven-dependency-helper/5b43ed2172fef6401a0b08f657fd10971eac0c53/lib/jsoup-1.11.3.jar -------------------------------------------------------------------------------- /lib/okhttp-3.14.4.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yiyingcanfeng/maven-dependency-helper/5b43ed2172fef6401a0b08f657fd10971eac0c53/lib/okhttp-3.14.4.jar -------------------------------------------------------------------------------- /lib/okio-1.17.2.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yiyingcanfeng/maven-dependency-helper/5b43ed2172fef6401a0b08f657fd10971eac0c53/lib/okio-1.17.2.jar -------------------------------------------------------------------------------- /resources/META-INF/plugin.xml: -------------------------------------------------------------------------------- 1 | 2 | com.yiycf.plugins.mavenDependencyHelper 3 | Maven Dependency Helper 4 | 2.5 5 | yiyingcanfeng 6 | 7 | Search dependency without open the browser 9 | GitHub | 10 | Issues 11 |

Features:

12 | 32 | ]]> 33 |
34 | 36 |
  • 37 |

    2.5

    38 |

    Fix some bugs.

    39 |
  • 40 |
  • 41 |

    2.4

    42 |

    Support add dependency text to pom.xml(available after 2020.3.4)

    43 |

    Fix some bugs.

    44 |
  • 45 |
  • 46 |

    2.3

    47 |

    Now can get dependency by cursor location without artifactId selected.

    48 |

    Optimize dependency search.

    49 |
  • 50 |
  • 51 |

    2.2

    52 | Compatibility fix for 2021.2 53 |
  • 54 |
  • 55 |

    2.1

    56 | Replace deprecated api. 57 |
  • 58 |
  • 59 |

    2.0

    60 |

    Supports more search sources, and program can automatically and periodically detect and choose the fastest search source, you can also choose what you like. You can set the interval in Settings/Tools

    61 |

    Add more build tools dependency text format.

    62 |
  • 63 |
  • 64 |

    1.4

    65 | Now the window can be closed when the ESC key is pressed 66 |
  • 67 |
  • 68 |

    1.3

    69 | Support for generating gradle dependency 70 |
  • 71 |
  • 72 |

    1.2

    73 | Fix NullPointerException that occurs in some cases 74 |
  • 75 |
  • 76 |

    1.1

    77 | Fix bug that not working on Android Studio 78 |
  • 79 | 80 | ]]> 81 |
    82 | 83 | 84 | 85 | 86 | 88 | 90 | com.intellij.modules.java 91 | 92 | 93 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 104 | 105 | 106 | 107 | 108 | 109 | org.jetbrains.idea.maven 110 |
    -------------------------------------------------------------------------------- /show1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yiyingcanfeng/maven-dependency-helper/5b43ed2172fef6401a0b08f657fd10971eac0c53/show1.gif -------------------------------------------------------------------------------- /show2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yiyingcanfeng/maven-dependency-helper/5b43ed2172fef6401a0b08f657fd10971eac0c53/show2.gif -------------------------------------------------------------------------------- /show3.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yiyingcanfeng/maven-dependency-helper/5b43ed2172fef6401a0b08f657fd10971eac0c53/show3.gif -------------------------------------------------------------------------------- /show4.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yiyingcanfeng/maven-dependency-helper/5b43ed2172fef6401a0b08f657fd10971eac0c53/show4.gif -------------------------------------------------------------------------------- /src/actions/AppSettingsState.java: -------------------------------------------------------------------------------- 1 | package actions; 2 | 3 | import com.intellij.openapi.application.ApplicationInfo; 4 | import com.intellij.openapi.components.PersistentStateComponent; 5 | import com.intellij.openapi.components.State; 6 | import com.intellij.openapi.components.Storage; 7 | import com.intellij.util.xmlb.XmlSerializerUtil; 8 | import org.apache.maven.artifact.versioning.DefaultArtifactVersion; 9 | import org.jetbrains.annotations.NotNull; 10 | import org.jetbrains.annotations.Nullable; 11 | 12 | import java.lang.reflect.InvocationTargetException; 13 | 14 | /** 15 | * @author z 16 | */ 17 | @State( 18 | name = "MavenDependencyHelper", 19 | storages = {@Storage("MavenDependencyHelper.xml")} 20 | ) 21 | public class AppSettingsState implements PersistentStateComponent { 22 | 23 | public int speedDetectInterval = 600; 24 | 25 | public static AppSettingsState getInstance() { 26 | // ServiceManager.getService(Class) is deprecated after 2021.2.1 27 | DefaultArtifactVersion version20113 = new DefaultArtifactVersion("2021.1.3"); 28 | DefaultArtifactVersion versionCurrent = new DefaultArtifactVersion(ApplicationInfo.getInstance().getFullVersion()); 29 | AppSettingsState service = null; 30 | if (versionCurrent.compareTo(version20113) <= 0) { 31 | try { 32 | service = (AppSettingsState) Class.forName("com.intellij.openapi.components.ServiceManager") 33 | .getMethod("getService", Class.class) 34 | .invoke(null, AppSettingsState.class); 35 | } catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { 36 | e.printStackTrace(); 37 | } 38 | } else { 39 | try { 40 | Class applicationManagerClass = Class.forName("com.intellij.openapi.application.ApplicationManager"); 41 | 42 | Object applicationInvoke = applicationManagerClass.getMethod("getApplication").invoke(null); 43 | service = (AppSettingsState) applicationInvoke.getClass().getMethod("getService", Class.class).invoke(applicationInvoke, AppSettingsState.class); 44 | 45 | } catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { 46 | e.printStackTrace(); 47 | } 48 | } 49 | return service; 50 | } 51 | 52 | @Nullable 53 | @Override 54 | public AppSettingsState getState() { 55 | return this; 56 | } 57 | 58 | @Override 59 | public void loadState(@NotNull AppSettingsState state) { 60 | XmlSerializerUtil.copyBean(state, this); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/actions/ApplicationSettingsConfigurable.java: -------------------------------------------------------------------------------- 1 | package actions; 2 | 3 | import com.intellij.openapi.options.Configurable; 4 | import com.intellij.openapi.options.ConfigurationException; 5 | import org.jetbrains.annotations.Nls; 6 | import org.jetbrains.annotations.Nullable; 7 | import searcher.DependencySearcherManager; 8 | import ui.AppSettingsForm; 9 | 10 | import javax.swing.*; 11 | 12 | /** 13 | * @author z 14 | */ 15 | public class ApplicationSettingsConfigurable implements Configurable { 16 | 17 | private AppSettingsForm form; 18 | 19 | @Nls(capitalization = Nls.Capitalization.Title) 20 | @Override 21 | public String getDisplayName() { 22 | return "MavenDependencyHelper"; 23 | } 24 | 25 | @Override 26 | public JComponent getPreferredFocusedComponent() { 27 | return form.getPreferredFocusedComponent(); 28 | } 29 | 30 | @Nullable 31 | @Override 32 | public JComponent createComponent() { 33 | form = new AppSettingsForm(); 34 | AppSettingsState settings = AppSettingsState.getInstance(); 35 | form.setIntervalText(settings.speedDetectInterval + ""); 36 | return form.getPanel(); 37 | } 38 | 39 | @Override 40 | public boolean isModified() { 41 | AppSettingsState settings = AppSettingsState.getInstance(); 42 | try { 43 | return Integer.parseInt(form.getIntervalText()) != settings.speedDetectInterval; 44 | }catch (NumberFormatException e) { 45 | return false; 46 | } 47 | } 48 | 49 | @Override 50 | public void apply() throws ConfigurationException { 51 | AppSettingsState settings = AppSettingsState.getInstance(); 52 | try { 53 | settings.speedDetectInterval = Integer.parseInt(form.getIntervalText()); 54 | DependencySearcherManager.setSpeedTestInterval(settings.speedDetectInterval); 55 | } catch (NumberFormatException ignored) { 56 | } 57 | } 58 | 59 | @Override 60 | public void reset() { 61 | AppSettingsState settings = AppSettingsState.getInstance(); 62 | form.setIntervalText(settings.speedDetectInterval + ""); 63 | DependencySearcherManager.setSpeedTestInterval(settings.speedDetectInterval); 64 | } 65 | 66 | @Override 67 | public void disposeUIResources() { 68 | form = null; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/actions/MavenDependencyHelperAction.java: -------------------------------------------------------------------------------- 1 | package actions; 2 | 3 | import com.intellij.openapi.actionSystem.AnAction; 4 | import com.intellij.openapi.actionSystem.AnActionEvent; 5 | import com.intellij.openapi.actionSystem.CommonDataKeys; 6 | import com.intellij.openapi.actionSystem.LangDataKeys; 7 | import com.intellij.openapi.application.ApplicationInfo; 8 | import com.intellij.openapi.editor.Editor; 9 | import com.intellij.openapi.module.Module; 10 | import com.intellij.openapi.project.Project; 11 | import com.intellij.openapi.ui.ComboBox; 12 | import com.intellij.openapi.vfs.VirtualFile; 13 | import com.intellij.psi.PsiFile; 14 | import com.intellij.psi.PsiManager; 15 | import com.intellij.psi.xml.XmlElement; 16 | import com.intellij.psi.xml.XmlFile; 17 | import com.intellij.ui.JBColor; 18 | import com.intellij.ui.components.JBLabel; 19 | import com.intellij.ui.components.JBList; 20 | import com.intellij.ui.components.JBScrollPane; 21 | import com.intellij.util.xml.DomFileElement; 22 | import com.intellij.util.xml.DomManager; 23 | import model.Artifact; 24 | import model.Dependency; 25 | import org.apache.maven.artifact.versioning.DefaultArtifactVersion; 26 | import org.dom4j.Document; 27 | import org.dom4j.DocumentException; 28 | import org.dom4j.Element; 29 | import org.dom4j.io.SAXReader; 30 | import org.jetbrains.annotations.NotNull; 31 | import org.jetbrains.annotations.Nullable; 32 | import org.jetbrains.idea.maven.dom.model.MavenDomDependencies; 33 | import org.jetbrains.idea.maven.dom.model.MavenDomDependency; 34 | import org.jetbrains.idea.maven.dom.model.MavenDomProjectModel; 35 | import org.jetbrains.idea.maven.model.MavenArtifact; 36 | import org.jetbrains.idea.maven.model.MavenArtifactNode; 37 | import org.jetbrains.idea.maven.model.MavenId; 38 | import org.jetbrains.idea.maven.navigator.MavenNavigationUtil; 39 | import org.jetbrains.idea.maven.project.MavenProject; 40 | import org.jetbrains.idea.maven.project.MavenProjectsManager; 41 | import org.jetbrains.idea.maven.utils.actions.MavenActionUtil; 42 | import searcher.DependencySearcher; 43 | import searcher.DependencySearcherManager; 44 | import searcher.impl.AliyunMavenDependencySearcher; 45 | import searcher.impl.MvnRepositoryComDependencySearcher; 46 | import searcher.impl.SearchMavenOrgDependencySearcher; 47 | 48 | import javax.swing.*; 49 | import javax.swing.event.ListSelectionEvent; 50 | import javax.swing.event.ListSelectionListener; 51 | import javax.swing.text.JTextComponent; 52 | import java.awt.*; 53 | import java.awt.datatransfer.Clipboard; 54 | import java.awt.datatransfer.StringSelection; 55 | import java.awt.event.*; 56 | import java.io.File; 57 | import java.io.IOException; 58 | import java.lang.reflect.InvocationTargetException; 59 | import java.util.List; 60 | import java.util.*; 61 | import java.util.concurrent.*; 62 | 63 | /** 64 | * @author yiyingcanfeng 65 | */ 66 | public class MavenDependencyHelperAction extends AnAction { 67 | 68 | private JFrame frame; 69 | private JTextArea textArea; 70 | private JButton copyVersionButton; 71 | private JButton copyTextAeraButton; 72 | private JButton searchButton; 73 | private JButton addToPomButton; 74 | private JComboBox comboBox; 75 | private JComboBox typeComboBox; 76 | private JComboBox sourceComboBox; 77 | private JTextField textField; 78 | private JBScrollPane scrollPane; 79 | private JList versionJList; 80 | private DefaultListModel versionListModel; 81 | private JScrollPane versionListScroller; 82 | private JTextComponent tipsTextComponent; 83 | private JBLabel sourceLabel; 84 | 85 | private String groupId; 86 | private String artifactId; 87 | private String version; 88 | private String scope; 89 | 90 | private static boolean addPomBtnShow; 91 | 92 | public static ThreadFactory threadFactory = Executors.defaultThreadFactory(); 93 | public static ScheduledThreadPoolExecutor scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(5, threadFactory); 94 | ; 95 | public static ThreadPoolExecutor threadPool = new ThreadPoolExecutor(3, 5, 10, TimeUnit.SECONDS, new ArrayBlockingQueue<>(2), threadFactory); 96 | ; 97 | public static DependencySearcher dependencySearcher; 98 | public static Map, String> searcherTextMap = new HashMap<>(); 99 | public static Map> textSearcherMap = new HashMap<>(); 100 | private static LinkedList sourceTextList = new LinkedList<>(); 101 | 102 | static { 103 | DefaultArtifactVersion version202014 = new DefaultArtifactVersion("2020.1.4"); 104 | String fullVersion = ApplicationInfo.getInstance().getFullVersion(); 105 | DefaultArtifactVersion versionCurrent = new DefaultArtifactVersion(fullVersion); 106 | addPomBtnShow = versionCurrent.compareTo(version202014) > 0; 107 | searcherTextMap.put(MvnRepositoryComDependencySearcher.class, "mvnrepository.com"); 108 | searcherTextMap.put(SearchMavenOrgDependencySearcher.class, "search.maven.org"); 109 | searcherTextMap.put(AliyunMavenDependencySearcher.class, "maven.aliyun.com"); 110 | textSearcherMap.put("mvnrepository.com", MvnRepositoryComDependencySearcher.class); 111 | textSearcherMap.put("search.maven.org", SearchMavenOrgDependencySearcher.class); 112 | textSearcherMap.put("maven.aliyun.com", AliyunMavenDependencySearcher.class); 113 | 114 | sourceTextList.add("mvnrepository.com"); 115 | sourceTextList.add("search.maven.org"); 116 | sourceTextList.add("maven.aliyun.com"); 117 | } 118 | 119 | private static VirtualFile getVirtualFile(MavenArtifactNode myArtifactNode, Project project, MavenProject mavenProject) { 120 | final MavenArtifactNode parent = myArtifactNode.getParent(); 121 | final VirtualFile file; 122 | if (parent == null) { 123 | file = mavenProject.getFile(); 124 | } else { 125 | MavenArtifact artifact = parent.getArtifact(); 126 | final MavenId id = new MavenId(artifact.getGroupId(), artifact.getArtifactId(), artifact.getBaseVersion()); 127 | 128 | final MavenProject pr = MavenProjectsManager.getInstance(project).findProject(id); 129 | file = pr == null ? MavenNavigationUtil.getArtifactFile(project, id) : pr.getFile(); 130 | } 131 | return file; 132 | } 133 | 134 | private MavenProject mavenProject; 135 | private Project project; 136 | private Module module; 137 | 138 | protected DomFileElement getDomFileElement(MavenArtifactNode mavenArtifactNode) { 139 | XmlFile xmlFile = getXmlFile(mavenArtifactNode); 140 | if (xmlFile == null) { 141 | return null; 142 | } 143 | return DomManager.getDomManager(project).getFileElement(xmlFile, MavenDomProjectModel.class); 144 | } 145 | 146 | protected XmlFile getXmlFile(MavenArtifactNode artifact) { 147 | VirtualFile virtualFile = getVirtualFile(artifact, project, mavenProject); 148 | if (virtualFile != null) { 149 | PsiFile psiFile = PsiManager.getInstance(project).findFile(virtualFile); 150 | if (psiFile instanceof XmlFile) { 151 | return (XmlFile) psiFile; 152 | } 153 | } 154 | return null; 155 | } 156 | 157 | public int getCollectionIndex(@NotNull MavenDomDependencies dependencies, @Nullable Editor editor) { 158 | if (editor != null) { 159 | int offset = editor.getCaretModel().getOffset(); 160 | List dependencyList = dependencies.getDependencies(); 161 | 162 | for (int i = 0; i < dependencyList.size(); ++i) { 163 | MavenDomDependency dependency = dependencyList.get(i); 164 | XmlElement xmlElement = dependency.getXmlElement(); 165 | if (xmlElement != null) { 166 | int startOffset = xmlElement.getTextRange().getStartOffset(); 167 | int endOffset = xmlElement.getTextRange().getEndOffset(); 168 | if (offset >= startOffset && offset <= endOffset) { 169 | return i; 170 | } 171 | } 172 | } 173 | } 174 | return -1; 175 | } 176 | 177 | @Override 178 | public void actionPerformed(@NotNull AnActionEvent e) { 179 | project = e.getProject(); 180 | if (dependencySearcher == null) { 181 | dependencySearcher = DependencySearcherManager.getFastest(); 182 | } 183 | sourceTextList.remove(searcherTextMap.get(dependencySearcher.getClass())); 184 | sourceTextList.addFirst(searcherTextMap.get(dependencySearcher.getClass())); 185 | this.groupId = ""; 186 | this.artifactId = ""; 187 | this.version = ""; 188 | this.scope = ""; 189 | 190 | if (MavenActionUtil.isMavenizedProject(e.getDataContext())) { 191 | mavenProject = MavenActionUtil.getMavenProject(e.getDataContext()); 192 | List dependencyTree = mavenProject.getDependencyTree(); 193 | if (dependencyTree.size() > 0) { 194 | DomFileElement domFileElement = getDomFileElement(dependencyTree.get(0)); 195 | MavenDomProjectModel rootElement = (MavenDomProjectModel) domFileElement.getRootElement(); 196 | module = rootElement.getModule(); 197 | MavenDomDependencies domDependencies = rootElement.getDependencies(); 198 | int dependencyIndex = getCollectionIndex(domDependencies, e.getData(CommonDataKeys.EDITOR)); 199 | Editor editor = e.getData(LangDataKeys.EDITOR); 200 | if (editor != null) { 201 | if (dependencyIndex >= 0) { 202 | MavenArtifactNode mavenArtifactNode = dependencyTree.get(dependencyIndex); 203 | this.groupId = mavenArtifactNode.getArtifact().getGroupId(); 204 | this.artifactId = mavenArtifactNode.getArtifact().getArtifactId(); 205 | } 206 | } 207 | } 208 | } 209 | 210 | initView(); 211 | if (this.groupId.length() > 0 && this.artifactId.length() > 0) { 212 | loadDependencyVersionsView(); 213 | } 214 | } 215 | 216 | //------------------ UI渲染 ------------------ // 217 | 218 | /** 219 | * 初始化界面 220 | */ 221 | private void initView() { 222 | frame = new JFrame("Maven Dependency Helper"); 223 | frame.setSize(520, 280); 224 | frame.setResizable(true); 225 | frame.setLocationRelativeTo(null); 226 | frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 227 | 228 | //esc键关闭窗口 229 | frame.getRootPane().registerKeyboardAction(e -> frame.dispose(), KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_IN_FOCUSED_WINDOW); 230 | 231 | //窗体打开时textField获取焦点 232 | frame.addWindowListener(new WindowAdapter() { 233 | @Override 234 | public void windowOpened(WindowEvent e) { 235 | textField.requestFocus(); 236 | } 237 | }); 238 | 239 | copyVersionButton = new JButton("Copy Version"); 240 | copyVersionButton.setFont(new Font(null, Font.PLAIN, 15)); 241 | 242 | copyTextAeraButton = new JButton("Copy Content"); 243 | copyTextAeraButton.setFont(new Font(null, Font.PLAIN, 15)); 244 | 245 | searchButton = new JButton("Search"); 246 | searchButton.setFont(new Font(null, Font.PLAIN, 15)); 247 | 248 | addToPomButton = new JButton("AddToPom"); 249 | addToPomButton.setFont(new Font(null, Font.PLAIN, 15)); 250 | 251 | comboBox = new ComboBox<>(); 252 | comboBox.setFont(new Font(null, Font.PLAIN, 15)); 253 | comboBox.addItem(artifactId); 254 | 255 | typeComboBox = new ComboBox<>(); 256 | typeComboBox.setFont(new Font(null, Font.PLAIN, 15)); 257 | typeComboBox.addItem("Maven"); 258 | typeComboBox.addItem("Gradle"); 259 | typeComboBox.addItem("SBT"); 260 | typeComboBox.addItem("Ivy"); 261 | typeComboBox.addItem("Grape"); 262 | typeComboBox.addItem("Leiningen"); 263 | 264 | textArea = new JTextArea(); 265 | textArea.setColumns(10); 266 | textArea.setRows(6); 267 | textArea.setFont(new Font(null, Font.PLAIN, 16)); 268 | 269 | textField = new JTextField(); 270 | textField.setFont(new Font(null, Font.PLAIN, 16)); 271 | 272 | scrollPane = new JBScrollPane(textArea); 273 | scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); 274 | 275 | versionListModel = new DefaultListModel<>(); 276 | versionJList = new JBList<>(versionListModel); 277 | versionJList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 278 | versionListScroller = new JBScrollPane(versionJList); 279 | versionListScroller.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); 280 | versionListScroller.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); 281 | 282 | versionJList.addListSelectionListener(versionJListSelectionListener); 283 | 284 | tipsTextComponent = new JTextPane(); 285 | tipsTextComponent.setFont(new Font(null, Font.PLAIN, 13)); 286 | tipsTextComponent.setForeground(JBColor.RED); 287 | 288 | sourceLabel = new JBLabel("source:"); 289 | sourceLabel.setFont(new Font(null, Font.PLAIN, 15)); 290 | 291 | sourceComboBox = new ComboBox<>(); 292 | sourceComboBox.setFont(new Font(null, Font.PLAIN, 15)); 293 | for (String s : sourceTextList) { 294 | sourceComboBox.addItem(s); 295 | } 296 | 297 | //设置组件的位置和大小 298 | setLocationAndSize(); 299 | 300 | //将组件添加到Container中 301 | addToContainer(); 302 | 303 | searchButton.addMouseListener(new MouseAdapter() { 304 | @Override 305 | public void mouseClicked(MouseEvent e) { 306 | if (!"".equals(textField.getText())) { 307 | search(); 308 | } 309 | } 310 | }); 311 | textField.addKeyListener(new KeyAdapter() { 312 | @Override 313 | public void keyReleased(KeyEvent e) { 314 | if (searchButton.isEnabled() && e.getKeyCode() == KeyEvent.VK_ENTER && !"".equals(textField.getText())) { 315 | search(); 316 | } 317 | } 318 | }); 319 | comboBox.addItemListener(this::comboBoxItemSelectEvent); 320 | typeComboBox.addItemListener(this::typeComboBoxItemSelectEvent); 321 | sourceComboBox.addItemListener(this::sourceComboBoxItemSelectEvent); 322 | copyTextAeraButton.addMouseListener(this.copyTextAreaButtonMouseListener); 323 | copyVersionButton.addMouseListener(versionCopyButtonMouseListener); 324 | addToPomButton.addMouseListener(new MouseAdapter() { 325 | @Override 326 | public void mouseClicked(MouseEvent e) { 327 | addDependencyToPom(); 328 | } 329 | }); 330 | } 331 | 332 | /** 333 | * 设置组件的位置和大小 334 | */ 335 | private void setLocationAndSize() { 336 | comboBox.setBounds(20, 10, 130, 30); 337 | textField.setBounds(170, 7, 330, 34); 338 | typeComboBox.setBounds(310, 45, 90, 28); 339 | copyVersionButton.setBounds(20, 45, 130, 28); 340 | copyTextAeraButton.setBounds(170, 45, 130, 28); 341 | searchButton.setBounds(410, 45, 90, 28); 342 | versionListScroller.setBounds(20, 77, 130, 153); 343 | scrollPane.setBounds(170, 108, 330, 122); 344 | tipsTextComponent.setBounds(170, 222, 330, 28); 345 | sourceLabel.setBounds(170, 77, 60, 28); 346 | sourceComboBox.setBounds(addPomBtnShow ? 220 : 240, 77, 180, 28); 347 | if (addPomBtnShow) { 348 | addToPomButton.setBounds(400, 77, 100, 28); 349 | } 350 | } 351 | 352 | /** 353 | * 将组件添加到Container中 354 | */ 355 | private void addToContainer() { 356 | frame.getContentPane().setLayout(null); 357 | frame.getContentPane().add(copyVersionButton); 358 | frame.getContentPane().add(copyTextAeraButton); 359 | frame.getContentPane().add(searchButton); 360 | frame.getContentPane().add(comboBox); 361 | frame.getContentPane().add(typeComboBox); 362 | frame.getContentPane().add(textField); 363 | frame.getContentPane().add(scrollPane); 364 | frame.getContentPane().add(versionListScroller); 365 | frame.getContentPane().add(tipsTextComponent); 366 | frame.getContentPane().add(sourceLabel); 367 | frame.getContentPane().add(sourceComboBox); 368 | if (addPomBtnShow) { 369 | frame.getContentPane().add(addToPomButton); 370 | } 371 | frame.setVisible(true); 372 | } 373 | 374 | //------------------ 事件 ------------------ // 375 | 376 | /** 377 | * 搜索依赖 378 | */ 379 | private void search() { 380 | String text = textField.getText(); 381 | searchButton.setText("Searching..."); 382 | searchButton.setEnabled(false); 383 | tipsTextComponent.setText(""); 384 | threadPool.execute(() -> { 385 | try { 386 | List artifacts = dependencySearcher.search(text); 387 | if (artifacts.size() == 0) { 388 | SwingUtilities.invokeLater(() -> { 389 | comboBox.removeAllItems(); 390 | versionListModel.removeAllElements(); 391 | textArea.setText(""); 392 | searchButton.setEnabled(true); 393 | searchButton.setText("Search"); 394 | }); 395 | return; 396 | } 397 | Artifact firstArtifact = artifacts.get(0); 398 | this.groupId = firstArtifact.getGroupId(); 399 | this.artifactId = firstArtifact.getArtifactId(); 400 | 401 | SwingUtilities.invokeLater(() -> { 402 | comboBox.removeAllItems(); 403 | for (Artifact one : artifacts) { 404 | comboBox.addItem(one.getGroupId() + "/" + one.getArtifactId()); 405 | } 406 | comboBox.setSelectedIndex(0); 407 | searchButton.setText("Search"); 408 | searchButton.setEnabled(true); 409 | }); 410 | } catch (IOException e) { 411 | SwingUtilities.invokeLater(() -> { 412 | versionListModel.removeAllElements(); 413 | textArea.setText(""); 414 | searchButton.setText("Search"); 415 | searchButton.setEnabled(true); 416 | tipsTextComponent.setText("failed: " + e.getMessage()); 417 | }); 418 | e.printStackTrace(); 419 | } 420 | }); 421 | } 422 | 423 | /** 424 | * 重新加载版本视图 425 | */ 426 | private void loadDependencyVersionsView() { 427 | copyVersionButton.setText("Loading..."); 428 | copyVersionButton.setEnabled(false); 429 | tipsTextComponent.setText(""); 430 | threadPool.execute(() -> { 431 | try { 432 | List dependencies = dependencySearcher.getDependencies(this.groupId, this.artifactId); 433 | SwingUtilities.invokeLater(() -> { 434 | versionListModel.removeAllElements(); 435 | for (Dependency dependency : dependencies) { 436 | versionListModel.addElement(dependency.getVersion()); 437 | } 438 | if (versionListModel.size() > 0) { 439 | versionJList.setSelectedIndex(0); 440 | } else { 441 | textArea.setText(""); 442 | } 443 | copyVersionButton.setText("Copy Version"); 444 | copyVersionButton.setEnabled(true); 445 | }); 446 | } catch (IOException e) { 447 | SwingUtilities.invokeLater(() -> { 448 | versionListModel.removeAllElements(); 449 | textArea.setText(""); 450 | copyVersionButton.setText("Copy Version"); 451 | copyVersionButton.setEnabled(true); 452 | tipsTextComponent.setText("failed: " + e.getMessage()); 453 | }); 454 | e.printStackTrace(); 455 | } 456 | }); 457 | } 458 | 459 | /** 460 | * 选择依赖comboBox Item选中事件 461 | * 462 | * @param event event 463 | */ 464 | private void comboBoxItemSelectEvent(ItemEvent event) { 465 | if (event.getStateChange() == ItemEvent.SELECTED) { 466 | String[] itemStringSplit = event.getItem().toString().split("/"); 467 | this.groupId = itemStringSplit[0]; 468 | this.artifactId = itemStringSplit[1]; 469 | loadDependencyVersionsView(); 470 | } 471 | } 472 | 473 | /** 474 | * 依赖类型ComboBox Item选中事件 475 | * 476 | * @param event event 477 | */ 478 | private void typeComboBoxItemSelectEvent(ItemEvent event) { 479 | if (event.getStateChange() != ItemEvent.SELECTED) return; 480 | 481 | String version = versionJList.getSelectedValue(); 482 | if (version == null || version.length() == 0) { 483 | textArea.setText(""); 484 | } else { 485 | String buildToolType = event.getItem().toString(); 486 | String dependencyText = dependencyTextByType(buildToolType); 487 | textArea.setText(dependencyText); 488 | } 489 | } 490 | 491 | /** 492 | * 数据源ComboBox Item选中事件 493 | * 494 | * @param event 495 | */ 496 | private void sourceComboBoxItemSelectEvent(ItemEvent event) { 497 | if (event.getStateChange() == ItemEvent.SELECTED) { 498 | String s = event.getItem().toString(); 499 | dependencySearcher = DependencySearcherManager.get(textSearcherMap.get(s)); 500 | } 501 | } 502 | 503 | /** 504 | * 版本选择事件 505 | */ 506 | private ListSelectionListener versionJListSelectionListener = new ListSelectionListener() { 507 | @Override 508 | public void valueChanged(ListSelectionEvent e) { 509 | JList jList = (JList) e.getSource(); 510 | Object selectedValue = jList.getSelectedValue(); 511 | version = selectedValue == null ? "" : selectedValue.toString(); 512 | String type = typeComboBox.getSelectedItem().toString(); 513 | String dependencyText = dependencyTextByType(type); 514 | textArea.setText(dependencyText); 515 | } 516 | }; 517 | 518 | /** 519 | * 依赖复制按钮事件 520 | */ 521 | private MouseListener copyTextAreaButtonMouseListener = new MouseAdapter() { 522 | @Override 523 | public void mouseClicked(MouseEvent e) { 524 | String text = textArea.getText(); 525 | if (text == null || text.length() == 0) return; 526 | 527 | StringSelection stringSelection = new StringSelection(text); 528 | Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); 529 | clipboard.setContents(stringSelection, null); 530 | ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1); 531 | copyTextAeraButton.setText("Copy Success!"); 532 | executorService.schedule(() -> { 533 | SwingUtilities.invokeLater(() -> { 534 | copyTextAeraButton.setText("Copy Content"); 535 | } 536 | 537 | ); 538 | }, 1000, TimeUnit.MILLISECONDS); 539 | } 540 | }; 541 | 542 | /** 543 | * 版本号复制按钮事件 544 | */ 545 | private MouseListener versionCopyButtonMouseListener = new MouseAdapter() { 546 | @Override 547 | public void mouseClicked(MouseEvent e) { 548 | String version = versionJList.getSelectedValue(); 549 | if (version == null || version.length() == 0) return; 550 | 551 | StringSelection stringSelection = new StringSelection(version); 552 | Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); 553 | clipboard.setContents(stringSelection, null); 554 | copyVersionButton.setText("Copy Success!"); 555 | ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1); 556 | executorService.schedule(() -> { 557 | SwingUtilities.invokeLater(() -> { 558 | copyVersionButton.setText("Copy Version"); 559 | } 560 | 561 | ); 562 | }, 1000, TimeUnit.MILLISECONDS); 563 | } 564 | }; 565 | 566 | //------------------ 辅助方法 ------------------ // 567 | 568 | /** 569 | * 读取并解析pom.xml,获取Dependency信息 570 | */ 571 | private List getDependenciesByPom(String filePath) { 572 | List d = new ArrayList<>(); 573 | if (filePath.contains("pom.xml")) { 574 | File file = new File(filePath); 575 | try { 576 | SAXReader saxReader = new SAXReader(); 577 | Document document = saxReader.read(file); 578 | Element rootElement = document.getRootElement(); 579 | Element dependenciesElement = rootElement.element("dependencies"); 580 | for (Iterator it = dependenciesElement.elementIterator(); it.hasNext(); ) { 581 | Dependency dependency = new Dependency(); 582 | Element element = (Element) it.next(); 583 | String groupId = element.element("groupId").getText(); 584 | String artifactId = element.element("artifactId").getText(); 585 | String version = element.element("version") == null ? "" : element.element("version").getText(); 586 | String scope = element.element("scope") == null ? "" : element.element("scope").getText(); 587 | dependency.setGroupId(groupId); 588 | dependency.setArtifactId(artifactId); 589 | dependency.setVersion(version); 590 | dependency.setScope(scope); 591 | d.add(dependency); 592 | } 593 | 594 | } catch (DocumentException e) { 595 | e.printStackTrace(); 596 | } 597 | } 598 | return d; 599 | } 600 | 601 | /** 602 | * 根据不同构建工具, 生成依赖文本 603 | */ 604 | private String dependencyTextByType(String type) { 605 | String text; 606 | switch (type) { 607 | case "Maven": 608 | text = dependencyTextForMaven(); 609 | break; 610 | case "Gradle": 611 | text = dependencyTextForGradle(); 612 | break; 613 | case "SBT": 614 | text = String.format("libraryDependencies += \"%s\" %s \"%s\" %s \"%s\"", 615 | this.groupId, "%", this.artifactId, "%", this.version); 616 | break; 617 | case "Ivy": 618 | text = String.format("", 619 | this.groupId, this.artifactId, this.version); 620 | break; 621 | case "Grape": 622 | text = String.format("@Grapes(\n" + 623 | " @Grab(group='junit', module='junit', version='4.13')\n" + 624 | ")", 625 | this.groupId, this.artifactId, this.version); 626 | break; 627 | case "Leiningen": 628 | text = String.format("[%s/%s \"%s\"]", this.groupId, this.artifactId, this.version); 629 | break; 630 | default: 631 | text = ""; 632 | } 633 | return text; 634 | } 635 | 636 | /** 637 | * 生成gradle的依赖文本 638 | */ 639 | private String dependencyTextForGradle() { 640 | String dependencyText; 641 | switch (scope) { 642 | case "test": 643 | dependencyText = String.format("testImplementation '%s:%s:%s'", groupId, artifactId, version); 644 | break; 645 | case "provided": 646 | dependencyText = String.format("compileOnly '%s:%s:%s'", groupId, artifactId, version); 647 | break; 648 | default: 649 | dependencyText = String.format("implementation '%s:%s:%s'", groupId, artifactId, version); 650 | break; 651 | } 652 | return dependencyText; 653 | } 654 | 655 | /** 656 | * 生成maven的依赖文本 657 | */ 658 | private String dependencyTextForMaven() { 659 | if (scope != null && !scope.equals("")) { 660 | return "\n" + 661 | " " + groupId + "\n" + 662 | " " + artifactId + "\n" + 663 | " " + version + "\n" + 664 | " " + scope + "\n" + 665 | ""; 666 | } else { 667 | return "\n" + 668 | " " + groupId + "\n" + 669 | " " + artifactId + "\n" + 670 | " " + version + "\n" + 671 | ""; 672 | } 673 | } 674 | 675 | private void addDependencyToPom() { 676 | String text = textArea.getText(); 677 | if (text == null || text.length() == 0) return; 678 | Dependency dependency = new Dependency(groupId, artifactId, version, !"".equals(scope) ? scope : null); 679 | if (addPomBtnShow) { 680 | try { 681 | Object o = Class.forName("com.intellij.externalSystem.DependencyModifierService") 682 | .getMethod("getInstance", Project.class).invoke(null, project); 683 | Object o1 = Class.forName("com.intellij.buildsystem.model.unified.UnifiedDependency") 684 | .getConstructor(String.class, String.class, String.class, String.class) 685 | .newInstance(dependency.getGroupId(), dependency.getArtifactId(), dependency.getVersion(), dependency.getScope()); 686 | Class.forName("com.intellij.externalSystem.DependencyModifierService").getDeclaredMethod("addDependency", Module.class, o1.getClass()).invoke(o, module, o1); 687 | } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException | ClassNotFoundException | InstantiationException ex) { 688 | ex.printStackTrace(); 689 | } 690 | } 691 | } 692 | } 693 | -------------------------------------------------------------------------------- /src/actions/MyInvocationHandler.java: -------------------------------------------------------------------------------- 1 | package actions; 2 | 3 | import java.lang.reflect.InvocationHandler; 4 | import java.lang.reflect.Method; 5 | 6 | /** 7 | * @author z 8 | */ 9 | public class MyInvocationHandler implements InvocationHandler { 10 | 11 | private Object target; 12 | 13 | public MyInvocationHandler(Object target) { 14 | this.target = target; 15 | } 16 | 17 | @Override 18 | public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 19 | return null; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/model/Artifact.java: -------------------------------------------------------------------------------- 1 | package model; 2 | 3 | /** 4 | * Identify a artifact. 5 | */ 6 | public class Artifact { 7 | 8 | private String groupId; 9 | private String artifactId; 10 | 11 | public String getGroupId() { 12 | return groupId; 13 | } 14 | 15 | public void setGroupId(String groupId) { 16 | this.groupId = groupId; 17 | } 18 | 19 | public String getArtifactId() { 20 | return artifactId; 21 | } 22 | 23 | public void setArtifactId(String artifactId) { 24 | this.artifactId = artifactId; 25 | } 26 | 27 | @Override 28 | public String toString() { 29 | return "ArtifactId{" + 30 | "groupId='" + groupId + '\'' + 31 | ", artifactId='" + artifactId + '\'' + 32 | '}'; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/model/Dependency.java: -------------------------------------------------------------------------------- 1 | package model; 2 | 3 | public class Dependency { 4 | private String groupId; 5 | private String artifactId; 6 | private String version; 7 | private String scope; 8 | 9 | public Dependency() { 10 | } 11 | 12 | public Dependency(String groupId, String artifactId, String version, String scope) { 13 | this.groupId = groupId; 14 | this.artifactId = artifactId; 15 | this.version = version; 16 | this.scope = scope; 17 | } 18 | 19 | @Override 20 | public String toString() { 21 | return "Dependency{" + 22 | "groupId='" + groupId + '\'' + 23 | ", artifactId='" + artifactId + '\'' + 24 | ", version='" + version + '\'' + 25 | ", scope='" + scope + '\'' + 26 | '}'; 27 | } 28 | 29 | public String getGroupId() { 30 | return groupId; 31 | } 32 | 33 | public void setGroupId(String groupId) { 34 | this.groupId = groupId; 35 | } 36 | 37 | public String getArtifactId() { 38 | return artifactId; 39 | } 40 | 41 | public void setArtifactId(String artifactId) { 42 | this.artifactId = artifactId; 43 | } 44 | 45 | public String getVersion() { 46 | return version; 47 | } 48 | 49 | public void setVersion(String version) { 50 | this.version = version; 51 | } 52 | 53 | public String getScope() { 54 | return scope; 55 | } 56 | 57 | public void setScope(String scope) { 58 | this.scope = scope; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/searcher/DependencySearcher.java: -------------------------------------------------------------------------------- 1 | package searcher; 2 | 3 | import model.Artifact; 4 | import model.Dependency; 5 | 6 | import java.io.IOException; 7 | import java.util.List; 8 | 9 | /** 10 | * To search dependency. 11 | */ 12 | public interface DependencySearcher { 13 | /** 14 | * get detect speed url 15 | */ 16 | String getDetectSpeedUrl(); 17 | 18 | int getSpeed(); 19 | 20 | void setSpeed(int speed); 21 | /** 22 | * Search dependency. 23 | */ 24 | List search(String text) throws IOException; 25 | 26 | /** 27 | * Fetch all version dependency by groupId & articleId. 28 | */ 29 | List getDependencies(String groupId, String articleId) throws IOException; 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/searcher/DependencySearcherManager.java: -------------------------------------------------------------------------------- 1 | package searcher; 2 | 3 | import actions.AppSettingsState; 4 | import actions.MavenDependencyHelperAction; 5 | import com.intellij.notification.Notification; 6 | import com.intellij.notification.NotificationDisplayType; 7 | import com.intellij.notification.NotificationGroup; 8 | import com.intellij.notification.NotificationType; 9 | import com.intellij.openapi.application.ApplicationInfo; 10 | import com.intellij.openapi.project.Project; 11 | import org.apache.maven.artifact.versioning.DefaultArtifactVersion; 12 | import org.jsoup.Jsoup; 13 | import searcher.impl.AliyunMavenDependencySearcher; 14 | import searcher.impl.MvnRepositoryComDependencySearcher; 15 | import searcher.impl.SearchMavenOrgDependencySearcher; 16 | import util.OkHttpUtils; 17 | 18 | import java.io.IOException; 19 | import java.lang.reflect.InvocationTargetException; 20 | import java.text.SimpleDateFormat; 21 | import java.util.Comparator; 22 | import java.util.Date; 23 | import java.util.HashMap; 24 | import java.util.Map; 25 | import java.util.concurrent.ScheduledFuture; 26 | import java.util.concurrent.ScheduledThreadPoolExecutor; 27 | import java.util.concurrent.ThreadPoolExecutor; 28 | import java.util.concurrent.TimeUnit; 29 | import java.util.stream.Collectors; 30 | 31 | /** 32 | * @author yiyingcanfneg 33 | */ 34 | public class DependencySearcherManager { 35 | 36 | private static NotificationGroup NOTIFICATION_GROUP = null; 37 | 38 | private static final HashMap, DependencySearcher> pool = new HashMap<>(); 39 | 40 | public static ThreadPoolExecutor threadPool = MavenDependencyHelperAction.threadPool; 41 | public static ScheduledThreadPoolExecutor scheduledThreadPoolExecutor = MavenDependencyHelperAction.scheduledThreadPoolExecutor; 42 | private static ScheduledFuture scheduledFuture; 43 | 44 | public static final int TIMEOUT = 3000; 45 | /** 46 | * 测速间隔 47 | */ 48 | private static int speedTestInterval = AppSettingsState.getInstance().speedDetectInterval; 49 | 50 | static { 51 | String fullVersion = ApplicationInfo.getInstance().getFullVersion(); 52 | // 'NotificationGroup(java.lang.String, com.intellij.notification.NotificationDisplayType, boolean)' is deprecated after 2020.2.4 53 | DefaultArtifactVersion version202024 = new DefaultArtifactVersion("2020.2.4"); 54 | DefaultArtifactVersion versionCurrent = new DefaultArtifactVersion(ApplicationInfo.getInstance().getFullVersion()); 55 | if (versionCurrent.compareTo(version202024) <= 0) { 56 | try { 57 | Class aClass = Class.forName("com.intellij.notification.NotificationGroup"); 58 | NOTIFICATION_GROUP = (NotificationGroup) aClass.getDeclaredConstructor( 59 | String.class, NotificationDisplayType.class, boolean.class 60 | ).newInstance("MavenDependencyHelper", NotificationDisplayType.NONE, true); 61 | } catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InstantiationException | InvocationTargetException e) { 62 | e.printStackTrace(); 63 | } 64 | //NOTIFICATION_GROUP = new NotificationGroup("MavenDependencyHelper", NotificationDisplayType.NONE, true); 65 | } else { 66 | try { 67 | Class notificationGroupManagerClass = Class.forName("com.intellij.notification.NotificationGroupManager"); 68 | Object notificationGroupManager = notificationGroupManagerClass.getMethod("getInstance").invoke(null); 69 | 70 | NOTIFICATION_GROUP = (NotificationGroup) notificationGroupManagerClass.getMethod("getNotificationGroup", String.class).invoke(notificationGroupManager, "MavenDependencyHelper"); 71 | } catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { 72 | e.printStackTrace(); 73 | } 74 | //NOTIFICATION_GROUP = NotificationGroupManager.getInstance().getNotificationGroup("MavenDependencyHelper"); 75 | } 76 | pool.put(AliyunMavenDependencySearcher.class, new AliyunMavenDependencySearcher()); 77 | pool.put(MvnRepositoryComDependencySearcher.class, new MvnRepositoryComDependencySearcher()); 78 | pool.put(SearchMavenOrgDependencySearcher.class, new SearchMavenOrgDependencySearcher()); 79 | // 定时对搜索源进行测速,用以选择访问速度最佳的搜索源 80 | if (scheduledFuture == null) { 81 | scheduledFuture = scheduledThreadPoolExecutor.scheduleAtFixedRate(DependencySearcherManager::task, 0, speedTestInterval, TimeUnit.SECONDS); 82 | } 83 | 84 | } 85 | 86 | private static void task() { 87 | websiteSpeedTest(); 88 | MavenDependencyHelperAction.dependencySearcher = getFastest(); 89 | 90 | StringBuilder stringBuilder = new StringBuilder("MavenDependencyHelper search source speed:\n"); 91 | for (Map.Entry> entry : MavenDependencyHelperAction.textSearcherMap.entrySet()) { 92 | int speed = pool.get(entry.getValue()).getSpeed(); 93 | stringBuilder.append(entry.getKey()).append(": ").append(speed); 94 | if (speed == TIMEOUT) { 95 | stringBuilder.append(" (timeout)"); 96 | } 97 | stringBuilder.append("\n"); 98 | } 99 | stringBuilder.append("detect speed interval: ").append(speedTestInterval).append("s\n"); 100 | stringBuilder.append("next detect time: ").append(new SimpleDateFormat("HH:mm").format(new Date(System.currentTimeMillis() + speedTestInterval * 1000L))); 101 | notify(stringBuilder.toString()); 102 | } 103 | 104 | public static void setSpeedTestInterval(int i) { 105 | speedTestInterval = i; 106 | scheduledFuture.cancel(false); 107 | scheduledFuture = scheduledThreadPoolExecutor.scheduleAtFixedRate(DependencySearcherManager::task, 0, speedTestInterval, TimeUnit.SECONDS); 108 | } 109 | 110 | public static DependencySearcher get(Class clazz) { 111 | return pool.get(clazz); 112 | } 113 | 114 | public static DependencySearcher getFastest() { 115 | return pool.values().stream().sorted(Comparator.comparingInt(DependencySearcher::getSpeed)).collect(Collectors.toList()).get(0); 116 | } 117 | 118 | public static void websiteSpeedTest() { 119 | for (DependencySearcher value : pool.values()) { 120 | threadPool.execute(() -> { 121 | long start = System.currentTimeMillis(); 122 | String detectSpeedUrl = value.getDetectSpeedUrl(); 123 | OkHttpUtils.get(detectSpeedUrl); 124 | //Jsoup.connect(detectSpeedUrl).timeout(TIMEOUT).ignoreContentType(true).execute(); 125 | long end = System.currentTimeMillis(); 126 | value.setSpeed((int) (end - start)); 127 | }); 128 | } 129 | } 130 | 131 | public static Notification notify(String content) { 132 | return notify(null, content); 133 | } 134 | 135 | public static Notification notify(Project project, String content) { 136 | final Notification notification = NOTIFICATION_GROUP.createNotification(content, NotificationType.INFORMATION); 137 | notification.notify(project); 138 | return notification; 139 | } 140 | 141 | } 142 | -------------------------------------------------------------------------------- /src/searcher/impl/AliyunMavenDependencySearcher.java: -------------------------------------------------------------------------------- 1 | package searcher.impl; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.JsonArray; 5 | import com.google.gson.JsonElement; 6 | import com.google.gson.JsonObject; 7 | import model.Artifact; 8 | import model.Dependency; 9 | import org.jsoup.Jsoup; 10 | import org.jsoup.nodes.Document; 11 | import searcher.DependencySearcher; 12 | 13 | import java.io.IOException; 14 | import java.io.UnsupportedEncodingException; 15 | import java.net.URLEncoder; 16 | import java.nio.charset.StandardCharsets; 17 | import java.util.ArrayList; 18 | import java.util.List; 19 | import java.util.Map; 20 | import java.util.concurrent.ConcurrentHashMap; 21 | import java.util.function.Function; 22 | import java.util.function.Predicate; 23 | import java.util.stream.Collectors; 24 | 25 | /** 26 | * Search dependencies by https://maven.aliyun.com/mvn/search 27 | */ 28 | public class AliyunMavenDependencySearcher implements DependencySearcher { 29 | 30 | /** 31 | * 超时毫秒 32 | */ 33 | private final int timeoutMs; 34 | 35 | /** 36 | * 网站速度,单位: ms 37 | */ 38 | private int speed = 1; 39 | 40 | /** 41 | * 用于测速的url 42 | */ 43 | public static final String DETECT_SPEED_URL = "https://maven.aliyun.com/artifact/aliyunMaven/searchArtifactByWords?_input_charset=utf-8&queryTerm=commons&repoId=central"; 44 | 45 | private static final String SEARCH_URL = "https://maven.aliyun.com/artifact/aliyunMaven/searchArtifactByWords?_input_charset=utf-8&queryTerm=%s&repoId=central"; 46 | private static final String EXACT_SEARCH_URL = "https://maven.aliyun.com/artifact/aliyunMaven/searchArtifactByGav?_input_charset=utf-8&groupId=%s&repoId=central&artifactId=%s&version="; 47 | 48 | public AliyunMavenDependencySearcher() { 49 | this(30000); 50 | } 51 | 52 | public AliyunMavenDependencySearcher(int timeoutMs) { 53 | if (timeoutMs <= 0) { 54 | throw new IllegalArgumentException("timeoutMs must grater than 0"); 55 | } 56 | this.timeoutMs = timeoutMs; 57 | } 58 | 59 | @Override 60 | public String getDetectSpeedUrl() { 61 | return DETECT_SPEED_URL; 62 | } 63 | 64 | @Override 65 | public List search(String text) throws IOException { 66 | 67 | Document document = Jsoup.connect(String.format(SEARCH_URL, text)) 68 | .timeout(timeoutMs).ignoreContentType(true).get(); 69 | JsonObject data = new Gson().fromJson(document.body().text(), JsonObject.class); 70 | List artifacts = new ArrayList<>(); 71 | if (data.get("successful").getAsBoolean()) { 72 | JsonArray array = data.getAsJsonArray("object"); 73 | 74 | for (JsonElement ele : array) { 75 | JsonObject doc = ele.getAsJsonObject(); 76 | if ("unknown".equals(doc.get("packaging").getAsString())) { 77 | continue; 78 | } 79 | if ("jar".equals(doc.get("packaging").getAsString())) { 80 | Artifact artifact = new Artifact(); 81 | String groupId = doc.get("groupId").getAsString(); 82 | if (groupId.startsWith("#") || groupId.startsWith("%23")) { 83 | continue; 84 | } 85 | artifact.setGroupId(groupId); 86 | artifact.setArtifactId(doc.get("artifactId").getAsString()); 87 | artifacts.add(artifact); 88 | } 89 | } 90 | } 91 | return artifacts.stream().filter(distinctByKey(Artifact::getGroupId)).collect(Collectors.toList()); 92 | } 93 | 94 | private static Predicate distinctByKey(Function keyExtractor) { 95 | Map seen = new ConcurrentHashMap<>(); 96 | return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null; 97 | } 98 | 99 | @Override 100 | public List getDependencies(String groupId, String articleId) throws IOException { 101 | Document document = Jsoup.connect(String.format(EXACT_SEARCH_URL, groupId, articleId)) 102 | .timeout(timeoutMs) 103 | .ignoreContentType(true).get(); 104 | JsonObject data = new Gson().fromJson(document.body().text(), JsonObject.class); 105 | 106 | List dependencies = new ArrayList<>(); 107 | if (data.get("successful").getAsBoolean()) { 108 | JsonArray docs = data.getAsJsonArray("object"); 109 | for (JsonElement ele : docs) { 110 | JsonObject doc = ele.getAsJsonObject(); 111 | if ("unknown".equals(doc.get("packaging").getAsString())) { 112 | continue; 113 | } 114 | if ("jar".equals(doc.get("packaging").getAsString())) { 115 | Dependency dependency = new Dependency(); 116 | String groupId1 = doc.get("groupId").getAsString(); 117 | if (groupId1.startsWith("#")) { 118 | continue; 119 | } 120 | dependency.setGroupId(groupId1); 121 | dependency.setArtifactId(doc.get("artifactId").getAsString()); 122 | dependency.setVersion(doc.get("version").getAsString()); 123 | dependencies.add(dependency); 124 | } 125 | } 126 | } 127 | return dependencies.stream().filter(distinctByKey(Dependency::getVersion)).collect(Collectors.toList()); 128 | } 129 | 130 | @Override 131 | public int getSpeed() { 132 | return speed; 133 | } 134 | 135 | @Override 136 | public void setSpeed(int speed) { 137 | this.speed = speed; 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /src/searcher/impl/MvnRepositoryComDependencySearcher.java: -------------------------------------------------------------------------------- 1 | package searcher.impl; 2 | 3 | import model.Artifact; 4 | import model.Dependency; 5 | import org.jsoup.Jsoup; 6 | import org.jsoup.nodes.Document; 7 | import org.jsoup.nodes.Element; 8 | import org.jsoup.select.Elements; 9 | import searcher.DependencySearcher; 10 | import util.OkHttpUtils; 11 | 12 | import java.io.IOException; 13 | import java.util.ArrayList; 14 | import java.util.List; 15 | 16 | /** 17 | * Search dependencies from https://mvnrepository.com 18 | */ 19 | public class MvnRepositoryComDependencySearcher implements DependencySearcher { 20 | 21 | /** 22 | * 超时毫秒 23 | */ 24 | private final int timeoutMs; 25 | 26 | /** 27 | * 网站速度,单位: ms 28 | */ 29 | private int speed = 0; 30 | 31 | /** 32 | * 用于测速的url 33 | */ 34 | public static final String DETECT_SPEED_URL = "https://mvnrepository.com/search?q=commons"; 35 | 36 | public MvnRepositoryComDependencySearcher() { 37 | this(30000); 38 | } 39 | 40 | public MvnRepositoryComDependencySearcher(int timeoutMs) { 41 | if (timeoutMs <= 0) { 42 | throw new IllegalArgumentException("timeoutMs must grater than 0"); 43 | } 44 | this.timeoutMs = timeoutMs; 45 | } 46 | 47 | @Override 48 | public String getDetectSpeedUrl() { 49 | return DETECT_SPEED_URL; 50 | } 51 | 52 | @Override 53 | public List search(String text) throws IOException { 54 | String searchUrl = "https://mvnrepository.com/search?q=" + text; 55 | // jsoup visit mvnrepository.com may return 403, use okhttp instead 56 | String s = OkHttpUtils.get(searchUrl); 57 | Document doc = Jsoup.parse(s); 58 | Elements elements = doc.getElementsByClass("im-subtitle"); 59 | 60 | List artifacts = new ArrayList<>(elements.size()); 61 | for (Element ele : elements) { 62 | Elements hrefs = ele.getElementsByAttribute("href"); 63 | if (hrefs.size() >= 2) { 64 | Artifact artifact = new Artifact(); 65 | artifact.setGroupId(hrefs.get(0).text()); 66 | artifact.setArtifactId(hrefs.get(1).text()); 67 | artifacts.add(artifact); 68 | } 69 | } 70 | return artifacts; 71 | } 72 | 73 | @Override 74 | public List getDependencies(String groupId, String artifactId) throws IOException { 75 | String url = String.format("https://mvnrepository.com/artifact/%s/%s", groupId, artifactId); 76 | // jsoup visit mvnrepository.com may return 403, use okhttp instead 77 | String s = OkHttpUtils.get(url); 78 | Document doc = Jsoup.parse(s); 79 | Elements elements = doc.getElementsByClass("vbtn release"); 80 | 81 | List dependencies = new ArrayList<>(elements.size()); 82 | for (Element ele : elements) { 83 | Dependency dependency = new Dependency(); 84 | dependency.setGroupId(groupId); 85 | dependency.setArtifactId(artifactId); 86 | dependency.setVersion(ele.text()); 87 | dependencies.add(dependency); 88 | } 89 | return dependencies; 90 | } 91 | 92 | @Override 93 | public int getSpeed() { 94 | return speed; 95 | } 96 | 97 | @Override 98 | public void setSpeed(int speed) { 99 | this.speed = speed; 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /src/searcher/impl/SearchMavenOrgDependencySearcher.java: -------------------------------------------------------------------------------- 1 | package searcher.impl; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.JsonArray; 5 | import com.google.gson.JsonElement; 6 | import com.google.gson.JsonObject; 7 | import model.Artifact; 8 | import model.Dependency; 9 | import org.jsoup.Jsoup; 10 | import org.jsoup.nodes.Document; 11 | import searcher.DependencySearcher; 12 | 13 | import java.io.IOException; 14 | import java.io.UnsupportedEncodingException; 15 | import java.net.URLEncoder; 16 | import java.nio.charset.StandardCharsets; 17 | import java.util.ArrayList; 18 | import java.util.List; 19 | 20 | /** 21 | * Search dependencies by https://search.maven.org/ 22 | */ 23 | public class SearchMavenOrgDependencySearcher implements DependencySearcher { 24 | 25 | /** 26 | * 超时毫秒 27 | */ 28 | private final int timeoutMs; 29 | 30 | /** 31 | * 网站速度,单位: ms 32 | */ 33 | private int speed = 2; 34 | 35 | /** 36 | * 用于测速的url 37 | */ 38 | public static final String DETECT_SPEED_URL = "https://search.maven.org/solrsearch/select?q=commons&start=0&rows=20"; 39 | 40 | private static final String SEARCH_URL = "https://search.maven.org/solrsearch/select?q=%s&start=%s&rows=%s"; 41 | 42 | public SearchMavenOrgDependencySearcher() { 43 | this(30000); 44 | } 45 | 46 | public SearchMavenOrgDependencySearcher(int timeoutMs) { 47 | if (timeoutMs <= 0) { 48 | throw new IllegalArgumentException("timeoutMs must grater than 0"); 49 | } 50 | this.timeoutMs = timeoutMs; 51 | } 52 | 53 | @Override 54 | public String getDetectSpeedUrl() { 55 | return DETECT_SPEED_URL; 56 | } 57 | 58 | @Override 59 | public List search(String text) throws IOException { 60 | Document document = Jsoup.connect(String.format(SEARCH_URL, encodeUtf8(text), 0, 20)) 61 | .timeout(timeoutMs).ignoreContentType(true).get(); 62 | JsonObject data = new Gson().fromJson(document.body().text(), JsonObject.class); 63 | JsonArray docs = data.getAsJsonObject("response").getAsJsonArray("docs"); 64 | 65 | List artifacts = new ArrayList<>(docs.size()); 66 | for (JsonElement ele : docs) { 67 | JsonObject doc = ele.getAsJsonObject(); 68 | Artifact artifact = new Artifact(); 69 | artifact.setGroupId(doc.get("g").getAsString()); 70 | artifact.setArtifactId(doc.get("a").getAsString()); 71 | artifacts.add(artifact); 72 | } 73 | 74 | return artifacts; 75 | } 76 | 77 | @Override 78 | public List getDependencies(String groupId, String articleId) throws IOException { 79 | String text = String.format("g:%s AND a:%s", encodeUtf8(groupId), encodeUtf8(articleId)) + "&core=gav"; 80 | Document document = Jsoup.connect(String.format(SEARCH_URL, text, 0, 100)) 81 | .timeout(timeoutMs) 82 | .ignoreContentType(true).get(); 83 | JsonObject data = new Gson().fromJson(document.body().text(), JsonObject.class); 84 | JsonArray docs = data.getAsJsonObject("response").getAsJsonArray("docs"); 85 | 86 | List dependencies = new ArrayList<>(docs.size()); 87 | for (JsonElement ele : docs) { 88 | JsonObject doc = ele.getAsJsonObject(); 89 | Dependency dependency = new Dependency(); 90 | dependency.setGroupId(doc.get("g").getAsString()); 91 | dependency.setArtifactId(doc.get("a").getAsString()); 92 | dependency.setVersion(doc.get("v").getAsString()); 93 | dependencies.add(dependency); 94 | } 95 | return dependencies; 96 | } 97 | 98 | private String encodeUtf8(String text) { 99 | try { 100 | return URLEncoder.encode(text, StandardCharsets.UTF_8.name()); 101 | } catch (UnsupportedEncodingException e) { 102 | throw new RuntimeException("Never happen.", e); 103 | } 104 | 105 | } 106 | 107 | @Override 108 | public int getSpeed() { 109 | return speed; 110 | } 111 | 112 | @Override 113 | public void setSpeed(int speed) { 114 | this.speed = speed; 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /src/ui/AppSettingsForm.form: -------------------------------------------------------------------------------- 1 | 2 |
    3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 |
    96 | -------------------------------------------------------------------------------- /src/ui/AppSettingsForm.java: -------------------------------------------------------------------------------- 1 | package ui; 2 | 3 | import javax.swing.*; 4 | 5 | /** 6 | * @author z 7 | */ 8 | public class AppSettingsForm { 9 | 10 | private JTextField textField; 11 | private JPanel panel; 12 | 13 | public JPanel getPanel() { 14 | return panel; 15 | } 16 | 17 | public void setIntervalText(String text) { 18 | textField.setText(text); 19 | } 20 | 21 | public String getIntervalText() { 22 | return textField.getText(); 23 | } 24 | 25 | public JComponent getPreferredFocusedComponent() { 26 | return textField; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/util/OkHttpUtils.java: -------------------------------------------------------------------------------- 1 | package util; 2 | 3 | import okhttp3.*; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | 7 | import java.io.IOException; 8 | import java.io.InputStream; 9 | import java.net.InetSocketAddress; 10 | import java.util.Map; 11 | 12 | public class OkHttpUtils { 13 | 14 | private static Proxy proxy; 15 | 16 | public static void setProxy(String ip, int port, String username, String password) { 17 | if (OkHttpUtils.proxy == null) { 18 | OkHttpUtils.proxy = new Proxy(ip, port, username, password); 19 | } 20 | } 21 | 22 | public static OkHttpClient getmOkHttpClientUseProxy() { 23 | if (mOkHttpClientUseProxy == null) { 24 | mOkHttpClientUseProxy = new OkHttpClient(); 25 | } 26 | return mOkHttpClientUseProxy; 27 | } 28 | 29 | 30 | static class Proxy { 31 | static String ip; 32 | static int port; 33 | static String username; 34 | static String password; 35 | static Authenticator proxyAuthenticator; 36 | static java.net.Proxy proxy; 37 | 38 | public Proxy(String ip, int port, String username, String password) { 39 | if (ip.equals(Proxy.ip) && Proxy.port == port && username.equals(Proxy.username) && password.equals(Proxy.password)) { 40 | return; 41 | } 42 | Proxy.ip = ip; 43 | Proxy.port = port; 44 | Proxy.username = username; 45 | Proxy.password = password; 46 | proxyAuthenticator = (route, response) -> { 47 | String credential = Credentials.basic(username, password); 48 | return response.request().newBuilder() 49 | .header("Proxy-Authorization", credential) 50 | .build(); 51 | }; 52 | proxy = new java.net.Proxy(java.net.Proxy.Type.HTTP, new InetSocketAddress(ip, port)); 53 | OkHttpUtils.mOkHttpClientUseProxy = new OkHttpClient 54 | .Builder() 55 | .proxy(proxy) 56 | .proxyAuthenticator(proxyAuthenticator) 57 | .build(); 58 | } 59 | } 60 | 61 | /** 62 | * 返回结果类型 63 | */ 64 | public enum ResultType { 65 | /** 66 | * STRING:字符串类型 67 | * STREAM:流 68 | */ 69 | STRING, STREAM 70 | } 71 | 72 | /** 73 | * 请求方式 74 | */ 75 | public enum RequestMethod { 76 | /** 77 | * SYNC:同步请求 78 | * ASYNC:异步请求 79 | */ 80 | GET, POST, DELETE, UPDATE, PUT 81 | } 82 | 83 | /** 84 | * 请求方式 85 | */ 86 | public enum RequestType { 87 | /** 88 | * SYNC:同步请求 89 | * ASYNC:异步请求 90 | */ 91 | SYNC, ASYNC 92 | } 93 | 94 | private static final OkHttpClient mOkHttpClient = new OkHttpClient(); 95 | 96 | private static OkHttpClient mOkHttpClientUseProxy; 97 | 98 | public static final MediaType JSON = MediaType.parse("application/json;charset=utf-8"); 99 | 100 | private static final Logger logger = LoggerFactory.getLogger(OkHttpUtils.class); 101 | 102 | public static OkHttpClient getOkHttpClient() { 103 | return mOkHttpClient; 104 | } 105 | 106 | /** 107 | * 发起get请求,获取字符串数据 108 | * 109 | * @param url url 110 | * @return 字符串 111 | */ 112 | public static String get(String url) { 113 | mOkHttpClient.proxy(); 114 | return stringGet(url, null); 115 | } 116 | 117 | /** 118 | * 发起get请求,获取字符串数据 119 | * 120 | * @param url url 121 | * @return 字符串 122 | */ 123 | public static String get(String url, boolean useProxy) { 124 | return stringGet(url, null, useProxy); 125 | } 126 | 127 | /** 128 | * 发起get请求,获取字符串数据 129 | * 130 | * @param url url 131 | * @param param param 132 | * @return 字符串 133 | */ 134 | public static String get(String url, Map param) { 135 | String result = ""; 136 | url += "?"; 137 | StringBuilder urlBuilder = new StringBuilder(url); 138 | for (Map.Entry entry : param.entrySet()) { 139 | urlBuilder.append(String.format("%s=%s&", entry.getKey(), entry.getValue())); 140 | } 141 | int lastIndexOf = urlBuilder.lastIndexOf("&"); 142 | if (lastIndexOf == urlBuilder.length() - 1) { 143 | urlBuilder.deleteCharAt(lastIndexOf); 144 | } 145 | url = urlBuilder.toString(); 146 | Request request = getRequest(url, null, RequestMethod.GET); 147 | return getString(result, request); 148 | } 149 | 150 | /** 151 | * 发起get请求 152 | * 153 | * @param url url 154 | * @param type 请求字符串数据还是二进制数据 155 | * @param header 请求头 156 | * @return 字符串 157 | */ 158 | public static Object get(String url, ResultType type, Map header) { 159 | switch (type) { 160 | //请求字符串数据 161 | case STRING: 162 | return stringGet(url, header); 163 | //请求二进制数据 164 | case STREAM: 165 | return streamGet(url, header); 166 | default: 167 | return ""; 168 | } 169 | } 170 | 171 | /** 172 | * 发起get请求 173 | * 174 | * @param url url 175 | * @param type 请求字符串数据还是二进制数据 176 | * @param header 请求头 177 | * @return 字符串 178 | */ 179 | public static Object get(String url, ResultType type, String json, Map header) { 180 | switch (type) { 181 | //请求字符串数据 182 | case STRING: 183 | return stringGet(url, header); 184 | //请求二进制数据 185 | case STREAM: 186 | return streamGet(url, header); 187 | default: 188 | return ""; 189 | } 190 | } 191 | 192 | /** 193 | * 发起post请求, 发送表单数据 194 | * 195 | * @param url url 196 | * @param requestFormMap 键值对的form表单数据 197 | * @return 198 | * @throws IOException 199 | */ 200 | public static String post(String url, Map requestFormMap) throws IOException { 201 | return post(url, RequestType.SYNC, requestFormMap, null, false); 202 | } 203 | 204 | /** 205 | * 发起post请求, 发送表单数据,携带自定义header 206 | * 207 | * @param url url 208 | * @param requestFormMap 键值对的form表单数据 209 | * @param header 键值对的自定义header 210 | * @return 211 | * @throws IOException 212 | */ 213 | public static String post(String url, Map requestFormMap, Map header) throws IOException { 214 | return post(url, RequestType.SYNC, requestFormMap, header, false); 215 | } 216 | 217 | /** 218 | * 发起post请求, 发送表单数据 219 | * 220 | * @param url url 221 | * @param json json数据 222 | * @return 223 | * @throws IOException 224 | */ 225 | public static String post(String url, String json) throws IOException { 226 | return post(url, RequestType.SYNC, json, null, false); 227 | } 228 | 229 | /** 230 | * 发起post请求, 发送表单数据 231 | * 232 | * @param url url 233 | * @param json json数据 234 | * @return 235 | * @throws IOException 236 | */ 237 | public static String post(String url, String json, boolean useProxy) throws IOException { 238 | return post(url, RequestType.SYNC, json, null, useProxy); 239 | } 240 | 241 | /** 242 | * 发起post请求 243 | * 244 | * @param requestType 同步请求还是异步请求 245 | * @param url url 246 | * @param requestFormMap 键值对形式的表单数据 247 | * @param header 请求头 248 | * @return 字符串 249 | */ 250 | public static String post(String url, RequestType requestType, Map requestFormMap, Map header, boolean useProxy) throws IOException { 251 | return stringPost(url, requestType, requestFormMap, header, useProxy); 252 | } 253 | 254 | /** 255 | * 发送post请求,获取字符数据 256 | * 257 | * @param url url 258 | * @param requestType 同步请求还是异步请求 259 | * @param json json数据 260 | * @param header 请求头 261 | * @return json字符串 262 | * @throws IOException IOException 263 | */ 264 | public static String post(String url, RequestType requestType, String json, Map header, boolean useProxy) throws IOException { 265 | return getString(url, requestType, json, header, RequestMethod.POST, useProxy); 266 | } 267 | 268 | /** 269 | * 发起put请求,获取字符数据 270 | * 271 | * @param url url 272 | * @param requestType 同步请求还是异步请求 273 | * @param json json数据 274 | * @param header 请求头 275 | * @return json字符串 276 | * @throws IOException IOException 277 | */ 278 | public static String put(String url, RequestType requestType, String json, Map header) throws IOException { 279 | return getString(url, requestType, json, header, RequestMethod.PUT, false); 280 | } 281 | 282 | /** 283 | * 发起delete请求,获取字符数据 284 | * 285 | * @param url 286 | * @param header 287 | * @return 288 | */ 289 | public static String delete(String url, Map header) { 290 | Request request = getRequest(url, header, RequestMethod.DELETE); 291 | return getString("", request); 292 | } 293 | 294 | /** 295 | * 发起get请求,获取字符数据 296 | * 297 | * @param url url 298 | * @param header 请求头 299 | * @return 字符串 300 | */ 301 | private static String stringGet(String url, Map header) { 302 | String result = ""; 303 | Request request = getRequest(url, header, RequestMethod.GET); 304 | return getString(result, request); 305 | } 306 | 307 | /** 308 | * 发起get请求,获取字符数据 309 | * 310 | * @param url url 311 | * @param header 请求头 312 | * @return 字符串 313 | */ 314 | private static String stringGet(String url, Map header, boolean useProxy) { 315 | String result = ""; 316 | Request request = getRequest(url, header, RequestMethod.GET); 317 | return getString(result, request, useProxy); 318 | } 319 | 320 | /** 321 | * 发起get请求,获取字符数据,携带json数据 322 | * 323 | * @param url url 324 | * @param json 需要携带的json数据 325 | * @param header 请求头 326 | * @return 字符串 327 | */ 328 | private static String stringGet(String url, String json, Map header) { 329 | String result = ""; 330 | RequestBody body = RequestBody.create(JSON, json); 331 | Request request = getRequest(url, header, body, RequestMethod.GET); 332 | return getString(result, request); 333 | } 334 | 335 | /** 336 | * get请求获取string数据 337 | * 338 | * @param result 339 | * @param request 340 | * @return 341 | */ 342 | private static String getString(String result, Request request) { 343 | try { 344 | Response response = mOkHttpClient.newCall(request).execute(); 345 | if (response.body() != null) { 346 | result = response.body().string(); 347 | } 348 | } catch (Exception e) { 349 | logger.error(e.toString()); 350 | } 351 | return result; 352 | } 353 | 354 | /** 355 | * get请求获取string数据 356 | * 357 | * @param result 358 | * @param request 359 | * @return 360 | */ 361 | private static String getString(String result, Request request, boolean useProxy) { 362 | try { 363 | Response response; 364 | if (useProxy) { 365 | response = mOkHttpClientUseProxy.newCall(request).execute(); 366 | } else { 367 | response = mOkHttpClient.newCall(request).execute(); 368 | } 369 | if (response.body() != null) { 370 | result = response.body().string(); 371 | } 372 | } catch (Exception e) { 373 | logger.error(e.toString()); 374 | } 375 | return result; 376 | } 377 | 378 | 379 | /** 380 | * 发起get请求,获取二进制数据 381 | * 382 | * @param url url 383 | * @param header header 384 | * @return InputStream 385 | */ 386 | private static InputStream streamGet(String url, Map header) { 387 | InputStream is = null; 388 | Request request = getRequest(url, header, RequestMethod.GET); 389 | try { 390 | Response response = mOkHttpClient.newCall(request).execute(); 391 | if (response.body() != null) { 392 | is = response.body().byteStream(); 393 | } 394 | } catch (Exception e) { 395 | logger.error(e.toString()); 396 | } 397 | return is; 398 | } 399 | 400 | /** 401 | * @param url url 402 | * @param header header 403 | * @return Request 404 | */ 405 | private static Request getRequest(String url, Map header, RequestMethod requestMethod) { 406 | Request request; 407 | if (header == null) { 408 | if (requestMethod == RequestMethod.DELETE) { 409 | request = new Request.Builder().url(url).delete().build(); 410 | } else { 411 | request = new Request.Builder().url(url).build(); 412 | } 413 | } else { 414 | Headers headerBuild = Headers.of(header); 415 | if (requestMethod == RequestMethod.DELETE) { 416 | request = new Request.Builder().url(url).delete().headers(headerBuild).build(); 417 | } else { 418 | request = new Request.Builder().url(url).headers(headerBuild).build(); 419 | 420 | } 421 | } 422 | return request; 423 | } 424 | 425 | /** 426 | * @param url url 427 | * @param header header 428 | * @param requestBody requestBody 429 | * @return Request 430 | */ 431 | private static Request getRequest(String url, Map header, RequestBody requestBody, RequestMethod requestMethod) { 432 | Request request; 433 | if (header == null) { 434 | if (requestMethod == RequestMethod.PUT) { 435 | request = new Request.Builder().url(url).put(requestBody).build(); 436 | } else if (requestMethod == RequestMethod.GET) { 437 | request = new Request.Builder().url(url).post(requestBody).build(); 438 | } else if (requestMethod == RequestMethod.POST) { 439 | request = new Request.Builder().url(url).post(requestBody).build(); 440 | } else { 441 | request = new Request.Builder().url(url).post(requestBody).build(); 442 | } 443 | } else { 444 | Headers headerBuild = Headers.of(header); 445 | if (requestMethod == RequestMethod.PUT) { 446 | request = new Request.Builder().url(url).put(requestBody).headers(headerBuild).build(); 447 | } else if (requestMethod == RequestMethod.GET) { 448 | request = new Request.Builder().url(url).post(requestBody).headers(headerBuild).build(); 449 | } else if (requestMethod == RequestMethod.POST) { 450 | request = new Request.Builder().url(url).post(requestBody).headers(headerBuild).build(); 451 | } else { 452 | request = new Request.Builder().url(url).post(requestBody).headers(headerBuild).build(); 453 | } 454 | } 455 | return request; 456 | } 457 | 458 | /** 459 | * 发送httppost请求,获取字符数据 460 | * 461 | * @param requestType 同步请求还是异步请求 462 | * @param url url 463 | * @param requestFormMap 键值对形式的数据 464 | * @param header 请求头 465 | * @return 字符串数据 466 | */ 467 | private static String stringPost(String url, RequestType requestType, Map requestFormMap, Map header, boolean useProxy) throws IOException { 468 | final String[] result = {""}; 469 | FormBody.Builder builder = new FormBody.Builder(); 470 | for (String key : requestFormMap.keySet()) { 471 | builder.add(key, requestFormMap.get(key)); 472 | } 473 | RequestBody requestBody = builder.build(); 474 | Request request = getRequest(url, header, requestBody, RequestMethod.POST); 475 | 476 | return getString(requestType, result, request, useProxy); 477 | } 478 | 479 | /** 480 | * 发送post请求,获取字符数据 481 | * 482 | * @param url url 483 | * @param requestType 同步请求还是异步请求 484 | * @param json json数据 485 | * @param header 请求头 486 | * @return json字符串 487 | * @throws IOException IOException 488 | */ 489 | private static String getString(String url, RequestType requestType, String json, Map header, RequestMethod requestMethod, boolean useProxy) throws IOException { 490 | final String[] result = {""}; 491 | RequestBody body = RequestBody.create(JSON, json); 492 | Request request = getRequest(url, header, body, requestMethod); 493 | 494 | return getString(requestType, result, request, useProxy); 495 | } 496 | 497 | /** 498 | * @param requestType 同步请求还是异步请求 499 | * @param result result 500 | * @param request request 501 | * @return 字符串 502 | * @throws IOException IOException 503 | */ 504 | private static String getString(RequestType requestType, final String[] result, Request request, boolean useProxy) throws IOException { 505 | switch (requestType) { 506 | //同步请求 507 | case SYNC: 508 | Response response; 509 | if (useProxy) { 510 | response = OkHttpUtils.getmOkHttpClientUseProxy().newCall(request).execute(); 511 | } else { 512 | response = OkHttpUtils.mOkHttpClient.newCall(request).execute(); 513 | } 514 | if (response.isSuccessful()) { 515 | if (response.body() != null) { 516 | result[0] = response.body().string(); 517 | } 518 | } else { 519 | int errorCode = response.code(); 520 | String message = ""; 521 | if (response.body() != null) { 522 | message = response.body().string(); 523 | } 524 | } 525 | break; 526 | //异步请求 527 | case ASYNC: 528 | Call call; 529 | if (useProxy) { 530 | call = OkHttpUtils.getmOkHttpClientUseProxy().newCall(request); 531 | } else { 532 | call = OkHttpUtils.mOkHttpClient.newCall(request); 533 | } 534 | call.enqueue(new Callback() { 535 | 536 | @Override 537 | public void onResponse(Call call, Response response) throws IOException { 538 | if (response.body() != null) { 539 | result[0] = response.body().string(); 540 | } else { 541 | int errorCode = response.code(); 542 | String message; 543 | if (response.body() != null) { 544 | message = response.body().string(); 545 | } 546 | } 547 | } 548 | 549 | @Override 550 | public void onFailure(Call call, IOException e) { 551 | logger.error(e.toString()); 552 | } 553 | }); 554 | break; 555 | default: 556 | result[0] = ""; 557 | break; 558 | } 559 | return result[0]; 560 | } 561 | } --------------------------------------------------------------------------------