Basis import

This commit is contained in:
feyris-tan 2026-04-26 21:28:28 +02:00
commit c2ad3fea05
32 changed files with 1614 additions and 0 deletions

38
.gitignore vendored Normal file
View File

@ -0,0 +1,38 @@
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### IntelliJ IDEA ###
.idea/modules.xml
.idea/jarRepositories.xml
.idea/compiler.xml
.idea/libraries/
*.iws
*.iml
*.ipr
### Eclipse ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/
### Mac OS ###
.DS_Store

7
.idea/encodings.xml generated Normal file
View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding">
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
</component>
</project>

14
.idea/misc.xml generated Normal file
View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="MavenProjectsManager">
<option name="originalFiles">
<list>
<option value="$PROJECT_DIR$/pom.xml" />
</list>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="corretto-17" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

6
.idea/sonarlint.xml generated Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="SonarLintProjectSettings">
<option name="bindingSuggestionsEnabled" value="false" />
</component>
</project>

124
.idea/uiDesigner.xml generated Normal file
View File

@ -0,0 +1,124 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Palette2">
<group name="Swing">
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
</item>
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
</item>
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.svg" removable="false" auto-create-binding="false" can-attach-label="true">
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
</item>
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
<initial-values>
<property name="text" value="Button" />
</initial-values>
</item>
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="RadioButton" />
</initial-values>
</item>
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="CheckBox" />
</initial-values>
</item>
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
<initial-values>
<property name="text" value="Label" />
</initial-values>
</item>
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
</item>
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
</item>
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
<preferred-size width="-1" height="20" />
</default-constraints>
</item>
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
</item>
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
</item>
</group>
</component>
</project>

6
.idea/vcs.xml generated Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

233
.idea/workspace.xml generated Normal file
View File

