View Javadoc

1   /*
2    *  XNap - A P2P framework and client.
3    *
4    *  See the file AUTHORS for copyright information.
5    *
6    *  This program 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.
9    *
10   *  This program 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 this program; if not, write to the Free Software
17   *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18   */
19  
20  package org.xnap.plugin.opennap.util;
21  
22  import java.io.File;
23  import java.io.IOException;
24  import java.io.RandomAccessFile;
25  import java.util.StringTokenizer;
26  
27  import org.xnap.XNap;
28  import org.xnap.io.Library;
29  import org.xnap.io.MetaInfoFile;
30  import org.xnap.util.Preferences;
31  import org.xnap.util.StringHelper;
32  
33  
34  public class OpenNapFileHelper
35  {
36  
37  
38      //--- Constant(s) ---
39  
40      //--- Data field(s) ---
41  
42      //--- Constructor(s) ---
43  
44      //--- Method(s) ---
45  
46      /***
47       * Converts the system-dependent pathname to the OpenNap format
48       * which uses '\' as separator.
49       */
50      public static String getShareString(int index, File file) 
51      {
52  		if (Preferences.getInstance().getShareFullPath()){
53  			String filename = file.getAbsolutePath();
54  			return mapFilename(filename.replace(File.separatorChar, '//'));
55  		}
56  		else {
57  			return index + "//" + mapFilename(file.getName());
58  		}
59      }
60  
61      /***
62       * Extracts index and filename from OpenNap specific shared filename and
63       * return file if it's a valid Shared entry.
64       *
65       * @return null, if filename is not part of repository
66       */
67      public static MetaInfoFile getSharedFileByIndex(String request) 
68      {
69  		StringTokenizer st = new StringTokenizer(request, "//");
70  
71  		if (st.countTokens() >= 2) {
72  			try {
73  				int index = Integer.parseInt(st.nextToken());
74  				String filename = st.nextToken("").substring(1);
75  
76  				if (index >= 0 && index < Library.getInstance().size()) {
77  					MetaInfoFile file = Library.getInstance().get(index);
78  					if (file != null && file.isShared()
79  						&& mapFilename(file.getName()).equals(filename)) {
80  
81  						return file;
82  					}
83  				}
84  			}
85  			catch (NumberFormatException e) {
86  			}
87  		}
88  
89  		return null;
90      }
91  
92      /***
93       * Retrieves repository file.
94       * First we try to retrieve the file by parsing for its repository index,
95       * if this does not work, we'll try to search for the file.
96       */
97      public static MetaInfoFile getSharedFile(String filename)
98      {
99  		MetaInfoFile file = getSharedFileByIndex(filename);
100 		if (file != null) {
101 			return file;
102 		}
103 
104 		String shortname = StringHelper.lastToken(filename, "//");
105 		MetaInfoFile[] results = Library.getInstance().search(shortname);
106 
107 		filename = filename.replace('//', File.separatorChar);
108 		if (results != null) {
109 			for (int i = 0; i < results.length; i++) {
110 				if (mapFilename(results[i].getAbsolutePath()).equals(filename)
111 					&& results[i].isShared()) {
112 
113 					return results[i];
114 				}
115 			}
116 		}
117     
118 		return null;
119     }
120 
121 	/***
122 	 * @see Library#isShared(File) */
123 	public static boolean isShared(File file)
124 	{
125 		return Library.getInstance().isShared(file);
126 	}
127 
128 	/***
129 	 * Replaces all characters that confuse OpenNap servers in
130 	 * filename by non confusing characters. Used to send share
131 	 * messages.
132 	 */
133 	public static String mapFilename(String filename)
134 	{
135 		//return filename.replace('"', '\uF020');
136 		return filename.replace('"', '\'');
137 	}
138 
139 	/***
140 	 * Appends <code>inFile</code> to <code>outFile</code> starting at
141 	 * <code>offset</code> off <code>inFile</code>
142 	 */
143 	public static void append(File outFile, File inFile, long offset) 
144 		throws IOException
145 	{
146 		RandomAccessFile in = null;
147 		RandomAccessFile out = null;
148 		try {
149 			out = new RandomAccessFile(outFile, "rw");
150 			out.seek(out.length());
151 
152 			in = new RandomAccessFile(inFile, "r");
153 			in.seek(offset);
154 
155 			// allocate 512 kb
156 			byte[] data = new byte[512 * 1024];
157 			long toWrite = in.length() - offset;
158 			while (toWrite > 0) {
159 				int len = (int)Math.min(data.length, toWrite);
160 				in.readFully(data, 0, len);
161 				out.write(data, 0, len);
162 				toWrite -= len;
163 			}
164 	    }
165 		finally {
166 			if (in != null) {
167 				try {
168 					in.close();
169 				}
170 				catch (IOException e) {
171 				}
172 			}
173 			if (out != null) {
174 				try {
175 					out.close();
176 				}
177 				catch (IOException e) {
178 				}
179 			}
180 		}
181 	}
182 
183 	public static void match(File f1, File f2, int byteCount) 
184 		throws IOException
185 	{
186 		RandomAccessFile f1In = null;
187 		RandomAccessFile f2In = null;
188 		try {
189 			f1In = new RandomAccessFile(f1, "r");
190 			f2In = new RandomAccessFile(f2, "r");
191 	
192 			byte[] f1Data = new byte[byteCount];
193 			f1In.seek(f1.length() - byteCount);
194 			f1In.readFully(f1Data);
195 
196 			byte[] f2Data = new byte[byteCount];
197 			f2In.seek(0);
198 			f2In.readFully(f2Data);
199 			
200 			for (int i = 0; i < byteCount; i++) {
201 				if (f1Data[i] != f2Data[i]) {
202 					throw new IOException(XNap.tr("merge failed at {0}",
203 												  new Integer(byteCount)));
204 				}
205 			}
206 	    }
207 		finally {
208 			if (f1In != null) {
209 				try {
210 					f1In.close();
211 				}
212 				catch (IOException e) {
213 				}
214 			}
215 			if (f2In != null) {
216 				try {
217 					f2In.close();
218 				}
219 				catch (IOException e) {
220 				}
221 			}
222 		}
223 
224 	}
225 
226 
227 }