Source code: com/flexstor/remote/resourcefork/ntfs/NtfsForkServerThread.java
1 /*
2 * NtfsForkServerThread.java
3 *
4 * Copyright $Date: 2003/08/11 03:53:52 $ FLEXSTOR.net Inc.
5 *
6 * This work is licensed for use and distribution under license terms found at
7 * http://www.flexstor.org/license.html
8 *
9 */
10
11 package com.flexstor.remote.resourcefork.ntfs;
12
13 import java.io.BufferedReader;
14 import java.io.IOException;
15 import java.io.InputStreamReader;
16 import java.net.InetAddress;
17 import java.net.UnknownHostException;
18
19 import com.flexstor.common.io.xfile.FlexXFile;
20
21 /**
22 * Server side implementation for requesting resource fork operations to files residing in a NTFS system.
23 */
24 public class NtfsForkServerThread
25 extends Thread
26 {
27 static final String IDENTIFIER = "$Id: NtfsForkServerThread.java,v 1.3 2003/08/11 03:53:52 aleric Exp $";
28
29 private final static int ENCODE = 1;
30 private final static int DECODE = 2;
31 private final static int COPY = 3;
32 private final static int MOVE = 4;
33 private final static int DELETE = 5;
34
35 private int nAction = 0;
36 private boolean bResult = false;
37 private String sInFile = null;
38 private String sDestination = null;
39 private Exception exception = null;
40
41 public void run()
42 {
43 try
44 {
45 switch ( nAction )
46 {
47 case ENCODE:
48 bResult = encode();
49 break;
50 case DECODE:
51 bResult = decode();
52 break;
53 case COPY:
54 bResult = copy();
55 break;
56 case MOVE:
57 bResult = move();
58 break;
59 case DELETE:
60 bResult = delete();
61 break;
62 }
63 }
64 catch ( IOException ioe )
65 {
66 exception = ioe;
67 ioe.printStackTrace();
68 bResult = false;
69 }
70 }
71
72 /**
73 * Creates a MacBinary file in the remote server
74 *
75 * @param sInFile Source file for creating MacBinary, must be local to the remote server.
76 * @param sLocation Destination for the MacBinary, must be local to the remote server.
77 * @return boolean indicating success or failure
78 */
79 public boolean encodeMacBinary( String sInFile, String sDestination )
80 throws Exception
81 {
82 this.nAction = ENCODE;
83 this.sInFile = sInFile;
84 this.sDestination = sDestination;
85
86 start();
87 join();
88
89 if ( exception != null )
90 throw exception;
91 else
92 return bResult;
93 }
94
95 private boolean encode()
96 throws IOException
97 {
98 // Transform paths to UNC paths
99 sInFile = getUNCPath( sInFile );
100 sDestination = getUNCPath( sDestination );
101
102 (new NtfsMacBinaryEncoder()).createMacBinary( sInFile, sDestination );
103 return true;
104 }
105
106 /**
107 * Splits a MacBinary file in the remote server
108 *
109 * @param sInFile MacBinary source file, must be local to the remote server.
110 * @param sLocation Destination for the data and resource fork, must be local to the remote server.
111 * @return boolean indicating success or failure
112 */
113 public boolean decodeMacBinary( String sInFile, String sDestination )
114 throws Exception
115 {
116 this.nAction = DECODE;
117 this.sInFile = sInFile;
118 this.sDestination = sDestination;
119
120 start();
121 join();
122
123 if ( exception != null )
124 throw exception;
125 else
126 return bResult;
127 }
128
129 private boolean decode()
130 throws IOException
131 {
132 // Transform paths to UNC paths
133 sInFile = getUNCPath( sInFile );
134 sDestination = getUNCPath( sDestination );
135
136 (new NtfsMacBinaryDecoder()).decodeMacBinary( sInFile, sDestination );
137 return true;
138 }
139
140 /**
141 * Copies a file from one location to another, both location in the remote server
142 *
143 * @param sInFile Source file, must be local to the remote server.
144 * @param sLocation Destination, must be local to the remote server.
145 * @return boolean indicating success or failure
146 */
147 public boolean copyFile( String sInFile, String sDestination )
148 throws Exception
149 {
150 this.nAction = COPY;
151 this.sInFile = sInFile;
152 this.sDestination = sDestination;
153
154 start();
155 join();
156
157 if ( exception != null )
158 throw exception;
159 else
160 return bResult;
161 }
162
163 private boolean copy()
164 throws IOException
165 {
166 // Transform paths to UNC paths
167 sInFile = getUNCPath( sInFile );
168 sDestination = getUNCPath( sDestination );
169
170 return executeExternal( "copy \"" + sInFile + "\" \"" + sDestination + "\"" );
171 }
172
173 /**
174 * Moves a file from one location to another, both location in the remote server
175 *
176 * @param sInFile Source file, must be local to the remote server.
177 * @param sLocation Destination, must be local to the remote server.
178 * @return boolean indicating success or failure
179 */
180 public boolean moveFile( String sInFile, String sDestination )
181 throws Exception
182 {
183 this.nAction = MOVE;
184 this.sInFile = sInFile;
185 this.sDestination = sDestination;
186
187 start();
188 join();
189
190 if ( exception != null )
191 throw exception;
192 else
193 return bResult;
194 }
195
196 private boolean move()
197 throws IOException
198 {
199 // Transform paths to UNC paths
200 sInFile = getUNCPath( sInFile );
201 sDestination = getUNCPath( sDestination );
202
203 return executeExternal( "move \"" + sInFile + "\" \"" + sDestination + "\"" );
204 }
205
206 /**
207 * Deletes a file in the remote server
208 *
209 * @param sInFile Source file to delete, must be local to the remote server.
210 * @return boolean indicating success or failure
211 */
212 public boolean deleteFile( String sInFile )
213 throws Exception
214 {
215 this.nAction = DELETE;
216 this.sInFile = sInFile;
217
218 start();
219 join();
220
221 if ( exception != null )
222 throw exception;
223 else
224 return bResult;
225 }
226
227 private boolean delete()
228 throws IOException
229 {
230 // Transform path to UNC path
231 sInFile = getUNCPath( sInFile );
232
233 // Without the sleep here, this thread will throw an error because the file is still
234 // being used by another thread.
235 try { Thread.sleep(1000); }
236 catch ( InterruptedException ie ) {}
237 return executeExternal( "del \"" + sInFile + "\"" );
238 }
239
240 private boolean executeExternal( String sCommand )
241 throws IOException
242 {
243 Process pr = null;
244 try
245 {
246 System.out.println( "Executing: " + sCommand );
247 String[] saCommand = new String[3];
248 saCommand[0] = "cmd.exe";
249 saCommand[1] = "/c";
250 saCommand[2] = sCommand;
251 pr = Runtime.getRuntime().exec(saCommand);
252 // Wait for process completion
253 pr.waitFor();
254 BufferedReader errorReader = new BufferedReader( new InputStreamReader( pr.getErrorStream() ) );
255 StringBuffer sbError = new StringBuffer();
256 String sErrorLine;
257 while ( (sErrorLine = errorReader.readLine()) != null )
258 sbError.append( sErrorLine + "\r\n" );
259
260 if ( sbError.length() > 0 )
261 throw new IOException( sbError.toString() );
262 else if ( pr.exitValue() != 0 )
263 {
264 BufferedReader inputReader = new BufferedReader( new InputStreamReader( pr.getInputStream() ) );
265 while ( (sErrorLine = inputReader.readLine()) != null )
266 sbError.append( sErrorLine + "\r\n" );
267
268 if ( sbError.length() > 0 )
269 throw new IOException( "NT Server: " + sCommand + ": " + sbError.toString() );
270 }
271 return true;
272 }
273 catch (IOException ioe)
274 {
275 throw ioe;
276 }
277 catch (InterruptedException ie)
278 {
279 ie.printStackTrace();
280 return false;
281 }
282 finally
283 {
284 if ( pr != null )
285 {
286 pr.destroy();
287 pr = null;
288 }
289 }
290 }
291
292 private String getUNCPath( String sPath )
293 {
294 String sUNC;
295 if ( System.getProperty("os.name").startsWith("Win") )
296 sUNC = "\\\\" + com.flexstor.common.util.InetUtil.getLocalHostName() + (new FlexXFile(sPath)).getLocalPath();
297 else
298 sUNC = (new FlexXFile(sPath)).getUNCPath();
299
300 // DOS commands won't accept forward slashes, so replace them
301 // with back slashes
302 if ( sUNC.indexOf('/') != -1 )
303 sUNC = sUNC.replace( '/', '\\' );
304 return sUNC;
305 }
306
307 private String getLocalHost()
308 {
309 try
310 {
311 InetAddress address = InetAddress.getLocalHost();
312 return address.getHostAddress();
313 }
314 catch( UnknownHostException uhe )
315 {
316 uhe.printStackTrace();
317 return null;
318 }
319 }
320 }