@ -0,0 +1,233 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AutoImportSettings">
<option name="autoReloadType" value="SELECTIVE" />
</component>
<component name="ChangeListManager">
<list default="true" id="37422155-9371-4ca2-b60a-3b633757b98b" name="Changes" comment="">
<change afterPath="$PROJECT_DIR$/.gitignore" afterDir="false" />
<change afterPath="$PROJECT_DIR$/.idea/encodings.xml" afterDir="false" />
<change afterPath="$PROJECT_DIR$/.idea/misc.xml" afterDir="false" />
<change afterPath="$PROJECT_DIR$/.idea/sonarlint.xml" afterDir="false" />
<change afterPath="$PROJECT_DIR$/.idea/uiDesigner.xml" afterDir="false" />
<change afterPath="$PROJECT_DIR$/.idea/vcs.xml" afterDir="false" />
<change afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change afterPath="$PROJECT_DIR$/pom.xml" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/main/java/moe/yo3explorer/dustspeck2/business/nuget/boundary/Dustspeck2Context.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/main/java/moe/yo3explorer/dustspeck2/business/nuget/boundary/IconService.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/main/java/moe/yo3explorer/dustspeck2/business/nuget/boundary/PackageBaseAddressService.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/main/java/moe/yo3explorer/dustspeck2/business/nuget/boundary/ReadmeUriTemplateService.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/main/java/moe/yo3explorer/dustspeck2/business/nuget/boundary/RegistrationsBaseUrlService.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/main/java/moe/yo3explorer/dustspeck2/business/nuget/boundary/SearchQueryService.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/main/java/moe/yo3explorer/dustspeck2/business/nuget/boundary/VersionPageService.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/main/java/moe/yo3explorer/dustspeck2/business/nuget/boundary/VulnerabilityBaseService.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/main/java/moe/yo3explorer/dustspeck2/business/nuget/boundary/VulnerabilityInfoService.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/main/java/moe/yo3explorer/dustspeck2/business/nuget/control/DataDirectoryNotConfiguredException.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/main/java/moe/yo3explorer/dustspeck2/business/nuget/control/FileStorage.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/main/java/moe/yo3explorer/dustspeck2/business/nuget/control/FileStorageAlreadyWorkingException.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/main/java/moe/yo3explorer/dustspeck2/business/nuget/control/HttpClient.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/main/java/moe/yo3explorer/dustspeck2/business/nuget/control/InternetConnectionChecker.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/main/java/moe/yo3explorer/dustspeck2/presentation/Dustspeck2HttpHandler.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/main/java/moe/yo3explorer/dustspeck2/presentation/Dustspeck2Service.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/main/java/moe/yo3explorer/dustspeck2/presentation/EnvironmentVariableMissingException.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/main/java/moe/yo3explorer/dustspeck2/presentation/Main.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/main/java/moe/yo3explorer/dustspeck2/presentation/ResourceService.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/main/java/moe/yo3explorer/dustspeck2/presentation/RootRedirectService.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/main/resources/META-INF/services/moe.yo3explorer.dustspeck2.presentation.Dustspeck2Service" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/main/resources/favicon.ico" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/main/resources/log4j2.xml" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="FileTemplateManagerImpl">
<option name="RECENT_TEMPLATES">
<list>
<option value="Interface" />
<option value="Class" />
</list>
</option>
</component>
<component name="Git.Settings">
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
</component>
<component name="MarkdownSettingsMigration">
<option name="stateVersion" value="1" />
</component>
<component name="MavenImportPreferences">
<option name="importingSettings">
<MavenImportingSettings>
<option name="workspaceImportEnabled" value="true" />
</MavenImportingSettings>
</option>
</component>
<component name="ProjectId" id="3CtYloVoQ7wNkfpGz8zLWOVFrsn" />
<component name="ProjectLevelVcsManager" settingsEditedManually="true" />
<component name="ProjectViewState">
<option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" />
</component>
<component name="PropertiesComponent"><![CDATA[{
"keyToString": {
"RunOnceActivity.OpenProjectViewOnStart": "true",
"RunOnceActivity.ShowReadmeOnStart": "true",
"SHARE_PROJECT_CONFIGURATION_FILES": "true",
"WebServerToolWindowFactoryState": "false",
"last_directory_selection": "C:/Users/Sascha Schiemann/IdeaProjects/dustspeck2/src/main/java/moe/yo3explorer",
"last_opened_file_path": "C:/Users/Sascha Schiemann/IdeaProjects/dustspeck2/src/main/resources",
"node.js.detected.package.eslint": "true",
"node.js.detected.package.tslint": "true",
"node.js.selected.package.eslint": "(autodetect)",
"node.js.selected.package.tslint": "(autodetect)",
"nodejs_package_manager_path": "npm",
"vue.rearranger.settings.migration": "true"
}
}]]></component>
<component name="RecentsManager">
<key name="CreateClassDialog.RecentsKey">
<recent name="moe.yo3explorer.dustspeck2.business.nuget.boundary" />
<recent name="moe.yo3explorer.dustspeck2.presentation" />
</key>
<key name="CopyFile.RECENT_KEYS">
<recent name="C:\Users\Sascha Schiemann\IdeaProjects\dustspeck2\src\main\resources" />
</key>
<key name="MoveFile.RECENT_KEYS">
<recent name="C:\Users\Sascha Schiemann\IdeaProjects\dustspeck2\src\main\java\moe\yo3explorer\dustspeck2\business\nuget\control" />
</key>
</component>
<component name="RunManager">
<configuration name="Main" type="Application" factoryName="Application" nameIsGenerated="true">
<envs>
<env name="DATA_DIRECTORY" value="C:\Temp\nuget" />
</envs>
<option name="MAIN_CLASS_NAME" value="moe.yo3explorer.dustspeck2.presentation.Main" />
<module name="dustspeck2" />
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
</component>
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
<component name="TaskManager">
<task active="true" id="Default" summary="Default task">
<changelist id="37422155-9371-4ca2-b60a-3b633757b98b" name="Changes" comment="" />
<created>1777206490693</created>
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1777206490693</updated>
<workItem from="1777206492029" duration="17811000" />
</task>
<servers />
</component>
<component name="TypeScriptGeneratedFilesManager">
<option name="version" value="3" />
</component>
<component name="XDebuggerManager">
<breakpoint-manager>
<breakpoints>
<line-breakpoint enabled="true" type="java-line">
<url>file://$PROJECT_DIR$/src/main/java/moe/yo3explorer/dustspeck2/business/nuget/boundary/RegistrationsBaseUrlService.java</url>
<line>44</line>
<option name="timeStamp" value="24" />
</line-breakpoint>
<line-breakpoint enabled="true" type="java-line">
<url>file://$PROJECT_DIR$/src/main/java/moe/yo3explorer/dustspeck2/business/nuget/boundary/ReadmeUriTemplateService.java</url>
<line>41</line>
<option name="timeStamp" value="29" />
</line-breakpoint>
<line-breakpoint enabled="true" type="java-line">
<url>file://$PROJECT_DIR$/src/main/java/moe/yo3explorer/dustspeck2/presentation/Dustspeck2HttpHandler.java</url>
<line>50</line>
<option name="timeStamp" value="31" />
</line-breakpoint>
<line-breakpoint enabled="true" type="java-line">
<url>file://$PROJECT_DIR$/src/main/java/moe/yo3explorer/dustspeck2/business/nuget/boundary/VulnerabilityInfoService.java</url>
<line>41</line>
<option name="timeStamp" value="34" />
</line-breakpoint>
<line-breakpoint enabled="true" type="java-line">
<url>file://$PROJECT_DIR$/src/main/java/moe/yo3explorer/dustspeck2/business/nuget/boundary/SearchQueryService.java</url>
<line>40</line>
<option name="timeStamp" value="41" />
</line-breakpoint>
<line-breakpoint enabled="true" type="java-line">
<url>file://$PROJECT_DIR$/src/main/java/moe/yo3explorer/dustspeck2/business/nuget/boundary/VersionPageService.java</url>
<line>43</line>
<option name="timeStamp" value="56" />
</line-breakpoint>
<line-breakpoint enabled="true" type="java-line">
<url>file://$PROJECT_DIR$/src/main/java/moe/yo3explorer/dustspeck2/business/nuget/boundary/VersionPageService.java</url>
<line>30</line>
<option name="timeStamp" value="57" />
</line-breakpoint>
<line-breakpoint enabled="true" type="java-line">
<url>file://$PROJECT_DIR$/src/main/java/moe/yo3explorer/dustspeck2/business/nuget/boundary/VersionPageService.java</url>
<line>33</line>
<option name="timeStamp" value="63" />
</line-breakpoint>
<line-breakpoint enabled="true" type="java-line">
<url>file://$PROJECT_DIR$/src/main/java/moe/yo3explorer/dustspeck2/business/nuget/boundary/VersionPageService.java</url>
<line>35</line>
<option name="timeStamp" value="64" />
</line-breakpoint>
<line-breakpoint enabled="true" type="java-line">
<url>file://$PROJECT_DIR$/src/main/java/moe/yo3explorer/dustspeck2/business/nuget/boundary/PackageBaseAddressService.java</url>
<line>32</line>
<option name="timeStamp" value="70" />
</line-breakpoint>
<line-breakpoint enabled="true" type="java-line">
<url>file://$PROJECT_DIR$/src/main/java/moe/yo3explorer/dustspeck2/business/nuget/boundary/PackageBaseAddressService.java</url>
<line>35</line>
<option name="timeStamp" value="71" />
</line-breakpoint>
<line-breakpoint enabled="true" type="java-line">
<url>file://$PROJECT_DIR$/src/main/java/moe/yo3explorer/dustspeck2/business/nuget/boundary/PackageBaseAddressService.java</url>
<line>37</line>
<option name="timeStamp" value="72" />
</line-breakpoint>
<line-breakpoint enabled="true" type="java-line">
<url>file://$PROJECT_DIR$/src/main/java/moe/yo3explorer/dustspeck2/business/nuget/boundary/PackageBaseAddressService.java</url>
<line>45</line>
<option name="timeStamp" value="73" />
</line-breakpoint>
<line-breakpoint enabled="true" type="java-line">
<url>file://$PROJECT_DIR$/src/main/java/moe/yo3explorer/dustspeck2/business/nuget/boundary/VulnerabilityBaseService.java</url>
<line>43</line>
<option name="timeStamp" value="83" />
</line-breakpoint>
<line-breakpoint enabled="true" type="java-line">
<url>file://$PROJECT_DIR$/src/main/java/moe/yo3explorer/dustspeck2/business/nuget/boundary/IconService.java</url>
<line>30</line>
<option name="timeStamp" value="89" />
</line-breakpoint>
<line-breakpoint enabled="true" type="java-line">
<url>file://$PROJECT_DIR$/src/main/java/moe/yo3explorer/dustspeck2/business/nuget/boundary/IconService.java</url>
<line>33</line>
<option name="timeStamp" value="90" />
</line-breakpoint>
<line-breakpoint enabled="true" type="java-line">
<url>file://$PROJECT_DIR$/src/main/java/moe/yo3explorer/dustspeck2/business/nuget/boundary/IconService.java</url>
<line>35</line>
<option name="timeStamp" value="91" />
</line-breakpoint>
<line-breakpoint enabled="true" type="java-line">
<url>file://$PROJECT_DIR$/src/main/java/moe/yo3explorer/dustspeck2/business/nuget/boundary/IconService.java</url>
<line>43</line>
<option name="timeStamp" value="92" />
</line-breakpoint>
<line-breakpoint enabled="true" type="java-line">
<url>file://$PROJECT_DIR$/src/main/java/moe/yo3explorer/dustspeck2/business/nuget/boundary/IconService.java</url>
<line>53</line>
<option name="timeStamp" value="94" />
</line-breakpoint>
<line-breakpoint enabled="true" type="java-line">
<url>file://$PROJECT_DIR$/src/main/java/moe/yo3explorer/dustspeck2/business/nuget/boundary/VulnerabilityInfoService.java</url>
<line>31</line>
<option name="timeStamp" value="103" />
</line-breakpoint>
</breakpoints>
</breakpoint-manager>
</component>
</project>

