summaryrefslogtreecommitdiffstats
path: root/src/main/java/org/openslx/satellitedaemon/ftp/FtpUploadWorker.java
blob: 9276ed9f2ab2e20c91d7b79db12b4d234752b6dd (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
package org.openslx.satellitedaemon.ftp;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.util.List;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;

import org.apache.log4j.Logger;
import org.openslx.filetransfer.Uploader;
import org.openslx.imagemaster.thrift.iface.ImageData;
import org.openslx.imagemaster.thrift.iface.UploadInfos;
import org.openslx.satellitedaemon.Globals;
import org.openslx.satellitedaemon.Globals.PropInt;
import org.openslx.satellitedaemon.Globals.PropString;
import org.openslx.satellitedaemon.db.DbImage;

// TODO: Rename all this FTP* Stuff (also the constants in Globals) now that we're not using ftp anymore 

public class FtpUploadWorker implements Runnable
{
	private static Logger log = Logger.getLogger( FtpUploadWorker.class );

	@Override
	public void run()
	{
		while ( true ) {
			// This List contains all Images in the Database that should be uploaded.
			List<DbImage> imageList = DbImage.getAllMarkedForUpload();
			log.info( "FtpUploadWorker: imageList Contains " + imageList.size() + " items." );
			
			// Upload one Image after the other.
			for ( DbImage image : imageList ) {
				// TODO: still some fields for ImageData, which i can't fill with info from DbImage.
				ImageData imDat = new ImageData( image.guid, image.rid,
						image.name, System.currentTimeMillis(), System.currentTimeMillis(), image.creator, "anyThing",
						true, false, "best", "theVeryBest", image.fileSize );
				char[] passphrase = Globals.getPropertyString( PropString.FTPSKEYSTOREPWD ).toCharArray();
				KeyStore keystore;
				try {
					
					// All the necessary KeyStore handling for the "context"-item.
					// TODO: Don't do this again and again for every image, but once before the loop (or in the constructor)
					// Or better yet in a central spot, as the downloadworker needs the context too. Maybe something like Globals.getMasterServerSslContext()
					keystore = KeyStore.getInstance( "JKS" );
					keystore.load( new FileInputStream( Globals.getPropertyString( PropString.FTPSKEYSTOREPATH ) ), passphrase );
					TrustManagerFactory tmf = TrustManagerFactory.getInstance( TrustManagerFactory.getDefaultAlgorithm() );
					tmf.init( keystore );
					SSLContext context = SSLContext.getInstance( "SSLv3" );
					TrustManager[] trustManagers = tmf.getTrustManagers();
					context.init( null, trustManagers, null );

					// uploadInfo and ThriftAuthentication
					UploadInfos upInfos = ThriftConnection.getUploadInfos( imDat );
					if ( upInfos == null ) {
						log.error( "The UploadInfos returned by ThriftConnection Class are null" );
						// FIXME: And then..? If you just continue, you'll run into a null pointer exception
					}
					
					// creating the uploader with the "context"-item.
					Uploader u = new Uploader( Globals.getPropertyString( PropString.FTPSERVERIP ), Globals.getPropertyInt( PropInt.FTPPORT ), context );
					u.sendToken( upInfos.token );
					
					// continue sending Blocks until getMissingBlocks is empty.
					while ( !upInfos.getMissingBlocks().isEmpty() ) {
						// Send all Blocks from upInfos.getMissingBlocks() in ranges.
						List<Integer> blocks = upInfos.getMissingBlocks();
						int start = 0;
						for ( int i = 0; i < blocks.size() - 1; i++ ) {
							if ( blocks.get( i ) != ( blocks.get( i + 1 ) - 1 ) ) { // TODO: !? u.sendRange expects byte values, upInfos contains block indexes (16MiB)
								u.sendRange( start, i );
								u.sendFile( image.path );
								start = i + 1;
							}
							if ( i == blocks.size() - 2 ) { // TODO: !=
								u.sendRange( start, blocks.size() - 1 );
								u.sendFile( image.path );
							}
						}
					}
					// FIXME: Should be inside loop, otherwise you'll only ever upload the first 20 blocks
					upInfos = ThriftConnection.getUploadInfos( imDat );

					// TODO: Use more local try/catch-blocks, not a big one around everything, so you know what exactly caused the exception
					// and can handle it properly. There are roughly 3 types of error/exception you can encounter:
					// 1) Expected exception: Something you expect to go wrong, so you handle it in the catch block and let the code flow continue
					// 2) Minor exception: Something went wrong and you can't continue trying to upload that image. Try to clean things up that
					//    you already did (like opening a file, opening a network connection) and then continue with the next image
					// 3) Major messup: Something went wrong that will prevent the whole application from continuing to work. Try to finish or cancel
					//    any operation going on in your application and then exit (and don't forget to log meaningful information about the error)
					// Basically all those empty catch blocks below should be moved up and filled with logic.
				} catch ( NoSuchAlgorithmException e ) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch ( CertificateException e ) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch ( FileNotFoundException e ) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch ( IOException e ) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch ( KeyStoreException e ) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch ( KeyManagementException e ) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}

			}
			try {
				Thread.sleep( 5 * 60 * 1000 );
			} catch ( InterruptedException e ) {
				Thread.currentThread().interrupt();
				return;
			}
		}

	}
}