├── .gitignore
├── README.md
├── pom.xml
├── short-license.txt
└── src
├── main
└── java
│ └── com
│ └── bmdsoftware
│ └── pacs
│ └── dicoogle
│ └── ipfs
│ ├── IPFSJettyPlugin.java
│ ├── IPFSPluginSet.java
│ ├── IPFSStore.java
│ └── services
│ ├── IPFSListWebService.java
│ └── IPFSStatusWebService.java
└── test
├── java
└── com
│ └── bmdsoftware
│ └── pacs
│ └── dicoogle
│ └── ipfs
│ ├── TestIPFS.java
│ └── TestStorage.java
└── resources
└── DoseSR_GE_01.DCM
/.gitignore:
--------------------------------------------------------------------------------
1 | /target/
2 |
3 | # Eclipse
4 | .classpath
5 | .project
6 | .settings/
7 |
8 | # Intellij
9 | .idea/
10 | *.iml
11 | *.iws
12 |
13 | # Mac
14 | .DS_Store
15 |
16 | # Maven
17 | log/
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Dicoogle IPFS Storage Plugin
2 | ========================
3 |
4 | This is a [Dicoogle](https://www.dicoogle.com) plugin to support the storage of files over [IPFS](https://ipfs.io/).
5 |
6 | Getting Started
7 | ---------------
8 |
9 | [IPFS](https://ipfs.io/) is a P2P distributed file system that targets to connect all computing devices with
10 | the same system of files. IPFS provides a high-throughput, content-addressed block storage model, with
11 | addressed with a hash URI. Dicoogle IPFS is as far as we know, the first PACS archive supporting [DICOM](https://www.dicomstandard.org/) communications
12 | with IPFS capabilities.
13 |
14 |
15 | ### Run IPFS Daemon
16 |
17 |
18 | 1. First, go to and download the IPFS. You can use Go IPFS Daemon.
19 | 2. Run init to create the hash files and keys with:
20 |
21 | $ ./ipfs init
22 |
23 | 3. Start the daemon:
24 |
25 | $ ./ipfs daemon
26 |
27 | It should retrieve something similar:
28 |
29 | ```
30 | Initializing daemon...
31 | Swarm listening on /ip4/127.0.0.1/tcp/4001
32 | Swarm listening on /ip4/169.254.195.127/tcp/4001
33 | Swarm listening on /ip4/172.20.20.25/tcp/4001
34 | Swarm listening on /ip4/192.168.1.72/tcp/4001
35 | Swarm listening on /ip6/::1/tcp/4001
36 | Swarm listening on /p2p-circuit/ipfs/QmPYwyhd9WfH6cmyXh4SJpSkxweeHmUbohao6g4H4zhD3G
37 | Swarm announcing /ip4/127.0.0.1/tcp/4001
38 | Swarm announcing /ip4/169.254.195.127/tcp/4001
39 | Swarm announcing /ip4/172.20.20.25/tcp/4001
40 | Swarm announcing /ip4/192.168.1.72/tcp/4001
41 | Swarm announcing /ip4/2.83.194.251/tcp/60663
42 | Swarm announcing /ip6/::1/tcp/4001
43 | API server listening on /ip4/127.0.0.1/tcp/5001
44 | Gateway (readonly) server listening on /ip4/127.0.0.1/tcp/8080
45 | Daemon is ready
46 | ```
47 |
48 |
49 | ### Using your plugin
50 |
51 | 1. Copy your plugin's package with dependencies (target/ipfs-plugin-1.0.0-SNAPSHOT-jar-with-dependencies.jar)
52 | to the "Plugins" folder inside the root folder of Dicoogle.
53 |
54 | 2. Run Dicoogle. The plugin will be automatically included.
55 |
56 |
57 | ### Configuration
58 |
59 | You can configure the IPFS endpoint in the Plugin settings. Check here:
60 |
61 |
62 | ```
63 | | => cat Plugins/settings/IPFS.xml
64 |
65 |
66 |
67 | /ip4/127.0.0.1/tcp/5001
68 |
69 |
70 | ```
71 |
72 | ### Available services
73 | If Dicoogle is running on PORT 8082:
74 |
75 | #### Check the current status
76 | Status Web service available at: ipfs/status?action=status
77 |
78 | URL: http://localhost:8082/ipfs/status?action=status
79 |
80 | #### Check the number of local files on IPFS
81 | List Web service available at: ipfs/status?action=fileCount
82 |
83 | URL: http://localhost:8082/ipfs/list?action=fileCount
84 |
85 | #### List of local files hashes on IPFS
86 | List Web service available at: ipfs/status?action=fileList
87 |
88 | URL: http://localhost:8082/ipfs/list?action=fileList
89 |
90 |
91 | ### Test data
92 |
93 | This repository uses DICOM data for testing. The DICOM files listed under `src/test/resources` are made available by [NEMA](medical.nema.org) in ftp://medical.nema.org/medical/dicom/DataSets/WG02/RDSR/.
94 |
95 | ### Troubleshooting
96 |
97 | By default Dicoogle and IPFS Daemon open the 8080 tcp port, so one of application should change the port to avoid
98 | problems.
99 |
100 |
101 | ## Use case
102 |
103 | 1) Store medical imaging over IPFS
104 | 2) Failures
105 | 3) Avoid changes in medical imaging
106 | 4) Allow tracebility
107 |
108 |
109 |
110 |
111 | ## Support and consulting
112 |
113 | [
](https://www.bmd-software.com)
114 |
115 | Please contact [BMD Software](https://www.bmd-software.com) for professional support and consulting services.
116 |
117 |
118 |
119 | Platforms
120 | ----------
121 |
122 | Dicoogle IPFS has been tested in:
123 |
124 | - Windows
125 | - Linux
126 | - Mac OS X
127 | - FreeBSD and OpenBSD
128 |
129 | For more information, please visit http://www.dicoogle.com
130 |
131 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 | com.bmdsofware.dicoogle
6 | ipfs-plugin
7 | ipfs
8 | 1.0.0-SNAPSHOT
9 | jar
10 |
11 |
12 | UTF-8
13 |
14 |
15 | 3.0.0
16 |
17 |
18 | 9.0.3.v20130506
19 |
20 |
21 | v1.3.3
22 |
23 |
24 |
25 |
26 |
27 |
28 | org.apache.maven.plugins
29 | maven-compiler-plugin
30 | 2.3.2
31 |
32 |
35 | 1.8
36 | 1.8
37 |
38 |
39 |
40 | maven-assembly-plugin
41 |
42 |
43 | jar-with-dependencies
44 |
45 |
46 |
47 |
48 |
49 |
50 | make-assembly
51 | package
52 |
53 | single
54 |
55 |
56 |
57 |
58 |
59 | com.mycila
60 | license-maven-plugin
61 | 2.4
62 |
63 |
64 |
65 | **/*.java
66 |
67 |
68 | **/package-info.java
69 |
70 |
71 |
72 |
73 |
74 | check
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 | maven-restlet
85 | Public online Restlet repository
86 | https://maven.restlet.org
87 |
88 |
89 |
90 | mavencentral
91 | https://repo1.maven.org/maven2/
92 |
93 | true
94 |
95 |
96 |
97 |
98 | dcm4che
99 | https://www.dcm4che.org/maven2/
100 |
101 | true
102 |
103 |
104 |
105 |
106 | jitpack.io
107 | https://jitpack.io
108 |
109 |
110 |
111 | mi
112 | https://bioinformatics.ua.pt/maven/content/repositories/mi
113 |
114 | false
115 |
116 |
117 |
118 |
119 | mi-snapshots
120 | https://bioinformatics.ua.pt/maven/content/repositories/mi-snapshots
121 |
122 | true
123 |
124 |
125 |
126 |
127 |
128 |
129 | org.restlet.jse
130 | org.restlet.ext.json
131 | 2.1.2
132 |
133 |
134 |
135 | pt.ua.ieeta
136 | dicoogle-sdk
137 | ${dicoogle.version}
138 |
139 |
140 |
141 | org.eclipse.jetty
142 | jetty-webapp
143 | ${jetty.version}
144 |
145 |
146 |
147 | com.github.ipfs
148 | java-ipfs-http-client
149 | ${ipfs-client.version}
150 |
151 |
152 |
153 | junit
154 | junit
155 | 4.13.1
156 | test
157 |
158 |
159 |
160 |
--------------------------------------------------------------------------------
/short-license.txt:
--------------------------------------------------------------------------------
1 | Copyright (C) 2018 BMD software, Lda
2 |
3 | This file is part of Dicoogle/${project.name}.
4 |
5 | Dicoogle/${project.name} is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | Dicoogle/${project.name} is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with Dicoogle. If not, see .
17 |
--------------------------------------------------------------------------------
/src/main/java/com/bmdsoftware/pacs/dicoogle/ipfs/IPFSJettyPlugin.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2018 BMD software, Lda
3 | *
4 | * This file is part of Dicoogle/ipfs.
5 | *
6 | * Dicoogle/ipfs is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * Dicoogle/ipfs is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with Dicoogle. If not, see .
18 | */
19 | package com.bmdsoftware.pacs.dicoogle.ipfs;
20 |
21 | import com.bmdsoftware.pacs.dicoogle.ipfs.services.IPFSListWebService;
22 | import com.bmdsoftware.pacs.dicoogle.ipfs.services.IPFSStatusWebService;
23 | import io.ipfs.api.IPFS;
24 | import org.eclipse.jetty.server.handler.HandlerList;
25 | import org.eclipse.jetty.servlet.ServletContextHandler;
26 | import org.eclipse.jetty.servlet.ServletHolder;
27 | import org.slf4j.Logger;
28 | import org.slf4j.LoggerFactory;
29 | import pt.ua.dicoogle.sdk.JettyPluginInterface;
30 | import pt.ua.dicoogle.sdk.core.DicooglePlatformInterface;
31 | import pt.ua.dicoogle.sdk.core.PlatformCommunicatorInterface;
32 | import pt.ua.dicoogle.sdk.settings.ConfigurationHolder;
33 |
34 | /**
35 | * IPFS Jetty Servlet plugin.
36 | *
37 | * @author Luís A. Bastião Silva -
38 | * @author Eriksson Monteiro -
39 | */
40 | public class IPFSJettyPlugin implements JettyPluginInterface, PlatformCommunicatorInterface {
41 | private static final Logger logger = LoggerFactory.getLogger(IPFSJettyPlugin.class);
42 |
43 | private boolean enabled;
44 | private ConfigurationHolder settings;
45 | private DicooglePlatformInterface platform;
46 | private final IPFSStatusWebService statusWebService;
47 | private final IPFSListWebService listWebService;
48 | private IPFS ipfs;
49 |
50 | public IPFSJettyPlugin(IPFS ipfs) {
51 | this.ipfs = ipfs;
52 | this.statusWebService = new IPFSStatusWebService(ipfs);
53 | this.listWebService = new IPFSListWebService(ipfs);
54 | this.enabled = true;
55 | }
56 |
57 | @Override
58 | public void setPlatformProxy(DicooglePlatformInterface pi) {
59 | this.platform = pi;
60 | // since web service is not a plugin interface, the platform interface must be provided manually
61 | this.statusWebService.setPlatformProxy(pi);
62 | }
63 |
64 | @Override
65 | public String getName() {
66 | return "IPFS";
67 | }
68 |
69 | @Override
70 | public boolean enable() {
71 | this.enabled = true;
72 | return true;
73 | }
74 |
75 | @Override
76 | public boolean disable() {
77 | this.enabled = false;
78 | return true;
79 | }
80 |
81 | @Override
82 | public boolean isEnabled() {
83 | return this.enabled;
84 | }
85 |
86 | @Override
87 | public void setSettings(ConfigurationHolder settings) {
88 | this.settings = settings;
89 | // use settings here
90 | }
91 |
92 | @Override
93 | public ConfigurationHolder getSettings() {
94 | return settings;
95 | }
96 |
97 |
98 | @Override
99 | public HandlerList getJettyHandlers() {
100 |
101 | ServletContextHandler handler = new ServletContextHandler();
102 | handler.setContextPath("/ipfs");
103 | handler.addServlet(new ServletHolder(this.statusWebService), "/status");
104 | handler.addServlet(new ServletHolder(this.listWebService), "/list");
105 | handler.addServlet(new ServletHolder(this.statusWebService), "/chain");
106 | handler.addServlet(new ServletHolder(this.statusWebService), "/hash");
107 | HandlerList l = new HandlerList();
108 | l.addHandler(handler);
109 |
110 |
111 | return l;
112 | }
113 |
114 | }
115 |
--------------------------------------------------------------------------------
/src/main/java/com/bmdsoftware/pacs/dicoogle/ipfs/IPFSPluginSet.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2018 BMD software, Lda
3 | *
4 | * This file is part of Dicoogle/ipfs.
5 | *
6 | * Dicoogle/ipfs is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * Dicoogle/ipfs is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with Dicoogle. If not, see .
18 | */
19 | package com.bmdsoftware.pacs.dicoogle.ipfs;
20 |
21 | import io.ipfs.api.IPFS;
22 | import net.xeoh.plugins.base.annotations.PluginImplementation;
23 | import org.apache.commons.configuration.XMLConfiguration;
24 | import org.restlet.resource.ServerResource;
25 | import org.slf4j.Logger;
26 | import org.slf4j.LoggerFactory;
27 | import pt.ua.dicoogle.sdk.*;
28 | import pt.ua.dicoogle.sdk.settings.ConfigurationHolder;
29 |
30 | import java.io.IOException;
31 | import java.util.Collection;
32 | import java.util.Collections;
33 |
34 | /**
35 | * The main plugin set.
36 | *
37 | * This is the entry point for all plugins.
38 | *
39 | * @author Luís A. Bastião Silva -
40 | * @author Eriksson Monteiro -
41 | */
42 | @PluginImplementation
43 | public class IPFSPluginSet implements PluginSet {
44 | // use slf4j for logging purposes
45 | private static final Logger logger = LoggerFactory.getLogger(IPFSPluginSet.class);
46 |
47 | // We will list each of our plugins as an attribute to the plugin set
48 |
49 | private final IPFSJettyPlugin jettyWeb;
50 | private final IPFSStore storage;
51 | private String endpoint = "/ip4/127.0.0.1/tcp/5001";
52 | private IPFS ipfs;
53 | private ConfigurationHolder settings;
54 |
55 | public IPFSPluginSet() throws IOException {
56 | logger.info("Initializing IPFS Plugin Set");
57 |
58 | // construct all plugins here
59 | logger.info("IPFS connecting to .. " + endpoint);
60 | try{
61 | IPFS ipfs = new IPFS(endpoint);
62 | }
63 | catch(Exception e){
64 | logger.error("IPFS is not ready to connect. Please, configure IPFS daemon.", e);
65 | }
66 | // Initialize other plugins and services
67 | this.jettyWeb = new IPFSJettyPlugin(ipfs);
68 | this.storage = new IPFSStore(ipfs);
69 | logger.info("IPFS Plugin Set was initialized.");
70 | }
71 |
72 |
73 | @Override
74 | public Collection getIndexPlugins() {
75 |
76 | return Collections.EMPTY_LIST;
77 | }
78 |
79 | @Override
80 | public Collection getQueryPlugins() {
81 | return Collections.EMPTY_LIST;
82 | }
83 |
84 | /**
85 | * This method is used to retrieve a name for identifying the plugin set. Keep it as a constant value.
86 | *
87 | * @return a unique name for the plugin set
88 | */
89 | @Override
90 | public String getName() {
91 | return "IPFS";
92 | }
93 |
94 | @Override
95 | public Collection getRestPlugins() {
96 | return Collections.EMPTY_LIST;
97 | }
98 |
99 | @Override
100 | public Collection getJettyPlugins() {
101 | return Collections.singleton(this.jettyWeb);
102 | }
103 |
104 | @Override
105 | public void shutdown() {
106 | }
107 |
108 | @Override
109 | public Collection getStoragePlugins() {
110 | return Collections.singleton(this.storage);
111 | }
112 |
113 | @Override
114 | public ConfigurationHolder getSettings() {
115 | return this.settings;
116 | }
117 |
118 | @Override
119 | public void setSettings(ConfigurationHolder xmlSettings) {
120 | this.settings = xmlSettings;
121 | XMLConfiguration cnf = this.settings.getConfiguration();
122 | cnf.setThrowExceptionOnMissing(true);
123 |
124 | try {
125 | endpoint = cnf.getString("ipfs.endpoint", "/ip4/127.0.0.1/tcp/5001");
126 |
127 | if (!cnf.containsKey("ipfs.endpoint")) {
128 | cnf.setProperty("ipfs.endpoint", "/ip4/127.0.0.1/tcp/5001");
129 | }
130 | } catch (Exception ex) {
131 | logger.warn("Failed to configure plugin: required fields are missing!", ex);
132 | }
133 | }
134 |
135 |
136 | }
--------------------------------------------------------------------------------
/src/main/java/com/bmdsoftware/pacs/dicoogle/ipfs/IPFSStore.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2018 BMD software, Lda
3 | *
4 | * This file is part of Dicoogle/ipfs.
5 | *
6 | * Dicoogle/ipfs is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * Dicoogle/ipfs is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with Dicoogle. If not, see .
18 | */
19 | package com.bmdsoftware.pacs.dicoogle.ipfs;
20 |
21 | import io.ipfs.api.IPFS;
22 | import io.ipfs.api.MerkleNode;
23 | import io.ipfs.api.NamedStreamable;
24 | import io.ipfs.multihash.Multihash;
25 | import org.dcm4che2.data.DicomObject;
26 | import org.dcm4che2.io.DicomInputStream;
27 | import org.dcm4che2.io.DicomOutputStream;
28 | import org.slf4j.Logger;
29 | import org.slf4j.LoggerFactory;
30 | import pt.ua.dicoogle.sdk.StorageInputStream;
31 | import pt.ua.dicoogle.sdk.StorageInterface;
32 | import pt.ua.dicoogle.sdk.settings.ConfigurationHolder;
33 |
34 | import java.io.ByteArrayInputStream;
35 | import java.io.ByteArrayOutputStream;
36 | import java.io.IOException;
37 | import java.io.InputStream;
38 | import java.net.URI;
39 | import java.net.URISyntaxException;
40 | import java.util.ArrayList;
41 | import java.util.Collection;
42 | import java.util.Iterator;
43 | import java.util.UUID;
44 |
45 | /**
46 | * @author Luís A. Bastião Silva -
47 | */
48 | public class IPFSStore implements StorageInterface {
49 |
50 | private static final Logger logger = LoggerFactory.getLogger(IPFSStore.class);
51 |
52 | private boolean enabled = true;
53 |
54 | private IPFS ipfs = null;
55 |
56 |
57 | public IPFSStore(IPFS ipfs) {
58 | this.ipfs = ipfs;
59 | }
60 |
61 | @Override
62 | public String getScheme() {
63 | return "ipfs";
64 | }
65 |
66 | @Override
67 | public Iterable at(final URI location, Object... objects) {
68 | Iterable c = new Iterable() {
69 |
70 | @Override
71 | public Iterator iterator() {
72 | Collection c2 = new ArrayList<>();
73 | StorageInputStream s = new StorageInputStream() {
74 |
75 | @Override
76 | public URI getURI() {
77 | return location;
78 | }
79 |
80 | @Override
81 | public InputStream getInputStream() throws IOException {
82 | Multihash filePointer = Multihash.fromBase58(location.toString().replaceFirst("ipfs://", ""));
83 |
84 | byte[] fileContents = new byte[0];
85 | try {
86 | fileContents = ipfs.cat(filePointer);
87 | } catch (IOException e) {
88 | logger.error("Failed to retrieve object", e);
89 | return null;
90 | }
91 |
92 | ByteArrayInputStream bin = new ByteArrayInputStream(fileContents);
93 | return bin;
94 | }
95 |
96 | @Override
97 | public long getSize() throws IOException {
98 | Multihash filePointer = Multihash.fromBase58(location.toString().replaceFirst("ipfs://", ""));
99 | return ipfs.get(filePointer).length;
100 | }
101 | };
102 | c2.add(s);
103 | return c2.iterator();
104 | }
105 | };
106 | return c;
107 |
108 | }
109 |
110 | @Override
111 | public URI store(DicomObject dicomObject, Object... objects) {
112 |
113 | ByteArrayOutputStream bos = new ByteArrayOutputStream();
114 | DicomOutputStream dos = new DicomOutputStream(bos);
115 | try {
116 | dos.writeDicomFile(dicomObject);
117 | } catch (IOException ex) {
118 | logger.error("Failed to store object", ex);
119 | }
120 |
121 |
122 | NamedStreamable.ByteArrayWrapper file = new NamedStreamable.ByteArrayWrapper(UUID.randomUUID().toString(), bos.toByteArray());
123 | MerkleNode addResult = null;
124 | try {
125 | addResult = ipfs.add(file).get(0);
126 | } catch (IOException e) {
127 | logger.error("Failed to store object", e);
128 | return null;
129 | }
130 |
131 | // Retrieve the hash
132 | try {
133 | return new URI("ipfs://" + addResult.hash.toBase58());
134 | } catch (URISyntaxException e) {
135 | logger.error("Failed to build uri ", e);
136 | return null;
137 | }
138 | }
139 |
140 | @Override
141 | public URI store(DicomInputStream dicomInputStream, Object... objects) throws IOException {
142 |
143 | DicomObject obj = dicomInputStream.readDicomObject();
144 | return store(obj);
145 | }
146 |
147 | @Override
148 | public void remove(URI uri) {
149 | try {
150 | ipfs.pin.rm(Multihash.fromBase58(uri.toString().replaceFirst("ipfs://", "")));
151 | } catch (IOException e) {
152 | logger.error("Failed to remove pin", e);
153 | }
154 | }
155 |
156 | @Override
157 | public String getName() {
158 | return "ipfs-storage";
159 | }
160 |
161 | @Override
162 | public boolean enable() {
163 | this.enabled = true;
164 | return true;
165 | }
166 |
167 | @Override
168 | public boolean disable() {
169 | this.enabled = false;
170 | return true;
171 | }
172 |
173 | @Override
174 | public boolean isEnabled() {
175 | return this.enabled;
176 | }
177 |
178 | @Override
179 | public ConfigurationHolder getSettings() {
180 | return null;
181 | }
182 |
183 | @Override
184 | public void setSettings(ConfigurationHolder configurationHolder) {
185 |
186 | }
187 | }
188 |
--------------------------------------------------------------------------------
/src/main/java/com/bmdsoftware/pacs/dicoogle/ipfs/services/IPFSListWebService.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2018 BMD software, Lda
3 | *
4 | * This file is part of Dicoogle/ipfs.
5 | *
6 | * Dicoogle/ipfs is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * Dicoogle/ipfs is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with Dicoogle. If not, see .
18 | */
19 | package com.bmdsoftware.pacs.dicoogle.ipfs.services;
20 |
21 | import io.ipfs.api.IPFS;
22 | import org.eclipse.jetty.http.HttpStatus;
23 | import org.slf4j.Logger;
24 | import org.slf4j.LoggerFactory;
25 | import pt.ua.dicoogle.sdk.core.DicooglePlatformInterface;
26 | import pt.ua.dicoogle.sdk.core.PlatformCommunicatorInterface;
27 |
28 | import javax.servlet.http.HttpServlet;
29 | import javax.servlet.http.HttpServletRequest;
30 | import javax.servlet.http.HttpServletResponse;
31 | import java.io.IOException;
32 | import java.io.PrintWriter;
33 | import java.util.stream.Collectors;
34 |
35 | /**
36 | * IPFS Jetty Plugin - Status
37 | *
38 | * @author Luís A. Bastião Silva -
39 | * @author Eriksson Monteiro -
40 | * @author Rui Lebre -
41 | */
42 | public class IPFSListWebService extends HttpServlet implements PlatformCommunicatorInterface {
43 | private static final Logger logger = LoggerFactory.getLogger(IPFSListWebService.class);
44 |
45 | private DicooglePlatformInterface platform;
46 | private IPFS ipfs = null;
47 |
48 | public IPFSListWebService(IPFS ipfs) {
49 | this.ipfs = ipfs;
50 | }
51 |
52 | @Override
53 | protected void doGet(HttpServletRequest req, HttpServletResponse response) throws IOException {
54 |
55 | String action = req.getParameter("action");
56 | if (action == null) {
57 | response.sendError(HttpStatus.BAD_REQUEST_400, "No action provided");
58 | return;
59 | }
60 |
61 | response.setContentType("text/json;charset=utf-8");
62 | PrintWriter out = response.getWriter();
63 |
64 | if (action.equalsIgnoreCase("fileCount")) {
65 | response.setStatus(HttpStatus.OK_200);
66 |
67 | out.print("{\"action\":\"fileCount\", \"host\":\"" + ipfs.host + "\", \"fileCount\":" + ipfs.refs.local().size() + "\"}");
68 | } else if (action.equalsIgnoreCase("filelist")) {
69 | response.setStatus(HttpStatus.OK_200);
70 | String localFileList = ipfs.refs.local().stream().map(Object::toString).collect(Collectors.joining("\", \"", "[\"", "\"]"));
71 |
72 | out.print("{\"action\":\"filelist\", \"host\":\"" + ipfs.host + "\", \"file_list\":" + localFileList + "}");
73 | } else {
74 | response.setStatus(HttpStatus.BAD_REQUEST_400);
75 | out.print("{\"action\":\"no action provided\"}");
76 | }
77 | }
78 |
79 | @Override
80 | public void setPlatformProxy(DicooglePlatformInterface core) {
81 | this.platform = core;
82 | }
83 |
84 | }
85 |
--------------------------------------------------------------------------------
/src/main/java/com/bmdsoftware/pacs/dicoogle/ipfs/services/IPFSStatusWebService.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2018 BMD software, Lda
3 | *
4 | * This file is part of Dicoogle/ipfs.
5 | *
6 | * Dicoogle/ipfs is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * Dicoogle/ipfs is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with Dicoogle. If not, see .
18 | */
19 | package com.bmdsoftware.pacs.dicoogle.ipfs.services;
20 |
21 | import io.ipfs.api.IPFS;
22 | import org.eclipse.jetty.http.HttpStatus;
23 | import org.slf4j.Logger;
24 | import org.slf4j.LoggerFactory;
25 | import pt.ua.dicoogle.sdk.core.DicooglePlatformInterface;
26 | import pt.ua.dicoogle.sdk.core.PlatformCommunicatorInterface;
27 |
28 | import javax.servlet.http.HttpServlet;
29 | import javax.servlet.http.HttpServletRequest;
30 | import javax.servlet.http.HttpServletResponse;
31 | import java.io.IOException;
32 | import java.io.PrintWriter;
33 |
34 | /**
35 | * IPFS Jetty Plugin - Status
36 | *
37 | * @author Luís A. Bastião Silva -
38 | * @author Eriksson Monteiro -
39 | * @author Rui Lebre -
40 | */
41 | public class IPFSStatusWebService extends HttpServlet implements PlatformCommunicatorInterface {
42 | private static final Logger logger = LoggerFactory.getLogger(IPFSStatusWebService.class);
43 |
44 | private DicooglePlatformInterface platform;
45 | private IPFS ipfs = null;
46 |
47 | public IPFSStatusWebService(IPFS ipfs) {
48 | this.ipfs = ipfs;
49 | }
50 |
51 | @Override
52 | protected void doGet(HttpServletRequest req, HttpServletResponse response) throws IOException {
53 |
54 | String action = req.getParameter("action");
55 | if (action == null) {
56 | response.sendError(HttpStatus.BAD_REQUEST_400, "No action provided");
57 | return;
58 | }
59 | response.setContentType("text/json;charset=utf-8");
60 | PrintWriter out = response.getWriter();
61 |
62 | if (action.equalsIgnoreCase("status")) {
63 | response.setStatus(HttpStatus.OK_200);
64 |
65 | out.print("{\"action\":\"status\", \"host\":\"" + ipfs.host + "\", \"status\":" + ipfs.stats.bw().toString() + "\"}");
66 | } else {
67 | response.setStatus(HttpStatus.BAD_REQUEST_400);
68 | out.print("{\"action\":\"no action provided\"}");
69 | }
70 | }
71 |
72 | @Override
73 | public void setPlatformProxy(DicooglePlatformInterface core) {
74 | this.platform = core;
75 | }
76 |
77 | }
78 |
--------------------------------------------------------------------------------
/src/test/java/com/bmdsoftware/pacs/dicoogle/ipfs/TestIPFS.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2018 BMD software, Lda
3 | *
4 | * This file is part of Dicoogle/ipfs.
5 | *
6 | * Dicoogle/ipfs is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * Dicoogle/ipfs is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with Dicoogle. If not, see .
18 | */
19 | package com.bmdsoftware.pacs.dicoogle.ipfs;
20 |
21 | import io.ipfs.api.IPFS;
22 | import io.ipfs.api.MerkleNode;
23 | import io.ipfs.api.NamedStreamable;
24 | import io.ipfs.multihash.Multihash;
25 | import org.junit.BeforeClass;
26 | import org.junit.Test;
27 |
28 | import java.io.*;
29 | import java.nio.charset.StandardCharsets;
30 | import java.util.Arrays;
31 | import java.util.List;
32 | import java.util.Map;
33 | import java.util.UUID;
34 |
35 | import static org.junit.Assert.assertNotNull;
36 | import static org.junit.Assert.assertTrue;
37 |
38 | /**
39 | * @author Rui Lebre -
40 | */
41 | public class TestIPFS {
42 | private static IPFS ipfs;
43 | private static String testFileContent = "test test test";
44 |
45 | @BeforeClass
46 | public static void setup() {
47 | ipfs = new IPFS("/ip4/127.0.0.1/tcp/5001");
48 | }
49 |
50 | @Test
51 | public void testFileOperations() throws IOException {
52 | NamedStreamable.ByteArrayWrapper file = new NamedStreamable.ByteArrayWrapper(UUID.randomUUID().toString(), testFileContent.getBytes(StandardCharsets.UTF_8));
53 |
54 | // Test add file
55 | MerkleNode addResult = ipfs.add(file).get(0);
56 | byte[] catResult = ipfs.cat(addResult.hash);
57 | assertTrue("Add file failed.", catResult.length > 0);
58 |
59 |
60 | // Test file content
61 | assertTrue("File content not equal.", Arrays.equals(catResult, file.getContents()));
62 |
63 | // Test file remove pin
64 | List pinRm = ipfs.pin.rm(addResult.hash, true);
65 | assertTrue("Pin removal failed.", pinRm.get(0).equals(addResult.hash));
66 |
67 | // Test garbage collector
68 | ipfs.repo.gc();
69 | }
70 |
71 | @Test
72 | public void testStats() throws IOException {
73 | Map stats = ipfs.stats.bw();
74 |
75 | assertNotNull("Stats null.", stats);
76 | }
77 |
78 | @Test
79 | public void testListLocal() throws IOException {
80 | List localRefs = ipfs.refs.local();
81 |
82 | assertNotNull("Local refs null.", localRefs);
83 | assertTrue("Local refs must be at least one.", localRefs.size() > 0);
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/src/test/java/com/bmdsoftware/pacs/dicoogle/ipfs/TestStorage.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2018 BMD software, Lda
3 | *
4 | * This file is part of Dicoogle/ipfs.
5 | *
6 | * Dicoogle/ipfs is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * Dicoogle/ipfs is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with Dicoogle. If not, see .
18 | */
19 | package com.bmdsoftware.pacs.dicoogle.ipfs;
20 |
21 | import org.dcm4che2.data.DicomObject;
22 | import org.dcm4che2.data.Tag;
23 | import org.dcm4che2.io.DicomInputStream;
24 | import org.junit.BeforeClass;
25 | import org.junit.Test;
26 | import pt.ua.dicoogle.sdk.PluginSet;
27 |
28 | import java.io.File;
29 | import java.io.IOException;
30 | import java.io.InputStream;
31 | import java.net.URI;
32 |
33 | import static org.junit.Assert.assertEquals;
34 |
35 | /**
36 | * @author Rui Lebre -
37 | */
38 | public class TestStorage {
39 | private static IPFSStore ipfsStorePlugin;
40 |
41 | @BeforeClass
42 | public static void setup() throws IOException {
43 | PluginSet ps = new IPFSPluginSet();
44 | ipfsStorePlugin = (IPFSStore) ps.getStoragePlugins().toArray()[0];
45 | }
46 |
47 | @Test
48 | public void testStorageDicomStream() throws IOException {
49 | ClassLoader classLoader = getClass().getClassLoader();
50 | File dicomFile = new File(classLoader.getResource("DoseSR_GE_01.DCM").getPath());
51 |
52 | // test store operation
53 | URI fileURI = ipfsStorePlugin.store(new DicomInputStream(dicomFile));
54 |
55 | // test at operation
56 | InputStream storedDicomStream = ipfsStorePlugin.at(fileURI).iterator().next().getInputStream();
57 |
58 | DicomObject originalDicomObj = new DicomInputStream(dicomFile).readDicomObject();
59 | DicomObject storedDicomObj = new DicomInputStream(storedDicomStream).readDicomObject();
60 |
61 | assertEquals(originalDicomObj.get(Tag.SOPInstanceUID), storedDicomObj.get(Tag.SOPInstanceUID));
62 |
63 | ipfsStorePlugin.remove(fileURI);
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/test/resources/DoseSR_GE_01.DCM:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BMDSoftware/dicoogle-ipfs-storage/06c524cff66dae869237f581186bb867781b9cff/src/test/resources/DoseSR_GE_01.DCM
--------------------------------------------------------------------------------