42
pom.xml Normal file
View File

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>moe.yo3explorer</groupId>
<artifactId>dustspeck2</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>io.undertow</groupId>
<artifactId>undertow-core</artifactId>
<version>2.1.0.Final</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.24.1</version>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.12.0</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.17.0</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,91 @@
package moe.yo3explorer.dustspeck2.business.nuget.boundary;
import moe.yo3explorer.dustspeck2.business.nuget.control.*;
import org.apache.commons.io.IOUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
public class Dustspeck2Context
{
private static Dustspeck2Context _instance;
private static Logger logger;
private String dataDirectory;
private Dustspeck2Context()
{
logger = LogManager.getLogger(Dustspeck2Context.class);
logger.info("Built context!");
}
public static Dustspeck2Context getInstance()
{
if (_instance == null)
{
_instance = new Dustspeck2Context();
}
return _instance;
}
public void setDataDirectory(String dataDirectory)
{
if (fileStorage != null)
throw new FileStorageAlreadyWorkingException();
this.dataDirectory = dataDirectory;
}
private FileStorage fileStorage;
public synchronized FileStorage getFileStorage() throws IOException
{
if (this.dataDirectory == null)
throw new DataDirectoryNotConfiguredException();
if (fileStorage == null)
{
fileStorage = new FileStorage(dataDirectory);
}
return fileStorage;
}
private HttpClient httpClient;
public synchronized HttpClient getHttpClient()
{
if (httpClient == null)
httpClient = new HttpClient();
return httpClient;
}
private boolean internetConnectionChecked;
private boolean isOffline;
public synchronized boolean isOffline()
{
if (!internetConnectionChecked)
{
isOffline = !InternetConnectionChecker.checkInternetConnection();
internetConnectionChecked = true;
}
return isOffline;
}
@NotNull
public byte[] patchJson(byte[] input, String newServer)
{
String sourceJson = IOUtils.toString(input, String.valueOf(StandardCharsets.UTF_8));
sourceJson = sourceJson.replace("https://api.nuget.org/","http://" + newServer + "/");
return sourceJson.getBytes(StandardCharsets.UTF_8);
}
public String guessMimeType(@NotNull String fname)
{
if (fname.endsWith(".nupkg"))
return "application/x-nupkg";
else if (fname.endsWith(".json"))
return "application/json";
else
return "octet/stream";
}
}

View File

@ -0,0 +1,60 @@
package moe.yo3explorer.dustspeck2.business.nuget.boundary;
import io.undertow.server.HttpServerExchange;
import io.undertow.util.HttpString;
import moe.yo3explorer.dustspeck2.business.nuget.control.FileStorage;
import moe.yo3explorer.dustspeck2.business.nuget.control.HttpClient;
import moe.yo3explorer.dustspeck2.presentation.Dustspeck2Service;
import java.io.IOException;
import java.nio.ByteBuffer;
public class IconService implements Dustspeck2Service
{
@Override
public boolean canHandle(String s)
{
return s.startsWith("/v3-flatcontainer/");
}
@Override
public void handleRequest(String queryString, String[] vines, HttpServerExchange httpServerExchange) throws IOException
{
String originalUrl = "https://api.nuget.org" + queryString;
Dustspeck2Context dustspeck2 = Dustspeck2Context.getInstance();
String mime = dustspeck2.guessMimeType(queryString);
String onDiskFilename = queryString;
FileStorage fileStorage = dustspeck2.getFileStorage();
if (fileStorage.testForFile(onDiskFilename))
{
byte[] buffer = fileStorage.getFile(queryString);
if (queryString.endsWith(".json"))
{
buffer = dustspeck2.patchJson(buffer, httpServerExchange.getHostAndPort());
}
httpServerExchange.setStatusCode(200);
httpServerExchange.getResponseHeaders().put(HttpString.tryFromString("Content-Type"),mime);
httpServerExchange.getResponseSender().send(ByteBuffer.wrap(buffer));
return;
}
if (dustspeck2.isOffline())
{
httpServerExchange.setStatusCode(404);
httpServerExchange.getResponseSender().send("");
return;
}
HttpClient httpClient = dustspeck2.getHttpClient();
byte[] file = httpClient.getFile(originalUrl);
fileStorage.writeFile(queryString, file);
if (queryString.endsWith(".json"))
{
file = dustspeck2.patchJson(file, httpServerExchange.getHostAndPort());
}
httpServerExchange.setStatusCode(200);
httpServerExchange.getResponseHeaders().put(HttpString.tryFromString("Content-Type"),mime);
httpServerExchange.getResponseSender().send(ByteBuffer.wrap(file));
}
}

View File

@ -0,0 +1,62 @@
package moe.yo3explorer.dustspeck2.business.nuget.boundary;
import io.undertow.server.HttpServerExchange;
import io.undertow.util.HttpString;
import moe.yo3explorer.dustspeck2.business.nuget.control.FileStorage;
import moe.yo3explorer.dustspeck2.business.nuget.control.HttpClient;
import moe.yo3explorer.dustspeck2.presentation.Dustspeck2Service;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
import java.nio.ByteBuffer;
public class PackageBaseAddressService implements Dustspeck2Service
{
@Override
public boolean canHandle(@NotNull String s)
{
return s.startsWith("/PackageBaseAddress/v3-flatcontainer");
}
@Override
public void handleRequest(@NotNull String queryString, String[] vines, HttpServerExchange httpServerExchange) throws IOException
{
String originalUrl = queryString.replace("/PackageBaseAddress","");
originalUrl = "https://api.nuget.org" + originalUrl;;
Dustspeck2Context dustspeck2 = Dustspeck2Context.getInstance();
String mime = dustspeck2.guessMimeType(queryString);
String onDiskFilename = queryString.replace("/PackageBaseAddress","");
FileStorage fileStorage = dustspeck2.getFileStorage();
if (fileStorage.testForFile(onDiskFilename))
{
byte[] buffer = fileStorage.getFile(onDiskFilename);
if (queryString.endsWith(".json"))
{
buffer = dustspeck2.patchJson(buffer, httpServerExchange.getHostAndPort());
}
httpServerExchange.setStatusCode(200);
httpServerExchange.getResponseHeaders().put(HttpString.tryFromString("Content-Type"),mime);
httpServerExchange.getResponseSender().send(ByteBuffer.wrap(buffer));
return;
}
if (dustspeck2.isOffline())
{
httpServerExchange.setStatusCode(404);
httpServerExchange.getResponseSender().send("");
return;
}
HttpClient httpClient = dustspeck2.getHttpClient();
byte[] file = httpClient.getFile(originalUrl);
fileStorage.writeFile(onDiskFilename, file);
if (queryString.endsWith(".json"))
{
file = dustspeck2.patchJson(file, httpServerExchange.getHostAndPort());
}
httpServerExchange.setStatusCode(200);
httpServerExchange.getResponseHeaders().put(HttpString.tryFromString("Content-Type"),mime);
httpServerExchange.getResponseSender().send(ByteBuffer.wrap(file));
}
}

View File

@ -0,0 +1,54 @@
package moe.yo3explorer.dustspeck2.business.nuget.boundary;
import io.undertow.server.HttpServerExchange;
import io.undertow.util.HttpString;
import moe.yo3explorer.dustspeck2.business.nuget.control.FileStorage;
import moe.yo3explorer.dustspeck2.business.nuget.control.HttpClient;
import moe.yo3explorer.dustspeck2.presentation.Dustspeck2Service;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
import java.nio.ByteBuffer;
public class ReadmeUriTemplateService implements Dustspeck2Service
{
@Override
public boolean canHandle(@NotNull String s)
{
return s.startsWith("/ReadmeUriTemplate/v3-flatcontainer/") && s.endsWith("/readme");
}
@Override
public void handleRequest(String queryString, @NotNull String[] vines, HttpServerExchange httpServerExchange) throws IOException
{
String readme = vines[vines.length - 1];
String version = vines[vines.length - 2];
String packageName = vines[vines.length - 3];
String liveUrl = String.format("https://api.nuget.org/v3-flatcontainer/%s/%s/%s",packageName,version,readme);
Dustspeck2Context dustspeck2 = Dustspeck2Context.getInstance();
FileStorage fileStorage = dustspeck2.getFileStorage();
if (fileStorage.testForFile(queryString))
{
byte[] buffer = fileStorage.getFile(queryString);
httpServerExchange.setStatusCode(200);
httpServerExchange.getResponseHeaders().put(HttpString.tryFromString("Content-Type"),"text/plain");
httpServerExchange.getResponseSender().send(ByteBuffer.wrap(buffer));
return;
}
if (dustspeck2.isOffline())
{
httpServerExchange.setStatusCode(404);
httpServerExchange.getResponseSender().send("");
return;
}
HttpClient httpClient = dustspeck2.getHttpClient();
byte[] file = httpClient.getFile(liveUrl);
fileStorage.writeFile(queryString, file);
httpServerExchange.setStatusCode(200);
httpServerExchange.getResponseHeaders().put(HttpString.tryFromString("Content-Type"),"text/plain");
httpServerExchange.getResponseSender().send(ByteBuffer.wrap(file));
}
}

View File

@ -0,0 +1,58 @@
package moe.yo3explorer.dustspeck2.business.nuget.boundary;
import io.undertow.server.HttpServerExchange;
import io.undertow.util.HttpString;
import moe.yo3explorer.dustspeck2.business.nuget.control.FileStorage;
import moe.yo3explorer.dustspeck2.business.nuget.control.HttpClient;
import moe.yo3explorer.dustspeck2.presentation.Dustspeck2Service;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
import java.nio.ByteBuffer;
public class RegistrationsBaseUrlService implements Dustspeck2Service
{
@Override
public boolean canHandle(@NotNull String s)
{
if (!s.endsWith(".json"))
return false;
return s.startsWith("/RegistrationsBaseUrl/v3/registration5-gz-semver2/");
}
@Override
public void handleRequest(String queryString, @NotNull String[] vines, HttpServerExchange httpServerExchange) throws IOException
{
String indexName = vines[vines.length - 1];
String packageName = vines[vines.length - 2];
String onDiskFilename = queryString.replace("/RegistrationsBaseUrl","");
Dustspeck2Context dustspeck2 = Dustspeck2Context.getInstance();
FileStorage fileStorage = dustspeck2.getFileStorage();
if (fileStorage.testForFile(onDiskFilename))
{
byte[] buffer = fileStorage.getFile(onDiskFilename);
buffer = dustspeck2.patchJson(buffer,httpServerExchange.getHostAndPort());
httpServerExchange.setStatusCode(200);
httpServerExchange.getResponseHeaders().put(HttpString.tryFromString("Content-Type"),"application/json");
httpServerExchange.getResponseSender().send(ByteBuffer.wrap(buffer));
return;
}
if (dustspeck2.isOffline())
{
httpServerExchange.setStatusCode(404);
httpServerExchange.getResponseSender().send("");
return;
}
HttpClient httpClient = dustspeck2.getHttpClient();
byte[] file = httpClient.getFile(String.format("https://api.nuget.org/v3/registration5-gz-semver2/%s/%s", packageName, indexName));
fileStorage.writeFile(onDiskFilename, file);
file = dustspeck2.patchJson(file,httpServerExchange.getHostAndPort());
httpServerExchange.setStatusCode(200);
httpServerExchange.getResponseHeaders().put(HttpString.tryFromString("Content-Type"),"application/json");
httpServerExchange.getResponseSender().send(ByteBuffer.wrap(file));
}
}

View File

@ -0,0 +1,53 @@
package moe.yo3explorer.dustspeck2.business.nuget.boundary;
import io.undertow.server.HttpServerExchange;
import io.undertow.util.HttpString;
import moe.yo3explorer.dustspeck2.business.nuget.control.FileStorage;
import moe.yo3explorer.dustspeck2.business.nuget.control.HttpClient;
import moe.yo3explorer.dustspeck2.presentation.Dustspeck2HttpHandler;
import moe.yo3explorer.dustspeck2.presentation.Dustspeck2Service;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
import java.nio.ByteBuffer;
public class SearchQueryService implements Dustspeck2Service
{
@Override
public boolean canHandle(@NotNull String s)
{
return s.equals("/SearchQueryService/query");
}
@Override
public void handleRequest(String queryString, String[] vines, @NotNull HttpServerExchange httpServerExchange) throws IOException
{
String filename = queryString + "/" + httpServerExchange.getQueryString();
Dustspeck2Context dustspeck2 = Dustspeck2Context.getInstance();
FileStorage fileStorage = dustspeck2.getFileStorage();
if (fileStorage.testForFile(filename))
{
byte[] buffer = fileStorage.getFile(filename);
buffer = dustspeck2.patchJson(buffer,httpServerExchange.getHostAndPort());
httpServerExchange.setStatusCode(200);
httpServerExchange.getResponseHeaders().put(HttpString.tryFromString("Content-Type"),"application/json");
httpServerExchange.getResponseSender().send(ByteBuffer.wrap(buffer));
return;
}
if (dustspeck2.isOffline())
{
httpServerExchange.setStatusCode(404);
return;
}
HttpClient httpClient = dustspeck2.getHttpClient();
byte[] buffer = httpClient.getFile("https://azuresearch-usnc.nuget.org/query", httpServerExchange.getQueryString());
fileStorage.writeFile(filename,buffer);
buffer = dustspeck2.patchJson(buffer,httpServerExchange.getHostAndPort());
httpServerExchange.setStatusCode(200);
httpServerExchange.getResponseHeaders().put(HttpString.tryFromString("Content-Type"),"application/json");
httpServerExchange.getResponseSender().send(ByteBuffer.wrap(buffer));
}
}

View File

@ -0,0 +1,62 @@
package moe.yo3explorer.dustspeck2.business.nuget.boundary;
import io.undertow.server.HttpServerExchange;
import io.undertow.util.HttpString;
import moe.yo3explorer.dustspeck2.business.nuget.control.FileStorage;
import moe.yo3explorer.dustspeck2.business.nuget.control.HttpClient;
import moe.yo3explorer.dustspeck2.presentation.Dustspeck2Service;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
import java.nio.ByteBuffer;
public class VersionPageService implements Dustspeck2Service
{
@Override
public boolean canHandle(@NotNull String s)
{
return s.startsWith("/v3/registration5-gz-semver2/");
}
@Override
public void handleRequest(String queryString, String[] vines, HttpServerExchange httpServerExchange) throws IOException
{
String onDiskFilename = String.format("RegistrationsBaseUrl/%s",queryString);
Dustspeck2Context dustspeck2 = Dustspeck2Context.getInstance();
String mime = dustspeck2.guessMimeType(queryString);
FileStorage fileStorage = dustspeck2.getFileStorage();
if (fileStorage.testForFile(onDiskFilename))
{
byte[] buffer = fileStorage.getFile(queryString);
if (queryString.endsWith(".json"))
{
buffer = dustspeck2.patchJson(buffer, httpServerExchange.getHostAndPort());
}
httpServerExchange.setStatusCode(200);
httpServerExchange.getResponseHeaders().put(HttpString.tryFromString("Content-Type"),mime);
httpServerExchange.getResponseSender().send(ByteBuffer.wrap(buffer));
return;
}
if (dustspeck2.isOffline())
{
httpServerExchange.setStatusCode(404);
httpServerExchange.getResponseSender().send("");
return;
}
HttpClient httpClient = dustspeck2.getHttpClient();
byte[] file = httpClient.getFile(String.format("https://api.nuget.org/%s",queryString));
fileStorage.writeFile(queryString, file);
if (queryString.endsWith(".json"))
{
file = dustspeck2.patchJson(file, httpServerExchange.getHostAndPort());
}
httpServerExchange.setStatusCode(200);
httpServerExchange.getResponseHeaders().put(HttpString.tryFromString("Content-Type"),mime);
httpServerExchange.getResponseSender().send(ByteBuffer.wrap(file));
}
}

View File

@ -0,0 +1,60 @@
package moe.yo3explorer.dustspeck2.business.nuget.boundary;
import io.undertow.server.HttpServerExchange;
import io.undertow.util.HttpString;
import moe.yo3explorer.dustspeck2.business.nuget.control.FileStorage;
import moe.yo3explorer.dustspeck2.business.nuget.control.HttpClient;
import moe.yo3explorer.dustspeck2.presentation.Dustspeck2Service;
import java.io.IOException;
import java.nio.ByteBuffer;
public class VulnerabilityBaseService implements Dustspeck2Service
{
@Override
public boolean canHandle(String s)
{
return s.startsWith("/v3-vulnerabilities/");
}
@Override
public void handleRequest(String queryString, String[] vines, HttpServerExchange httpServerExchange) throws IOException
{
String originalUrl = "https://api.nuget.org" + queryString;
Dustspeck2Context dustspeck2 = Dustspeck2Context.getInstance();
String mime = dustspeck2.guessMimeType(queryString);
String onDiskFilename = queryString;
FileStorage fileStorage = dustspeck2.getFileStorage();
if (fileStorage.testForFile(onDiskFilename))
{
byte[] buffer = fileStorage.getFile(queryString);
if (queryString.endsWith(".json"))
{
buffer = dustspeck2.patchJson(buffer, httpServerExchange.getHostAndPort());
}
httpServerExchange.setStatusCode(200);
httpServerExchange.getResponseHeaders().put(HttpString.tryFromString("Content-Type"),mime);
httpServerExchange.getResponseSender().send(ByteBuffer.wrap(buffer));
return;
}
if (dustspeck2.isOffline())
{
httpServerExchange.setStatusCode(404);
httpServerExchange.getResponseSender().send("");
return;
}
HttpClient httpClient = dustspeck2.getHttpClient();
byte[] file = httpClient.getFile(originalUrl);
fileStorage.writeFile(queryString, file);
if (queryString.endsWith(".json"))
{
file = dustspeck2.patchJson(file, httpServerExchange.getHostAndPort());
}
httpServerExchange.setStatusCode(200);
httpServerExchange.getResponseHeaders().put(HttpString.tryFromString("Content-Type"),mime);
httpServerExchange.getResponseSender().send(ByteBuffer.wrap(file));
}
}

View File

@ -0,0 +1,57 @@
package moe.yo3explorer.dustspeck2.business.nuget.boundary;
import io.undertow.server.HttpServerExchange;
import io.undertow.util.HttpString;
import moe.yo3explorer.dustspeck2.business.nuget.control.FileStorage;
import moe.yo3explorer.dustspeck2.business.nuget.control.HttpClient;
import moe.yo3explorer.dustspeck2.presentation.Dustspeck2Service;
import org.apache.commons.io.IOUtils;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
public class VulnerabilityInfoService implements Dustspeck2Service
{
@Override
public boolean canHandle(@NotNull String s)
{
return s.equals("/VulnerabilityInfo/v3/vulnerabilities/index.json");
}
@Override
public void handleRequest(String queryString, String[] vines, HttpServerExchange httpServerExchange) throws IOException
{
String onDiskFilename = queryString.replace("/VulnerabilityInfo/","");
Dustspeck2Context dustspeck2 = Dustspeck2Context.getInstance();
FileStorage fileStorage = dustspeck2.getFileStorage();
if (fileStorage.testForFile(onDiskFilename))
{
byte[] buffer = fileStorage.getFile(onDiskFilename);
buffer = dustspeck2.patchJson(buffer,httpServerExchange.getHostAndPort());
httpServerExchange.setStatusCode(200);
httpServerExchange.getResponseHeaders().put(HttpString.tryFromString("Content-Type"),"application/json");
httpServerExchange.getResponseSender().send(ByteBuffer.wrap(buffer));
return;
}
if (dustspeck2.isOffline())
{
httpServerExchange.setStatusCode(404);
httpServerExchange.getResponseSender().send("");
return;
}
HttpClient httpClient = dustspeck2.getHttpClient();
byte[] file = httpClient.getFile("https://api.nuget.org/v3/vulnerabilities/index.json");
fileStorage.writeFile(onDiskFilename, file);
file = dustspeck2.patchJson(file,httpServerExchange.getHostAndPort());
httpServerExchange.setStatusCode(200);
httpServerExchange.getResponseHeaders().put(HttpString.tryFromString("Content-Type"),"application/json");
httpServerExchange.getResponseSender().send(ByteBuffer.wrap(file));
}
}

View File

@ -0,0 +1,5 @@
package moe.yo3explorer.dustspeck2.business.nuget.control;
public class DataDirectoryNotConfiguredException extends RuntimeException
{
}

View File

@ -0,0 +1,58 @@
package moe.yo3explorer.dustspeck2.business.nuget.control;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
public class FileStorage
{
private final Path outdirAsPath;
private final String outdirAsString;
private final File outdirAsFile;
private final Logger logger;
public FileStorage(String dataDirectory) throws IOException
{
logger = LogManager.getLogger(getClass());
logger.info("Initialized File Storage");
outdirAsString = dataDirectory;
outdirAsPath = Path.of(dataDirectory);
outdirAsFile = outdirAsPath.toFile();
if (!outdirAsFile.isDirectory())
{
Files.createDirectories(outdirAsPath);
logger.info(String.format("Created directory: %s", dataDirectory));
}
}
public boolean testForFile(String queryString)
{
Path path = Paths.get(outdirAsString,queryString);
File file = path.toFile();
return file.isFile();
}
public byte[] getFile(String queryString) throws IOException
{
Path path = Paths.get(outdirAsString,queryString);
FileInputStream fis = new FileInputStream(path.toFile());
byte[] result = fis.readAllBytes();
fis.close();
return result;
}
public void writeFile(String queryString, byte[] file) throws IOException
{
Path path = Paths.get(outdirAsString,queryString);
Files.createDirectories(path.getParent());
Files.write(path,file);
}
}

View File

@ -0,0 +1,5 @@
package moe.yo3explorer.dustspeck2.business.nuget.control;
public class FileStorageAlreadyWorkingException extends RuntimeException
{
}

View File

@ -0,0 +1,36 @@
package moe.yo3explorer.dustspeck2.business.nuget.control;
import okhttp3.Call;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import java.io.IOException;
public class HttpClient
{
private final OkHttpClient client;
public HttpClient()
{
this.client = new OkHttpClient();
}
public byte[] getFile(String path) throws IOException
{
Request request = new Request.Builder()
.url(path)
.build();
Call call = client.newCall(request);
Response response = call.execute();
byte[] bytes = response.body().bytes();
return bytes;
}
public byte[] getFile(String path, String queryString) throws IOException
{
String newPath = String.format("%s?%s",path,queryString);
return getFile(newPath);
}
}

View File

@ -0,0 +1,67 @@
package moe.yo3explorer.dustspeck2.business.nuget.control;
import okhttp3.Call;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.io.IOException;
import java.util.Random;
public class InternetConnectionChecker
{
private InternetConnectionChecker() {}
public static boolean checkInternetConnection()
{
Logger logger = LogManager.getLogger(InternetConnectionChecker.class);
String[] sites = new String[]
{
"http://www.google.com", "http://www.youtube.com", "http://www.amazon.com",
"http://www.archive.org", "http://store.steampowered.com", "http://www.microsoft.com",
"http://www.apple.com", "http://www.facebook.com", "http://www.nintendo.co.jp",
"http://www.sony.co.jp", "http://www.discord.com", "http://www.netflix.com",
"http://www.spotify.com", "http://www.vw.de", "http://www.nestle.com", "http://www.disney.com",
"http://www.toyota.co.jp", "http://www.bp.com", "http://www.shell.com", "http://www.basf.de",
"http://www.siemens.de", "http://www.boeing.com", "http://www.ibm.com", "http://www.axa.fr",
"http://www.bahn.de", "http://www.intel.com", "http://www.samsung.com", "http://www.tesla.com",
"http://de.wikipedia.org", "http://www.debian.org", "http://www.sega.co.jp",
"http://www.nuget.org/", "http://www.github.com", "http://www.msftconnecttest.com/ncsi.txt"
};
int fails = 0;
OkHttpClient client = new OkHttpClient();
Random rng = new Random();
while (true)
{
String site = sites[rng.nextInt(sites.length)];
Request request = new Request.Builder()
.url(site)
.build();
try
{
Call call = client.newCall(request);
Response execute = call.execute();
int code = execute.code();
logger.info(String.format("GET %s returned %d, so I'm gonna assume I have internet.",site,code));
execute.close();
return true;
}
catch (Throwable t)
{
fails++;
}
if (fails >= 3)
{
logger.info("Could not verify the internet connection, so I'm gonna assume I'm offline.");
return false;
}
}
}
}

View File

@ -0,0 +1,55 @@
package moe.yo3explorer.dustspeck2.presentation;
import io.undertow.server.HttpHandler;
import io.undertow.server.HttpServerExchange;
import io.undertow.util.HttpString;
import moe.yo3explorer.dustspeck2.business.nuget.boundary.Dustspeck2Context;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.jetbrains.annotations.NotNull;
import java.util.List;
import java.util.ServiceLoader;
public class Dustspeck2HttpHandler implements HttpHandler
{
private static Logger logger;
private final List<Dustspeck2Service> services;
public Dustspeck2HttpHandler()
{
if (logger == null)
{
logger = LogManager.getLogger(getClass());
logger.info("Loaded the HTTP handler.");
}
ServiceLoader<Dustspeck2Service> loader = ServiceLoader.load(Dustspeck2Service.class);
services = loader.stream().map(ServiceLoader.Provider::get).toList();
logger.info(String.format("Discovered %d services",services.size()));
}
@Override
public void handleRequest(@NotNull HttpServerExchange httpServerExchange) throws Exception
{
String queryString = httpServerExchange.getRequestURI();
logger.info(String.format("%s %s", httpServerExchange.getRequestMethod().toString(), queryString));
String[] vines = queryString.split("/");
httpServerExchange.getResponseHeaders().put(new HttpString("Server"),"sophia.net/Dustspeck2");
for (Dustspeck2Service serviceCandidate: services)
{
if (serviceCandidate.canHandle(queryString))
{
serviceCandidate.handleRequest(queryString, vines, httpServerExchange);
return;
}
}
httpServerExchange.setStatusCode(404);
httpServerExchange.getResponseSender().send("");
httpServerExchange.getResponseSender().close();
}
}

View File

@ -0,0 +1,13 @@
package moe.yo3explorer.dustspeck2.presentation;
import io.undertow.server.HttpHandler;
import io.undertow.server.HttpServerExchange;
import java.io.IOException;
public interface Dustspeck2Service
{
boolean canHandle(String s);
void handleRequest(String queryString, String[] vines, HttpServerExchange httpServerExchange) throws IOException;
}

View File

@ -0,0 +1,9 @@
package moe.yo3explorer.dustspeck2.presentation;
public class EnvironmentVariableMissingException extends RuntimeException
{
public EnvironmentVariableMissingException(String setting)
{
super(String.format("Environment vatiable %s is not configured.", setting));
}
}

View File

@ -0,0 +1,40 @@
package moe.yo3explorer.dustspeck2.presentation;
import io.undertow.Undertow;
import io.undertow.server.HttpHandler;
import moe.yo3explorer.dustspeck2.business.nuget.boundary.Dustspeck2Context;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.Map;
public class Main
{
public static void main(String[] args)
{
Logger logger = LogManager.getLogger(Main.class);
logger.info("Hello! This is Dustspeck2!");
Map<String, String> getenv = System.getenv();
String[] env = new String[] {"DATA_DIRECTORY"};
for (String setting : env)
{
if (!getenv.containsKey(setting))
{
throw new EnvironmentVariableMissingException(setting);
}
}
Dustspeck2Context dustspeck2 = Dustspeck2Context.getInstance();
dustspeck2.setDataDirectory(getenv.get("DATA_DIRECTORY"));
Dustspeck2HttpHandler dustspeck2HttpHandler = new Dustspeck2HttpHandler();
Undertow server = Undertow.builder()
.addHttpListener(8080, "0.0.0.0")
.setHandler(dustspeck2HttpHandler).build();
logger.info("Began listening on port 8080...");
server.start();
}
}

View File

@ -0,0 +1,63 @@
package moe.yo3explorer.dustspeck2.presentation;
import io.undertow.server.HttpServerExchange;
import io.undertow.util.HttpString;
import org.apache.commons.io.IOUtils;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
public class ResourceService implements Dustspeck2Service
{
@Override
public boolean canHandle(@NotNull String s)
{
switch (s)
{
case "/index.json":
case "/favicon.ico":
return true;
default:
return false;
}
}
private String indexJson;
private byte[] faviconIco;
@Override
public void handleRequest(@NotNull String queryString, String[] vines, @NotNull HttpServerExchange httpServerExchange) throws IOException
{
String hostAndPort = httpServerExchange.getHostAndPort();
hostAndPort = String.format("http://%s",hostAndPort);
switch (queryString)
{
case "/index.json":
if (indexJson == null)
{
InputStream indexStream = getClass().getClassLoader().getResourceAsStream("index.json");
indexJson = IOUtils.toString(indexStream, StandardCharsets.UTF_8);
indexJson = indexJson.replace("{0}", hostAndPort);
}
httpServerExchange.getResponseHeaders().put(HttpString.tryFromString("Content-Type"),"application/json");
httpServerExchange.getResponseSender().send(indexJson);
httpServerExchange.getResponseSender().close();
return;
case "/favicon.ico":
if (faviconIco == null)
{
InputStream faviconStream = getClass().getClassLoader().getResourceAsStream("favicon.ico");
faviconIco = IOUtils.toByteArray(faviconStream);
}
httpServerExchange.getResponseHeaders().put(HttpString.tryFromString("Content-Type"),"application/json");
httpServerExchange.getResponseSender().send(ByteBuffer.wrap(faviconIco));
httpServerExchange.getResponseSender().close();
return;
}
}
}

View File

@ -0,0 +1,25 @@
package moe.yo3explorer.dustspeck2.presentation;
import io.undertow.server.HttpServerExchange;
import io.undertow.util.HttpString;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
public class RootRedirectService implements Dustspeck2Service
{
@Override
public boolean canHandle(String s)
{
return s.equals("/");
}
@Override
public void handleRequest(String queryString, String[] vines, @NotNull HttpServerExchange httpServerExchange) throws IOException
{
httpServerExchange.setStatusCode(301);
httpServerExchange.getResponseHeaders().put(HttpString.tryFromString("Location"),"/index.json");
httpServerExchange.getResponseSender().send("");
httpServerExchange.getResponseSender().close();
}
}

View File

@ -0,0 +1,10 @@
moe.yo3explorer.dustspeck2.presentation.RootRedirectService
moe.yo3explorer.dustspeck2.presentation.ResourceService
moe.yo3explorer.dustspeck2.business.nuget.boundary.RegistrationsBaseUrlService
moe.yo3explorer.dustspeck2.business.nuget.boundary.ReadmeUriTemplateService
moe.yo3explorer.dustspeck2.business.nuget.boundary.VulnerabilityInfoService
moe.yo3explorer.dustspeck2.business.nuget.boundary.SearchQueryService
moe.yo3explorer.dustspeck2.business.nuget.boundary.VersionPageService
moe.yo3explorer.dustspeck2.business.nuget.boundary.PackageBaseAddressService
moe.yo3explorer.dustspeck2.business.nuget.boundary.VulnerabilityBaseService
moe.yo3explorer.dustspeck2.business.nuget.boundary.IconService

Binary file not shown.

After

Width:  |  Height:  |  Size: 894 B

View File

@ -0,0 +1,182 @@
{
"version": "3.0.0",
"resources": [
{
"@id": "{0}/SearchQueryService/query",
"@type": "SearchQueryService",
"comment": "Query endpoint of NuGet Search service (primary)"
},
{
"@id": "{0}/SearchAutocompleteService/autocomplete",
"@type": "SearchAutocompleteService",
"comment": "Autocomplete endpoint of NuGet Search service (primary)"
},
{
"@id": "{0}/SearchGalleryQueryService/",
"@type": "SearchGalleryQueryService/3.0.0-rc",
"comment": "Azure Website based Search Service used by Gallery (primary)"
},
{
"@id": "{0}/RegistrationsBaseUrl/v3/registration5-semver1/",
"@type": "RegistrationsBaseUrl",
"comment": "Base URL of Azure storage where NuGet package registration info is stored"
},
{
"@id": "{0}/PackageBaseAddress/v3-flatcontainer/",
"@type": "PackageBaseAddress/3.0.0",
"comment": "Base URL of where NuGet packages are stored, in the format {0}/api.nuget.org/v3-flatcontainer/{id-lower}/{version-lower}/{id-lower}.{version-lower}.nupkg"
},
{
"@id": "{0}/LegacyGallery/api/v2",
"@type": "LegacyGallery"
},
{
"@id": "{0}/LegacyGallery/api/v2",
"@type": "LegacyGallery/2.0.0"
},
{
"@id": "{0}/PackagePublish/api/v2/package",
"@type": "PackagePublish/2.0.0"
},
{
"@id": "{0}/SymbolPackagePublish/api/v2/symbolpackage",
"@type": "SymbolPackagePublish/4.9.0",
"comment": "The gallery symbol publish endpoint."
},
{
"@id": "{0}/SearchQueryService/query",
"@type": "SearchQueryService/3.0.0-rc",
"comment": "Query endpoint of NuGet Search service (primary) used by RC clients"
},
{
"@id": "{0}/SearchQueryService/query",
"@type": "SearchQueryService/3.0.0-rc",
"comment": "Query endpoint of NuGet Search service (secondary) used by RC clients"
},
{
"@id": "{0}/SearchQueryService/query",
"@type": "SearchQueryService/3.5.0",
"comment": "Query endpoint of NuGet Search service (primary) that supports package type filtering"
},
{
"@id": "{0}/SearchQueryService/query",
"@type": "SearchQueryService/3.5.0",
"comment": "Query endpoint of NuGet Search service (secondary) that supports package type filtering"
},
{
"@id": "{0}/SearchAutocompleteService/autocomplete",
"@type": "SearchAutocompleteService/3.0.0-rc",
"comment": "Autocomplete endpoint of NuGet Search service (primary) used by RC clients"
},
{
"@id": "{0}/SearchAutocompleteService/autocomplete",
"@type": "SearchAutocompleteService/3.0.0-rc",
"comment": "Autocomplete endpoint of NuGet Search service (secondary) used by RC clients"
},
{
"@id": "{0}/SearchAutocompleteService/autocomplete",
"@type": "SearchAutocompleteService/3.5.0",
"comment": "Autocomplete endpoint of NuGet Search service (primary) that supports package type filtering"
},
{
"@id": "{0}/SearchAutocompleteService/autocomplete",
"@type": "SearchAutocompleteService/3.5.0",
"comment": "Autocomplete endpoint of NuGet Search service (secondary) that supports package type filtering"
},
{
"@id": "{0}/RegistrationsBaseUrl/v3/registration5-semver1/",
"@type": "RegistrationsBaseUrl/3.0.0-rc",
"comment": "Base URL of Azure storage where NuGet package registration info is stored used by RC clients. This base URL does not include SemVer 2.0.0 packages."
},
{
"@id": "{0}/ReportAbuseUriTemplate/packages/{id}/{version}/ReportAbuse",
"@type": "ReportAbuseUriTemplate/3.0.0-rc",
"comment": "URI template used by NuGet Client to construct Report Abuse URL for packages used by RC clients"
},
{
"@id": "{0}/PackageDisplayMetadataUriTemplate/v3/registration5-semver1/{id-lower}/index.json",
"@type": "PackageDisplayMetadataUriTemplate/3.0.0-rc",
"comment": "URI template used by NuGet Client to construct display metadata for Packages using ID"
},
{
"@id": "{0}/PackageVersionDisplayMetadataUriTemplate/v3/registration5-semver1/{id-lower}/{version-lower}.json",
"@type": "PackageVersionDisplayMetadataUriTemplate/3.0.0-rc",
"comment": "URI template used by NuGet Client to construct display metadata for Packages using ID, Version"
},
{
"@id": "{0}/SearchQueryService/query",
"@type": "SearchQueryService/3.0.0-beta",
"comment": "Query endpoint of NuGet Search service (primary) used by beta clients"
},
{
"@id": "{0}/SearchQueryService/query",
"@type": "SearchQueryService/3.0.0-beta",
"comment": "Query endpoint of NuGet Search service (secondary) used by beta clients"
},
{
"@id": "{0}/SearchAutocompleteService/autocomplete",
"@type": "SearchAutocompleteService/3.0.0-beta",
"comment": "Autocomplete endpoint of NuGet Search service (primary) used by beta clients"
},
{
"@id": "{0}/SearchAutocompleteService/autocomplete",
"@type": "SearchAutocompleteService/3.0.0-beta",
"comment": "Autocomplete endpoint of NuGet Search service (secondary) used by beta clients"
},
{
"@id": "{0}/RegistrationsBaseUrl/v3/registration5-semver1/",
"@type": "RegistrationsBaseUrl/3.0.0-beta",
"comment": "Base URL of Azure storage where NuGet package registration info is stored used by Beta clients. This base URL does not include SemVer 2.0.0 packages."
},
{
"@id": "{0}/ReportAbuseUriTemplate/packages/{id}/{version}/ReportAbuse",
"@type": "ReportAbuseUriTemplate/3.0.0-beta",
"comment": "URI template used by NuGet Client to construct Report Abuse URL for packages"
},
{
"@id": "{0}/PackageDetailsUriTemplate/packages/{id}/{version}?_src=template",
"@type": "PackageDetailsUriTemplate/5.1.0",
"comment": "URI template used by NuGet Client to construct details URL for packages"
},
{
"@id": "{0}/OwnerDetailsUriTemplate/profiles/{owner}?_src=template",
"@type": "OwnerDetailsUriTemplate/6.11.0",
"comment": "URI template used by NuGet Client to construct owner URL for packages"
},
{
"@id": "{0}/RegistrationsBaseUrl/v3/registration5-gz-semver1/",
"@type": "RegistrationsBaseUrl/3.4.0",
"comment": "Base URL of Azure storage where NuGet package registration info is stored in GZIP format. This base URL does not include SemVer 2.0.0 packages."
},
{
"@id": "{0}/RegistrationsBaseUrl/v3/registration5-gz-semver2/",
"@type": "RegistrationsBaseUrl/3.6.0",
"comment": "Base URL of Azure storage where NuGet package registration info is stored in GZIP format. This base URL includes SemVer 2.0.0 packages."
},
{
"@id": "{0}/RegistrationsBaseUrl/v3/registration5-gz-semver2/",
"@type": "RegistrationsBaseUrl/Versioned",
"clientVersion": "4.3.0-alpha",
"comment": "Base URL of Azure storage where NuGet package registration info is stored in GZIP format. This base URL includes SemVer 2.0.0 packages."
},
{
"@id": "{0}/VulnerabilityInfo/v3/vulnerabilities/index.json",
"@type": "VulnerabilityInfo/6.7.0",
"comment": "The endpoint for discovering information about vulnerabilities of packages in this package source."
},
{
"@id": "{0}/Catalog/v3/catalog0/index.json",
"@type": "Catalog/3.0.0",
"comment": "Index of the NuGet package catalog."
},
{
"@id": "{0}/ReadmeUriTemplate/v3-flatcontainer/{lower_id}/{lower_version}/readme",
"@type": "ReadmeUriTemplate/6.13.0",
"comment": "URI template used by NuGet Client to construct a URL for downloading a package's README."
}
],
"@context": {
"@vocab": "http://schema.nuget.org/services#",
"comment": "http://www.w3.org/2000/01/rdf-schema#comment"
}
}

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<Configuration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="https://logging.apache.org/xml/ns"
xsi:schemaLocation="https://logging.apache.org/xml/ns">
<Appenders>
<Console name="CONSOLE">
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n" />
</Console>
</Appenders>
<Loggers>
<Logger name="com.mycompany" level="INFO"/>
<Root level="INFO">
<AppenderRef ref="CONSOLE"/>
</Root>
</Loggers>
</Configuration>